|
@@ -26,7 +26,300 @@ static int read_line(const struct Map_info *, OGRGeometryH, long,
|
|
|
static int get_line_type(const struct Map_info *, long);
|
|
|
static int read_next_line_ogr(struct Map_info *, struct line_pnts *,
|
|
|
struct line_cats *, int);
|
|
|
+#endif
|
|
|
+
|
|
|
+/*!
|
|
|
+ \brief Read next feature from OGR layer.
|
|
|
+ Skip empty features (level 1 without topology).
|
|
|
+
|
|
|
+ This function implements sequential access.
|
|
|
+
|
|
|
+ The action of this routine can be modified by:
|
|
|
+ - Vect_read_constraint_region()
|
|
|
+ - Vect_read_constraint_type()
|
|
|
+ - Vect_remove_constraints()
|
|
|
+
|
|
|
+ \param Map pointer to Map_info structure
|
|
|
+ \param[out] line_p container used to store line points within
|
|
|
+ \param[out] line_c container used to store line categories within
|
|
|
+
|
|
|
+ \return feature type
|
|
|
+ \return -2 no more features (EOF)
|
|
|
+ \return -1 out of memory
|
|
|
+*/
|
|
|
+int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
+ struct line_cats *line_c)
|
|
|
+{
|
|
|
+#ifdef HAVE_OGR
|
|
|
+ return read_next_line_ogr(Map, line_p, line_c, FALSE);
|
|
|
+#else
|
|
|
+ G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
+ return -1;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+/*!
|
|
|
+ \brief Read next feature from OGR layer on topological level.
|
|
|
+
|
|
|
+ This function implements sequential access.
|
|
|
+
|
|
|
+ \param Map pointer to Map_info structure
|
|
|
+ \param[out] line_p container used to store line points within
|
|
|
+ (pointer to line_pnts struct)
|
|
|
+ \param[out] line_c container used to store line categories within
|
|
|
+ (pointer to line_cats struct)
|
|
|
+
|
|
|
+ \return feature type
|
|
|
+ \return -2 no more features (EOF)
|
|
|
+ \return -1 on failure
|
|
|
+*/
|
|
|
+int V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
+ struct line_cats *line_c)
|
|
|
+{
|
|
|
+#ifdef HAVE_OGR
|
|
|
+ int line, ret;
|
|
|
+ struct P_line *Line;
|
|
|
+ struct bound_box lbox, mbox;
|
|
|
+
|
|
|
+ G_debug(3, "V2_read_next_line_ogr()");
|
|
|
+
|
|
|
+ if (Map->constraint.region_flag)
|
|
|
+ Vect_get_constraint_box(Map, &mbox);
|
|
|
+
|
|
|
+ while(TRUE) {
|
|
|
+ line = Map->next_line;
|
|
|
+
|
|
|
+ if (Map->next_line > Map->plus.n_lines)
|
|
|
+ return -2; /* nothing to read */
|
|
|
+
|
|
|
+ Map->next_line++;
|
|
|
+ Line = Map->plus.Line[line];
|
|
|
+ if (Line == NULL) { /* skip dead features */
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Map->constraint.type_flag) {
|
|
|
+ /* skip feature by type */
|
|
|
+ if (!(Line->type & Map->constraint.type))
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Line->type == GV_CENTROID) {
|
|
|
+ G_debug(4, "Centroid");
|
|
|
+
|
|
|
+ if (line_p != NULL) {
|
|
|
+ int i, found;
|
|
|
+ struct bound_box box;
|
|
|
+ struct boxlist list;
|
|
|
+ struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
|
|
|
+
|
|
|
+ /* get area bbox */
|
|
|
+ Vect_get_area_box(Map, topo->area, &box);
|
|
|
+ /* search in spatial index for centroid with area bbox */
|
|
|
+ dig_init_boxlist(&list, TRUE);
|
|
|
+ Vect_select_lines_by_box(Map, &box, Line->type, &list);
|
|
|
+
|
|
|
+ found = 0;
|
|
|
+ for (i = 0; i < list.n_values; i++) {
|
|
|
+ if (list.id[i] == line) {
|
|
|
+ found = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Vect_reset_line(line_p);
|
|
|
+ Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
|
|
|
+ }
|
|
|
+ if (line_c != NULL) {
|
|
|
+ /* cat = FID and offset = FID for centroid */
|
|
|
+ Vect_reset_cats(line_c);
|
|
|
+ Vect_cat_set(line_c, 1, (int) Line->offset);
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = GV_CENTROID;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ret = read_next_line_ogr(Map, line_p, line_c, TRUE);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (line_p && Map->constraint.region_flag) {
|
|
|
+ /* skip feature by region */
|
|
|
+ Vect_line_box(line_p, &lbox);
|
|
|
+ if (!Vect_box_overlap(&lbox, &mbox))
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* skip feature by field ignored */
|
|
|
+
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
+ return -1;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+/*!
|
|
|
+ \brief Read feature from OGR layer at given offset (level 1 without topology)
|
|
|
+
|
|
|
+ This function implements random access on level 1.
|
|
|
+
|
|
|
+ \param Map pointer to Map_info structure
|
|
|
+ \param[out] line_p container used to store line points within
|
|
|
+ (pointer line_pnts struct)
|
|
|
+ \param[out] line_c container used to store line categories within
|
|
|
+ (pointer line_cats struct)
|
|
|
+ \param offset given offset
|
|
|
+
|
|
|
+ \return line type
|
|
|
+ \return 0 dead line
|
|
|
+ \return -2 no more features
|
|
|
+ \return -1 on failure
|
|
|
+*/
|
|
|
+int V1_read_line_ogr(struct Map_info *Map,
|
|
|
+ struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
|
|
|
+{
|
|
|
+#ifdef HAVE_OGR
|
|
|
+ long FID;
|
|
|
+ int type;
|
|
|
+ OGRGeometryH hGeom;
|
|
|
+
|
|
|
+ struct Format_info_ogr *ogr_info;
|
|
|
+
|
|
|
+ ogr_info = &(Map->fInfo.ogr);
|
|
|
+ G_debug(4, "V1_read_line_ogr(): offset = %lu offset_num = %lu",
|
|
|
+ (long) offset, (long) ogr_info->offset.array_num);
|
|
|
+
|
|
|
+ if (offset >= ogr_info->offset.array_num)
|
|
|
+ return -2;
|
|
|
+
|
|
|
+ if (line_p != NULL)
|
|
|
+ Vect_reset_line(line_p);
|
|
|
+ if (line_c != NULL)
|
|
|
+ Vect_reset_cats(line_c);
|
|
|
+
|
|
|
+ FID = ogr_info->offset.array[offset];
|
|
|
+ G_debug(4, " FID = %ld", FID);
|
|
|
+
|
|
|
+ /* coordinates */
|
|
|
+ if (line_p != NULL) {
|
|
|
+ /* Read feature to cache if necessary */
|
|
|
+ if (ogr_info->feature_cache_id != FID) {
|
|
|
+ G_debug(4, "Read feature (FID = %ld) to cache", FID);
|
|
|
+ if (ogr_info->feature_cache) {
|
|
|
+ OGR_F_Destroy(ogr_info->feature_cache);
|
|
|
+ }
|
|
|
+ ogr_info->feature_cache =
|
|
|
+ OGR_L_GetFeature(ogr_info->layer, FID);
|
|
|
+ if (ogr_info->feature_cache == NULL) {
|
|
|
+ G_warning(_("Unable to get feature geometry, FID %ld"),
|
|
|
+ FID);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ ogr_info->feature_cache_id = FID;
|
|
|
+ }
|
|
|
+
|
|
|
+ hGeom = OGR_F_GetGeometryRef(ogr_info->feature_cache);
|
|
|
+ if (hGeom == NULL) {
|
|
|
+ G_warning(_("Unable to get feature geometry, FID %ld"),
|
|
|
+ FID);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ type = read_line(Map, hGeom, offset + 1, line_p);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ type = get_line_type(Map, FID);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* category */
|
|
|
+ if (line_c != NULL) {
|
|
|
+ Vect_cat_set(line_c, 1, (int) FID);
|
|
|
+ }
|
|
|
+
|
|
|
+ return type;
|
|
|
+#else
|
|
|
+ G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
+ return -1;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+/*!
|
|
|
+ \brief Reads feature from OGR layer on topological level.
|
|
|
+
|
|
|
+ This function implements random access on level 2.
|
|
|
+
|
|
|
+ \param Map pointer to Map_info structure
|
|
|
+ \param[out] line_p container used to store line points within
|
|
|
+ (pointer to line_pnts struct)
|
|
|
+ \param[out] line_c container used to store line categories within
|
|
|
+ (pointer to line_cats struct)
|
|
|
+ \param line feature id (starts at 1)
|
|
|
+
|
|
|
+ \return feature type
|
|
|
+ \return -2 no more features
|
|
|
+ \return -1 on failure
|
|
|
+*/
|
|
|
+int V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
+ struct line_cats *line_c, int line)
|
|
|
+{
|
|
|
+#ifdef HAVE_OGR
|
|
|
+ struct P_line *Line;
|
|
|
+
|
|
|
+ G_debug(4, "V2_read_line_ogr() line = %d", line);
|
|
|
+
|
|
|
+ Line = Map->plus.Line[line];
|
|
|
+ if (Line == NULL) {
|
|
|
+ G_warning(_("Attempt to read dead feature %d"), line);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Line->type == GV_CENTROID) {
|
|
|
+ if (line_p != NULL) {
|
|
|
+ int i, found;
|
|
|
+ struct bound_box box;
|
|
|
+ struct boxlist list;
|
|
|
+ struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
|
|
|
+
|
|
|
+ G_debug(4, "Centroid: area = %d", topo->area);
|
|
|
+ Vect_reset_line(line_p);
|
|
|
+
|
|
|
+ if (topo->area > 0 && topo->area <= Map->plus.n_areas) {
|
|
|
+ /* get area bbox */
|
|
|
+ Vect_get_area_box(Map, topo->area, &box);
|
|
|
+ /* search in spatial index for centroid with area bbox */
|
|
|
+ dig_init_boxlist(&list, 1);
|
|
|
+ Vect_select_lines_by_box(Map, &box, Line->type, &list);
|
|
|
+
|
|
|
+ found = 0;
|
|
|
+ for (i = 0; i < list.n_values; i++) {
|
|
|
+ if (list.id[i] == line) {
|
|
|
+ found = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (line_c != NULL) {
|
|
|
+ /* cat = FID and offset = FID for centroid */
|
|
|
+ Vect_reset_cats(line_c);
|
|
|
+ Vect_cat_set(line_c, 1, (int) Line->offset);
|
|
|
+ }
|
|
|
+
|
|
|
+ return GV_CENTROID;
|
|
|
+ }
|
|
|
+
|
|
|
+ return V1_read_line_ogr(Map, line_p, line_c, Line->offset);
|
|
|
+#else
|
|
|
+ G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
+ return -1;
|
|
|
+#endif
|
|
|
+}
|
|
|
|
|
|
+#ifdef HAVE_OGR
|
|
|
/*!
|
|
|
\brief Recursively read feature and add all elements to points_cache and types_cache.
|
|
|
|
|
@@ -42,40 +335,44 @@ static int read_next_line_ogr(struct Map_info *, struct line_pnts *,
|
|
|
int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
|
|
|
{
|
|
|
int line, i, np, ng, tp;
|
|
|
+
|
|
|
+ struct Format_info_ogr *ogr_info;
|
|
|
+
|
|
|
OGRwkbGeometryType type;
|
|
|
OGRGeometryH hGeom2;
|
|
|
|
|
|
G_debug(4, "cache_feature() ftype = %d", ftype);
|
|
|
|
|
|
- /* Alloc space */
|
|
|
- line = Map->fInfo.ogr.lines_num;
|
|
|
- if (line == Map->fInfo.ogr.lines_alloc) {
|
|
|
- Map->fInfo.ogr.lines_alloc += 20;
|
|
|
- Map->fInfo.ogr.lines =
|
|
|
- (struct line_pnts **)G_realloc((void *)Map->fInfo.ogr.lines,
|
|
|
- Map->fInfo.ogr.lines_alloc *
|
|
|
+ ogr_info = &(Map->fInfo.ogr);
|
|
|
+
|
|
|
+ /* alloc space in lines cache */
|
|
|
+ line = ogr_info->cache.lines_num;
|
|
|
+ if (line == ogr_info->cache.lines_alloc) {
|
|
|
+ ogr_info->cache.lines_alloc += 1;
|
|
|
+ ogr_info->cache.lines =
|
|
|
+ (struct line_pnts **)G_realloc((void *)ogr_info->cache.lines,
|
|
|
+ ogr_info->cache.lines_alloc *
|
|
|
sizeof(struct line_pnts *));
|
|
|
|
|
|
- Map->fInfo.ogr.lines_types =
|
|
|
- (int *)G_realloc(Map->fInfo.ogr.lines_types,
|
|
|
- Map->fInfo.ogr.lines_alloc * sizeof(int));
|
|
|
-
|
|
|
- for (i = Map->fInfo.ogr.lines_num; i < Map->fInfo.ogr.lines_alloc; i++)
|
|
|
- Map->fInfo.ogr.lines[i] = Vect_new_line_struct();
|
|
|
+ ogr_info->cache.lines_types =
|
|
|
+ (int *)G_realloc(ogr_info->cache.lines_types,
|
|
|
+ ogr_info->cache.lines_alloc * sizeof(int));
|
|
|
|
|
|
+ for (i = ogr_info->cache.lines_num; i < ogr_info->cache.lines_alloc; i++)
|
|
|
+ ogr_info->cache.lines[i] = Vect_new_line_struct();
|
|
|
}
|
|
|
- Vect_reset_line(Map->fInfo.ogr.lines[line]);
|
|
|
+ Vect_reset_line(ogr_info->cache.lines[line]);
|
|
|
|
|
|
type = wkbFlatten(OGR_G_GetGeometryType(hGeom));
|
|
|
|
|
|
switch (type) {
|
|
|
case wkbPoint:
|
|
|
G_debug(4, "Point");
|
|
|
- Vect_append_point(Map->fInfo.ogr.lines[line],
|
|
|
+ Vect_append_point(ogr_info->cache.lines[line],
|
|
|
OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
|
|
|
OGR_G_GetZ(hGeom, 0));
|
|
|
- Map->fInfo.ogr.lines_types[line] = GV_POINT;
|
|
|
- Map->fInfo.ogr.lines_num++;
|
|
|
+ ogr_info->cache.lines_types[line] = GV_POINT;
|
|
|
+ ogr_info->cache.lines_num++;
|
|
|
return 0;
|
|
|
break;
|
|
|
|
|
@@ -83,18 +380,18 @@ int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
|
|
|
G_debug(4, "LineString");
|
|
|
np = OGR_G_GetPointCount(hGeom);
|
|
|
for (i = 0; i < np; i++) {
|
|
|
- Vect_append_point(Map->fInfo.ogr.lines[line],
|
|
|
+ Vect_append_point(ogr_info->cache.lines[line],
|
|
|
OGR_G_GetX(hGeom, i), OGR_G_GetY(hGeom, i),
|
|
|
OGR_G_GetZ(hGeom, i));
|
|
|
}
|
|
|
|
|
|
if (ftype > 0) { /* Polygon rings */
|
|
|
- Map->fInfo.ogr.lines_types[line] = ftype;
|
|
|
+ ogr_info->cache.lines_types[line] = ftype;
|
|
|
}
|
|
|
else {
|
|
|
- Map->fInfo.ogr.lines_types[line] = GV_LINE;
|
|
|
+ ogr_info->cache.lines_types[line] = GV_LINE;
|
|
|
}
|
|
|
- Map->fInfo.ogr.lines_num++;
|
|
|
+ ogr_info->cache.lines_num++;
|
|
|
return 0;
|
|
|
break;
|
|
|
|
|
@@ -116,232 +413,109 @@ int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
|
|
|
cache_feature(Map, hGeom2, tp);
|
|
|
}
|
|
|
return 0;
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- G_warning(_("OGR feature type %d not supported"), type);
|
|
|
- return 1;
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-int read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
- struct line_cats *line_c, int ignore_constraint)
|
|
|
-{
|
|
|
- int itype;
|
|
|
- struct bound_box lbox, mbox;
|
|
|
- OGRFeatureH hFeature;
|
|
|
- OGRGeometryH hGeom;
|
|
|
-
|
|
|
- struct Format_info_ogr *fInfo;
|
|
|
-
|
|
|
- G_debug(3, "V1_read_next_line_ogr()");
|
|
|
-
|
|
|
- if (line_p != NULL)
|
|
|
- Vect_reset_line(line_p);
|
|
|
- if (line_c != NULL)
|
|
|
- Vect_reset_cats(line_c);
|
|
|
-
|
|
|
- if (Map->constraint.region_flag && !ignore_constraint)
|
|
|
- Vect_get_constraint_box(Map, &mbox);
|
|
|
-
|
|
|
- fInfo = &(Map->fInfo.ogr);
|
|
|
- while (TRUE) {
|
|
|
- /* Read feature to cache if necessary */
|
|
|
- while (fInfo->lines_next == fInfo->lines_num) {
|
|
|
- hFeature = OGR_L_GetNextFeature(fInfo->layer);
|
|
|
- if (hFeature == NULL) {
|
|
|
- return -2;
|
|
|
- } /* no more features */
|
|
|
-
|
|
|
- hGeom = OGR_F_GetGeometryRef(hFeature);
|
|
|
- if (hGeom == NULL) { /* feature without geometry */
|
|
|
- OGR_F_Destroy(hFeature);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- fInfo->feature_cache_id = (int)OGR_F_GetFID(hFeature);
|
|
|
- if (fInfo->feature_cache_id == OGRNullFID) {
|
|
|
- G_warning(_("OGR feature without ID"));
|
|
|
- }
|
|
|
-
|
|
|
- /* Cache the feature */
|
|
|
- fInfo->lines_num = 0;
|
|
|
- cache_feature(Map, hGeom, -1);
|
|
|
- G_debug(4, "%d lines read to cache", fInfo->lines_num);
|
|
|
- OGR_F_Destroy(hFeature);
|
|
|
-
|
|
|
- fInfo->lines_next = 0; /* next to be read from cache */
|
|
|
- }
|
|
|
-
|
|
|
- /* Read next part of the feature */
|
|
|
- G_debug(4, "read next cached line %d", fInfo->lines_next);
|
|
|
- itype = fInfo->lines_types[fInfo->lines_next];
|
|
|
-
|
|
|
- /* Constraint on Type of line
|
|
|
- * Default is all of Point, Line, Area and whatever else comes along
|
|
|
- */
|
|
|
- if (Map->constraint.type_flag && !ignore_constraint) {
|
|
|
- if (!(itype & Map->constraint.type)) {
|
|
|
- fInfo->lines_next++;
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Constraint on specified region */
|
|
|
- if (Map->constraint.region_flag && !ignore_constraint) {
|
|
|
- Vect_line_box(fInfo->lines[fInfo->lines_next],
|
|
|
- &lbox);
|
|
|
-
|
|
|
- if (!Vect_box_overlap(&lbox, &mbox)) {
|
|
|
- fInfo->lines_next++;
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (line_p != NULL)
|
|
|
- Vect_append_points(line_p,
|
|
|
- fInfo->lines[fInfo->lines_next], GV_FORWARD);
|
|
|
-
|
|
|
- if (line_c != NULL && fInfo->feature_cache_id != OGRNullFID)
|
|
|
- Vect_cat_set(line_c, 1, fInfo->feature_cache_id);
|
|
|
-
|
|
|
- fInfo->lines_next++;
|
|
|
- G_debug(4, "next line read, type = %d", itype);
|
|
|
-
|
|
|
- return itype;
|
|
|
- }
|
|
|
- return -2; /* not reached */
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
-/*!
|
|
|
- \brief Read next feature from OGR layer. Skip empty features (level 1)
|
|
|
-
|
|
|
- This function implements sequential access.
|
|
|
-
|
|
|
- The action of this routine can be modified by:
|
|
|
- - Vect_read_constraint_region()
|
|
|
- - Vect_read_constraint_type()
|
|
|
- - Vect_remove_constraints()
|
|
|
-
|
|
|
- \param Map pointer to Map_info structure
|
|
|
- \param[out] line_p container used to store line points within
|
|
|
- \param[out] line_c container used to store line categories within
|
|
|
-
|
|
|
- \return feature type
|
|
|
- \return -2 no more features (EOF)
|
|
|
- \return -1 out of memory
|
|
|
-*/
|
|
|
-int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
- struct line_cats *line_c)
|
|
|
-{
|
|
|
-#ifdef HAVE_OGR
|
|
|
- return read_next_line_ogr(Map, line_p, line_c, FALSE);
|
|
|
-#else
|
|
|
- G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
- return -1;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-/*!
|
|
|
- \brief Read next feature from OGR layer (topology level).
|
|
|
+ break;
|
|
|
|
|
|
- This function implements sequential access.
|
|
|
+ default:
|
|
|
+ G_warning(_("OGR feature type %d not supported"), type);
|
|
|
+ return 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- \param Map pointer to Map_info structure
|
|
|
- \param[out] line_p container used to store line points within
|
|
|
- \param[out] line_c container used to store line categories within
|
|
|
-
|
|
|
- \return feature type
|
|
|
- \return -2 no more features (EOF)
|
|
|
- \return -1 out of memory
|
|
|
-*/
|
|
|
-int V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
- struct line_cats *line_c)
|
|
|
+int read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
+ struct line_cats *line_c, int ignore_constraint)
|
|
|
{
|
|
|
-#ifdef HAVE_OGR
|
|
|
- int line, ret;
|
|
|
- struct P_line *Line;
|
|
|
+ int itype;
|
|
|
struct bound_box lbox, mbox;
|
|
|
+ OGRFeatureH hFeature;
|
|
|
+ OGRGeometryH hGeom;
|
|
|
|
|
|
- G_debug(3, "V2_read_next_line_ogr()");
|
|
|
-
|
|
|
- if (Map->constraint.region_flag)
|
|
|
+ struct Format_info_ogr *ogr_info;
|
|
|
+
|
|
|
+ G_debug(3, "V1_read_next_line_ogr()");
|
|
|
+
|
|
|
+ if (Map->constraint.region_flag && !ignore_constraint)
|
|
|
Vect_get_constraint_box(Map, &mbox);
|
|
|
-
|
|
|
- while(TRUE) {
|
|
|
- line = Map->next_line;
|
|
|
-
|
|
|
- if (Map->next_line > Map->plus.n_lines)
|
|
|
- return -2;
|
|
|
-
|
|
|
- Map->next_line++;
|
|
|
-
|
|
|
- Line = Map->plus.Line[line];
|
|
|
- if (Line == NULL) { /* Dead line */
|
|
|
- continue;
|
|
|
- }
|
|
|
|
|
|
- if ((Map->constraint.type_flag &&
|
|
|
- !(Line->type & Map->constraint.type))) {
|
|
|
- continue;
|
|
|
- }
|
|
|
+ ogr_info = &(Map->fInfo.ogr);
|
|
|
+ while (TRUE) {
|
|
|
+ /* reset data structures */
|
|
|
+ if (line_p != NULL)
|
|
|
+ Vect_reset_line(line_p);
|
|
|
+ if (line_c != NULL)
|
|
|
+ Vect_reset_cats(line_c);
|
|
|
+
|
|
|
+ /* read feature to cache if necessary */
|
|
|
+ while (ogr_info->cache.lines_next == ogr_info->cache.lines_num) {
|
|
|
+ hFeature = OGR_L_GetNextFeature(ogr_info->layer);
|
|
|
+ if (hFeature == NULL) {
|
|
|
+ return -2; /* nothing to read */
|
|
|
+ }
|
|
|
|
|
|
- if (Line->type == GV_CENTROID) {
|
|
|
- G_debug(4, "Centroid");
|
|
|
-
|
|
|
- if (line_p != NULL) {
|
|
|
- int i, found;
|
|
|
- struct bound_box box;
|
|
|
- struct boxlist list;
|
|
|
- struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
|
|
|
-
|
|
|
- /* get area bbox */
|
|
|
- Vect_get_area_box(Map, topo->area, &box);
|
|
|
- /* search in spatial index for centroid with area bbox */
|
|
|
- dig_init_boxlist(&list, TRUE);
|
|
|
- Vect_select_lines_by_box(Map, &box, Line->type, &list);
|
|
|
-
|
|
|
- found = 0;
|
|
|
- for (i = 0; i < list.n_values; i++) {
|
|
|
- if (list.id[i] == line) {
|
|
|
- found = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Vect_reset_line(line_p);
|
|
|
- Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
|
|
|
+ hGeom = OGR_F_GetGeometryRef(hFeature);
|
|
|
+ if (hGeom == NULL) { /* skip feature without geometry */
|
|
|
+ G_warning(_("Feature without geometry. Skipped."));
|
|
|
+ OGR_F_Destroy(hFeature);
|
|
|
+ continue;
|
|
|
}
|
|
|
- if (line_c != NULL) {
|
|
|
- /* cat = FID and offset = FID for centroid */
|
|
|
- Vect_reset_cats(line_c);
|
|
|
- Vect_cat_set(line_c, 1, (int) Line->offset);
|
|
|
+
|
|
|
+ /* cache OGR feature */
|
|
|
+ ogr_info->feature_cache_id = (int)OGR_F_GetFID(hFeature);
|
|
|
+ if (ogr_info->feature_cache_id == OGRNullFID) {
|
|
|
+ G_warning(_("OGR feature without ID"));
|
|
|
}
|
|
|
-
|
|
|
- ret = GV_CENTROID;
|
|
|
+
|
|
|
+ /* cache feature */
|
|
|
+ ogr_info->cache.lines_num = 0;
|
|
|
+ cache_feature(Map, hGeom, -1);
|
|
|
+ G_debug(4, "%d lines read to cache", ogr_info->cache.lines_num);
|
|
|
+ OGR_F_Destroy(hFeature);
|
|
|
+
|
|
|
+ /* next to be read from cache */
|
|
|
+ ogr_info->cache.lines_next = 0;
|
|
|
}
|
|
|
- else {
|
|
|
- ret = read_next_line_ogr(Map, line_p, line_c, TRUE);
|
|
|
+
|
|
|
+ /* read next part of the feature */
|
|
|
+ G_debug(4, "read next cached line %d", ogr_info->cache.lines_next);
|
|
|
+ itype = ogr_info->cache.lines_types[ogr_info->cache.lines_next];
|
|
|
+
|
|
|
+ if (Map->constraint.type_flag && !ignore_constraint) {
|
|
|
+ /* skip feature by type */
|
|
|
+ if (!(itype & Map->constraint.type)) {
|
|
|
+ ogr_info->cache.lines_next++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- if (Map->constraint.region_flag) {
|
|
|
- Vect_line_box(line_p, &lbox);
|
|
|
+
|
|
|
+ if (Map->constraint.region_flag && !ignore_constraint) {
|
|
|
+ /* skip feature by region */
|
|
|
+ Vect_line_box(ogr_info->cache.lines[ogr_info->cache.lines_next],
|
|
|
+ &lbox);
|
|
|
+
|
|
|
if (!Vect_box_overlap(&lbox, &mbox)) {
|
|
|
+ ogr_info->cache.lines_next++;
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return ret;
|
|
|
+ /* skip feature by field - ignored */
|
|
|
+
|
|
|
+ if (line_p != NULL)
|
|
|
+ Vect_append_points(line_p,
|
|
|
+ ogr_info->cache.lines[ogr_info->cache.lines_next], GV_FORWARD);
|
|
|
+
|
|
|
+ if (line_c != NULL && ogr_info->feature_cache_id != OGRNullFID)
|
|
|
+ Vect_cat_set(line_c, 1, ogr_info->feature_cache_id);
|
|
|
+
|
|
|
+ ogr_info->cache.lines_next++;
|
|
|
+ G_debug(4, "next line read, type = %d", itype);
|
|
|
+
|
|
|
+ return itype;
|
|
|
}
|
|
|
-#else
|
|
|
- G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
- return -1;
|
|
|
-#endif
|
|
|
+
|
|
|
+ return -1; /* not reached */
|
|
|
}
|
|
|
|
|
|
-#ifdef HAVE_OGR
|
|
|
/*!
|
|
|
\brief Recursively descend to feature and read the part
|
|
|
|
|
@@ -358,12 +532,17 @@ int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
|
|
|
{
|
|
|
int i, nPoints;
|
|
|
int eType, line;
|
|
|
+
|
|
|
+ const struct Format_info_ogr *ogr_info;
|
|
|
+
|
|
|
OGRGeometryH hGeom2;
|
|
|
|
|
|
/* Read coors if hGeom is a simple element (wkbPoint,
|
|
|
* wkbLineString) otherwise descend to geometry specified by
|
|
|
* offset[offset] */
|
|
|
|
|
|
+ ogr_info = &(Map->fInfo.ogr);
|
|
|
+
|
|
|
eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
|
|
|
G_debug(4, "OGR geometry type: %d", eType);
|
|
|
|
|
@@ -394,8 +573,8 @@ int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
|
|
|
case wkbMultiLineString:
|
|
|
case wkbMultiPolygon:
|
|
|
case wkbGeometryCollection:
|
|
|
- G_debug(4, "\t->more geoms -> part %d", Map->fInfo.ogr.offset[offset]);
|
|
|
- hGeom2 = OGR_G_GetGeometryRef(hGeom, Map->fInfo.ogr.offset[offset]);
|
|
|
+ G_debug(4, "\t->more geoms -> part %d", ogr_info->offset.array[offset]);
|
|
|
+ hGeom2 = OGR_G_GetGeometryRef(hGeom, ogr_info->offset.array[offset]);
|
|
|
line = read_line(Map, hGeom2, offset + 1, Points);
|
|
|
if (eType == wkbPolygon || wkbMultiPolygon)
|
|
|
return GV_BOUNDARY;
|
|
@@ -429,12 +608,17 @@ int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
|
|
|
int get_line_type(const struct Map_info *Map, long FID)
|
|
|
{
|
|
|
int eType;
|
|
|
+
|
|
|
+ const struct Format_info_ogr *ogr_info;
|
|
|
+
|
|
|
OGRFeatureH hFeat;
|
|
|
OGRGeometryH hGeom;
|
|
|
|
|
|
G_debug(4, "get_line_type() fid = %ld", FID);
|
|
|
|
|
|
- hFeat = OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
|
|
|
+ ogr_info = &(Map->fInfo.ogr);
|
|
|
+
|
|
|
+ hFeat = OGR_L_GetFeature(ogr_info->layer, FID);
|
|
|
if (hFeat == NULL)
|
|
|
return -1;
|
|
|
|
|
@@ -473,155 +657,3 @@ int get_line_type(const struct Map_info *Map, long FID)
|
|
|
return -1;
|
|
|
}
|
|
|
#endif
|
|
|
-
|
|
|
-/*!
|
|
|
- \brief Read feature from OGR layer at given offset (level 1)
|
|
|
-
|
|
|
- This function implements random access on level 1.
|
|
|
-
|
|
|
- \param Map pointer to Map_info structure
|
|
|
- \param[out] line_p container used to store line points within
|
|
|
- \param[out] line_c container used to store line categories within
|
|
|
- \param offset given offset
|
|
|
-
|
|
|
- \return line type
|
|
|
- \return 0 dead line
|
|
|
- \return -2 no more features
|
|
|
- \return -1 out of memory
|
|
|
-*/
|
|
|
-int V1_read_line_ogr(struct Map_info *Map,
|
|
|
- struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
|
|
|
-{
|
|
|
-#ifdef HAVE_OGR
|
|
|
- long FID;
|
|
|
- int type;
|
|
|
- OGRGeometryH hGeom;
|
|
|
-
|
|
|
- struct Format_info_ogr *fInfo;
|
|
|
-
|
|
|
- fInfo = &(Map->fInfo.ogr);
|
|
|
- G_debug(4, "V1_read_line_ogr() offset = %lu offset_num = %lu",
|
|
|
- (long) offset, (long) fInfo->offset_num);
|
|
|
-
|
|
|
- if (offset >= fInfo->offset_num)
|
|
|
- return -2;
|
|
|
-
|
|
|
- if (line_p != NULL)
|
|
|
- Vect_reset_line(line_p);
|
|
|
- if (line_c != NULL)
|
|
|
- Vect_reset_cats(line_c);
|
|
|
-
|
|
|
- FID = fInfo->offset[offset];
|
|
|
- G_debug(4, " FID = %ld", FID);
|
|
|
-
|
|
|
- /* coordinates */
|
|
|
- if (line_p != NULL) {
|
|
|
- /* Read feature to cache if necessary */
|
|
|
- if (fInfo->feature_cache_id != FID) {
|
|
|
- G_debug(4, "Read feature (FID = %ld) to cache", FID);
|
|
|
- if (fInfo->feature_cache) {
|
|
|
- OGR_F_Destroy(fInfo->feature_cache);
|
|
|
- }
|
|
|
- fInfo->feature_cache =
|
|
|
- OGR_L_GetFeature(fInfo->layer, FID);
|
|
|
- if (fInfo->feature_cache == NULL) {
|
|
|
- G_fatal_error(_("Unable to get feature geometry, FID %ld"),
|
|
|
- FID);
|
|
|
- }
|
|
|
- fInfo->feature_cache_id = FID;
|
|
|
- }
|
|
|
-
|
|
|
- hGeom = OGR_F_GetGeometryRef(fInfo->feature_cache);
|
|
|
- if (hGeom == NULL) {
|
|
|
- G_fatal_error(_("Unable to get feature geometry, FID %ld"),
|
|
|
- FID);
|
|
|
- }
|
|
|
-
|
|
|
- type = read_line(Map, hGeom, offset + 1, line_p);
|
|
|
- }
|
|
|
- else {
|
|
|
- type = get_line_type(Map, FID);
|
|
|
- }
|
|
|
-
|
|
|
- /* category */
|
|
|
- if (line_c != NULL) {
|
|
|
- Vect_cat_set(line_c, 1, (int) FID);
|
|
|
- }
|
|
|
-
|
|
|
- return type;
|
|
|
-#else
|
|
|
- G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
- return -1;
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-/*!
|
|
|
- \brief Reads feature from OGR layer (topology level)
|
|
|
-
|
|
|
- This function implements random access on level 2.
|
|
|
-
|
|
|
- \param Map pointer to Map_info structure
|
|
|
- \param[out] line_p container used to store line points within
|
|
|
- \param[out] line_c container used to store line categories within
|
|
|
- \param line feature id
|
|
|
-
|
|
|
- \return feature type
|
|
|
- \return -2 no more features
|
|
|
- \return -1 out of memory
|
|
|
-*/
|
|
|
-int V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
- struct line_cats *line_c, int line)
|
|
|
-{
|
|
|
-#ifdef HAVE_OGR
|
|
|
- struct P_line *Line;
|
|
|
- G_debug(4, "V2_read_line_ogr() line = %d", line);
|
|
|
-
|
|
|
- Line = Map->plus.Line[line];
|
|
|
-
|
|
|
- if (Line == NULL)
|
|
|
- G_fatal_error(_("Attempt to read dead feature %d"), line);
|
|
|
-
|
|
|
- if (Line->type == GV_CENTROID) {
|
|
|
- if (line_p != NULL) {
|
|
|
- int i, found;
|
|
|
- struct bound_box box;
|
|
|
- struct boxlist list;
|
|
|
- struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
|
|
|
-
|
|
|
- G_debug(4, "Centroid: area = %d", topo->area);
|
|
|
- Vect_reset_line(line_p);
|
|
|
-
|
|
|
- if (topo->area > 0 && topo->area <= Map->plus.n_areas) {
|
|
|
- /* get area bbox */
|
|
|
- Vect_get_area_box(Map, topo->area, &box);
|
|
|
- /* search in spatial index for centroid with area bbox */
|
|
|
- dig_init_boxlist(&list, 1);
|
|
|
- Vect_select_lines_by_box(Map, &box, Line->type, &list);
|
|
|
-
|
|
|
- found = 0;
|
|
|
- for (i = 0; i < list.n_values; i++) {
|
|
|
- if (list.id[i] == line) {
|
|
|
- found = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (line_c != NULL) {
|
|
|
- /* cat = FID and offset = FID for centroid */
|
|
|
- Vect_reset_cats(line_c);
|
|
|
- Vect_cat_set(line_c, 1, (int) Line->offset);
|
|
|
- }
|
|
|
-
|
|
|
- return GV_CENTROID;
|
|
|
- }
|
|
|
-
|
|
|
- return V1_read_line_ogr(Map, line_p, line_c, Line->offset);
|
|
|
-#else
|
|
|
- G_fatal_error(_("GRASS is not compiled with OGR support"));
|
|
|
- return -1;
|
|
|
-#endif
|
|
|
-}
|