GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
read_ogr.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/Vlib/read_ogr.c
3
4 \brief Vector library - reading data (OGR format)
5
6 Higher level functions for reading/writing/manipulating vectors.
7
8 SPDX-FileCopyrightText: 2001-2011 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Radim Blazek, Piero Cavalieri
12 \author Martin Landa <landa.martin gmail.com>
13 */
14
15#include <grass/vector.h>
16#include <grass/glocale.h>
17
18#include <ogr_api.h>
19
20static int cache_feature(struct Map_info *, OGRGeometryH, int);
21static int read_line(struct Map_info *, OGRGeometryH, long, struct line_pnts *);
22static int get_line_type(struct Map_info *, long);
23static int read_next_line_ogr(struct Map_info *, struct line_pnts *,
24 struct line_cats *, int);
25
26/*!
27 \brief Read next feature from OGR layer.
28 Skip empty features (level 1 without topology).
29
30 This function implements sequential access.
31
32 The action of this routine can be modified by:
33 - Vect_read_constraint_region()
34 - Vect_read_constraint_type()
35 - Vect_remove_constraints()
36
37 \param Map pointer to Map_info structure
38 \param[out] line_p container used to store line points within
39 \param[out] line_c container used to store line categories within
40
41 \return feature type
42 \return -2 no more features (EOF)
43 \return -1 out of memory
44 */
46 struct line_cats *line_c)
47{
48 return read_next_line_ogr(Map, line_p, line_c, FALSE);
49}
50
51/*!
52 \brief Read next feature from OGR layer on topological level.
53
54 This function implements sequential access.
55
56 \param Map pointer to Map_info structure
57 \param[out] line_p container used to store line points within
58 (pointer to line_pnts struct)
59 \param[out] line_c container used to store line categories within
60 (pointer to line_cats struct)
61
62 \return feature type
63 \return -2 no more features (EOF)
64 \return -1 on failure
65 */
67 struct line_cats *line_c)
68{
69 int line, ret;
70 struct P_line *Line;
71 struct bound_box lbox, mbox;
72
73 G_debug(3, "V2_read_next_line_ogr()");
74
75 if (Map->constraint.region_flag)
77
78 while (TRUE) {
79 line = Map->next_line;
80
81 if (Map->next_line > Map->plus.n_lines)
82 return -2; /* nothing to read */
83
84 Map->next_line++;
85 Line = Map->plus.Line[line];
86 if (Line == NULL) { /* skip dead features */
87 continue;
88 }
89
90 if (Map->constraint.type_flag) {
91 /* skip feature by type */
92 if (!(Line->type & Map->constraint.type))
93 continue;
94 }
95
96 if (Line->type == GV_CENTROID) {
97 G_debug(4, "Centroid");
98
99 if (line_p != NULL) {
100 int i, found;
101 struct bound_box box;
102 struct boxlist list;
103 struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
104
105 /* get area bbox */
106 Vect_get_area_box(Map, topo->area, &box);
107 /* search in spatial index for centroid with area bbox */
109 Vect_select_lines_by_box(Map, &box, Line->type, &list);
110
111 found = 0;
112 for (i = 0; i < list.n_values; i++) {
113 if (list.id[i] == line) {
114 found = i;
115 break;
116 }
117 }
118
121 0.0);
122 }
123 if (line_c != NULL) {
124 /* cat = FID and offset = FID for centroid */
126 Vect_cat_set(line_c, 1, (int)Line->offset);
127 }
128
130 }
131 else {
132 ret = read_next_line_ogr(Map, line_p, line_c, TRUE);
133 }
134
135 if (line_p && Map->constraint.region_flag) {
136 /* skip feature by region */
138 if (!Vect_box_overlap(&lbox, &mbox))
139 continue;
140 }
141
142 /* skip feature by field ignored */
143
144 return ret;
145 }
146}
147
148/*!
149 \brief Read feature from OGR layer at given offset (level 1 without topology)
150
151 This function implements random access on level 1.
152
153 \param Map pointer to Map_info structure
154 \param[out] line_p container used to store line points within
155 (pointer line_pnts struct)
156 \param[out] line_c container used to store line categories within
157 (pointer line_cats struct)
158 \param offset given offset
159
160 \return line type
161 \return 0 dead line
162 \return -2 no more features
163 \return -1 on failure
164 */
166 struct line_cats *line_c, off_t offset)
167{
168 long fid;
169 int type;
171
173
174 ogr_info = &(Map->fInfo.ogr);
175 G_debug(3, "V1_read_line_ogr(): offset = %lu offset_num = %lu",
176 (long)offset, (long)ogr_info->offset.array_num);
177
178 if (offset >= ogr_info->offset.array_num)
179 return -2; /* nothing to read */
180
181 if (line_p != NULL)
183 if (line_c != NULL)
185
186 fid = ogr_info->offset.array[offset];
187 G_debug(4, " fid = %ld", fid);
188
189 /* coordinates */
190 if (line_p != NULL) {
191 /* read feature to cache if necessary */
192 if (ogr_info->cache.fid != fid) {
193 G_debug(4, "Read feature (fid = %ld) to cache", fid);
194 if (ogr_info->feature_cache) {
195 OGR_F_Destroy(ogr_info->feature_cache);
196 }
197 ogr_info->feature_cache = OGR_L_GetFeature(ogr_info->layer, fid);
198 if (ogr_info->feature_cache == NULL) {
199 G_warning(_("Unable to get feature geometry, fid %ld"), fid);
200 return -1;
201 }
202 ogr_info->cache.fid = fid;
203 }
204
205 hGeom = OGR_F_GetGeometryRef(ogr_info->feature_cache);
206 if (hGeom == NULL) {
207 G_warning(_("Unable to get feature geometry, fid %ld"), fid);
208 return -1;
209 }
210
211 type = read_line(Map, hGeom, offset + 1, line_p);
212 }
213 else {
214 type = get_line_type(Map, fid);
215 }
216
217 /* category */
218 if (line_c != NULL) {
219 Vect_cat_set(line_c, 1, (int)fid);
220 }
221
222 return type;
223}
224
225/*!
226 \brief Recursively read feature and add all elements to points_cache and
227 types_cache.
228
229 ftype: if > 0 use this type (because parts of Polygon are read as
230 wkbLineString)
231
232 \param Map pointer to Map_info structure
233 \param[out] hGeom OGR geometry
234 \param ftype feature type
235
236 \return 0 on success
237 \return 1 on error
238 */
239int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
240{
241 int line, i, np, ng, tp;
242
244
247
248 G_debug(4, "cache_feature() ftype = %d", ftype);
249
250 ogr_info = &(Map->fInfo.ogr);
251
252 /* alloc space in lines cache */
253 line = ogr_info->cache.lines_num;
254 if (line == ogr_info->cache.lines_alloc) {
255 ogr_info->cache.lines_alloc += 1;
256 ogr_info->cache.lines = (struct line_pnts **)G_realloc(
257 (void *)ogr_info->cache.lines,
258 ogr_info->cache.lines_alloc * sizeof(struct line_pnts *));
259
260 ogr_info->cache.lines_types =
261 (int *)G_realloc(ogr_info->cache.lines_types,
262 ogr_info->cache.lines_alloc * sizeof(int));
263
264 for (i = ogr_info->cache.lines_num; i < ogr_info->cache.lines_alloc;
265 i++)
266 ogr_info->cache.lines[i] = Vect_new_line_struct();
267 }
268 Vect_reset_line(ogr_info->cache.lines[line]);
269
271
272 switch (type) {
273 case wkbPoint:
274 G_debug(4, "Point");
275 Vect_append_point(ogr_info->cache.lines[line], OGR_G_GetX(hGeom, 0),
277 ogr_info->cache.lines_types[line] = GV_POINT;
278 ogr_info->cache.lines_num++;
279 return 0;
280 break;
281
282 case wkbLineString:
283 G_debug(4, "LineString");
285 for (i = 0; i < np; i++) {
286 Vect_append_point(ogr_info->cache.lines[line], OGR_G_GetX(hGeom, i),
288 }
289
290 if (ftype > 0) { /* Polygon rings */
291 ogr_info->cache.lines_types[line] = ftype;
292 }
293 else {
294 ogr_info->cache.lines_types[line] = GV_LINE;
295 }
296 ogr_info->cache.lines_num++;
297 return 0;
298 break;
299
300 case wkbMultiPoint:
302 case wkbPolygon:
303 case wkbMultiPolygon:
306 G_debug(4, "%d geoms -> next level", ng);
307 if (type == wkbPolygon) {
308 tp = GV_BOUNDARY;
309 }
310 else {
311 tp = -1;
312 }
313 for (i = 0; i < ng; i++) {
315 cache_feature(Map, hGeom2, tp);
316 }
317 return 0;
318 break;
319
320 default:
321 G_warning(_("OGR feature type %d not supported"), type);
322 return 1;
323 break;
324 }
325}
326
327int read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
329{
330 int itype;
331 struct bound_box lbox, mbox;
334
336
337 G_debug(3, "V1_read_next_line_ogr()");
338
339 if (Map->constraint.region_flag && !ignore_constraint)
341
342 ogr_info = &(Map->fInfo.ogr);
343 while (TRUE) {
344 /* reset data structures */
345 if (line_p != NULL)
347 if (line_c != NULL)
349
350 /* read feature to cache if necessary */
351 while (ogr_info->cache.lines_next == ogr_info->cache.lines_num) {
353 if (hFeature == NULL) {
354 return -2; /* nothing to read */
355 }
356
358 if (hGeom == NULL) { /* skip feature without geometry */
359 G_warning(_("Feature without geometry. Skipped."));
361 continue;
362 }
363
364 /* cache OGR feature */
365 ogr_info->cache.fid = (int)OGR_F_GetFID(hFeature);
366 if (ogr_info->cache.fid == OGRNullFID) {
367 G_warning(_("OGR feature without ID"));
368 }
369
370 /* cache feature */
371 ogr_info->cache.lines_num = 0;
372 cache_feature(Map, hGeom, -1);
373 G_debug(4, "%d lines read to cache", ogr_info->cache.lines_num);
375
376 /* next to be read from cache */
377 ogr_info->cache.lines_next = 0;
378 }
379
380 /* read next part of the feature */
381 G_debug(4, "read next cached line %d", ogr_info->cache.lines_next);
382 itype = ogr_info->cache.lines_types[ogr_info->cache.lines_next];
383
384 if (Map->constraint.type_flag && !ignore_constraint) {
385 /* skip feature by type */
386 if (!(itype & Map->constraint.type)) {
387 ogr_info->cache.lines_next++;
388 continue;
389 }
390 }
391
392 if (Map->constraint.region_flag && !ignore_constraint) {
393 /* skip feature by region */
394 Vect_line_box(ogr_info->cache.lines[ogr_info->cache.lines_next],
395 &lbox);
396
397 if (!Vect_box_overlap(&lbox, &mbox)) {
398 ogr_info->cache.lines_next++;
399 continue;
400 }
401 }
402
403 /* skip feature by field - ignored */
404
405 if (line_p != NULL)
407 line_p, ogr_info->cache.lines[ogr_info->cache.lines_next],
408 GV_FORWARD);
409
410 if (line_c != NULL && ogr_info->cache.fid != OGRNullFID)
411 Vect_cat_set(line_c, 1, ogr_info->cache.fid);
412
413 ogr_info->cache.lines_next++;
414 G_debug(4, "next line read, type = %d", itype);
415
416 return itype;
417 }
418
419 return -1; /* not reached */
420}
421
422/*!
423 \brief Recursively descend to feature and read the part
424
425 \param Map pointer to Map_info structure
426 \param hGeom OGR geometry
427 \param offset given offset
428 \param[out] Points container used to store line points within
429
430 \return feature type
431 \return -1 on error
432 */
433int read_line(struct Map_info *Map, OGRGeometryH hGeom, long offset,
434 struct line_pnts *Points)
435{
436 int i, nPoints;
437 int eType, line;
438
439 const struct Format_info_ogr *ogr_info;
440
442
443 /* Read coors if hGeom is a simple element (wkbPoint,
444 * wkbLineString) otherwise descend to geometry specified by
445 * offset[offset] */
446
447 ogr_info = &(Map->fInfo.ogr);
448
450 G_debug(4, "OGR geometry type: %d", eType);
451
452 switch (eType) {
453 case wkbPoint:
454 G_debug(4, "\t->Point");
455 if (Points) {
458 }
459 return GV_POINT;
460 break;
461
462 case wkbLineString:
463 G_debug(4, "\t->LineString");
464 if (Points) {
466 for (i = 0; i < nPoints; i++) {
469 }
470 }
471 return GV_LINE;
472 break;
473
474 case wkbPolygon:
475 case wkbMultiPoint:
477 case wkbMultiPolygon:
479 G_debug(4, "\t->more geoms -> part %d", ogr_info->offset.array[offset]);
481 line = read_line(Map, hGeom2, offset + 1, Points);
483 return GV_BOUNDARY;
484 if (eType == wkbMultiPoint)
485 return GV_POINT;
487 return GV_LINE;
488 return line;
489 break;
490
491 default:
492 G_warning(_("OGR feature type '%s' not supported"),
494 break;
495 }
496
497 return -1;
498}
499
500/*!
501 \brief Recursively descend to feature and read the part
502
503 \param Map pointer to Map_info structure
504 \param hGeom OGR geometry
505 \param offset given offset
506 \param[out] Points container used to store line points within
507
508 \return feature type
509 \return -1 on error
510 */
511int get_line_type(struct Map_info *Map, long fid)
512{
513 int eType;
514
515 const struct Format_info_ogr *ogr_info;
516
519
520 G_debug(4, "get_line_type() fid = %ld", fid);
521
522 ogr_info = &(Map->fInfo.ogr);
523
524 hFeat = OGR_L_GetFeature(ogr_info->layer, fid);
525 if (hFeat == NULL)
526 return -1;
527
529 if (hGeom == NULL)
530 return -1;
531
533
535
536 G_debug(4, "OGR Geometry of type: %d", eType);
537
538 switch (eType) {
539 case wkbPoint:
540 case wkbMultiPoint:
541 return GV_POINT;
542 break;
543
544 case wkbLineString:
546 return GV_LINE;
547 break;
548
549 case wkbPolygon:
550 case wkbMultiPolygon:
552 return GV_BOUNDARY;
553 break;
554
555 default:
556 G_warning(_("OGR feature type %d not supported"), eType);
557 break;
558 }
559
560 return -1;
561}
#define NULL
Definition ccmath.h:32
#define G_realloc(p, n)
Definition defs/gis.h:138
void G_warning(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int Vect_reset_cats(struct line_cats *)
Reset category structure to make sure cats structure is clean to be re-used.
void Vect_line_box(const struct line_pnts *, struct bound_box *)
Get bounding box of line.
Definition line.c:886
int Vect_cat_set(struct line_cats *, int, int)
Add new field/cat to category structure if doesn't exist yet.
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.
int Vect_get_area_box(struct Map_info *, int, struct bound_box *)
Get bounding box of area.
int Vect_select_lines_by_box(struct Map_info *, const struct bound_box *, int, struct boxlist *)
Select lines with bounding boxes by box.
Definition sindex.c:30
void Vect_reset_line(struct line_pnts *)
Reset line.
Definition line.c:127
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:43
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:146
int Vect_append_points(struct line_pnts *, const struct line_pnts *, int)
Appends points to the end of a line.
Definition line.c:333
#define GV_CENTROID
#define GV_LINE
#define GV_POINT
Feature types used in memory on run time (may change)
#define GV_BOUNDARY
#define GV_FORWARD
Line direction indicator forward/backward.
int dig_init_boxlist(struct boxlist *, int)
#define TRUE
Definition gis.h:75
#define FALSE
Definition gis.h:79
#define _(str)
Definition glocale.h:10
int V1_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
Read feature from OGR layer at given offset (level 1 without topology)
Definition read_ogr.c:165
int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c)
Read next feature from OGR layer. Skip empty features (level 1 without topology).
Definition read_ogr.c:45
int V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p, struct line_cats *line_c)
Read next feature from OGR layer on topological level.
Definition read_ogr.c:66
Non-native format info (OGR)
struct Format_info_offset offset
Offset list used for building pseudo-topology.
Vector map info.
Vector geometry.
char type
Line type.
off_t offset
Offset in coor file for line.
void * topo
Topology info.
Centroid topology.
plus_t area
Area number, negative for duplicate centroid.
Bounding box.
Definition dig_structs.h:62
List of bounding boxes with id.
Feature category info.
Feature geometry info - coordinates.
Definition manage.h:4