GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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],
111  line, 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", "%d primitives registered", plus->n_lines), plus->n_lines);
120  G_verbose_message(n_("One vertex registered", "%" PRId64 " vertices registered", npoints), npoints);
121 
122  plus->built = GV_BUILD_BASE;
123  }
124 
125  if (build < GV_BUILD_AREAS)
126  return 1;
127 
128  if (plus->built < GV_BUILD_AREAS) {
129  /* Build areas */
130  /* Go through all bundaries and try to build area for both sides */
131  if (plus->n_blines > 0) {
132  counter = 1;
133  G_important_message(_("Building areas..."));
134  G_percent(0, plus->n_blines, 1);
135  for (line = 1; line <= plus->n_lines; line++) {
136 
137  /* build */
138  if (plus->Line[line] == NULL)
139  continue; /* dead */
140 
141  Line = plus->Line[line];
142  if (Line->type != GV_BOUNDARY)
143  continue;
144 
145  G_percent(counter++, plus->n_blines, 1);
146 
147  for (s = 0; s < 2; s++) {
148  if (s == 0)
149  side = GV_LEFT;
150  else
151  side = GV_RIGHT;
152 
153  G_debug(3, "Build area for line = %d, side = %d", line, side);
154  Vect_build_line_area(Map, line, side);
155  }
156  }
157  G_verbose_message(n_("One area built", "%d areas built", plus->n_areas), plus->n_areas);
158  G_verbose_message(n_("One isle built", "%d isles built", plus->n_isles), plus->n_isles);
159  }
160  plus->built = GV_BUILD_AREAS;
161  }
162 
163  if (build < GV_BUILD_ATTACH_ISLES)
164  return 1;
165 
166  /* Attach isles to areas */
167  if (plus->built < GV_BUILD_ATTACH_ISLES) {
168  if (plus->n_isles > 0) {
169  G_important_message(_("Attaching islands..."));
170  G_percent(0, plus->n_isles, 1);
171  for (i = 1; i <= plus->n_isles; i++) {
172  G_percent(i, plus->n_isles, 1);
173  Vect_get_isle_box(Map, i, &box);
174  Vect_attach_isle(Map, i, &box);
175  }
176  }
178  }
179 
180  if (build < GV_BUILD_CENTROIDS)
181  return 1;
182 
183  /* Attach centroids to areas */
184  if (plus->built < GV_BUILD_CENTROIDS) {
185  struct P_topo_c *topo;
186 
187  if (plus->n_blines > 0) {
188  counter = 1;
189  G_important_message(_("Attaching centroids..."));
190  G_percent(0, plus->n_clines, 1);
191 
192  for (line = 1; line <= plus->n_lines; line++) {
193 
194  Line = plus->Line[line];
195  if (!Line)
196  continue; /* dead */
197 
198  if (Line->type != GV_CENTROID)
199  continue;
200 
201  G_percent(counter++, plus->n_clines, 1);
202 
203  Vect_read_line(Map, Points, NULL, line);
204  area = Vect_find_area(Map, Points->x[0], Points->y[0]);
205 
206  if (area > 0) {
207  G_debug(3, "Centroid (line=%d) in area %d", line, area);
208 
209  Area = plus->Area[area];
210  topo = (struct P_topo_c *)Line->topo;
211 
212  if (Area->centroid == 0) { /* first */
213  Area->centroid = line;
214  topo->area = area;
215  }
216  else { /* duplicate */
217  topo->area = -area;
218  }
219  }
220  }
221  }
222  plus->built = GV_BUILD_CENTROIDS;
223  }
224 
225  /* Add areas to category index */
226  /* add message and G_percent() ?
227  * it seems fast enough, no message / precent needed */
228  for (i = 1; i <= plus->n_areas; i++) {
229  int c;
230 
231  if (plus->Area[i] == NULL)
232  continue;
233 
234  if (plus->Area[i]->centroid > 0) {
235  Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);
236 
237  for (c = 0; c < Cats->n_cats; c++) {
238  dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
239  GV_AREA);
240  }
241  }
242 
243  if (plus->Area[i]->centroid == 0 || Cats->n_cats == 0) /* no centroid or no cats */
244  dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
245  }
246 
248 
249  return 1;
250 }
int Vect_build_nat(struct Map_info *Map, int build)
Build topology.
Definition: build_nat.c:34
#define TRUE
Definition: gis.h:59
plus_t n_areas
Current number of areas.
Definition: dig_structs.h:951
Bounding box.
Definition: dig_structs.h:65
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:77
if(!(yy_init))
Definition: sqlp.yy.c:775
int built
Highest level of topology currently available.
Definition: dig_structs.h:873
void void void G_important_message(const char *,...) __attribute__((format(printf
plus_t area
Area number, negative for duplicate centroid.
Definition: dig_structs.h:1537
#define GV_LEFT
Boundary side indicator left/right.
Definition: dig_defines.h:174
Vector geometry.
Definition: dig_structs.h:1574
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
int Vect_box_copy(struct bound_box *, const struct bound_box *)
Copy box B to box A.
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
Definition: dig_defines.h:125
#define n_(strs, strp, num)
Definition: glocale.h:11
struct P_area ** Area
Array of areas.
Definition: dig_structs.h:891
int dig_line_box(const struct line_pnts *, struct bound_box *)
int n_points
Number of points.
Definition: dig_structs.h:1692
#define GV_CENTROID
Definition: dig_defines.h:185
void G_progress(long, int)
Print progress info messages.
Definition: percent.c:160
plus_t n_isles
Current number of isles.
Definition: dig_structs.h:955
plus_t centroid
Number of first centroid within area.
Definition: dig_structs.h:1628
#define NULL
Definition: ccmath.h:32
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:947
Feature category info.
Definition: dig_structs.h:1702
int dig_cidx_add_cat(struct Plus_head *, int, int, int, int)
Definition: diglib/cindex.c:73
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:136
void G_message(const char *,...) __attribute__((format(printf
double * x
Array of X coordinates.
Definition: dig_structs.h:1680
char type
Line type.
Definition: dig_structs.h:1586
Feature geometry info - coordinates.
Definition: dig_structs.h:1675
Centroid topology.
Definition: dig_structs.h:1532
Basic topology-related info.
Definition: dig_structs.h:784
int64_t grass_int64
Definition: gis.h:620
#define GV_BUILD_AREAS
Topology levels - build areas.
Definition: dig_defines.h:127
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition: line.c:45
void Vect_destroy_cats_struct(struct line_cats *)
Frees all memory associated with line_cats structure, including the struct itself.
void * topo
Topology info.
Definition: dig_structs.h:1599
int Vect_attach_isle(struct Map_info *, int, const struct bound_box *)
(Re)Attach isle to area
Definition: build.c:378
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1715
int * cat
Array of categories.
Definition: dig_structs.h:1711
#define GV_BOUNDARY
Definition: dig_defines.h:184
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1286
int Vect_box_extend(struct bound_box *, const struct bound_box *)
Extend box A by box B.
struct bound_box box
Bounding box of features.
Definition: dig_structs.h:877
int Vect_rewind(struct Map_info *)
Rewind vector map to cause reads to start at beginning.
int Vect_get_isle_box(const struct Map_info *, int, struct bound_box *)
Get bounding box of isle.
struct dig_head head
Header info.
Definition: dig_structs.h:1403
#define GV_BUILD_ATTACH_ISLES
Topology levels - attach islands to areas.
Definition: dig_defines.h:129
int Vect_find_area(struct Map_info *, double, double)
Find the nearest area.
void G_percent(long, long, int)
Print percent complete messages.
Definition: percent.c:62
Vector map info.
Definition: dig_structs.h:1259
double * y
Array of Y coordinates.
Definition: dig_structs.h:1684
Area (topology) info.
Definition: dig_structs.h:1605
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
void G_warning(const char *,...) __attribute__((format(printf
#define GV_RIGHT
Definition: dig_defines.h:175
#define GV_AREA
Definition: dig_defines.h:188
#define _(str)
Definition: glocale.h:10
off_t last_offset
Offset of last read line.
Definition: dig_structs.h:366
plus_t n_clines
Current number of centroids.
Definition: dig_structs.h:914
#define GV_BUILD_CENTROIDS
Topology levels - assign centroids to areas.
Definition: dig_defines.h:131
int * field
Array of layers (fields)
Definition: dig_structs.h:1707
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
Definition: dig_defines.h:133
int Vect_read_next_line(const struct Map_info *, struct line_pnts *, struct line_cats *)
Read next vector feature.
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:910
void void G_verbose_message(const char *,...) __attribute__((format(printf
int Vect_read_line(const struct Map_info *, struct line_pnts *, struct line_cats *, int)
Read vector feature (topological level required)
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect__build_downgrade(struct Map_info *, int)
Downgrade build level (for internal use only)
Definition: build.c:760