GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
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 SPDX-FileCopyrightText: 2001-2009, 2011-2012 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Original author CERL, probably Dave Gerdes or Mike Higgins.
12 \author Update to GRASS 5.7 by Radim Blazek and David D. Gray.
13 \author Update to GRASS 7 by Martin Landa <landa.martin gmail.com>
14 */
15
16#include <sys/types.h>
17#include <grass/vector.h>
18#include <grass/glocale.h>
19
20static int read_line_nat(struct Map_info *, struct line_pnts *,
21 struct line_cats *, off_t);
22
23/*! \brief Read vector feature on non-topological level (level 1) -
24 native format - internal use only
25
26 This function implements random access for native format,
27 constraints are ignored!
28
29 \param Map pointer to Map_info struct
30 \param[out] Points container used to store line points within
31 (pointer to line_pnts struct)
32 \param[out] Cats container used to store line categories within
33 (pointer to line_cats struct)
34 \param offset given offset
35
36 \return feature type (GV_POINT, GV_LINE, ...)
37 \return 0 dead line
38 \return -2 nothing to read
39 \return -1 on failure
40 */
41int V1_read_line_nat(struct Map_info *Map, struct line_pnts *Points,
42 struct line_cats *Cats, off_t offset)
43{
44 return read_line_nat(Map, Points, Cats, offset);
45}
46
47/*! \brief Read next vector feature on non-topological level (level
48 1) - native format - internal use only.
49
50 This function implements sequential access, constraints are
51 reflected, see Vect_set_constraint_region(),
52 Vect_set_constraint_type(), or Vect_set_constraint_field().
53
54 Dead features are skipped.
55
56 Vect_rewind() can be used to reset reading.
57
58 \param Map pointer to Map_info struct
59 \param[out] line_p container used to store line points within
60 (pointer to line_pnts struct)
61 \param[out] line_c container used to store line categories within
62 (pointer to line_cats struct)
63
64 \return feature type (GV_POINT, GV_LINE, ...)
65 \return 0 dead line
66 \return -2 nothing to read
67 \return -1 on failure
68 */
70 struct line_cats *line_c)
71{
72 int itype;
73 off_t offset;
74 struct bound_box lbox, mbox;
75
76 G_debug(3, "V1_read_next_line_nat()");
77
78 if (Map->constraint.region_flag)
80
81 while (TRUE) {
82 offset = dig_ftell(&(Map->dig_fp));
83 itype = read_line_nat(Map, line_p, line_c, offset);
84 if (itype < 0)
85 return itype; /* nothing to read or failure */
86
87 if (itype == 0) /* skip dead line */
88 continue;
89
90 if (Map->constraint.type_flag) {
91 /* skip feature by type */
92 if (!(itype & Map->constraint.type))
93 continue;
94 }
95
96 if (line_p && Map->constraint.region_flag) {
97 /* skip feature by region */
99
100 if (!Vect_box_overlap(&lbox, &mbox))
101 continue;
102 }
103
104 if (line_c && Map->constraint.field_flag) {
105 /* skip feature by field */
106 if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
107 continue;
108 }
109
110 return itype;
111 }
112
113 return -1; /* NOTREACHED */
114}
115
116/*! \brief Read vector feature on topological level (level 2) -
117 native format - internal use only
118
119 This function implements random access for native format,
120 constraints are ignored!
121
122 Note: Topology must be built at level >= GV_BUILD_BASE
123
124 \param Map pointer to Map_info struct
125 \param[out] line_p container used to store line points within (pointer to
126 line_pnts struct)
127 \param[out] line_c container used to store line categories
128 within (pointer to line_cats struct)
129 \param line feature id to read (starts at 1)
130
131 \return feature type (GV_POINT, GV_LINE, ...)
132 \return -2 nothing to read
133 \return -1 on failure
134 */
136 struct line_cats *line_c, int line)
137{
138 struct P_line *Line;
139
140 G_debug(3, "V2_read_line_nat(): line = %d", line);
141
142 if (line < 1 || line > Map->plus.n_lines) {
143 G_warning(_("Attempt to access feature with invalid id (%d)"), line);
144 return -1;
145 }
146
147 Line = Map->plus.Line[line];
148 if (Line == NULL) {
149 G_warning(_("Attempt to access dead feature %d"), line);
150 return -1;
151 }
152
153 return read_line_nat(Map, line_p, line_c, Line->offset);
154}
155
156/*! \brief Read next vector feature on topological level (level 2) -
157 native format - internal use only.
158
159 This function implements sequential access, constraints are
160 reflected, see Vect_set_constraint_region(),
161 Vect_set_constraint_type(), or Vect_set_constraint_field().
162
163 Use Vect_rewind() to reset reading.
164
165 Dead feature are skipped.
166
167 \param Map pointer to Map_info struct
168 \param[out] line_p container used to store line points within
169 (pointer to line_pnts struct)
170 \param[out] line_c container used to store line categories within
171 (pointer to line_cats struct)
172
173 \return feature type (GV_POINT, GV_LINE, ...)
174 \return -2 nothing to read
175 \return -1 on error
176 */
178 struct line_cats *line_c)
179{
180 int line, ret;
181 struct P_line *Line;
182 struct bound_box lbox, mbox;
183
184 G_debug(3, "V2_read_next_line_nat()");
185
186 if (Map->constraint.region_flag)
188
189 while (TRUE) {
190 line = Map->next_line;
191
192 if (line > Map->plus.n_lines)
193 return -2; /* nothing to read */
194
195 Line = Map->plus.Line[line];
196 if (Line == NULL) {
197 /* skip dead line */
198 Map->next_line++;
199 continue;
200 }
201
202 if (Map->constraint.type_flag) {
203 /* skip feature by type */
204 if (!(Line->type & Map->constraint.type)) {
205 Map->next_line++;
206 continue;
207 }
208 }
209
210 Map->next_line++;
211 ret = read_line_nat(Map, line_p, line_c, Line->offset);
212 if (ret < 0)
213 return ret;
214
215 if (line_p && Map->constraint.region_flag) {
216 /* skip feature by bbox */
218
219 if (!Vect_box_overlap(&lbox, &mbox))
220 continue;
221 }
222
223 if (line_c && Map->constraint.field_flag) {
224 /* skip feature by field */
225 if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
226 continue;
227 }
228
229 return ret;
230 }
231
232 return -1; /* NOTREACHED */
233}
234
235/*!
236 \brief Read line from coor file
237
238 \param Map vector map layer
239 \param[out] p container used to store line points within
240 \param[out] c container used to store line categories within
241 \param offset given offset
242
243 \return line type ( > 0 )
244 \return 0 dead line
245 \return -1 out of memory
246 \return -2 end of file
247 */
248int read_line_nat(struct Map_info *Map, struct line_pnts *p,
249 struct line_cats *c, off_t offset)
250{
251 register int i, dead = 0;
252 int n_points;
253 off_t size;
254 int n_cats, do_cats;
255 int type;
256 char rhead, nc;
257 short field;
258
259 G_debug(3, "Vect__Read_line_nat: offset = %lu", (unsigned long)offset);
260
261 Map->head.last_offset = offset;
262
263 /* reads must set in_head, but writes use default */
264 dig_set_cur_port(&(Map->head.port));
265
266 dig_fseek(&(Map->dig_fp), offset, 0);
267
268 if (0 >= dig__fread_port_C(&rhead, 1, &(Map->dig_fp)))
269 return (-2);
270
271 if (!(rhead & 0x01)) /* dead line */
272 dead = 1;
273
274 if (rhead & 0x02) /* categories exists */
275 do_cats =
276 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 else {
323 if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
324 size = (off_t)(2 * PORT_INT) * n_cats;
325 }
326 else { /* coor format 5.0 */
327 size = (off_t)(PORT_SHORT + PORT_INT) * n_cats;
328 }
329
330 dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
331 }
332 }
333
334 if (type & GV_POINTS) {
335 n_points = 1;
336 }
337 else {
338 if (0 >= dig__fread_port_I(&n_points, 1, &(Map->dig_fp)))
339 return (-2);
340 }
341
342 G_debug(3, " n_points = %d", n_points);
343
344 if (p != NULL) {
345 if (0 > dig_alloc_points(p, n_points + 1))
346 return (-1);
347
348 p->n_points = n_points;
349 if (0 >= dig__fread_port_D(p->x, n_points, &(Map->dig_fp)))
350 return (-2);
351 if (0 >= dig__fread_port_D(p->y, n_points, &(Map->dig_fp)))
352 return (-2);
353
354 if (Map->head.with_z) {
355 if (0 >= dig__fread_port_D(p->z, n_points, &(Map->dig_fp)))
356 return (-2);
357 }
358 else {
359 for (i = 0; i < n_points; i++)
360 p->z[i] = 0.0;
361 }
362 }
363 else {
364 if (Map->head.with_z)
365 size = (off_t)n_points * 3 * PORT_DOUBLE;
366
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}
#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:886
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:77
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
int dig__fread_port_D(double *, size_t, struct gvfile *)
Read doubles from the Portable Vector Format.
Definition portable.c:77
int dig_alloc_points(struct line_pnts *, int)
allocate room for 'num' X and Y arrays in struct line_pnts
off_t dig_ftell(struct gvfile *file)
Get struct gvfile position.
Definition file.c:34
int dig_set_cur_port(struct Port_info *)
Set current Port_info structure.
Definition portable.c:994
int dig__fread_port_C(char *, size_t, struct gvfile *)
Read chars from the Portable Vector Format.
Definition portable.c:509
int dig__fread_port_S(short *, size_t, struct gvfile *)
Read shorts from the Portable Vector Format.
Definition portable.c:426
int dig__fread_port_I(int *, size_t, struct gvfile *)
Read integers from the Portable Vector Format.
Definition portable.c:343
int dig_fseek(struct gvfile *file, off_t offset, int whence)
Set struct gvfile position.
Definition file.c:58
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.
#define TRUE
Definition gis.h:75
#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:135
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:69
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:41
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:177
Vector map info.
Vector geometry.
char type
Line type.
off_t offset
Offset in coor file for line.
Bounding box.
Definition dig_structs.h:62
Feature category info.
int * field
Array of layers (fields)
int * cat
Array of categories.
int n_cats
Number of categories attached to element.
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.
double * z
Array of Z coordinates.