build_nat.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*!
  2. \file lib/vector/Vlib/build_nat.c
  3. \brief Vector library - Building topology for native format
  4. (C) 2001-2009, 2011 by the GRASS Development Team
  5. This program is free software under the
  6. GNU General Public License (>=v2).
  7. Read the file COPYING that comes with GRASS
  8. for details.
  9. \author Original author CERL, probably Dave Gerdes or Mike Higgins.
  10. \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
  11. */
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <grass/glocale.h>
  17. #include <grass/vector.h>
  18. /*!
  19. \brief Build topology
  20. \param Map_info 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;
  29. off_t offset;
  30. int side, area;
  31. struct line_pnts *Points;
  32. struct line_cats *Cats;
  33. struct P_line *Line;
  34. struct P_area *Area;
  35. struct bound_box box;
  36. G_debug(3, "Vect_build_nat() build = %d", build);
  37. plus = &(Map->plus);
  38. if (build == plus->built)
  39. return 1; /* Do nothing */
  40. /* Check if upgrade or downgrade */
  41. if (build < plus->built) {
  42. /* -> downgrade */
  43. Vect__build_downgrade(Map, build);
  44. return 1;
  45. }
  46. /* -> upgrade */
  47. Points = Vect_new_line_struct();
  48. Cats = Vect_new_cats_struct();
  49. if (plus->built < GV_BUILD_BASE) {
  50. register int npoints, c;
  51. /*
  52. * We shall go through all primitives in coor file and add
  53. * new node for each end point to nodes structure if the node
  54. * with the same coordinates doesn't exist yet.
  55. */
  56. /* register lines, create nodes */
  57. Vect_rewind(Map);
  58. G_message(_("Registering primitives..."));
  59. i = 0;
  60. npoints = 0;
  61. while (TRUE) {
  62. /* register line */
  63. type = Vect_read_next_line(Map, Points, Cats);
  64. /* Note: check for dead lines is not needed, because they are skipped by V1_read_next_line_nat() */
  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(_("%d primitives registered"), plus->n_lines);
  94. G_message(_("%d vertices registered"), 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(_("%d areas built"), plus->n_areas);
  123. G_message(_("%d isles built"), 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. return 1;
  185. }