build_nat.c 5.6 KB

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