areas_io.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* Cell-file area extraction */
  2. /* Input/output and line tracing routines */
  3. /* Jean Ezell */
  4. /* US Army Corps of Engineers */
  5. /* Construction Engineering Research Lab */
  6. /* Modelling and Simulation Team */
  7. /* Champaign, IL 61820 */
  8. /* November 1987 - January 1988 */
  9. /* input is a raster map found in the normal GRASS way */
  10. /* outputs are binary digit files and a supplemental area file */
  11. /* to be used to improve the dlg labelling process */
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #include <grass/gis.h>
  16. #include <grass/raster.h>
  17. #include <grass/glocale.h>
  18. #include <grass/dbmi.h>
  19. #include <grass/vector.h>
  20. #include "global.h"
  21. /* function prototypes */
  22. static int write_bnd(struct COOR *, struct COOR *, int);
  23. static int write_smooth_bnd(struct COOR *, struct COOR *, int);
  24. /* write_line - attempt to write a line to output */
  25. /* just returns if line is not completed yet */
  26. int write_boundary(struct COOR *seed)
  27. {
  28. struct COOR *point, *line_begin, *line_end, *last;
  29. int dir, line_type, n, n1;
  30. point = seed;
  31. if ((dir = at_end(point))) { /* already have one end of line */
  32. line_begin = point;
  33. line_end = find_end(point, dir, &line_type, &n);
  34. if (line_type == OPEN)
  35. return (-1); /* unfinished line */
  36. direction = dir;
  37. }
  38. else { /* in middle of a line */
  39. line_end = find_end(point, FORWARD, &line_type, &n);
  40. if (line_type == OPEN) /* line not finished */
  41. return (-1);
  42. if (line_type == END) { /* found one end at least *//* look for other one */
  43. line_begin = find_end(point, BACKWARD, &line_type, &n1);
  44. if (line_type == OPEN) /* line not finished */
  45. return (-1);
  46. if (line_type == LOOP) { /* this should NEVER be the case */
  47. return (-1);
  48. }
  49. direction = at_end(line_begin); /* found both ends now; total length */
  50. n += n1; /* is sum of distances to each end */
  51. }
  52. else {
  53. /* line_type = LOOP by default */
  54. /* already have correct length */
  55. line_begin = line_end; /* end and beginning are the same */
  56. direction = FORWARD; /* direction is arbitrary */
  57. }
  58. }
  59. dir = direction;
  60. if (smooth_flag == SMOOTH)
  61. write_smooth_bnd(line_begin, line_end, n);
  62. else
  63. write_bnd(line_begin, line_end, n);
  64. /* now free all the pointers */
  65. direction = dir;
  66. point = line_begin;
  67. last = NULPTR;
  68. n1 = 0;
  69. /* skip first and last point */
  70. while ((point = move(point)) == line_begin);
  71. while (point && point != line_end) {
  72. last = point;
  73. n1++;
  74. point = move(point);
  75. if (point == last) {
  76. /* should not happen */
  77. G_warning("loop during free ptrs, ptr %d of %d", n1, n);
  78. point = move(point);
  79. }
  80. if (last->fptr != NULPTR)
  81. if (last->fptr->fptr == last)
  82. last->fptr->fptr = NULPTR;
  83. /* it can be NULL after the previous line, even though before it wasn't */
  84. if (last->fptr != NULPTR)
  85. if (last->fptr->bptr == last)
  86. last->fptr->bptr = NULPTR;
  87. if (last->bptr != NULPTR)
  88. if (last->bptr->fptr == last)
  89. last->bptr->fptr = NULPTR;
  90. if (last->bptr != NULPTR)
  91. if (last->bptr->bptr == last)
  92. last->bptr->bptr = NULPTR;
  93. free_ptr(last);
  94. }
  95. if (point != line_end) {
  96. /* should not happen */
  97. G_warning("Line end not reached, possible memory leak");
  98. }
  99. /* free first and last point */
  100. free_ptr(line_begin);
  101. if (line_end != line_begin)
  102. free_ptr(line_end);
  103. return (0);
  104. }
  105. /* write_bnd - actual writing part of write_line */
  106. /* writes binary and ASCII digit files and supplemental file */
  107. static int write_bnd(struct COOR *line_begin, struct COOR *line_end, /* start and end point of line */
  108. int n /* number of points to write */
  109. )
  110. {
  111. static struct line_pnts *points = NULL;
  112. double x;
  113. double y;
  114. struct COOR *p, *last;
  115. int i;
  116. if (!points)
  117. points = Vect_new_line_struct();
  118. Vect_reset_line(points);
  119. p = line_begin;
  120. y = cell_head.north - (double)p->row * cell_head.ns_res;
  121. x = cell_head.west + (double)p->col * cell_head.ew_res;
  122. Vect_append_point(points, x, y, 0.0);
  123. for (i = 0; i < n; i++) {
  124. last = p;
  125. /* this should NEVER happen */
  126. if ((p = move(p)) == NULPTR)
  127. G_fatal_error(_("write_bnd: line terminated unexpectedly\n"
  128. "previous (%d) point %p (%d,%d,%d) %p %p"),
  129. direction, last, last->row, last->col, last->node,
  130. last->fptr, last->bptr);
  131. y = cell_head.north - p->row * cell_head.ns_res;
  132. x = cell_head.west + p->col * cell_head.ew_res;
  133. Vect_append_point(points, x, y, 0.0);
  134. }
  135. Vect_write_line(&Map, GV_BOUNDARY, points, Cats);
  136. return 0;
  137. }
  138. /* write_smooth_bnd - actual writing part of write_line for smoothed lines */
  139. /* writes binary and ASCII digit files and supplemental file */
  140. #define SNAP_THRESH 0.00001
  141. static int write_smooth_bnd(struct COOR *line_begin, struct COOR *line_end, /* start and end point of line */
  142. int n /* number of points to write */
  143. )
  144. {
  145. static struct line_pnts *points = NULL;
  146. double x, y;
  147. double dx, dy;
  148. int idx, idy;
  149. struct COOR *p, *last;
  150. int i, total;
  151. if (!points)
  152. points = Vect_new_line_struct();
  153. Vect_reset_line(points);
  154. p = line_begin;
  155. /* allocate the arrays and get the first point */
  156. y = cell_head.north - (double)p->row * cell_head.ns_res;
  157. x = cell_head.west + (double)p->col * cell_head.ew_res;
  158. Vect_append_point(points, x, y, 0.0);
  159. /* generate the list of smoothed points, may be duplicate points */
  160. total = 1;
  161. for (i = 0; i < n; i++) {
  162. if (i < 10)
  163. G_debug(3, " row: %d col: %d\n", p->row, p->col);
  164. last = p;
  165. if ((p = move(p)) == NULPTR) { /* this should NEVER happen */
  166. G_debug(3, "write_smooth_bnd: line terminated unexpectedly\n");
  167. G_debug(3, " previous (%d) point %p (%d,%d,%d) %p %p\n",
  168. direction, last, last->row, last->col, last->node,
  169. last->fptr, last->bptr);
  170. exit(EXIT_FAILURE);
  171. }
  172. idy = (p->row - last->row);
  173. idx = (p->col - last->col);
  174. dy = (idy > 0) ? 0.5 : ((idy < 0) ? -0.5 : 0.0); /* dy = 0.0, 0.5, or -0.5 */
  175. dx = (idx > 0) ? 0.5 : ((idx < 0) ? -0.5 : 0.0); /* dx = 0.0, 0.5, or -0.5 */
  176. y = cell_head.north - (last->row + dy) * cell_head.ns_res;
  177. x = cell_head.west + (last->col + dx) * cell_head.ew_res;
  178. total++;
  179. Vect_append_point(points, x, y, 0.0);
  180. y = cell_head.north - (p->row - dy) * cell_head.ns_res;
  181. x = cell_head.west + (p->col - dx) * cell_head.ew_res;
  182. total++;
  183. Vect_append_point(points, x, y, 0.0);
  184. } /* end of for i */
  185. y = cell_head.north - (double)p->row * cell_head.ns_res;
  186. x = cell_head.west + (double)p->col * cell_head.ew_res;
  187. total++;
  188. Vect_append_point(points, x, y, 0.0);
  189. /* strip out the duplicate points from the list */
  190. Vect_line_prune(points);
  191. if (total != points->n_points)
  192. G_debug(3, "removed duplicates: %d", total - points->n_points);
  193. Vect_write_line(&Map, GV_BOUNDARY, points, Cats);
  194. return 0;
  195. }
  196. /* write_area - make table of area equivalences and write attribute file */
  197. int write_area(struct area_table *a_list, /* list of areas */
  198. struct equiv_table *e_list, /* list of equivalences between areas */
  199. int n_areas, /* lengths of e_list, a_list */
  200. int n_equiv)
  201. {
  202. struct line_pnts *points = Vect_new_line_struct();
  203. int n, i;
  204. struct area_table *p;
  205. char *temp_buf;
  206. int *equivs;
  207. int cat;
  208. int catNum;
  209. double x, y;
  210. equivs = NULL;
  211. total_areas = 0;
  212. if (n_equiv < n_areas) {
  213. equivs = (int *)G_malloc(n_areas * sizeof(int));
  214. n = n_equiv;
  215. }
  216. else {
  217. equivs = (int *)G_malloc(n_equiv * sizeof(int));
  218. n = n_areas;
  219. }
  220. for (i = 0; i < n; i++) {
  221. if ((e_list + i)->mapped)
  222. equivs[i] = (e_list + i)->where;
  223. else {
  224. total_areas++;
  225. equivs[i] = i;
  226. }
  227. }
  228. if (n < n_areas) {
  229. for (i = n; i < n_areas; i++) {
  230. total_areas++;
  231. equivs[i] = i;
  232. }
  233. }
  234. catNum = 1;
  235. G_important_message(_("Writing areas..."));
  236. for (i = 0, p = a_list; i < n_areas; i++, p++) {
  237. G_percent(i, n_areas, 3);
  238. if (equivs[i] == i && p->width > 0 && !Rast_is_d_null_value(&(p->cat))) {
  239. char buf[1000];
  240. if (value_flag) { /* raster value */
  241. cat = (int)p->cat;
  242. }
  243. else { /* sequence */
  244. cat = catNum;
  245. catNum++;
  246. }
  247. x = cell_head.west + (p->col +
  248. (p->width / 2.0)) * cell_head.ew_res;
  249. y = cell_head.north - (p->row + 0.5) * cell_head.ns_res;
  250. switch (data_type) {
  251. case CELL_TYPE:
  252. G_debug(3,
  253. "vector x = %.3f, y = %.3f, cat = %d; raster cat = %d",
  254. x, y, cat, (int)p->cat);
  255. break;
  256. case FCELL_TYPE:
  257. G_debug(3,
  258. "vector x = %.3f, y = %.3f, cat = %d; raster cat = %f",
  259. x, y, cat, (float)p->cat);
  260. break;
  261. case DCELL_TYPE:
  262. G_debug(3,
  263. "vector x = %.3f, y = %.3f, cat = %d; raster cat = %lf",
  264. x, y, cat, p->cat);
  265. break;
  266. }
  267. Vect_reset_line(points);
  268. Vect_append_point(points, x, y, 0.0);
  269. Vect_reset_cats(Cats);
  270. Vect_cat_set(Cats, 1, cat);
  271. Vect_write_line(&Map, GV_CENTROID, points, Cats);
  272. if (driver != NULL && !value_flag) {
  273. sprintf(buf, "insert into %s values (%d, ", Fi->table, cat);
  274. db_set_string(&sql, buf);
  275. switch (data_type) {
  276. case CELL_TYPE:
  277. sprintf(buf, "%d", (int)p->cat);
  278. break;
  279. case FCELL_TYPE:
  280. case DCELL_TYPE:
  281. sprintf(buf, "%f", p->cat);
  282. break;
  283. }
  284. db_append_string(&sql, buf);
  285. if (has_cats) {
  286. temp_buf = Rast_get_d_cat(&p->cat, &RastCats);
  287. db_set_string(&label, temp_buf);
  288. db_double_quote_string(&label);
  289. sprintf(buf, ", '%s'", db_get_string(&label));
  290. db_append_string(&sql, buf);
  291. }
  292. db_append_string(&sql, ")");
  293. G_debug(3, "%s", db_get_string(&sql));
  294. if (db_execute_immediate(driver, &sql) != DB_OK)
  295. G_fatal_error(_("Cannot insert new row: %s"),
  296. db_get_string(&sql));
  297. }
  298. }
  299. }
  300. G_percent(1, 1, 1);
  301. if (equivs)
  302. G_free(equivs);
  303. return 0;
  304. }