2
\file lib/vector/Vlib/read_ogr.c
4
4
\brief Vector library - reading data (OGR format)
6
6
Higher level functions for reading/writing/manipulating vectors.
8
(C) 2001-2008 by the GRASS Development Team
8
(C) 2001-2011 by the GRASS Development Team
10
This program is free software under the
11
GNU General Public License (>=v2).
12
Read the file COPYING that comes with GRASS
10
This program is free software under the GNU General Public License
11
(>=v2). Read the file COPYING that comes with GRASS for details.
15
13
\author Radim Blazek, Piero Cavalieri
14
\author Martin Landa <landa.martin gmail.com>
20
#include <grass/gis.h>
21
#include <grass/Vect.h>
17
#include <grass/vector.h>
22
18
#include <grass/glocale.h>
25
21
#include <ogr_api.h>
28
* \brief Recursively read feature and add all elements to points_cache and types_cache.
30
* ftype : if > 0 use this type (because parts of Polygon are read as wkbLineString)
32
* \param Map vector map layer
33
* \param hGeom OGR geometry
34
* \param ftype feature type
39
static int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
23
static int cache_feature(struct Map_info *, OGRGeometryH, int);
24
static int read_line(const struct Map_info *, OGRGeometryH, long,
26
static int get_line_type(const struct Map_info *, long);
27
static int read_next_line_ogr(struct Map_info *, struct line_pnts *,
28
struct line_cats *, int);
32
\brief Read next feature from OGR layer.
33
Skip empty features (level 1 without topology).
35
This function implements sequential access.
37
The action of this routine can be modified by:
38
- Vect_read_constraint_region()
39
- Vect_read_constraint_type()
40
- Vect_remove_constraints()
42
\param Map pointer to Map_info structure
43
\param[out] line_p container used to store line points within
44
\param[out] line_c container used to store line categories within
47
\return -2 no more features (EOF)
48
\return -1 out of memory
50
int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
51
struct line_cats *line_c)
54
return read_next_line_ogr(Map, line_p, line_c, FALSE);
56
G_fatal_error(_("GRASS is not compiled with OGR support"));
62
\brief Read next feature from OGR layer on topological level.
64
This function implements sequential access.
66
\param Map pointer to Map_info structure
67
\param[out] line_p container used to store line points within
68
(pointer to line_pnts struct)
69
\param[out] line_c container used to store line categories within
70
(pointer to line_cats struct)
73
\return -2 no more features (EOF)
76
int V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
77
struct line_cats *line_c)
82
struct bound_box lbox, mbox;
84
G_debug(3, "V2_read_next_line_ogr()");
86
if (Map->constraint.region_flag)
87
Vect_get_constraint_box(Map, &mbox);
90
line = Map->next_line;
92
if (Map->next_line > Map->plus.n_lines)
93
return -2; /* nothing to read */
96
Line = Map->plus.Line[line];
97
if (Line == NULL) { /* skip dead features */
101
if (Map->constraint.type_flag) {
102
/* skip feature by type */
103
if (!(Line->type & Map->constraint.type))
107
if (Line->type == GV_CENTROID) {
108
G_debug(4, "Centroid");
110
if (line_p != NULL) {
112
struct bound_box box;
114
struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
117
Vect_get_area_box(Map, topo->area, &box);
118
/* search in spatial index for centroid with area bbox */
119
dig_init_boxlist(&list, TRUE);
120
Vect_select_lines_by_box(Map, &box, Line->type, &list);
123
for (i = 0; i < list.n_values; i++) {
124
if (list.id[i] == line) {
130
Vect_reset_line(line_p);
131
Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
133
if (line_c != NULL) {
134
/* cat = FID and offset = FID for centroid */
135
Vect_reset_cats(line_c);
136
Vect_cat_set(line_c, 1, (int) Line->offset);
142
ret = read_next_line_ogr(Map, line_p, line_c, TRUE);
145
if (line_p && Map->constraint.region_flag) {
146
/* skip feature by region */
147
Vect_line_box(line_p, &lbox);
148
if (!Vect_box_overlap(&lbox, &mbox))
152
/* skip feature by field ignored */
157
G_fatal_error(_("GRASS is not compiled with OGR support"));
163
\brief Read feature from OGR layer at given offset (level 1 without topology)
165
This function implements random access on level 1.
167
\param Map pointer to Map_info structure
168
\param[out] line_p container used to store line points within
169
(pointer line_pnts struct)
170
\param[out] line_c container used to store line categories within
171
(pointer line_cats struct)
172
\param offset given offset
176
\return -2 no more features
177
\return -1 on failure
179
int V1_read_line_ogr(struct Map_info *Map,
180
struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
187
struct Format_info_ogr *ogr_info;
189
ogr_info = &(Map->fInfo.ogr);
190
G_debug(3, "V1_read_line_ogr(): offset = %lu offset_num = %lu",
191
(long) offset, (long) ogr_info->offset.array_num);
193
if (offset >= ogr_info->offset.array_num)
194
return -2; /* nothing to read */
197
Vect_reset_line(line_p);
199
Vect_reset_cats(line_c);
201
fid = ogr_info->offset.array[offset];
202
G_debug(4, " fid = %ld", fid);
205
if (line_p != NULL) {
206
/* read feature to cache if necessary */
207
if (ogr_info->cache.fid != fid) {
208
G_debug(4, "Read feature (fid = %ld) to cache", fid);
209
if (ogr_info->feature_cache) {
210
OGR_F_Destroy(ogr_info->feature_cache);
212
ogr_info->feature_cache =
213
OGR_L_GetFeature(ogr_info->layer, fid);
214
if (ogr_info->feature_cache == NULL) {
215
G_warning(_("Unable to get feature geometry, fid %ld"),
219
ogr_info->cache.fid = fid;
222
hGeom = OGR_F_GetGeometryRef(ogr_info->feature_cache);
224
G_warning(_("Unable to get feature geometry, fid %ld"),
229
type = read_line(Map, hGeom, offset + 1, line_p);
232
type = get_line_type(Map, fid);
236
if (line_c != NULL) {
237
Vect_cat_set(line_c, 1, (int) fid);
242
G_fatal_error(_("GRASS is not compiled with OGR support"));
249
\brief Recursively read feature and add all elements to points_cache and types_cache.
251
ftype: if > 0 use this type (because parts of Polygon are read as wkbLineString)
253
\param Map pointer to Map_info structure
254
\param[out] hGeom OGR geometry
255
\param ftype feature type
260
int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
41
262
int line, i, np, ng, tp;
264
struct Format_info_ogr *ogr_info;
42
266
OGRwkbGeometryType type;
43
267
OGRGeometryH hGeom2;
45
G_debug(4, "cache_feature");
269
G_debug(4, "cache_feature() ftype = %d", ftype);
48
line = Map->fInfo.ogr.lines_num;
49
if (line == Map->fInfo.ogr.lines_alloc) {
50
Map->fInfo.ogr.lines_alloc += 20;
51
Map->fInfo.ogr.lines =
52
(struct line_pnts **)G_realloc((void *)Map->fInfo.ogr.lines,
53
Map->fInfo.ogr.lines_alloc *
271
ogr_info = &(Map->fInfo.ogr);
273
/* alloc space in lines cache */
274
line = ogr_info->cache.lines_num;
275
if (line == ogr_info->cache.lines_alloc) {
276
ogr_info->cache.lines_alloc += 1;
277
ogr_info->cache.lines =
278
(struct line_pnts **)G_realloc((void *)ogr_info->cache.lines,
279
ogr_info->cache.lines_alloc *
54
280
sizeof(struct line_pnts *));
56
Map->fInfo.ogr.lines_types =
57
(int *)G_realloc(Map->fInfo.ogr.lines_types,
58
Map->fInfo.ogr.lines_alloc * sizeof(int));
60
for (i = Map->fInfo.ogr.lines_num; i < Map->fInfo.ogr.lines_alloc;
62
Map->fInfo.ogr.lines[i] = Vect_new_line_struct();
282
ogr_info->cache.lines_types =
283
(int *)G_realloc(ogr_info->cache.lines_types,
284
ogr_info->cache.lines_alloc * sizeof(int));
286
for (i = ogr_info->cache.lines_num; i < ogr_info->cache.lines_alloc; i++)
287
ogr_info->cache.lines[i] = Vect_new_line_struct();
65
Vect_reset_line(Map->fInfo.ogr.lines[line]);
289
Vect_reset_line(ogr_info->cache.lines[line]);
67
291
type = wkbFlatten(OGR_G_GetGeometryType(hGeom));
71
295
G_debug(4, "Point");
72
Vect_append_point(Map->fInfo.ogr.lines[line],
296
Vect_append_point(ogr_info->cache.lines[line],
73
297
OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
74
298
OGR_G_GetZ(hGeom, 0));
75
Map->fInfo.ogr.lines_types[line] = GV_POINT;
76
Map->fInfo.ogr.lines_num++;
299
ogr_info->cache.lines_types[line] = GV_POINT;
300
ogr_info->cache.lines_num++;
127
* \brief Read next line from OGR layer. Skip empty features.
129
* The action of this routine can be modified by:
130
* - Vect_read_constraint_region()
131
* - Vect_read_constraint_type()
132
* - Vect_remove_constraints()
134
* \param Map vector map layer
135
* \param line_p container used to store line points within
136
* \param line_c container used to store line categories within
139
* \return -2 no more features (EOF)
140
* \return -1 out of memory
143
V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
144
struct line_cats *line_c)
350
int read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
351
struct line_cats *line_c, int ignore_constraint)
147
BOUND_BOX lbox, mbox;
354
struct bound_box lbox, mbox;
148
355
OGRFeatureH hFeature;
149
356
OGRGeometryH hGeom;
358
struct Format_info_ogr *ogr_info;
151
360
G_debug(3, "V1_read_next_line_ogr()");
154
Vect_reset_line(line_p);
156
Vect_reset_cats(line_c);
158
if (Map->Constraint_region_flag)
362
if (Map->constraint.region_flag && !ignore_constraint)
159
363
Vect_get_constraint_box(Map, &mbox);
162
/* Read feature to chache if necessary */
163
while (Map->fInfo.ogr.lines_next == Map->fInfo.ogr.lines_num) {
164
hFeature = OGR_L_GetNextFeature(Map->fInfo.ogr.layer);
365
ogr_info = &(Map->fInfo.ogr);
367
/* reset data structures */
369
Vect_reset_line(line_p);
371
Vect_reset_cats(line_c);
373
/* read feature to cache if necessary */
374
while (ogr_info->cache.lines_next == ogr_info->cache.lines_num) {
375
hFeature = OGR_L_GetNextFeature(ogr_info->layer);
166
376
if (hFeature == NULL) {
168
} /* no more features */
377
return -2; /* nothing to read */
170
380
hGeom = OGR_F_GetGeometryRef(hFeature);
171
if (hGeom == NULL) { /* feature without geometry */
381
if (hGeom == NULL) { /* skip feature without geometry */
382
G_warning(_("Feature without geometry. Skipped."));
172
383
OGR_F_Destroy(hFeature);
176
Map->fInfo.ogr.feature_cache_id = (int)OGR_F_GetFID(hFeature);
177
if (Map->fInfo.ogr.feature_cache_id == OGRNullFID) {
387
/* cache OGR feature */
388
ogr_info->cache.fid = (int)OGR_F_GetFID(hFeature);
389
if (ogr_info->cache.fid == OGRNullFID) {
178
390
G_warning(_("OGR feature without ID"));
181
/* Cache the feature */
182
Map->fInfo.ogr.lines_num = 0;
394
ogr_info->cache.lines_num = 0;
183
395
cache_feature(Map, hGeom, -1);
184
G_debug(4, "%d lines read to cache", Map->fInfo.ogr.lines_num);
396
G_debug(4, "%d lines read to cache", ogr_info->cache.lines_num);
185
397
OGR_F_Destroy(hFeature);
187
Map->fInfo.ogr.lines_next = 0; /* next to be read from cache */
399
/* next to be read from cache */
400
ogr_info->cache.lines_next = 0;
190
/* Read next part of the feature */
191
G_debug(4, "read next cached line %d", Map->fInfo.ogr.lines_next);
192
itype = Map->fInfo.ogr.lines_types[Map->fInfo.ogr.lines_next];
403
/* read next part of the feature */
404
G_debug(4, "read next cached line %d", ogr_info->cache.lines_next);
405
itype = ogr_info->cache.lines_types[ogr_info->cache.lines_next];
194
/* Constraint on Type of line
195
* Default is all of Point, Line, Area and whatever else comes along
197
if (Map->Constraint_type_flag) {
198
if (!(itype & Map->Constraint_type)) {
199
Map->fInfo.ogr.lines_next++;
407
if (Map->constraint.type_flag && !ignore_constraint) {
408
/* skip feature by type */
409
if (!(itype & Map->constraint.type)) {
410
ogr_info->cache.lines_next++;
204
/* Constraint on specified region */
205
if (Map->Constraint_region_flag) {
206
Vect_line_box(Map->fInfo.ogr.lines[Map->fInfo.ogr.lines_next],
415
if (Map->constraint.region_flag && !ignore_constraint) {
416
/* skip feature by region */
417
Vect_line_box(ogr_info->cache.lines[ogr_info->cache.lines_next],
209
420
if (!Vect_box_overlap(&lbox, &mbox)) {
210
Map->fInfo.ogr.lines_next++;
421
ogr_info->cache.lines_next++;
426
/* skip feature by field - ignored */
215
428
if (line_p != NULL)
216
429
Vect_append_points(line_p,
217
Map->fInfo.ogr.lines[Map->fInfo.ogr.
218
lines_next], GV_FORWARD);
220
if (line_c != NULL && Map->fInfo.ogr.feature_cache_id != OGRNullFID)
221
Vect_cat_set(line_c, 1, Map->fInfo.ogr.feature_cache_id);
223
Map->fInfo.ogr.lines_next++;
430
ogr_info->cache.lines[ogr_info->cache.lines_next], GV_FORWARD);
432
if (line_c != NULL && ogr_info->cache.fid != OGRNullFID)
433
Vect_cat_set(line_c, 1, ogr_info->cache.fid);
435
ogr_info->cache.lines_next++;
224
436
G_debug(4, "next line read, type = %d", itype);
227
return -2; /* not reached */
231
* \brief Read next line from OGR layer.
233
* \param Map vector map layer
234
* \param line_p container used to store line points within
235
* \param line_c container used to store line categories within
238
* \return -2 no more features (EOF)
239
* \return -1 out of memory
242
V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
243
struct line_cats *line_c)
245
if (Map->next_line > Map->plus.n_lines)
248
return V2_read_line_ogr(Map, line_p, line_c, Map->next_line++);
252
* \brief Recursively descend to feature and read the part
254
* \param Map vector map layer
255
* \param hGeom OGR geometry
256
* \param offset given offset
257
* \param Points container used to store line pointes within
262
static int read_line(struct Map_info *Map, OGRGeometryH hGeom, long offset,
263
struct line_pnts *Points)
441
return -1; /* not reached */
445
\brief Recursively descend to feature and read the part
447
\param Map pointer to Map_info structure
448
\param hGeom OGR geometry
449
\param offset given offset
450
\param[out] Points container used to store line pointes within
455
int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
456
struct line_pnts *Points)
461
const struct Format_info_ogr *ogr_info;
465
/* Read coors if hGeom is a simple element (wkbPoint,
466
* wkbLineString) otherwise descend to geometry specified by
469
ogr_info = &(Map->fInfo.ogr);
471
eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
472
G_debug(4, "OGR geometry type: %d", eType);
476
G_debug(4, "\t->Point");
478
Vect_append_point(Points, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
479
OGR_G_GetZ(hGeom, 0));
485
G_debug(4, "\t->LineString");
487
nPoints = OGR_G_GetPointCount(hGeom);
488
for (i = 0; i < nPoints; i++) {
489
Vect_append_point(Points, OGR_G_GetX(hGeom, i),
490
OGR_G_GetY(hGeom, i), OGR_G_GetZ(hGeom, i));
498
case wkbMultiLineString:
499
case wkbMultiPolygon:
500
case wkbGeometryCollection:
501
G_debug(4, "\t->more geoms -> part %d", ogr_info->offset.array[offset]);
502
hGeom2 = OGR_G_GetGeometryRef(hGeom, ogr_info->offset.array[offset]);
503
line = read_line(Map, hGeom2, offset + 1, Points);
504
if (eType == wkbPolygon || eType == wkbMultiPolygon)
506
if (eType == wkbMultiPoint)
508
if (eType == wkbMultiLineString)
514
G_warning(_("OGR feature type '%s' not supported"),
515
OGRGeometryTypeToName(eType));
523
\brief Recursively descend to feature and read the part
525
\param Map pointer to Map_info structure
526
\param hGeom OGR geometry
527
\param offset given offset
528
\param[out] Points container used to store line pointes within
533
int get_line_type(const struct Map_info *Map, long fid)
269
/* Read coors if hGeom is a simple element (wkbPoint, wkbLineString) otherwise
270
* descend to geometry specified by offset[offset] */
272
G_debug(4, "read_line() offset = %ld", offset);
537
const struct Format_info_ogr *ogr_info;
542
G_debug(4, "get_line_type() fid = %ld", fid);
544
ogr_info = &(Map->fInfo.ogr);
546
hFeat = OGR_L_GetFeature(ogr_info->layer, fid);
550
hGeom = OGR_F_GetGeometryRef(hFeat);
274
554
eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
556
OGR_F_Destroy(hFeat);
275
558
G_debug(4, "OGR Geometry of type: %d", eType);
280
Vect_append_point(Points, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
281
OGR_G_GetZ(hGeom, 0));
285
566
case wkbLineString:
286
G_debug(4, "LineString");
287
nPoints = OGR_G_GetPointCount(hGeom);
288
for (i = 0; i < nPoints; i++) {
289
Vect_append_point(Points, OGR_G_GetX(hGeom, i),
290
OGR_G_GetY(hGeom, i), OGR_G_GetZ(hGeom, i));
567
case wkbMultiLineString:
297
case wkbMultiLineString:
298
572
case wkbMultiPolygon:
299
573
case wkbGeometryCollection:
300
G_debug(4, " more geoms -> part %d", Map->fInfo.ogr.offset[offset]);
301
hGeom2 = OGR_G_GetGeometryRef(hGeom, Map->fInfo.ogr.offset[offset]);
302
return (read_line(Map, hGeom2, offset + 1, Points));
306
578
G_warning(_("OGR feature type %d not supported"), eType);
313
* \brief Read line from layer on given offset.
315
* \param Map vector map layer
316
* \param line_p container used to store line points within
317
* \param line_c container used to store line categories within
318
* \param line line id
321
* \return -2 end of table (last row)
322
* \return -1 out of memory
325
V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
326
struct line_cats *line_c, int line)
335
G_debug(4, "V2_read_line_ogr() line = %d", line);
338
Vect_reset_line(line_p);
340
Vect_reset_cats(line_c);
342
Line = Map->plus.Line[line];
343
offset = (int)Line->offset;
345
if (Line->type == GV_CENTROID) {
346
G_debug(4, "Centroid");
348
Node = Map->plus.Node[node];
351
if (line_p != NULL) {
352
Vect_append_point(line_p, Node->x, Node->y, 0.0);
356
if (line_c != NULL) {
357
/* cat = FID and offset = FID for centroid */
358
Vect_cat_set(line_c, 1, (int)offset);
361
return (GV_CENTROID);
364
FID = Map->fInfo.ogr.offset[offset];
365
G_debug(4, " FID = %ld", FID);
368
if (line_p != NULL) {
369
/* Read feature to cache if necessary */
370
if (Map->fInfo.ogr.feature_cache_id != FID) {
371
G_debug(4, "Read feature (FID = %ld) to cache.", FID);
372
if (Map->fInfo.ogr.feature_cache) {
373
OGR_F_Destroy(Map->fInfo.ogr.feature_cache);
375
Map->fInfo.ogr.feature_cache =
376
OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
377
if (Map->fInfo.ogr.feature_cache == NULL) {
378
G_fatal_error(_("Unable to get feature geometry, FID %ld"),
381
Map->fInfo.ogr.feature_cache_id = FID;
384
hGeom = OGR_F_GetGeometryRef(Map->fInfo.ogr.feature_cache);
386
G_fatal_error(_("Unable to get feature geometry, FID %ld"),
390
read_line(Map, hGeom, Line->offset + 1, line_p);
394
if (line_c != NULL) {
395
Vect_cat_set(line_c, 1, (int)FID);
401
return -2; /* not reached */