[GRASS-SVN] r71464 - grass/trunk/vector/v.in.ogr

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Sep 4 11:15:16 PDT 2017


Author: mmetz
Date: 2017-09-04 11:15:15 -0700 (Mon, 04 Sep 2017)
New Revision: 71464

Modified:
   grass/trunk/vector/v.in.ogr/main.c
Log:
v.in.ogr: use interleaved reading for OSM

Modified: grass/trunk/vector/v.in.ogr/main.c
===================================================================
--- grass/trunk/vector/v.in.ogr/main.c	2017-09-03 02:14:01 UTC (rev 71463)
+++ grass/trunk/vector/v.in.ogr/main.c	2017-09-04 18:15:15 UTC (rev 71464)
@@ -29,6 +29,7 @@
 #include <grass/glocale.h>
 #include <gdal_version.h>	/* needed for OFTDate */
 #include "ogr_api.h"
+#include "cpl_conv.h"
 #include "global.h"
 
 #ifndef MAX
@@ -48,6 +49,25 @@
 
 char *get_datasource_name(const char *, int);
 
+struct OGR_iterator
+{
+    OGRDataSourceH *Ogr_ds;
+    char *dsn;
+    int nlayers;
+    int has_nonempty_layers;
+    int ogr_interleaved_reading;
+    OGRLayerH Ogr_layer;
+    OGRFeatureDefnH Ogr_featuredefn;
+    int requested_layer;
+    int curr_layer;
+};
+
+void OGR_iterator_init(struct OGR_iterator *OGR_iter, OGRDataSourceH *Ogr_ds,
+                       char *dsn, int nlayers,
+		       int ogr_interleaved_reading);
+void OGR_iterator_reset(struct OGR_iterator *OGR_iter);
+OGRFeatureH ogr_getnextfeature(struct OGR_iterator *, int);
+
 int main(int argc, char *argv[])
 {
     struct GModule *module;
@@ -92,6 +112,7 @@
     /* OGR */
     OGRDataSourceH Ogr_ds;
     const char *ogr_driver_name;
+    int osm_interleaved_reading;
     OGRLayerH Ogr_layer;
     OGRFieldDefnH Ogr_field;
     char *Ogr_fieldname;
@@ -102,6 +123,7 @@
     OGRSpatialReferenceH Ogr_projection;
     OGREnvelope oExt;
     int have_ogr_extent = 0;
+    struct OGR_iterator OGR_iter;
 
     int OFTIntegerListlength;
 
@@ -115,7 +137,8 @@
     char **available_layer_names;	/* names of layers to be imported */
     int navailable_layers;
     int layer_id;
-    unsigned int n_features, feature_count;
+    unsigned int feature_count;
+    GIntBig *n_features, n_import_features;
     int overwrite;
     double area_size;
     int use_tmp_vect;
@@ -408,14 +431,27 @@
     if (Ogr_ds == NULL)
 	G_fatal_error(_("Unable to open data source <%s>"), dsn);
 
+    /* driver name */
     ogr_driver_name = OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds));
+    G_verbose_message(_("Using OGR driver '%s'"), ogr_driver_name);
+
+    /* OSM interleaved reading */
+    osm_interleaved_reading = 0;
     if (strcmp(ogr_driver_name, "OSM") == 0) {
+
+	CPLSetConfigOption("OGR_INTERLEAVED_READING", "YES");
+	/* re-open OGR DSN */
 	OGR_DS_Destroy(Ogr_ds);
-	G_warning(_("OpenStreetMap import can result in missing features. "
-	            "Please use ogr2ogr first to convert to a different format."));
-	G_fatal_error(_("OSM import cancelled."));
+	Ogr_ds = OGROpen(dsn, FALSE, NULL);
+	osm_interleaved_reading = 1;
     }
+    if (osm_interleaved_reading)
+	G_verbose_message(_("Using OSM interleaved reading"));
 
