build_nat.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*!
  2. \file lib/vector/Vlib/build_nat.c
  3. \brief Vector library - Building topology for native format
  4. (C) 2001-2013 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Original author CERL, probably Dave Gerdes or Mike Higgins.
  8. \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
  9. */
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <inttypes.h>
  15. #include <grass/glocale.h>
  16. #include <grass/vector.h>
  17. static struct line_pnts *Points;
  18. /*!
  19. \brief Build topology
  20. \param Map vector map
  21. \param build build level
  22. \return 1 on success
  23. \return 0 on error
  24. */
  25. int Vect_build_nat(struct Map_info *Map, int build)
  26. {
  27. struct Plus_head *plus;
  28. int i, s, type, line, counter;
  29. off_t offset;
  30. int side, area;
  31. struct line_cats *Cats;
  32. struct P_line *Line;
  33. struct P_area *Area;
  34. struct bound_box box;
  35. G_debug(3, "Vect_build_nat() build = %d", build);
  36. plus = &(Map->plus);
  37. if (build == plus->built)
  38. return 1; /* Do nothing */
  39. /* Check if upgrade or downgrade */
  40. if (build < plus->built) {
  41. /* -> downgrade */
  42. Vect__build_downgrade(Map, build);
  43. return 1;
  44. }
  45. /* -> upgrade */
  46. if (!Points)
  47. Points = Vect_new_line_struct();
  48. Cats = Vect_new_cats_struct();
  49. if (plus->built < GV_BUILD_BASE) {
  50. int c;
  51. grass_int64 npoints;
  52. /*
  53. * We shall go through all primitives in coor file and add
  54. * new node for each end point to nodes structure if the node
  55. * with the same coordinates doesn't exist yet.
  56. */
  57. /* register lines, create nodes */
  58. Vect_rewind(Map);
  59. G_message(_("Registering primitives..."));
  60. i = 0;
  61. npoints = 0;
  62. while (TRUE) {
  63. /* register line */
  64. type = Vect_read_next_line(Map, Points, Cats);
  65. /* Note: check for dead lines is not needed, because they
  66. are skipped by V1_read_next_line() */
  67. if (type == -1) {
  68. G_warning(_("Unable to read vector map"));
  69. return 0;
  70. }
  71. else if (type == -2) {
  72. break;
  73. }
  74. G_progress(++i, 1e4);
  75. npoints += Points->n_points;
  76. offset = Map->head.last_offset;
  77. G_debug(3, "Register line: offset = %lu", (unsigned long)offset);
  78. dig_line_box(Points, &box);
  79. line = dig_add_line(plus, type, Points, &box, offset);
  80. if (line == 1)
  81. Vect_box_copy(&(plus->box), &box);
  82. else
  83. Vect_box_extend(&(plus->box), &box);
  84. /* Add all categories to category index */
  85. if (build == GV_BUILD_ALL) {
  86. for (c = 0; c < Cats->n_cats; c++) {
  87. dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c],
  88. line, type);
  89. }
  90. if (Cats->n_cats == 0) /* add field 0, cat 0 */
  91. dig_cidx_add_cat(plus, 0, 0, line, type);
  92. }
  93. }
  94. G_progress(1, 1);
  95. G_verbose_message(n_("One primitive registered", "%d primitives registered", plus->n_lines), plus->n_lines);
  96. G_verbose_message(n_("One vertex registered", "%" PRId64 " vertices registered", npoints), npoints);
  97. plus->built = GV_BUILD_BASE;
  98. }
  99. if (build < GV_BUILD_AREAS)
  100. return 1;
  101. if (plus->built < GV_BUILD_AREAS) {
  102. /* Build areas */
  103. /* Go through all bundaries and try to build area for both sides */
  104. if (plus->n_blines > 0) {
  105. counter = 1;
  106. G_important_message(_("Building areas..."));
  107. G_percent(0, plus->n_blines, 1);
  108. for (line = 1; line <= plus->n_lines; line++) {
  109. /* build */
  110. if (plus->Line[line] == NULL)
  111. continue; /* dead */
  112. Line = plus->Line[line];
  113. if (Line->type != GV_BOUNDARY)
  114. continue;
  115. G_percent(counter++, plus->n_blines, 1);
  116. for (s = 0; s < 2; s++) {
  117. if (s == 0)
  118. side = GV_LEFT;
  119. else
  120. side = GV_RIGHT;
  121. G_debug(3, "Build area for line = %d, side = %d", line, side);
  122. Vect_build_line_area(Map, line, side);
  123. }
  124. }
  125. G_verbose_message(n_("One area built", "%d areas built", plus->n_areas), plus->n_areas);
  126. G_verbose_message(n_("One isle built", "%d isles built", plus->n_isles), plus->n_isles);
  127. }
  128. plus->built = GV_BUILD_AREAS;
  129. }
  130. if (build < GV_BUILD_ATTACH_ISLES)
  131. return 1;
  132. /* Attach isles to areas */
  133. if (plus->built < GV_BUILD_ATTACH_ISLES) {
  134. if (plus->n_isles > 0) {
  135. G_important_message(_("Attaching islands..."));
  136. G_percent(0, plus->n_isles, 1);
  137. for (i = 1; i <= plus->n_isles; i++) {
  138. G_percent(i, plus->n_isles, 1);
  139. Vect_get_isle_box(Map, i, &box);
  140. Vect_attach_isle(Map, i, &box);
  141. }
  142. }
  143. plus->built = GV_BUILD_ATTACH_ISLES;
  144. }
  145. if (build < GV_BUILD_CENTROIDS)
  146. return 1;
  147. /* Attach centroids to areas */
  148. if (plus->built < GV_BUILD_CENTROIDS) {
  149. struct P_topo_c *topo;
  150. if (plus->n_blines > 0) {
  151. counter = 1;
  152. G_important_message(_("Attaching centroids..."));
  153. G_percent(0, plus->n_clines, 1);
  154. for (line = 1; line <= plus->n_lines; line++) {
  155. Line = plus->Line[line];
  156. if (!Line)
  157. continue; /* dead */
  158. if (Line->type != GV_CENTROID)
  159. continue;
  160. G_percent(counter++, plus->n_clines, 1);
  161. Vect_read_line(Map, Points, NULL, line);
  162. area = Vect_find_area(Map, Points->x[0], Points->y[0]);
  163. if (area > 0) {
  164. G_debug(3, "Centroid (line=%d) in area %d", line, area);
  165. Area = plus->Area[area];
  166. topo = (struct P_topo_c *)Line->topo;
  167. if (Area->centroid == 0) { /* first */
  168. Area->centroid = line;
  169. topo->area = area;
  170. }
  171. else { /* duplicate */
  172. topo->area = -area;
  173. }
  174. }
  175. }
  176. }
  177. plus->built = GV_BUILD_CENTROIDS;
  178. }
  179. /* Add areas to category index */
  180. /* add message and G_percent() ?
  181. * it seems fast enough, no message / precent needed */
  182. for (i = 1; i <= plus->n_areas; i++) {
  183. int c;
  184. if (plus->Area[i] == NULL)
  185. continue;
  186. if (plus->Area[i]->centroid > 0) {
  187. Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);
  188. for (c = 0; c < Cats->n_cats; c++) {
  189. dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
  190. GV_AREA);
  191. }
  192. }
  193. if (plus->Area[i]->centroid == 0 || Cats->n_cats == 0) /* no centroid or no cats */
  194. dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
  195. }
  196. Vect_destroy_cats_struct(Cats);
  197. return 1;
  198. }