GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-57a646b4a4
build_nat.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/build_nat.c
3 
4  \brief Vector library - Building topology for native format
5 
6  (C) 2001-2013 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
12  \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
13  */
14 
15 #include <string.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <sys/types.h>
19 #include <inttypes.h>
20 #include <grass/glocale.h>
21 #include <grass/vector.h>
22 
23 static struct line_pnts *Points;
24 
25 /*!
26  \brief Build topology
27 
28  \param Map vector map
29  \param build build level
30 
31  \return 1 on success
32  \return 0 on error
33  */
34 int Vect_build_nat(struct Map_info *Map, int build)
35 {
36  struct Plus_head *plus;
37  int i, s, type, line, counter;
38  off_t offset;
39  int side, area;
40  struct line_cats *Cats;
41  struct P_line *Line;
42  struct P_area *Area;
43  struct bound_box box;
44 
45  G_debug(3, "Vect_build_nat() build = %d", build);
46 
47  plus = &(Map->plus);
48 
49  if (build == plus->built)
50  return 1; /* Do nothing */
51 
52  /* Check if upgrade or downgrade */
53  if (build < plus->built) {
54  /* -> downgrade */
55  Vect__build_downgrade(Map, build);
56  return 1;
57  }
58 
59  /* -> upgrade */
60  if (!Points)
61  Points = Vect_new_line_struct();
62  Cats = Vect_new_cats_struct();
63 
64  if (plus->built < GV_BUILD_BASE) {
65  int c;
66  grass_int64 npoints;
67 
68  /*
69  * We shall go through all primitives in coor file and add
70  * new node for each end point to nodes structure if the node
71  * with the same coordinates doesn't exist yet.
72  */
73 
74  /* register lines, create nodes */
75  Vect_rewind(Map);
76  G_message(_("Registering primitives..."));
77  i = 0;
78  npoints = 0;
79  while (TRUE) {
80  /* register line */
81  type = Vect_read_next_line(Map, Points, Cats);
82 
83  /* Note: check for dead lines is not needed, because they
84  are skipped by V1_read_next_line() */
85  if (type == -1) {
86  G_warning(_("Unable to read vector map"));
87  return 0;
88  }
89  else if (type == -2) {
90  break;
91  }
92 
93  G_progress(++i, 1e4);
94 
95  npoints += Points->n_points;
96 
97  offset = Map->head.last_offset;
98 
99  G_debug(3, "Register line: offset = %lu", (unsigned long)offset);
100  dig_line_box(Points, &box);
101  line = dig_add_line(plus, type, Points, &box, offset);
102  if (line == 1)
103  Vect_box_copy(&(plus->box), &box);
104  else
105  Vect_box_extend(&(plus->box), &box);
106 
107  /* Add all categories to category index */
108  if (build == GV_BUILD_ALL) {
109  for (c = 0; c < Cats->n_cats; c++) {
110  dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], line,
111  type);
112  }
113  if (Cats->n_cats == 0) /* add field 0, cat 0 */
114  dig_cidx_add_cat(plus, 0, 0, line, type);
115  }
116  }
117  G_progress(1, 1);
118 
119  G_verbose_message(n_("One primitive registered",
120  "%d primitives registered", plus->n_lines),
121  plus->n_lines);
122  G_verbose_message(n_("One vertex registered",
123  "%" PRId64 " vertices registered", npoints),
124  npoints);
125 
126  plus->built = GV_BUILD_BASE;
127  }
128 
129  if (build < GV_BUILD_AREAS)
130  return 1;
131 
132  if (plus->built < GV_BUILD_AREAS) {
133  /* Build areas */
134  /* Go through all bundaries and try to build area for both sides */
135  if (plus->n_blines > 0) {
136  counter = 1;
137  G_important_message(_("Building areas..."));
138  G_percent(0, plus->n_blines, 1);
139  for (line = 1; line <= plus->n_lines; line++) {
140 
141  /* build */
142  if (plus->Line[line] == NULL)
143  continue; /* dead */
144 
145  Line = plus->Line[line];
146  if (Line->type != GV_BOUNDARY)
147  continue;
148 
149  G_percent(counter++, plus->n_blines, 1);
150 
151  for (s = 0; s < 2; s++) {
152  if (s == 0)
153  side = GV_LEFT;
154  else
155  side = GV_RIGHT;
156 
157  G_debug(3, "Build area for line = %d, side = %d", line,
158  side);
159  Vect_build_line_area(Map, line, side);
160  }
161  }
163  n_("One area built", "%d areas built", plus->n_areas),
164  plus->n_areas);
166  n_("One isle built", "%d isles built", plus->n_isles),
167  plus->n_isles);
168  }
169  plus->built = GV_BUILD_AREAS;
170  }
171 
172  if (build < GV_BUILD_ATTACH_ISLES)
173  return 1;
174 
175  /* Attach isles to areas */
176  if (plus->built < GV_BUILD_ATTACH_ISLES) {
177  if (plus->n_isles > 0) {
178  G_important_message(_("Attaching islands..."));
179  G_percent(0, plus->n_isles, 1);
180  for (i = 1; i <= plus->n_isles; i++) {
181  G_percent(i, plus->n_isles, 1);
182  Vect_get_isle_box(Map, i, &box);
183  Vect_attach_isle(Map, i, &box);
184  }
185  }
187  }
188 
189  if (build < GV_BUILD_CENTROIDS)
190  return 1;
191 
192  /* Attach centroids to areas */
193  if (plus->built < GV_BUILD_CENTROIDS) {
194  struct P_topo_c *topo;
195 
196  if (plus->n_blines > 0) {
197  counter = 1;
198  G_important_message(_("Attaching centroids..."));
199  G_percent(0, plus->n_clines, 1);
200 
201  for (line = 1; line <= plus->n_lines; line++) {
202 
203  Line = plus->Line[line];
204  if (!Line)
205  continue; /* dead */
206 
207  if (Line->type != GV_CENTROID)
208  continue;
209 
210  G_percent(counter++, plus->n_clines, 1);
211 
212  Vect_read_line(Map, Points, NULL, line);
213  area = Vect_find_area(Map, Points->x[0], Points->y[0]);
214 
215  if (area > 0) {
216  G_debug(3, "Centroid (line=%d) in area %d", line, area);
217 
218  Area = plus->Area[area];
219  topo = (struct P_topo_c *)Line->topo;
220 
221  if (Area->centroid == 0) { /* first */
222  Area->centroid = line;
223  topo->area = area;
224  }
225  else { /* duplicate */
226  topo->area = -area;
227  }
228  }
229  }
230  }
231  plus->built = GV_BUILD_CENTROIDS;
232  }
233 
234  /* Add areas to category index */
235  /* add message and G_percent() ?
236  * it seems fast enough, no message / percent needed */
237  for (i = 1; i <= plus->n_areas; i++) {
238  int c;
239 
240  if (plus->Area[i] == NULL)
241  continue;
242 
243  if (plus->Area[i]->centroid > 0) {
244  Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);
245 
246  for (c = 0; c < Cats->n_cats; c++) {
247  dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
248  GV_AREA);
249  }
250  }
251 
252  if (plus->Area[i]->centroid == 0 ||
253  Cats->n_cats == 0) /* no centroid or no cats */
254  dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
255  }
256 
258 
259  return 1;
260 }
int Vect_build_nat(struct Map_info *Map, int build)
Build topology.
Definition: build_nat.c:34
#define NULL
Definition: ccmath.h:32
void G_percent(long, long, int)
Print percent complete messages.
Definition: percent.c:61
void G_warning(const char *,...) __attribute__((format(printf
void G_progress(long, int)
Print progress info messages.
Definition: percent.c:158
void void G_verbose_message(const char *,...) __attribute__((format(printf
void void void G_important_message(const char *,...) __attribute__((format(printf
void G_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int Vect_build_line_area(struct Map_info *, int, int)
Build area on given side of line (GV_LEFT or GV_RIGHT)
Definition: build.c:79
void Vect__build_downgrade(struct Map_info *, int)
Downgrade build level (for internal use only)
Definition: build.c:771
int Vect_box_extend(struct bound_box *, const struct bound_box *)
Extend box A by box B.
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
int Vect_read_line(struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int Vect_attach_isle(struct Map_info *, int, const struct bound_box *)
(Re)Attach isle to area
Definition: build.c:385
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
int Vect_get_isle_box(struct Map_info *, int, struct bound_box *)
Get bounding box of isle.
int Vect_rewind(struct Map_info *)
Rewind vector map to cause reads to start at beginning.
int Vect_read_next_line(struct Map_info *, struct line_pnts *, struct line_cats *)
Read next vector feature.
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
int Vect_find_area(struct Map_info *, double, double)
Find the nearest area.
int Vect_box_copy(struct bound_box *, const struct bound_box *)
Copy box B to box A.
#define GV_CENTROID
Definition: dig_defines.h:186
#define GV_BOUNDARY
Definition: dig_defines.h:185
#define GV_BUILD_ATTACH_ISLES
Topology levels - attach islands to areas.
Definition: dig_defines.h:129
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
Definition: dig_defines.h:125
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
Definition: dig_defines.h:134
#define GV_BUILD_AREAS
Topology levels - build areas.
Definition: dig_defines.h:127
#define GV_BUILD_CENTROIDS
Topology levels - assign centroids to areas.
Definition: dig_defines.h:131
#define GV_RIGHT
Definition: dig_defines.h:176
#define GV_AREA
Definition: dig_defines.h:189
#define GV_LEFT
Boundary side indicator left/right.
Definition: dig_defines.h:175
int dig_cidx_add_cat(struct Plus_head *, int, int, int, int)
Definition: diglib/cindex.c:72
int dig_add_line(struct Plus_head *, int, const struct line_pnts *, const struct bound_box *, off_t)
Add new line to Plus_head structure.
Definition: plus_line.c:133
int dig_line_box(const struct line_pnts *, struct bound_box *)
#define TRUE
Definition: gis.h:79
int64_t grass_int64
Definition: gis.h:635
#define n_(strs, strp, num)
Definition: glocale.h:11
#define _(str)
Definition: glocale.h:10
if(!(yy_init))
Definition: sqlp.yy.c:775
Vector map info.
Definition: dig_structs.h:1243
struct dig_head head
Header info.
Definition: dig_structs.h:1388
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1270
Area (topology) info.
Definition: dig_structs.h:1583
plus_t centroid
Number of first centroid within area.
Definition: dig_structs.h:1605
Vector geometry.
Definition: dig_structs.h:1553
char type
Line type.
Definition: dig_structs.h:1564
void * topo
Topology info.
Definition: dig_structs.h:1577
Centroid topology.
Definition: dig_structs.h:1514
plus_t area
Area number, negative for duplicate centroid.
Definition: dig_structs.h:1518
Basic topology-related info.
Definition: dig_structs.h:769
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:871
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:931
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:894
struct P_area ** Area
Array of areas.
Definition: dig_structs.h:875
plus_t n_clines
Current number of centroids.
Definition: dig_structs.h:898
plus_t n_isles
Current number of isles.
Definition: dig_structs.h:939
struct bound_box box
Bounding box of features.
Definition: dig_structs.h:861
plus_t n_areas
Current number of areas.
Definition: dig_structs.h:935
int built
Highest level of topology currently available.
Definition: dig_structs.h:857
Bounding box.
Definition: dig_structs.h:64
off_t last_offset
Offset of last read line.
Definition: dig_structs.h:358
Feature category info.
Definition: dig_structs.h:1677
int * field
Array of layers (fields)
Definition: dig_structs.h:1681
int * cat
Array of categories.
Definition: dig_structs.h:1685
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1689
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
double * y
Array of Y coordinates.
Definition: dig_structs.h:1659
double * x
Array of X coordinates.
Definition: dig_structs.h:1655
int n_points
Number of points.
Definition: dig_structs.h:1667