GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-835afb4352
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) \param[out] Cats container used to store line categories
129  within (pointer to line_cats struct) \param line feature id to read (starts
130  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, struct line_pnts *line_p,
137  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  */
178 int V2_read_next_line_nat(struct Map_info *Map, struct line_pnts *line_p,
179  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, struct line_pnts *p,
250  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 =
277  1; /* do not return here let file offset moves forward to next */
278  else /* line */
279  do_cats = 0;
280 
281  rhead >>= 2;
282  type = dig_type_from_store((int)rhead);
283 
284  G_debug(3, " type = %d, do_cats = %d dead = %d", type, do_cats, dead);
285 
286  if (c != NULL)
287  c->n_cats = 0;
288 
289  if (do_cats) {
290  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
291  if (0 >= dig__fread_port_I(&n_cats, 1, &(Map->dig_fp)))
292  return (-2);
293  }
294  else { /* coor format 5.0 */
295  if (0 >= dig__fread_port_C(&nc, 1, &(Map->dig_fp)))
296  return (-2);
297  n_cats = (int)nc;
298  }
299  G_debug(3, " n_cats = %d", n_cats);
300 
301  if (c != NULL) {
302  c->n_cats = n_cats;
303  if (n_cats > 0) {
304  if (0 > dig_alloc_cats(c, (int)n_cats + 1))
305  return -1;
306 
307  if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
308  if (0 >=
309  dig__fread_port_I(c->field, n_cats, &(Map->dig_fp)))
310  return (-2);
311  }
312  else { /* coor format 5.0 */
313  for (i = 0; i < n_cats; i++) {
314  if (0 >= dig__fread_port_S(&field, 1, &(Map->dig_fp)))
315  return (-2);
316  c->field[i] = (int)field;
317  }
318  }
319  if (0 >= dig__fread_port_I(c->cat, n_cats, &(Map->dig_fp)))
320  return (-2);
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 
368  else
369  size = (off_t)n_points * 2 * PORT_DOUBLE;
370 
371  dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
372  }
373 
374  G_debug(3, " off = %lu", (unsigned long)dig_ftell(&(Map->dig_fp)));
375 
376  if (dead)
377  return 0;
378 
379  return type;
380 }
#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:79
#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:136
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:178
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