+    navailable_layers = OGR_DS_GetLayerCount(Ogr_ds);
+    OGR_iterator_init(&OGR_iter, &Ogr_ds, dsn, navailable_layers,
+		      osm_interleaved_reading);
+
     if (param.geom->answer) {
 #if GDAL_VERSION_NUM >= 1110000
         if (!OGR_DS_TestCapability(Ogr_ds, ODsCCreateGeomFieldAfterCreateLayer)) {
@@ -492,6 +528,10 @@
 	for (i = 0; i < nlayers; i++)
 	    layers[i] = i;
     }
+    n_features = (GIntBig *)G_malloc(nlayers * sizeof(GIntBig));
+    for (i = 0; i < nlayers; i++) {
+	n_features[i] = 0;
+    }
 
     if (param.out->answer) {
 	output = G_store(param.out->answer);
@@ -850,7 +890,10 @@
 
     /* check if input id 3D and if we need a tmp vector */
     /* estimate distance for boundary splitting --> */
+    OGR_iterator_reset(&OGR_iter);
     for (layer = 0; layer < nlayers; layer++) {
+	GIntBig ogr_feature_count;
+
 	layer_id = layers[layer];
 
 	Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
@@ -864,19 +907,30 @@
                               param.geom->answer, OGR_L_GetName(Ogr_layer));
         }
 #endif
-	n_features = feature_count = 0;
+	feature_count = 0;
 
-	n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
-	OGR_L_ResetReading(Ogr_layer);
+	ogr_feature_count = 0;
+	if (n_features[layer_id] == 0)
+	    ogr_feature_count = OGR_L_GetFeatureCount(Ogr_layer, 1);
+	if (ogr_feature_count > 0)
+	    n_features[layer_id] = ogr_feature_count;
 
 	/* count polygons and isles */
+	if (!osm_interleaved_reading) {
+	    OGR_L_ResetReading(Ogr_layer);
+	}
 	G_message(_("Check if OGR layer <%s> contains polygons..."),
 		  layer_names[layer]);
-	while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
-	    G_percent(feature_count++, n_features, 1);	/* show something happens */
+	while ((Ogr_feature = ogr_getnextfeature(&OGR_iter, layer_id)) != NULL) {
+	    if (ogr_feature_count > 0)
+		G_percent(feature_count++, n_features[layer], 1);	/* show something happens */
 
+	    if (ogr_feature_count <= 0)
+		n_features[layer]++;
+
             /* Geometry */
 #if GDAL_VERSION_NUM >= 1110000
+            Ogr_featuredefn = OGR_iter.Ogr_featuredefn;
             for (i = 0; i < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); i++) {
                 if (igeom > -1 && i != igeom)
                     continue; /* use only geometry defined via param.geom */
@@ -899,6 +953,11 @@
 	G_percent(1, 1, 1);
     }
 
+    n_import_features = 0;
+    for (i = 0; i < nlayers; i++)
+	n_import_features += n_features[i];
+    G_message("Importing %lld features", n_import_features);
+
     G_debug(1, "n polygon boundaries: %d", n_polygon_boundaries);
     if (n_polygon_boundaries > 50) {
 	split_distance =
@@ -946,10 +1005,11 @@
     ncentr = n_overlaps = n_polygons = 0;
 
     /* Points and lines are written immediately with categories. Boundaries of polygons are
-     * written to the vector then cleaned and centroids are calculated for all areas in cleaan vector.
+     * written to the vector then cleaned and centroids are calculated for all areas in clean vector.
      * Then second pass through finds all centroids in each polygon feature and adds its category
      * to the centroid. The result is that one centroids may have 0, 1 ore more categories
      * of one ore more (more input layers) fields. */
+    OGR_iterator_reset(&OGR_iter);
     for (layer = 0; layer < nlayers; layer++) {
 	layer_id = layers[layer];
 
@@ -1171,16 +1231,15 @@
 	nogeom = 0;
 	feature_count = 0;
 
-	n_features = OGR_L_GetFeatureCount(Ogr_layer, TRUE);
-	G_important_message(_("Importing %d features (OGR layer <%s>)..."),
-			    n_features, layer_names[layer]);
-        
-        OGR_L_ResetReading(Ogr_layer);
-	while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
-	    G_percent(feature_count++, n_features, 1);	/* show something happens */
+	G_important_message(_("Importing %lld features (OGR layer <%s>)..."),
+			    n_features[layer], layer_names[layer]);
 
+	while ((Ogr_feature = ogr_getnextfeature(&OGR_iter, layer_id)) != NULL) {
+	    G_percent(feature_count++, n_features[layer], 1);	/* show something happens */
+
             /* Geometry */
 #if GDAL_VERSION_NUM >= 1110000
+            Ogr_featuredefn = OGR_iter.Ogr_featuredefn;
             for (i = 0; i < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); i++) {
                 if (igeom > -1 && i != igeom)
                     continue; /* use only geometry defined via param.geom */
@@ -1313,7 +1372,6 @@
 		      nogeom == 1 ? "feature" : "features");
     }
 
-
     separator = "-----------------------------------------------------";
     G_message("%s", separator);
 
@@ -1444,6 +1502,7 @@
 	}
 
 	/* Go through all layers and find centroids for each polygon */
+	OGR_iterator_reset(&OGR_iter);
 	for (layer = 0; layer < nlayers; layer++) {
 	    G_message("%s", separator);
 	    G_message(_("Finding centroids for OGR layer <%s>..."), layer_names[layer]);
@@ -1456,13 +1515,12 @@
             if (param.geom->answer)
                 igeom = OGR_FD_GetGeomFieldIndex(Ogr_featuredefn, param.geom->answer);
 #endif
-            
-	    n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
+
 	    OGR_L_ResetReading(Ogr_layer);
 
 	    cat = 0;		/* field = layer + 1 */
-	    while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
-		G_percent(cat, n_features, 2);
+	    while ((Ogr_feature = ogr_getnextfeature(&OGR_iter, layer_id)) != NULL) {
+		G_percent(cat, n_features[layer], 2);
 
                 /* Category */
                 if (key_idx > -1)
@@ -1472,6 +1530,7 @@
 
 		/* Geometry */
 #if GDAL_VERSION_NUM >= 1110000
+		Ogr_featuredefn = OGR_iter.Ogr_featuredefn;
                 for (i = 0; i < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); i++) {
                     if (igeom > -1 && i != igeom)
                         continue; /* use only geometry defined via param.geom */
@@ -1747,3 +1806,117 @@
 
     exit(EXIT_SUCCESS);
 }
+
+void OGR_iterator_init(struct OGR_iterator *OGR_iter, OGRDataSourceH *Ogr_ds,
+                       char *dsn, int nlayers,
+		       int ogr_interleaved_reading)
+{
+    OGR_iter->Ogr_ds = Ogr_ds;
+    OGR_iter->dsn = dsn;
+    OGR_iter->nlayers = nlayers;
+    OGR_iter->ogr_interleaved_reading = ogr_interleaved_reading;
+    OGR_iter->requested_layer = -1;
+    OGR_iter->curr_layer = -1;
+    OGR_iter->Ogr_layer = NULL;
+    OGR_iter->has_nonempty_layers = 0;
+}
+
+void OGR_iterator_reset(struct OGR_iterator *OGR_iter)
+{
+    OGR_iter->requested_layer = -1;
+    OGR_iter->curr_layer = -1;
+    OGR_iter->Ogr_layer = NULL;
+    OGR_iter->has_nonempty_layers = 0;
+}
+
+OGRFeatureH ogr_getnextfeature(struct OGR_iterator *OGR_iter, int layer)
+{
+    if (OGR_iter->requested_layer != layer) {
+	/* reset OGR reading */
+	if (!OGR_iter->ogr_interleaved_reading) {
+	    OGR_iter->curr_layer = layer;
+	    OGR_iter->Ogr_layer = OGR_DS_GetLayer(*(OGR_iter->Ogr_ds), OGR_iter->curr_layer);
+	    OGR_iter->Ogr_featuredefn = OGR_L_GetLayerDefn(OGR_iter->Ogr_layer);
+	    OGR_L_ResetReading(OGR_iter->Ogr_layer);
+	}
+	else {
+	    /* need to re-open OGR DSN in order to start reading from the beginning
+	     * NOTE: any constraints are lost */
+	    OGR_DS_Destroy(*(OGR_iter->Ogr_ds));
+	    *(OGR_iter->Ogr_ds) = OGROpen(OGR_iter->dsn, FALSE, NULL);
+	    if (*(OGR_iter->Ogr_ds) == NULL)
+		G_fatal_error(_("Unable to re-open data source <%s>"), OGR_iter->dsn);
+	    OGR_iter->curr_layer = 0;
+	    OGR_iter->Ogr_layer = OGR_DS_GetLayer(*(OGR_iter->Ogr_ds), OGR_iter->curr_layer);
+	    OGR_iter->Ogr_featuredefn = OGR_L_GetLayerDefn(OGR_iter->Ogr_layer);
+	    OGR_iter->has_nonempty_layers = 0;
+	}
+	OGR_iter->requested_layer = layer;
+    }
+
+    if (OGR_iter->Ogr_layer == NULL)
+	return NULL;
+
+    if (!OGR_iter->ogr_interleaved_reading) {
+	OGRFeatureH Ogr_feature;
+
+	Ogr_feature = OGR_L_GetNextFeature(OGR_iter->Ogr_layer);
+	if (Ogr_feature == NULL)
+	    OGR_iter->Ogr_layer = NULL;
+
+	return Ogr_feature;
+    }
+    else {
+	OGRFeatureH Ogr_feature;
+
+	/* fetch next feature */
+	while (1) {
+	    while (OGR_iter->curr_layer != layer) {
+		while ((Ogr_feature = OGR_L_GetNextFeature(OGR_iter->Ogr_layer)) != NULL) {
+		    OGR_iter->has_nonempty_layers = 1;
+		    OGR_F_Destroy(Ogr_feature);
+		}
+		OGR_iter->curr_layer++;
+		if (OGR_iter->curr_layer == OGR_iter->nlayers) {
+		    if (!OGR_iter->has_nonempty_layers) {
+			OGR_iter->Ogr_layer = NULL;
+
+			return NULL;
+		    }
+		    else {
+			OGR_iter->curr_layer = 0;
+			OGR_iter->has_nonempty_layers = 0;
+		    }
+		}
+		G_debug(3, "advancing to layer %d ...", OGR_iter->curr_layer);
+		OGR_iter->Ogr_layer = OGR_DS_GetLayer(*(OGR_iter->Ogr_ds), OGR_iter->curr_layer);
+		OGR_iter->Ogr_featuredefn = OGR_L_GetLayerDefn(OGR_iter->Ogr_layer);
+	    }
+	    Ogr_feature = OGR_L_GetNextFeature(OGR_iter->Ogr_layer);
+	    if (Ogr_feature != NULL) {
+		OGR_iter->has_nonempty_layers = 1;
+
+		return Ogr_feature;
+	    }
+	    else {
+		OGR_iter->curr_layer++;
+		if (OGR_iter->curr_layer == OGR_iter->nlayers) {
+		    if (!OGR_iter->has_nonempty_layers) {
+			OGR_iter->Ogr_layer = NULL;
+
+			return NULL;
+		    }
+		    else {
+			OGR_iter->curr_layer = 0;
+			OGR_iter->has_nonempty_layers = 0;
+		    }
+		}
+		G_debug(3, "advancing to layer %d ...", OGR_iter->curr_layer);
+		OGR_iter->Ogr_layer = OGR_DS_GetLayer(*(OGR_iter->Ogr_ds), OGR_iter->curr_layer);
+		OGR_iter->Ogr_featuredefn = OGR_L_GetLayerDefn(OGR_iter->Ogr_layer);
+	    }
+	}
+    }
+
+    return NULL;
+}



More information about the grass-commit mailing list