resolve.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include <grass/config.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <grass/gis.h>
  5. #include <grass/raster.h>
  6. #include "tinf.h"
  7. CELL select_dir(CELL i)
  8. {
  9. CELL dir[256] = { 0, 1, 2, 2, 4, 1, 2, 2, 8, 1,
  10. 8, 2, 8, 4, 4, 2, 16, 16, 16, 2, 16, 4, 4,
  11. 2, 8, 8, 8, 8, 8, 8, 8, 4, 32, 1, 2, 2,
  12. 4, 4, 2, 2, 32, 8, 8, 2, 8, 8, 4, 4, 32,
  13. 32, 32, 32, 16, 32, 4, 2, 16, 16, 16, 16, 8, 16,
  14. 8, 8, 64, 64, 64, 1, 64, 1, 2, 2, 64, 64, 8,
  15. 2, 8, 8, 4, 2, 16, 64, 64, 2, 16, 64, 2, 2,
  16. 16, 8, 8, 8, 8, 8, 8, 4, 32, 64, 32, 1, 32,
  17. 32, 32, 2, 32, 32, 32, 2, 32, 8, 4, 4, 32, 32,
  18. 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 8,
  19. 8, 128, 128, 128, 1, 4, 1, 2, 2, 128, 128, 2, 1,
  20. 8, 4, 4, 2, 16, 128, 2, 1, 4, 128, 2, 1, 8,
  21. 128, 8, 1, 8, 8, 4, 2, 32, 128, 1, 1, 128, 128,
  22. 2, 1, 32, 128, 32, 1, 8, 128, 4, 2, 32, 32, 32,
  23. 1, 32, 128, 32, 1, 16, 16, 16, 1, 16, 16, 8, 4,
  24. 128, 128, 128, 128, 128, 128, 2, 1, 128, 128, 128, 1, 128,
  25. 128, 4, 2, 64, 128, 128, 1, 128, 128, 128, 1, 8, 128,
  26. 8, 1, 8, 8, 8, 2, 64, 128, 64, 128, 64, 128, 64,
  27. 128, 32, 64, 64, 128, 64, 64, 64, 1, 32, 64, 64, 128,
  28. 64, 64, 64, 128, 32, 32, 32, 64, 32, 32, 16, 128
  29. };
  30. return dir[i];
  31. }
  32. void flink(int i, int j, int nl, int ns, CELL * p1, CELL * p2, CELL * p3,
  33. int *active, int *goagain)
  34. {
  35. CELL bitmask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
  36. CELL outflow, cwork, c[8];
  37. int k;
  38. cwork = p2[j];
  39. if (Rast_is_c_null_value(p2 + j) || cwork >= 0 || cwork == -256)
  40. return;
  41. cwork = -cwork;
  42. for (k = 7; k >= 0; k--) {
  43. c[k] = 0;
  44. if (cwork >= bitmask[k]) {
  45. c[k] = 1;
  46. cwork -= bitmask[k];
  47. }
  48. }
  49. outflow = 0;
  50. /* There's no need to resolve directions at cells adjacent to null cells,
  51. * as those directions will be resolved before we get here */
  52. /* look one row back */
  53. cwork = p1[j - 1];
  54. if (cwork > 0 && cwork != 4 && c[6])
  55. outflow += 64;
  56. cwork = p1[j];
  57. if (cwork > 0 && cwork != 8 && c[7])
  58. outflow += 128;
  59. cwork = p1[j + 1];
  60. if (cwork > 0 && cwork != 16 && c[0])
  61. outflow += 1;
  62. /* look at this row */
  63. cwork = p2[j - 1];
  64. if (cwork > 0 && cwork != 2 && c[5])
  65. outflow += 32;
  66. cwork = p2[j + 1];
  67. if (cwork > 0 && cwork != 32 && c[1])
  68. outflow += 2;
  69. /* look one row forward */
  70. cwork = p3[j - 1];
  71. if (cwork > 0 && cwork != 1 && c[4])
  72. outflow += 16;
  73. cwork = p3[j];
  74. if (cwork > 0 && cwork != 128 && c[3])
  75. outflow += 8;
  76. cwork = p3[j + 1];
  77. if (cwork > 0 && cwork != 64 && c[2])
  78. outflow += 4;
  79. if (outflow == 0) {
  80. *active = 1;
  81. }
  82. else {
  83. *goagain = 1;
  84. p2[j] = select_dir(outflow);
  85. }
  86. return;
  87. }
  88. void resolve(int fd, int nl, struct band3 *bnd)
  89. {
  90. CELL cvalue;
  91. int *active;
  92. int offset, isz, i, j, pass, activity, goagain, done;
  93. active = (int *)G_calloc(nl, sizeof(int));
  94. isz = sizeof(CELL);
  95. /* select a direction when there are multiple non-flat links */
  96. lseek(fd, bnd->sz, SEEK_SET);
  97. for (i = 1; i < nl - 1; i += 1) {
  98. read(fd, bnd->b[0], bnd->sz);
  99. for (j = 1; j < bnd->ns - 1; j += 1) {
  100. offset = j * isz;
  101. if (Rast_is_c_null_value((void *)(bnd->b[0] + offset)))
  102. continue;
  103. memcpy(&cvalue, bnd->b[0] + offset, isz);
  104. if (cvalue > 0)
  105. cvalue = select_dir(cvalue);
  106. memcpy(bnd->b[0] + offset, &cvalue, isz);
  107. }
  108. lseek(fd, -bnd->sz, SEEK_CUR);
  109. write(fd, bnd->b[0], bnd->sz);
  110. }
  111. pass = 0;
  112. for (i = 1; i < nl - 1; i += 1)
  113. active[i] = 1;
  114. /* select a direction when there are multiple flat links */
  115. do {
  116. done = 1;
  117. pass += 1;
  118. activity = 0;
  119. lseek(fd, 0, SEEK_SET);
  120. advance_band3(fd, bnd);
  121. advance_band3(fd, bnd);
  122. for (i = 1; i < nl - 1; i++) {
  123. lseek(fd, (off_t) (i + 1) * bnd->sz, SEEK_SET);
  124. advance_band3(fd, bnd);
  125. if (!active[i])
  126. continue;
  127. done = 0;
  128. active[i] = 0;
  129. do {
  130. goagain = 0;
  131. for (j = 1; j < bnd->ns - 1; j += 1) {
  132. flink(i, j, nl, bnd->ns,
  133. (void *)bnd->b[0], (void *)bnd->b[1],
  134. (void *)bnd->b[2], &active[i], &goagain);
  135. if (goagain)
  136. activity = 1;
  137. }
  138. } while (goagain);
  139. lseek(fd, (off_t) i * bnd->sz, SEEK_SET);
  140. write(fd, bnd->b[1], bnd->sz);
  141. }
  142. if (!activity) {
  143. done = 1;
  144. continue;
  145. }
  146. activity = 0;
  147. lseek(fd, (off_t) (nl - 1) * bnd->sz, SEEK_SET);
  148. retreat_band3(fd, bnd);
  149. retreat_band3(fd, bnd);
  150. for (i = nl - 2; i >= 1; i -= 1) {
  151. lseek(fd, (off_t) (i - 1) * bnd->sz, SEEK_SET);
  152. retreat_band3(fd, bnd);
  153. if (!active[i])
  154. continue;
  155. done = 0;
  156. active[i] = 0;
  157. do {
  158. goagain = 0;
  159. for (j = 1; j < bnd->ns - 1; j++) {
  160. flink(i, j, nl, bnd->ns,
  161. (void *)bnd->b[0], (void *)bnd->b[1],
  162. (void *)bnd->b[2], &active[i], &goagain);
  163. if (goagain)
  164. activity = 1;
  165. }
  166. } while (goagain);
  167. lseek(fd, (off_t) i * bnd->sz, SEEK_SET);
  168. write(fd, bnd->b[1], bnd->sz);
  169. }
  170. if (!activity) {
  171. done = 1;
  172. }
  173. } while (!done);
  174. G_free(active);
  175. return;
  176. }