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