GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
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
23static 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 */
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 */
56 return 1;
57 }
58
59 /* -> upgrade */
60 if (!Points)
61 Points = Vect_new_line_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 */
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);
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
174 return 1;
175 }
176
177 /* Attach isles to areas */
178 if (plus->built < GV_BUILD_ATTACH_ISLES) {
179 if (plus->n_isles > 0) {
180 G_important_message(_("Attaching islands..."));
181 G_percent(0, plus->n_isles, 1);
182 for (i = 1; i <= plus->n_isles; i++) {
183 G_percent(i, plus->n_isles, 1);
184 Vect_get_isle_box(Map, i, &box);
185 Vect_attach_isle(Map, i, &box);
186 }
187 }
189 }
190
193 return 1;
194 }
195
196 /* Attach centroids to areas */
197 if (plus->built < GV_BUILD_CENTROIDS) {
198 struct P_topo_c *topo;
199
200 if (plus->n_blines > 0) {
201 counter = 1;
202 G_important_message(_("Attaching centroids..."));
203 G_percent(0, plus->n_clines, 1);
204
205 for (line = 1; line <= plus->n_lines; line++) {
206
207 Line = plus->Line[line];
208 if (!Line)
209 continue; /* dead */
210
211 if (Line->type != GV_CENTROID)
212 continue;
213
214 G_percent(counter++, plus->n_clines, 1);
215
216 Vect_read_line(Map, Points, NULL, line);
217 area = Vect_find_area(Map, Points->x[0], Points->y[0]);
218
219 if (area > 0) {
220 G_debug(3, "Centroid (line=%d) in area %d", line, area);
221
222 Area = plus->Area[area];
223 topo = (struct P_topo_c *)Line->topo;
224
225 if (Area->centroid == 0) { /* first */
226 Area->centroid = line;
227 topo->area = area;
228 }
229 else { /* duplicate */
230 topo->area = -area;
231 }
232 }
233 }
234 }
236 }
237
238 /* Add areas to category index */
239 /* add message and G_percent() ?
240 * it seems fast enough, no message / percent needed */
241 for (i = 1; i <= plus->n_areas; i++) {
242 int c;
243
244 if (plus->Area[i] == NULL)
245 continue;
246
247 if (plus->Area[i]->centroid > 0) {
248 Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);
249
250 for (c = 0; c < Cats->n_cats; c++) {
251 dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
252 GV_AREA);
253 }
254 }
255
256 if (plus->Area[i]->centroid == 0 ||
257 Cats->n_cats == 0) /* no centroid or no cats */
258 dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
259 }
260
262
263 return 1;
264}
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:72
void Vect__build_downgrade(struct Map_info *, int)
Downgrade build level (for internal use only)
Definition build.c:767
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:378
struct line_cats * Vect_new_cats_struct(void)
Creates and initializes line_cats structure.
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_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
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
#define GV_BOUNDARY
#define GV_BUILD_ATTACH_ISLES
Topology levels - attach islands to areas.
#define GV_BUILD_BASE
Topology levels - basic level (without areas and isles)
#define GV_BUILD_ALL
Topology levels - build everything (currently same as GV_BUILD_CENTROIDS)
#define GV_BUILD_AREAS
Topology levels - build areas.
#define GV_BUILD_CENTROIDS
Topology levels - assign centroids to areas.
#define GV_RIGHT
#define GV_AREA
#define GV_LEFT
Boundary side indicator left/right.
int dig_cidx_add_cat(struct Plus_head *, int, int, int, int)
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:78
int64_t grass_int64
Definition gis.h:641
#define n_(strs, strp, num)
Definition glocale.h:11
#define _(str)
Definition glocale.h:10
Vector map info.
Area (topology) info.
plus_t centroid
Number of first centroid within area.
Vector geometry.
char type
Line type.
void * topo
Topology info.
Centroid topology.
plus_t area
Area number, negative for duplicate centroid.
Basic topology-related info.
struct P_line ** Line
Array of vector geometries.
plus_t n_lines
Current number of lines.
plus_t n_blines
Current number of boundaries.
struct P_area ** Area
Array of areas.
plus_t n_clines
Current number of centroids.
plus_t n_isles
Current number of isles.
struct bound_box box
Bounding box of features.
plus_t n_areas
Current number of areas.
int built
Highest level of topology currently available.
Bounding box.
Definition dig_structs.h:62
Feature category info.
Feature geometry info - coordinates.