GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
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 SPDX-FileCopyrightText: 2001-2013 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
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
13#include <string.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <sys/types.h>
17#include <inttypes.h>
18#include <grass/glocale.h>
19#include <grass/vector.h>
20
21static struct line_pnts *Points;
22
23/*!
24 \brief Build topology
25
26 \param Map vector map
27 \param build build level
28
29 \return 1 on success
30 \return 0 on error
31 */
33{
34 struct Plus_head *plus;
35 int i, s, type, line, counter;
36 off_t offset;
37 int side, area;
38 struct line_cats *Cats;
39 struct P_line *Line;
40 struct P_area *Area;
41 struct bound_box box;
42
43 G_debug(3, "Vect_build_nat() build = %d", build);
44
45 plus = &(Map->plus);
46
47 if (build == plus->built)
48 return 1; /* Do nothing */
49
50 /* Check if upgrade or downgrade */
51 if (build < plus->built) {
52 /* -> downgrade */
54 return 1;
55 }
56
57 /* -> upgrade */
58 if (!Points)
59 Points = Vect_new_line_struct();
61
62 if (plus->built < GV_BUILD_BASE) {
63 int c;
64 grass_int64 npoints;
65
66 /*
67 * We shall go through all primitives in coor file and add
68 * new node for each end point to nodes structure if the node
69 * with the same coordinates doesn't exist yet.
70 */
71
72 /* register lines, create nodes */
74 G_message(_("Registering primitives..."));
75 i = 0;
76 npoints = 0;
77 while (TRUE) {
78 /* register line */
79 type = Vect_read_next_line(Map, Points, Cats);
80
81 /* Note: check for dead lines is not needed, because they
82 are skipped by V1_read_next_line() */
83 if (type == -1) {
84 G_warning(_("Unable to read vector map"));
85 return 0;
86 }
87 else if (type == -2) {
88 break;
89 }
90
91 G_progress(++i, 1e4);
92
93 npoints += Points->n_points;
94
95 offset = Map->head.last_offset;
96
97 G_debug(3, "Register line: offset = %lu", (unsigned long)offset);
98 dig_line_box(Points, &box);
99 line = dig_add_line(plus, type, Points, &box, offset);
100 if (line == 1)
101 Vect_box_copy(&(plus->box), &box);
102 else
103 Vect_box_extend(&(plus->box), &box);
104
105 /* Add all categories to category index */
106 if (build == GV_BUILD_ALL) {
107 for (c = 0; c < Cats->n_cats; c++) {
108 dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], line,
109 type);
110 }
111 if (Cats->n_cats == 0) /* add field 0, cat 0 */
112 dig_cidx_add_cat(plus, 0, 0, line, type);
113 }
114 }
115 G_progress(1, 1);
116
117 G_verbose_message(n_("One primitive registered",
118 "%d primitives registered", plus->n_lines),
119 plus->n_lines);
120 G_verbose_message(n_("One vertex registered",
121 "%" PRId64 " vertices registered", npoints),
122 npoints);
123
124 plus->built = GV_BUILD_BASE;
125 }
126
127 if (build < GV_BUILD_AREAS)
128 return 1;
129
130 if (plus->built < GV_BUILD_AREAS) {
131 /* Build areas */
132 /* Go through all bundaries and try to build area for both sides */
133 if (plus->n_blines > 0) {
134 counter = 1;
135 G_important_message(_("Building areas..."));
136 G_percent(0, plus->n_blines, 1);
137 for (line = 1; line <= plus->n_lines; line++) {
138
139 /* build */
140 if (plus->Line[line] == NULL)
141 continue; /* dead */
142
143 Line = plus->Line[line];
144 if (Line->type != GV_BOUNDARY)
145 continue;
146
147 G_percent(counter++, plus->n_blines, 1);
148
149 for (s = 0; s < 2; s++) {
150 if (s == 0)
151 side = GV_LEFT;
152 else
153 side = GV_RIGHT;
154
155 G_debug(3, "Build area for line = %d, side = %d", line,
156 side);
158 }
159 }
161 n_("One area built", "%d areas built", plus->n_areas),
162 plus->n_areas);
164 n_("One isle built", "%d isles built", plus->n_isles),
165 plus->n_isles);
166 }
167 plus->built = GV_BUILD_AREAS;
168 }
169
172 return 1;
173 }
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
191 return 1;
192 }
193
194 /* Attach centroids to areas */
195 if (plus->built < GV_BUILD_CENTROIDS) {
196 struct P_topo_c *topo;
197
198 if (plus->n_blines > 0) {
199 counter = 1;
200 G_important_message(_("Attaching centroids..."));
201 G_percent(0, plus->n_clines, 1);
202
203 for (line = 1; line <= plus->n_lines; line++) {
204
205 Line = plus->Line[line];
206 if (!Line)
207 continue; /* dead */
208
209 if (Line->type != GV_CENTROID)
210 continue;
211
212 G_percent(counter++, plus->n_clines, 1);
213
214 Vect_read_line(Map, Points, NULL, line);
215 area = Vect_find_area(Map, Points->x[0], Points->y[0]);
216
217 if (area > 0) {
218 G_debug(3, "Centroid (line=%d) in area %d", line, area);
219
220 Area = plus->Area[area];
221 topo = (struct P_topo_c *)Line->topo;
222
223 if (Area->centroid == 0) { /* first */
224 Area->centroid = line;
225 topo->area = area;
226 }
227 else { /* duplicate */
228 topo->area = -area;
229 }
230 }
231 }
232 }
234 }
235
236 /* Add areas to category index */
237 /* add message and G_percent() ?
238 * it seems fast enough, no message / percent needed */
239 for (i = 1; i <= plus->n_areas; i++) {
240 int c;
241
242 if (plus->Area[i] == NULL)
243 continue;
244
245 if (plus->Area[i]->centroid > 0) {
246 Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);
247
248 for (c = 0; c < Cats->n_cats; c++) {
249 dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
250 GV_AREA);
251 }
252 }
253
254 if (plus->Area[i]->centroid == 0 ||
255 Cats->n_cats == 0) /* no centroid or no cats */
256 dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
257 }
258
260
261 return 1;
262}
int Vect_build_nat(struct Map_info *Map, int build)
Build topology.
Definition build_nat.c:32
#define NULL
Definition ccmath.h:32
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:59
void G_warning(const char *,...) __attribute__((format(printf
void G_progress(long, int)
Print progress info messages.
Definition percent.c:156
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:70
void Vect__build_downgrade(struct Map_info *, int)
Downgrade build level (for internal use only)
Definition build.c:765
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:376
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:43
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:75
int64_t grass_int64
Definition gis.h:638
#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.