grid.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /****************************************************************************
  2. *
  3. * MODULE: r.terraflow
  4. *
  5. * COPYRIGHT (C) 2007 Laura Toma
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. *****************************************************************************/
  18. #include <string.h>
  19. #include <assert.h>
  20. #include "grid.h"
  21. #include "common.h"
  22. #define GRID_DEBUG if(0)
  23. /* leave a border of 1 cell around */
  24. grid::grid(dimension_type giMin, dimension_type gjMin,
  25. dimension_type iMax, dimension_type jMax,
  26. long gsize, cclabel_type glabel) :
  27. iMin(giMin-1), jMin(gjMin-1), label(glabel), size(gsize) {
  28. width = jMax - jMin + 2;
  29. height = iMax - iMin + 2;
  30. assert((size_t)width*height*sizeof(gridElement) < getAvailableMemory());
  31. data = new gridElement[(size_t)width*height];
  32. assert(data);
  33. memset(data, 0, (size_t)width*height*sizeof(gridElement));
  34. }
  35. grid::~grid() {
  36. delete [] data;
  37. }
  38. void
  39. grid::load(AMI_STREAM<plateauType> &str) {
  40. AMI_err ae;
  41. plateauType *pt;
  42. GRID_DEBUG cout << "loading grid" << endl;
  43. for(int i=0; i<size; i++) {
  44. ae = str.read_item(&pt);
  45. assert(ae == AMI_ERROR_NO_ERROR);
  46. /* cout << *pt << endl; */
  47. assert(pt->valid);
  48. assert(pt->cclabel == label);
  49. dimension_type pti, ptj;
  50. pti = pt->i - iMin;
  51. ptj = pt->j - jMin;
  52. gridElement *datap = data + (size_t)pti * width + ptj;
  53. datap->dir = pt->dir;
  54. datap->depth = DEPTH_INITIAL; /* initial depth */
  55. datap->valid = 1;
  56. #ifdef KEEP_COORDS
  57. datap->i = pt->i;
  58. datap->j = pt->j;
  59. #endif
  60. if(datap->dir) {
  61. /* if it has a dir, it's on the boundary */
  62. boundaryQueue[0].enqueue(datap);
  63. }
  64. }
  65. }
  66. void
  67. grid::save(AMI_STREAM<waterType> &str) {
  68. GRID_DEBUG cout << "saving grid" << endl;
  69. for(dimension_type i=1; i<height-1; i++) {
  70. gridElement *rowp = data + (size_t)i * width;
  71. for(dimension_type j=1; j<width-1; j++) {
  72. gridElement *datap = rowp + j;
  73. if(datap->valid) {
  74. /* DONT save the label */
  75. waterType wt(i+iMin, j+jMin, datap->dir, LABEL_UNDEF, datap->depth);
  76. AMI_err ae = str.write_item(wt);
  77. assert(ae == AMI_ERROR_NO_ERROR);
  78. }
  79. }
  80. }
  81. }
  82. void
  83. grid::print() {
  84. cout << " ";
  85. for(int i=0; i<width; i++) {
  86. printf("%2d", (jMin + i%10));
  87. }
  88. cout << endl;
  89. for(int j=0; j<height; j++) {
  90. printf("%3d ", j + iMin);
  91. for(int i=0; i<width; i++) {
  92. if(data[i + (size_t)width * j].valid) {
  93. cout << " " << directionSymbol(data[i + (size_t)width * j].dir);
  94. } else {
  95. cout << " .";
  96. }
  97. }
  98. cout << endl;
  99. }
  100. }
  101. gridElement *
  102. grid::getNeighbour(gridElement *datap, int k) {
  103. switch(k) {
  104. case 0:
  105. datap += 1;
  106. break;
  107. case 1:
  108. datap += width + 1;
  109. break;
  110. case 2:
  111. datap += width;
  112. break;
  113. case 3:
  114. datap += width - 1;
  115. break;
  116. case 4:
  117. datap -= 1;
  118. break;
  119. case 5:
  120. datap -= (width + 1);
  121. break;
  122. case 6:
  123. datap -= width;
  124. break;
  125. case 7:
  126. datap -= (width - 1);
  127. break;
  128. default:
  129. assert(0);
  130. break;
  131. }
  132. return datap;
  133. }
  134. direction_type
  135. grid::getDirection(int k) {
  136. return 1<<((k+4)%8); /* converse direction */
  137. }
  138. void
  139. grid::assignDirections(int sfdmode) {
  140. gridElement *datap, *np;
  141. #ifdef KEEP_COORDS
  142. GRID_DEBUG cout << "points in queue=" << boundaryQueue[0].length() << endl;
  143. GRID_DEBUG for(int i=0; i<boundaryQueue[0].length(); i++) {
  144. boundaryQueue[0].peek(i,&datap);
  145. cout << datap->i << "," << datap->j << endl;
  146. }
  147. GRID_DEBUG cout << endl;
  148. #endif
  149. int k1=0, k2=1;
  150. while(!boundaryQueue[k1].isEmpty()) {
  151. while(boundaryQueue[k1].dequeue(&datap)) {
  152. /* should only find dominant if not on edge */
  153. if(sfdmode && datap->depth > DEPTH_INITIAL) {
  154. datap->dir = findDominant(datap->dir);
  155. }
  156. #ifdef KEEP_COORDS
  157. GRID_DEBUG cout << "(" << datap->i << "," << datap->j << ") "
  158. << "my direction is " << datap->dir;
  159. #endif
  160. for(int i=0; i<8; i++) {
  161. np = getNeighbour(datap, i);
  162. if(np->valid) {
  163. if(!np->dir) {
  164. np->depth = datap->depth + 1;
  165. boundaryQueue[k2].enqueue(np);
  166. #ifdef KEEP_COORDS
  167. GRID_DEBUG cout << " pushing " << "(" << np->i << "," << np->j << ")";
  168. #endif
  169. }
  170. if(np->depth == datap->depth + 1) { /* can only update ifin othr list */
  171. np->dir |= getDirection(i); /* neighbor points to us */
  172. /* if(!np->dir) np->dir |= getDirection(i); */
  173. }
  174. }
  175. }
  176. GRID_DEBUG cout << endl;
  177. }
  178. k1 ^= 1;
  179. k2 ^= 1;
  180. }
  181. }