GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-b35369f6b7
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
read_nat.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/read_nat.c
3 
4  \brief Vector library - reading features (native format)
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  (C) 2001-2009, 2011-2012 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Original author CERL, probably Dave Gerdes or Mike Higgins.
14  \author Update to GRASS 5.7 by Radim Blazek and David D. Gray.
15  \author Update to GRASS 7 by Martin Landa <landa.martin gmail.com>
16  */
17 
18 #include <sys/types.h>
19 #include <grass/vector.h>
20 #include <grass/glocale.h>
21 
22 static int read_line_nat(struct Map_info *, struct line_pnts *,
23  struct line_cats *, off_t);
24 
25 /*! \brief Read vector feature on non-topological level (level 1) -
26  native format - internal use only
27 
28  This function implements random access for native format,
29  constraints are ignored!
30 
31  \param Map pointer to Map_info struct
32  \param[out] Points container used to store line points within
33  (pointer to line_pnts struct)
34  \param[out] Cats container used to store line categories within
35  (pointer to line_cats struct)
36  \param offset given offset
37 
38  \return feature type (GV_POINT, GV_LINE, ...)
39  \return 0 dead line
40  \return -2 nothing to read
41  \return -1 on failure
42  */
43 int V1_read_line_nat(struct Map_info *Map, struct line_pnts *Points,
44  struct line_cats *Cats, off_t offset)
45 {
46  return read_line_nat(Map, Points, Cats, offset);
47 }
48 
49 /*! \brief Read next vector feature on non-topological level (level
50  1) - native format - internal use only.
51 
52  This function implements sequential access, constraints are
53  reflected, see Vect_set_constraint_region(),
54  Vect_set_constraint_type(), or Vect_set_constraint_field().
55 
56  Dead features are skipped.
57 
58  Vect_rewind() can be used to reset reading.
59 
60  \param Map pointer to Map_info struct
61  \param[out] line_p container used to store line points within
62  (pointer to line_pnts struct)
63  \param[out] line_c container used to store line categories within
64  (pointer to line_cats struct)
65 
66  \return feature type (GV_POINT, GV_LINE, ...)
67  \return 0 dead line
68  \return -2 nothing to read
69  \return -1 on failure
70  */
71 int V1_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p,
72  struct line_cats *line_c)
73 {
74  int itype;
75  off_t offset;
76  struct bound_box lbox, mbox;
77 
78  G_debug(3, "V1_read_next_line_nat()");
79 
80  if (Map->constraint.region_flag)
81  Vect_get_constraint_box(Map, &mbox);
82 
83  while (TRUE) {
84  offset = dig_ftell(&(Map->dig_fp));
85  itype = read_line_nat(Map, line_p, line_c, offset);
86  if (itype < 0)
87  return itype; /* nothing to read or failure */
88 
89  if (itype == 0) /* skip dead line */
90  continue;
91 
92  if (Map->constraint.type_flag) {
93  /* skip feature by type */
94  if (!(itype & Map->constraint.type))
95  continue;
96  }
97 
98  if (line_p && Map->constraint.region_flag) {
99  /* skip feature by region */
100  Vect_line_box(line_p, &lbox);
101 
102  if (!Vect_box_overlap(&lbox, &mbox))
103  continue;
104  }
105 
106  if (line_c && Map->constraint.field_flag) {
107  /* skip feature by field */
108  if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
109  continue;
110  }
111 
112  return itype;
113  }
114 
115  return -1; /* NOTREACHED */
116 }
117 
118 /*! \brief Read vector feature on topological level (level 2) -
119  native format - internal use only
120 
121  This function implements random access for native format,
122  constraints are ignored!
123 
124  Note: Topology must be built at level >= GV_BUILD_BASE
125 
126  \param Map pointer to Map_info struct
127  \param[out] Points container used to store line points within (pointer to
128  line_pnts struct)
129  \param[out] Cats container used to store line categories
130  within (pointer to line_cats struct)
131  \param line feature id to read (starts at 1)
132 
133  \return feature type (GV_POINT, GV_LINE, ...)
134  \return -2 nothing to read
135  \return -1 on failure
136  */
137 int V2_read_line_nat(struct Map_info *Map, struct line_pnts *line_p,
138  struct line_cats *line_c, int line)
139 {
140  struct P_line *Line;
141 
142  G_debug(3, "V2_read_line_nat(): line = %d", line);
143 
144  if (line < 1 || line > Map->plus.n_lines) {
145  G_warning(_("Attempt to access feature with invalid id (%d)"), line);
146  return -1;
147  }
148 
149  Line = Map->plus.Line[line];
150  if (Line == NULL) {
151  G_warning(_("Attempt to access dead feature %d"), line);
152  return -1;
153  }
154 
155  return read_line_nat(Map, line_p, line_c, Line->offset);
156 }
157 
158 /*! \brief Read next vector feature on topological level (level 2) -
159  native format - internal use only.
160 
161  This function implements sequential access, constraints are
162  reflected, see Vect_set_constraint_region(),
163  Vect_set_constraint_type(), or Vect_set_constraint_field().
164 
165  Use Vect_rewind() to reset reading.
166 
167  Dead feature are skipped.
168 
169  \param Map pointer to Map_info struct
170  \param[out] line_p container used to store line points within
171  (pointer to line_pnts struct)
172  \param[out] line_c container used to store line categories within
173  (pointer to line_cats struct)
174 
175  \return feature type (GV_POINT, GV_LINE, ...)
176  \return -2 nothing to read
177  \return -1 on error
178  */
179 int V2_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p,
180  struct line_cats *line_c)
181 {
182  int line, ret;
183  struct P_line *Line;
184  struct bound_box lbox, mbox;
185 
186  G_debug(3, "V2_read_next_line_nat()");
187 
188  if (Map->constraint.region_flag)
189  Vect_get_constraint_box(Map, &mbox);
190 
191  while (TRUE) {
192  line = Map->next_line;
193 
194  if (line > Map->plus.n_lines)
195  return -2; /* nothing to read */
196 
197  Line = Map->plus.Line[line];
198  if (Line == NULL) {
199  /* skip dead line */
200  Map->next_line++;
201  continue;
202  }
203 
204  if (Map->constraint.type_flag) {
205  /* skip feature by type */
206  if (!(Line->type & Map->constraint.type)) {
207  Map->next_line++;
208  continue;
209  }
210  }
211 
212  Map->next_line++;
213  ret = read_line_nat(Map, line_p, line_c, Line->offset);
214  if (ret < 0)
215  return ret;
216 
217  if (line_p && Map->constraint.region_flag) {
218  /* skip feature by bbox */
219  Vect_line_box(line_p, &lbox);
220 
221  if (!Vect_box_overlap(&lbox, &mbox))
222  continue;
223  }
224 
225  if (line_c && Map->constraint.field_flag) {
226  /* skip feature by field */
227  if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
228  continue;
229  }
230 
231  return ret;
232  }
233 
234  return -1; /* NOTREACHED */
235 }
236 
237 /*!
238  \brief Read line from coor file
239 
240  \param Map vector map layer
241  \param[out] p container used to store line points within
242  \param[out] c container used to store line categories within
243  \param offset given offset
244 
245  \return line type ( > 0 )
246  \return 0 dead line
247  \return -1 out of memory
248  \return -2 end of file
249  */
250 int read_line_nat(struct Map_info *Map, struct line_pnts *p,
251  struct line_cats *c, off_t offset)
252 {
253  register int i, dead = 0;
254  int n_points;
255  off_t size;
256  int n_cats, do_cats;
257  int type;
258  char rhead, nc;
259  short field;
260 
261  G_debug(3, "Vect__Read_line_nat: offset = %lu", (unsigned long)offset);
262 
263  Map->head.last_offset = offset;
264 
265  /* reads must set in_head, but writes use default */
266  dig_set_cur_port(&(Map->head.port));
267 
268  dig_fseek(&(Map->dig_fp), offset, 0);
269 
270  if (0 >= dig__fread_port_C(&rhead, 1, &(Map->dig_fp)))
271  return (-2);
272 
273  if (!(rhead & 0x01)) /* dead line */
274  dead = 1;
275 
276  if (rhead & 0x02) /* categories exists */
277  do_cats =
278  1; /* do not return here let file offset moves forward to next */
279  else /* line */
280  do_cats = 0;
281 
282  rhead >>= 2;
283  type = dig_type_from_store((int)rhead);
284 
285  G_debug(3, " type = %d, do_cats = %d dead = %d", type, do_cats, dead);
286 
287  if (c != NULL)
288  c->n_cats = 0;
289 
290  if (do_cats) {
291  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
292  if (0 >= dig__fread_port_I(&n_cats, 1, &(Map->dig_fp)))
293  return (-2);
294  }
295  else { /* coor format 5.0 */
296  if (0 >= dig__fread_port_C(&nc, 1, &(Map->dig_fp)))
297  return (-2);
298  n_cats = (int)nc;
299  }
300  G_debug(3, " n_cats = %d", n_cats);
301 
302  if (c != NULL) {
303  c->n_cats = n_cats;
304  if (n_cats > 0) {
305  if (0 > dig_alloc_cats(c, (int)n_cats + 1))
306  return -1;
307 
308  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
309  if (0 >=
310  dig__fread_port_I(c->field, n_cats, &(Map->dig_fp)))
311  return (-2);
312  }
313  else { /* coor format 5.0 */
314  for (i = 0; i < n_cats; i++) {
315  if (0 >= dig__fread_port_S(&field, 1, &(Map->dig_fp)))
316  return (-2);
317  c->field[i] = (int)field;
318  }
319  }
320  if (0 >= dig__fread_port_I(c->cat, n_cats, &(Map->dig_fp)))
321  return (-2);
322  }
323  }
324  else {
325  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
326  size = (off_t)(2 * PORT_INT) * n_cats;
327  }
328  else { /* coor format 5.0 */
329  size = (off_t)(PORT_SHORT + PORT_INT) * n_cats;
330  }
331 
332  dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
333  }
334  }
335 
336  if (type & GV_POINTS) {
337  n_points = 1;
338  }
339  else {
340  if (0 >= dig__fread_port_I(&n_points, 1, &(Map->dig_fp)))
341  return (-2);
342  }
343 
344  G_debug(3, " n_points = %d", n_points);
345 
346  if (p != NULL) {
347  if (0 > dig_alloc_points(p, n_points + 1))
348  return (-1);
349 
350  p->n_points = n_points;
351  if (0 >= dig__fread_port_D(p->x, n_points, &(Map->dig_fp)))
352  return (-2);
353  if (0 >= dig__fread_port_D(p->y, n_points, &(Map->dig_fp)))
354  return (-2);
355 
356  if (Map->head.with_z) {
357  if (0 >= dig__fread_port_D(p->z, n_points, &(Map->dig_fp)))
358  return (-2);
359  }
360  else {
361  for (i = 0; i < n_points; i++)
362  p->z[i] = 0.0;
363  }
364  }
365  else {
366  if (Map->head.with_z)
367  size = (off_t)n_points * 3 * PORT_DOUBLE;
368 
369  else
370  size = (off_t)n_points * 2 * PORT_DOUBLE;
371 
372  dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
373  }
374 
375  G_debug(3, " off = %lu", (unsigned long)dig_ftell(&(Map->dig_fp)));
376 
377  if (dead)
378  return 0;
379 
380  return type;
381 }
#define NULL
Definition: ccmath.h:32
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_line_box(const struct line_pnts *, struct bound_box *)
Get bounding box of line.
Definition: line.c:888
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
int Vect_get_constraint_box(struct Map_info *, struct bound_box *)
Get constraint box.
Definition: constraint.c:79
int Vect_box_overlap(const struct bound_box *, const struct bound_box *)
Tests for overlap of two boxes.
#define PORT_SHORT
Definition: dig_defines.h:49
#define PORT_DOUBLE
Sizes of types used in portable format (different names used in Vlib/ and diglib/ for the same thing)
Definition: dig_defines.h:45
#define PORT_INT
Definition: dig_defines.h:48
#define GV_POINTS
Definition: dig_defines.h:192
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.
Definition: portable.c:79
int dig_alloc_points(struct line_pnts *, int)
allocate room for 'num' X and Y arrays in struct line_pnts
Definition: struct_alloc.c:336
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition: file.c:36
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:996
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:511
int dig__fread_port_S(short *, size_t, struct gvfile *)
Read shorts from the Portable Vector Format.
Definition: portable.c:428
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:345
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition: file.c:60
int dig_type_from_store(int)
Convert type from store type.
int dig_alloc_cats(struct line_cats *, int)
Allocate room for 'num' fields and category arrays in struct line_cats.
Definition: struct_alloc.c:380
#define TRUE
Definition: gis.h:78
#define _(str)
Definition: glocale.h:10
int V2_read_line_nat(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, int line)
Read vector feature on topological level (level 2) - native format - internal use only.
Definition: read_nat.c:137
int V1_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c)
Read next vector feature on non-topological level (level 1) - native format - internal use only.
Definition: read_nat.c:71
int V1_read_line_nat(struct Map_info *Map, struct line_pnts *Points, struct line_cats *Cats, off_t offset)
Read vector feature on non-topological level (level 1) - native format - internal use only.
Definition: read_nat.c:43
int V2_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c)
Read next vector feature on topological level (level 2) - native format - internal use only.
Definition: read_nat.c:179
Vector map info.
Definition: dig_structs.h:1243
struct gvfile dig_fp
GV file pointer (native format only)
Definition: dig_structs.h:1395
struct dig_head head
Header info.
Definition: dig_structs.h:1388
int field
Field number constraint (see line_cats structure)
Definition: dig_structs.h:1367
int field_flag
Non-zero value to enable field constraint.
Definition: dig_structs.h:1363
plus_t next_line
Feature id for sequential access.
Definition: dig_structs.h:1338
int type
Feature type constraint.
Definition: dig_structs.h:1359
int type_flag
Non-zero value to enable feature type constraint.
Definition: dig_structs.h:1355
struct Map_info::@11 constraint
Constraints for sequential feature access.
int region_flag
Non-zero value to enable region constraint.
Definition: dig_structs.h:1347
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1270
Vector geometry.
Definition: dig_structs.h:1553
char type
Line type.
Definition: dig_structs.h:1564
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1571
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
int minor
Current version (minor)
Definition: dig_structs.h:275
Bounding box.
Definition: dig_structs.h:64
struct Version_info coor_version
Version info for coor file.
Definition: dig_structs.h:331
off_t last_offset
Offset of last read line.
Definition: dig_structs.h:358
int with_z
2D/3D vector data
Definition: dig_structs.h:339
struct Port_info port
Portability information.
Definition: dig_structs.h:353
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
double * z
Array of Z coordinates.
Definition: dig_structs.h:1663