GRASS GIS 7 Programmer's Manual  7.5.svn(2018)-r73122
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 <grass/glocale.h>
20 #include <grass/vector.h>
21 
22 static struct line_pnts *Points;
23 
24 /*!
25  \brief Build topology
26 
27  \param Map vector map
28  \param build build level
29 
30  \return 1 on success
31  \return 0 on error
32  */
33 int Vect_build_nat(struct Map_info *Map, int build)
34 {
35  struct Plus_head *plus;
36  int i, s, type, line, counter;
37  off_t offset;
38  int side, area;
39  struct line_cats *Cats;
40  struct P_line *Line;
41  struct P_area *Area;
42  struct bound_box box;
43 
44  G_debug(3, "Vect_build_nat() build = %d", build);
45 
46  plus = &(Map->plus);
47 
48  if (build == plus->built)
49  return 1; /* Do nothing */
50 
51  /* Check if upgrade or downgrade */
52  if (build < plus->built) {
53  /* -> downgrade */
54  Vect__build_downgrade(Map, build);
55  return 1;
56  }
57 
58  /* -> upgrade */
59  if (!Points)
60  Points = Vect_new_line_struct();
61  Cats = Vect_new_cats_struct();
62 
63  if (plus->built < GV_BUILD_BASE) {
64  int c;
65  grass_int64 npoints;
66 
67  /*
68  * We shall go through all primitives in coor file and add
69  * new node for each end point to nodes structure if the node
70  * with the same coordinates doesn't exist yet.
71  */
72 
73  /* register lines, create nodes */
74  Vect_rewind(Map);
75  G_message(_("Registering primitives..."));
76  i = 0;
77  npoints = 0;
78  while (TRUE) {
79  /* register line */
80  type = Vect_read_next_line(Map, Points, Cats);
81 
82  /* Note: check for dead lines is not needed, because they
83  are skipped by V1_read_next_line() */
84  if (type == -1) {
85  G_warning(_("Unable to read vector map"));
86  return 0;
87  }
88  else if (type == -2) {
89  break;
90  }
91 
92  G_progress(++i, 1e4);
93 
94  npoints += Points->n_points;
95 
96  offset = Map->head.last_offset;
97 
98  G_debug(3, "Register line: offset = %lu", (unsigned long)offset);
99  dig_line_box(Points, &box);
100  line = dig_add_line(plus, type, Points, &box, offset);
101  if (line == 1)
102  Vect_box_copy(&(plus->box), &box);
103  else
104  Vect_box_extend(&(plus->box), &box);
105 
106  /* Add all categories to category index */
107  if (build == GV_BUILD_ALL) {
108  for (c = 0; c < Cats->n_cats; c++) {
109  dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c],
110  line, type);
111  }
112  if (Cats->n_cats == 0) /* add field 0, cat 0 */
113  dig_cidx_add_cat(plus, 0, 0, line, type);
114  }
115  }
116  G_progress(1, 1);
117 
118  G_verbose_message(n_("One primitive registered", "%d primitives registered", plus->n_lines), plus->n_lines);
119  G_verbose_message(n_("One vertex registered", "%jd vertices registered", npoints), npoints);
120 
121  plus->built = GV_BUILD_BASE;
122  }
123 
124  if (build < GV_BUILD_AREAS)
125  return 1;
126 
127  if (plus->built < GV_BUILD_AREAS) {
128  /* Build areas */
129  /* Go through all bundaries and try to build area for both sides */
130  if (plus->n_blines > 0) {
131  counter = 1;
132  G_important_message(_("Building areas..."));
133  G_percent(0, plus->n_blines, 1);
134  for (line = 1; line <= plus->n_lines; line++) {
135 
136  /* build */
137  if (plus->Line[line] == NULL)
138  continue; /* dead */
139 
140  Line = plus->Line[line];
141  if (Line->type != GV_BOUNDARY)
142  continue;
143 
144  G_percent(counter++, plus->n_blines, 1);
145 
146  for (s = 0; s < 2; s++) {
147  if (s == 0)
148  side = GV_LEFT;
149  else
150  side = GV_RIGHT;
151 
152  G_debug(3, "Build area for line = %d, side = %d", line, side);
153  Vect_build_line_area(Map, line, side);
154  }
155  }
156  G_verbose_message(n_("One area built", "%d areas built", plus->n_areas), plus->n_areas);
157  G_verbose_message(n_("One isle built", "%d isles built", plus->n_isles), plus->n_isles);
158  }
159  plus->built = GV_BUILD_AREAS;
160  }
161 
162  if (build < GV_BUILD_ATTACH_ISLES)
163  return 1;
164 
165  /* Attach isles to areas */
166  if (plus->built < GV_BUILD_ATTACH_ISLES) {
167  if (plus->n_isles > 0) {
168  G_important_message(_("Attaching islands..."));
169  G_percent(0, plus->n_isles, 1);
170  for (i = 1; i <= plus->n_isles; i++) {
171  G_percent(i, plus->n_isles, 1);
172  Vect_get_isle_box(Map, i, &box);
173  Vect_attach_isle(Map, i, &box);
174  }
175  }
177  }
178 
179  if (build < GV_BUILD_CENTROIDS)
180  return 1;
181 
182  /* Attach centroids to areas */
183  if (plus->built < GV_BUILD_CENTROIDS) {
184  struct P_topo_c *topo;
185 
186  if (plus->n_blines > 0) {
187  counter = 1;
188  G_important_message(_("Attaching centroids..."));
189  G_percent(0, plus->n_clines, 1);
190 
191  for (line = 1; line <= plus->n_lines; line++) {
192 
193  Line = plus->Line[line];
194  if (!Line)
195  continue; /* dead */
196 
197  if (Line->type != GV_CENTROID)
198  continue;
199 
200  G_percent(counter++, plus->n_clines, 1);
201 
202  Vect_read_line(Map, Points, NULL, line);
203  area = Vect_find_area(Map, Points->x[0], Points->y[0]);
204 
205  if (area > 0) {
206  G_debug(3, "Centroid (line=%d) in area %d", line, area);
207 
208  Area = plus->Area[area];
209  topo = (struct P_topo_c *)Line->topo;
210 
211  if (Area->centroid == 0) { /* first */
212  Area->centroid = line;
213  topo->area = area;
214  }
215  else { /* duplicate */
216  topo->area = -area;
217  }
218  }
219  }
220  }
221  plus->built = GV_BUILD_CENTROIDS;
222  }
223 
224  /* Add areas to category index */
225  /* add message and G_percent() ?
226  * it seems fast enough, no message / precent needed */
227  for (i = 1; i <= plus->n_areas; i++) {
228  int c;
229 
230  if (plus->Area[i] == NULL)
231  continue;
232 
233  if (plus->Area[i]->centroid > 0) {
234  Vect_read_line(Map, NULL, Cats, plus->Area[i]->centroid);
235 
236  for (c = 0; c < Cats->n_cats; c++) {
237  dig_cidx_add_cat(plus, Cats->field[c], Cats->cat[c], i,
238  GV_AREA);
239  }
240  }
241 
242  if (plus->Area[i]->centroid == 0 || Cats->n_cats == 0) /* no centroid or no cats */
243  dig_cidx_add_cat(plus, 0, 0, i, GV_AREA);
244  }
245 
247 
248  return 1;
249 }
int Vect_build_nat(struct Map_info *Map, int build)
Build topology.
Definition: build_nat.c:33
#define TRUE
Definition: gis.h:49
plus_t n_areas
Current number of areas.
Definition: dig_structs.h:951
int Vect_get_isle_box(const struct Map_info *Map, int isle, struct bound_box *Box)
Get bounding box of isle.
Bounding box.
Definition: dig_structs.h:65
int built
Highest level of topology currently available.
Definition: dig_structs.h:873
plus_t area
Area number, negative for duplicate centroid.
Definition: dig_structs.h:1537
void G_important_message(const char *msg,...)
Print a message to stderr even in brief mode (verbosity=1)
Definition: gis/error.c:131
#define GV_LEFT
Boundary side indicator left/right.
Definition: dig_defines.h:174
void G_verbose_message(const char *msg,...)
Print a message to stderr but only if module is in verbose mode.
Definition: gis/error.c:109
Vector geometry.
Definition: dig_structs.h:1574
if(!YY_CURRENT_BUFFER)
Definition: sqlp.yy.c:803
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
struct line_pnts * Vect_new_line_struct()
Creates and initializes a line_pnts structure.
Definition: line.c:45
#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:14
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 Vect_destroy_cats_struct(struct line_cats *p)
Frees all memory associated with line_cats structure, including the struct itself.
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
int Vect_find_area(struct Map_info *Map, double x, double y)
Find the nearest area.
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
#define GV_BUILD_AREAS
Topology levels - build areas.
Definition: dig_defines.h:127
int Vect_build_line_area(struct Map_info *Map, int iline, int side)
Build area on given side of line (GV_LEFT or GV_RIGHT)
Definition: build.c:77
void * topo
Topology info.
Definition: dig_structs.h:1599
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1715
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
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
struct bound_box box
Bounding box of features.
Definition: dig_structs.h:877
void G_percent(long n, long d, int s)
Print percent complete messages.
Definition: percent.c:62
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_attach_isle(struct Map_info *Map, int isle, const struct bound_box *box)
(Re)Attach isle to area
Definition: build.c:378
Vector map info.
Definition: dig_structs.h:1259
void G_progress(long n, int s)
Print progress info messages.
Definition: percent.c:160
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()
Creates and initializes line_cats structure.
int Vect_box_copy(struct bound_box *A, const struct bound_box *B)
Copy box B to box A.
int Vect_read_next_line(const struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c)
Read next vector feature.
#define GV_RIGHT
Definition: dig_defines.h:175
#define GV_AREA
Definition: dig_defines.h:188
#define _(str)
Definition: glocale.h:13
int Vect_box_extend(struct bound_box *A, const struct bound_box *B)
Extend box A by box B.
void G_message(const char *msg,...)
Print a message to stderr.
Definition: gis/error.c:90
off_t last_offset
Offset of last read line.
Definition: dig_structs.h:366
int Vect_read_line(const struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature (topological level required)
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
void Vect__build_downgrade(struct Map_info *Map, int build)
Downgrade build level (for internal use only)
Definition: build.c:760
plus_t n_blines
Current number of boundaries.
Definition: dig_structs.h:910
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:204
int Vect_rewind(struct Map_info *Map)
Rewind vector map to cause reads to start at beginning.