build_nat.c 5.4 KB

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