GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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 *,
23  struct line_pnts *, 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,
44  struct line_pnts *Points,
45  struct line_cats *Cats, off_t offset)
46 {
47  return read_line_nat(Map, Points, Cats, offset);
48 }
49 
50 /*! \brief Read next vector feature on non-topological level (level
51  1) - native format - internal use only.
52 
53  This function implements sequential access, constraints are
54  reflected, see Vect_set_constraint_region(),
55  Vect_set_constraint_type(), or Vect_set_constraint_field().
56 
57  Dead features are skipped.
58 
59  Vect_rewind() can be used to reset reading.
60 
61  \param Map pointer to Map_info struct
62  \param[out] line_p container used to store line points within
63  (pointer to line_pnts struct)
64  \param[out] line_c container used to store line categories within
65  (pointer to line_cats struct)
66 
67  \return feature type (GV_POINT, GV_LINE, ...)
68  \return 0 dead line
69  \return -2 nothing to read
70  \return -1 on failure
71 */
73  struct line_pnts *line_p, struct line_cats *line_c)
74 {
75  int itype;
76  off_t offset;
77  struct bound_box lbox, mbox;
78 
79  G_debug(3, "V1_read_next_line_nat()");
80 
81  if (Map->constraint.region_flag)
82  Vect_get_constraint_box(Map, &mbox);
83 
84  while (TRUE) {
85  offset = dig_ftell(&(Map->dig_fp));
86  itype = read_line_nat(Map, line_p, line_c, offset);
87  if (itype < 0)
88  return itype; /* nothing to read or failure */
89 
90  if (itype == 0) /* skip dead line */
91  continue;
92 
93  if (Map->constraint.type_flag) {
94  /* skip feature by type */
95  if (!(itype & Map->constraint.type))
96  continue;
97  }
98 
99  if (line_p && Map->constraint.region_flag) {
100  /* skip feature by region */
101  Vect_line_box(line_p, &lbox);
102 
103  if (!Vect_box_overlap(&lbox, &mbox))
104  continue;
105  }
106 
107  if (line_c && Map->constraint.field_flag) {
108  /* skip feature by field */
109  if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
110  continue;
111  }
112 
113  return itype;
114  }
115 
116  return -1; /* NOTREACHED */
117 }
118 
119 /*! \brief Read vector feature on topological level (level 2) -
120  native format - internal use only
121 
122  This function implements random access for native format,
123  constraints are ignored!
124 
125  Note: Topology must be built at level >= GV_BUILD_BASE
126 
127  \param Map pointer to Map_info struct
128  \param[out] Points container used to store line points within (pointer to line_pnts struct)
129  \param[out] Cats container used to store line categories within (pointer to line_cats struct)
130  \param line feature id to read (starts at 1)
131 
132  \return feature type (GV_POINT, GV_LINE, ...)
133  \return -2 nothing to read
134  \return -1 on failure
135 */
136 int V2_read_line_nat(struct Map_info *Map,
137  struct line_pnts *line_p, struct line_cats *line_c, int line)
138 {
139  struct P_line *Line;
140 
141  G_debug(3, "V2_read_line_nat(): line = %d", line);
142 
143  if (line < 1 || line > Map->plus.n_lines) {
144  G_warning(_("Attempt to access feature with invalid id (%d)"), line);
145  return -1;
146  }
147 
148  Line = Map->plus.Line[line];
149  if (Line == NULL) {
150  G_warning(_("Attempt to access dead feature %d"), line);
151  return -1;
152  }
153 
154  return read_line_nat(Map, line_p, line_c, Line->offset);
155 }
156 
157 /*! \brief Read next vector feature on topological level (level 2) -
158  native format - internal use only.
159 
160  This function implements sequential access, constraints are
161  reflected, see Vect_set_constraint_region(),
162  Vect_set_constraint_type(), or Vect_set_constraint_field().
163 
164  Use Vect_rewind() to reset reading.
165 
166  Dead feature are skipped.
167 
168  \param Map pointer to Map_info struct
169  \param[out] line_p container used to store line points within
170  (pointer to line_pnts struct)
171  \param[out] line_c container used to store line categories within
172  (pointer to line_cats struct)
173 
174  \return feature type (GV_POINT, GV_LINE, ...)
175  \return -2 nothing to read
176  \return -1 on error
177 */
179  struct line_pnts *line_p, struct line_cats *line_c)
180 {
181  int line, ret;
182  struct P_line *Line;
183  struct bound_box lbox, mbox;
184 
185  G_debug(3, "V2_read_next_line_nat()");
186 
187  if (Map->constraint.region_flag)
188  Vect_get_constraint_box(Map, &mbox);
189 
190  while (TRUE) {
191  line = Map->next_line;
192 
193  if (line > Map->plus.n_lines)
194  return -2; /* nothing to read */
195 
196  Line = Map->plus.Line[line];
197  if (Line == NULL) {
198  /* skip dead line */
199  Map->next_line++;
200  continue;
201  }
202 
203  if (Map->constraint.type_flag) {
204  /* skip feature by type */
205  if (!(Line->type & Map->constraint.type)) {
206  Map->next_line++;
207  continue;
208  }
209  }
210 
211  Map->next_line++;
212  ret = read_line_nat(Map, line_p, line_c, Line->offset);
213  if (ret < 0)
214  return ret;
215 
216  if (line_p && Map->constraint.region_flag) {
217  /* skip feature by bbox */
218  Vect_line_box(line_p, &lbox);
219 
220  if (!Vect_box_overlap(&lbox, &mbox))
221  continue;
222  }
223 
224  if (line_c && Map->constraint.field_flag) {
225  /* skip feature by field */
226  if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
227  continue;
228  }
229 
230  return ret;
231  }
232 
233  return -1; /* NOTREACHED */
234 }
235 
236 /*!
237  \brief Read line from coor file
238 
239  \param Map vector map layer
240  \param[out] p container used to store line points within
241  \param[out] c container used to store line categories within
242  \param offset given offset
243 
244  \return line type ( > 0 )
245  \return 0 dead line
246  \return -1 out of memory
247  \return -2 end of file
248 */
249 int read_line_nat(struct Map_info *Map,
250  struct line_pnts *p, struct line_cats *c, off_t offset)
251 {
252  register int i, dead = 0;
253  int n_points;
254  off_t size;
255  int n_cats, do_cats;
256  int type;
257  char rhead, nc;
258  short field;
259 
260  G_debug(3, "Vect__Read_line_nat: offset = %lu", (unsigned long) offset);
261 
262  Map->head.last_offset = offset;
263 
264  /* reads must set in_head, but writes use default */
265  dig_set_cur_port(&(Map->head.port));
266 
267  dig_fseek(&(Map->dig_fp), offset, 0);
268 
269  if (0 >= dig__fread_port_C(&rhead, 1, &(Map->dig_fp)))
270  return (-2);
271 
272  if (!(rhead & 0x01)) /* dead line */
273  dead = 1;
274 
275  if (rhead & 0x02) /* categories exists */
276  do_cats = 1; /* do not return here let file offset moves forward to next */
277  else /* line */
278  do_cats = 0;
279 
280  rhead >>= 2;
281  type = dig_type_from_store((int)rhead);
282 
283  G_debug(3, " type = %d, do_cats = %d dead = %d", type, do_cats, dead);
284 
285  if (c != NULL)
286  c->n_cats = 0;
287 
288  if (do_cats) {
289  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
290  if (0 >= dig__fread_port_I(&n_cats, 1, &(Map->dig_fp)))
291  return (-2);
292  }
293  else { /* coor format 5.0 */
294  if (0 >= dig__fread_port_C(&nc, 1, &(Map->dig_fp)))
295  return (-2);
296  n_cats = (int)nc;
297  }
298  G_debug(3, " n_cats = %d", n_cats);
299 
300  if (c != NULL) {
301  c->n_cats = n_cats;
302  if (n_cats > 0) {
303  if (0 > dig_alloc_cats(c, (int)n_cats + 1))
304  return -1;
305 
306  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
307  if (0 >=
308  dig__fread_port_I(c->field, n_cats, &(Map->dig_fp)))
309  return (-2);
310  }
311  else { /* coor format 5.0 */
312  for (i = 0; i < n_cats; i++) {
313  if (0 >= dig__fread_port_S(&field, 1, &(Map->dig_fp)))
314  return (-2);
315  c->field[i] = (int)field;
316  }
317  }
318  if (0 >= dig__fread_port_I(c->cat, n_cats, &(Map->dig_fp)))
319  return (-2);
320 
321  }
322  }
323  else {
324  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
325  size = (off_t) (2 * PORT_INT) * n_cats;
326  }
327  else { /* coor format 5.0 */
328  size = (off_t) (PORT_SHORT + PORT_INT) * n_cats;
329  }
330 
331  dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
332  }
333  }
334 
335  if (type & GV_POINTS) {
336  n_points = 1;
337  }
338  else {
339  if (0 >= dig__fread_port_I(&n_points, 1, &(Map->dig_fp)))
340  return (-2);
341  }
342 
343  G_debug(3, " n_points = %d", n_points);
344 
345  if (p != NULL) {
346  if (0 > dig_alloc_points(p, n_points + 1))
347  return (-1);
348 
349  p->n_points = n_points;
350  if (0 >= dig__fread_port_D(p->x, n_points, &(Map->dig_fp)))
351  return (-2);
352  if (0 >= dig__fread_port_D(p->y, n_points, &(Map->dig_fp)))
353  return (-2);
354 
355  if (Map->head.with_z) {
356  if (0 >= dig__fread_port_D(p->z, n_points, &(Map->dig_fp)))
357  return (-2);
358  }
359  else {
360  for (i = 0; i < n_points; i++)
361  p->z[i] = 0.0;
362  }
363  }
364  else {
365  if (Map->head.with_z)
366  size = (off_t) n_points * 3 * PORT_DOUBLE;
367  else
368  size = (off_t) n_points * 2 * PORT_DOUBLE;
369 
370  dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
371  }
372 
373  G_debug(3, " off = %lu", (unsigned long) dig_ftell(&(Map->dig_fp)));
374 
375  if (dead)
376  return 0;
377 
378  return type;
379 }
struct Version_info coor_version
Version info for coor file.
Definition: dig_structs.h:339
#define TRUE
Definition: gis.h:59
#define PORT_SHORT
Definition: dig_defines.h:49
Bounding box.
Definition: dig_structs.h:65
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:72
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1593
Vector geometry.
Definition: dig_structs.h:1574
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:887
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition: portable.c:343
int region_flag
Non-zero value to enable region constraint.
Definition: dig_structs.h:1362
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition: portable.c:509
int n_points
Number of points.
Definition: dig_structs.h:1692
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:136
#define GV_POINTS
Definition: dig_defines.h:191
void Vect_line_box(const struct line_pnts *, struct bound_box *)
Get bounding box of line.
Definition: line.c:922
#define NULL
Definition: ccmath.h:32
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:178
int type
Feature type constraint.
Definition: dig_structs.h:1374
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition: file.c:36
plus_t n_lines
Current number of lines.
Definition: dig_structs.h:947
#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
Feature category info.
Definition: dig_structs.h:1702
int dig_alloc_cats(struct line_cats *, int)
Allocate room for &#39;num&#39; fields and category arrays in struct line_cats.
Definition: struct_alloc.c:383
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
int with_z
2D/3D vector data
Definition: dig_structs.h:347
int field_flag
Non-zero value to enable field constraint.
Definition: dig_structs.h:1378
plus_t next_line
Feature id for sequential access.
Definition: dig_structs.h:1353
struct Map_info::@11 constraint
Constraints for sequential feature access.
struct Port_info port
Portability information.
Definition: dig_structs.h:361
int dig_type_from_store(int)
Convert type from store type.
int n_cats
Number of categories attached to element.
Definition: dig_structs.h:1715
int * cat
Array of categories.
Definition: dig_structs.h:1711
int Vect_get_constraint_box(const struct Map_info *, struct bound_box *)
Get constraint box.
Definition: constraint.c:79
int dig_alloc_points(struct line_pnts *, int)
allocate room for &#39;num&#39; X and Y arrays in struct line_pnts
Definition: struct_alloc.c:336
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1286
int type_flag
Non-zero value to enable feature type constraint.
Definition: dig_structs.h:1370
struct dig_head head
Header info.
Definition: dig_structs.h:1403
Vector map info.
Definition: dig_structs.h:1259
double * y
Array of Y coordinates.
Definition: dig_structs.h:1684
int dig__fread_port_S(short *, size_t, struct gvfile *)
Read shorts from the Portable Vector Format.
Definition: portable.c:426
void G_warning(const char *,...) __attribute__((format(printf
double * z
Array of Z coordinates.
Definition: dig_structs.h:1688
#define _(str)
Definition: glocale.h:10
struct gvfile dig_fp
GV file pointer (native format only)
Definition: dig_structs.h:1410
off_t last_offset
Offset of last read line.
Definition: dig_structs.h:366
int * field
Array of layers (fields)
Definition: dig_structs.h:1707
int minor
Current version (minor)
Definition: dig_structs.h:282
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition: portable.c:1001
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 Vect_box_overlap(const struct bound_box *, const struct bound_box *)
Tests for overlap of two boxes.
int field
Field number constraint (see line_cats structure)
Definition: dig_structs.h:1382
#define PORT_INT
Definition: dig_defines.h:48
int G_debug(int, const char *,...) __attribute__((format(printf
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition: file.c:60
int Vect_cat_get(const struct line_cats *, int, int *)
Get first found category of given field.
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.
Definition: portable.c:79