Browse Source

v.in.ogr: support GDAL RFC41 (Support for multiple geometry fields in OGR)
v.external: -t print also geometry column (useful when layer has multiple geometries)
fix compilation of v.in.ogr and v.external agaist GDAL < 1.11
v.in.ogr: add example from multiple geometry columns to the manual
(merge https://trac.osgeo.org/grass/changeset/63604,63608-63609,63618,63685,63689 from trunk)


git-svn-id: https://svn.osgeo.org/grass/grass/branches/releasebranch_7_0@63690 15284696-431f-4ddb-bdfa-cd5b030d7da7

Martin Landa 10 years ago
parent
commit
057e152aa2
4 changed files with 178 additions and 47 deletions
  1. 1 1
      vector/v.external/args.c
  2. 25 6
      vector/v.external/list.c
  3. 112 38
      vector/v.in.ogr/main.c
  4. 40 2
      vector/v.in.ogr/v.in.ogr.html

+ 1 - 1
vector/v.external/args.c

@@ -51,7 +51,7 @@ void parse_args(int argc, char **argv,
     flags->tlist->key = 't';
     flags->tlist->label = _("List available layers including feature type "
 			    "in data source and exit");
-    flags->tlist->description = _("Format: layer name,type,projection check");
+    flags->tlist->description = _("Format: layer name,type,projection check,geometry");
     flags->tlist->guisection = _("Print");
     flags->tlist->suppress_required = YES;
 

+ 25 - 6
vector/v.external/list.c

@@ -278,14 +278,18 @@ int list_layers_ogr(FILE *fd, const char *dsn, const char *layer, int print_type
     for (i = 0; i < nlayers; i++) {
 	Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
 	Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
-	Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
+#if GDAL_VERSION_NUM < 1110000      
+        Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
+#endif
 	layer_name = (char *) OGR_FD_GetName(Ogr_featuredefn);
 
 	if (fd) {
 	    if (print_types) {
-		int proj_same;
+                int proj_same, igeom;
 		OGRSpatialReferenceH Ogr_projection;
-
+#if GDAL_VERSION_NUM >= 1110000
+                OGRGeomFieldDefnH Ogr_geomdefn;
+#endif
 		/* projection check */
 		Ogr_projection = OGR_L_GetSpatialRef(Ogr_layer);
 		proj_same = 0;
@@ -304,9 +308,24 @@ int list_layers_ogr(FILE *fd, const char *dsn, const char *layer, int print_type
 			proj_same = 0;
 		}
 		G_suppress_warnings(FALSE);
-		fprintf(fd, "%s,%s,%d\n", layer_name,
-			feature_type(OGRGeometryTypeToName(Ogr_geom_type)),
-			proj_same);
+#if GDAL_VERSION_NUM >= 1110000
+                for (igeom = 0; igeom < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); igeom++) {
+                    Ogr_geomdefn = OGR_FD_GetGeomFieldDefn(Ogr_featuredefn, igeom);
+                    if (!Ogr_geomdefn) {
+                        G_warning(_("Invalid geometry column %d"), igeom);
+                        continue;
+                    }
+
+                    Ogr_geom_type = OGR_GFld_GetType(Ogr_geomdefn);
+                    fprintf(fd, "%s,%s,%d,%s\n", layer_name,
+                            feature_type(OGRGeometryTypeToName(Ogr_geom_type)),
+                            proj_same, OGR_GFld_GetNameRef(Ogr_geomdefn));
+                }
+#else
+                    fprintf(fd, "%s,%s,%d,\n", layer_name,
+                            feature_type(OGRGeometryTypeToName(Ogr_geom_type)),
+                            proj_same);
+#endif
 	    }
 	    else {
 		fprintf(fd, "%s\n", layer_name);

+ 112 - 38
vector/v.in.ogr/main.c

@@ -52,7 +52,7 @@ int main(int argc, char *argv[])
     struct _param {
 	struct Option *dsn, *out, *layer, *spat, *where,
 	    *min_area;
-        struct Option *snap, *type, *outloc, *cnames, *encoding, *key;
+        struct Option *snap, *type, *outloc, *cnames, *encoding, *key, *geom;
     } param;
     struct _flag {
 	struct Flag *list, *no_clean, *force2d, *notab,
@@ -62,7 +62,7 @@ int main(int argc, char *argv[])
 
     char *desc;
 
-    int i, j, layer, nogeom, ncnames;
+    int i, j, layer, nogeom, ncnames, igeom;
     double xmin, ymin, xmax, ymax;
     int ncols = 0, type;
     double min_area, snap;
@@ -240,6 +240,12 @@ int main(int argc, char *argv[])
         _("If not given, categories are generated as unique values and stored in 'cat' column");
     param.key->guisection = _("Attributes");
 
+    param.geom = G_define_standard_option(G_OPT_DB_COLUMN);
+    param.geom->key = "geometry";
+    param.geom->label = _("Name of geometry column");
+    param.geom->description = _("If not given, all geometry columns from the input are used");
+    param.geom->guisection = _("Selection");
+
     flag.formats = G_define_flag();
     flag.formats->key = 'f';
     flag.formats->description = _("List supported OGR formats and exit");
@@ -427,6 +433,20 @@ int main(int argc, char *argv[])
     if (Ogr_ds == NULL)
 	G_fatal_error(_("Unable to open data source <%s>"), dsn);
 
+    if (param.geom->answer) {
+#if GDAL_VERSION_NUM >= 1110000
+        if (!OGR_DS_TestCapability(Ogr_ds, ODsCCreateGeomFieldAfterCreateLayer)) {
+            G_warning(_("Option <%s> will be ignored. OGR doesn't support it for selected format (%s)."),
+                      param.geom->key, OGR_Dr_GetName(OGR_DS_GetDriver(Ogr_ds)));
+            param.geom->answer = NULL;
+        }
+#else
+        G_warning(_("Option <%s> will be ignored. Multiple geometry fields are supported by GDAL >= 1.11"),
+                  param.geom->key);
+        param.geom->answer = NULL;
+#endif
+    }
+
     /* check encoding for given driver */
     if (param.encoding->answer) {
         const char *ogr_driver;
@@ -816,7 +836,15 @@ int main(int argc, char *argv[])
 
 	Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
 	Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
-
+        igeom = -1;
+#if GDAL_VERSION_NUM >= 1110000
+        if (param.geom->answer) {
+            igeom = OGR_FD_GetGeomFieldIndex(Ogr_featuredefn, param.geom->answer);
+            if (igeom < 0)
+                G_fatal_error(_("Geometry column <%s> not found in OGR layer <%s>"),
+                              param.geom->answer, OGR_L_GetName(Ogr_layer));
+        }
+#endif
 	n_features = feature_count = 0;
 
 	n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
@@ -827,15 +855,27 @@ int main(int argc, char *argv[])
 		  layer_names[layer]);
 	while ((Ogr_feature = OGR_L_GetNextFeature(Ogr_layer)) != NULL) {
 	    G_percent(feature_count++, n_features, 1);	/* show something happens */
-	    /* Geometry */
-	    Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
-	    if (Ogr_geometry != NULL) {
-		if (!flag.no_clean->answer)
-		    poly_count(Ogr_geometry, (type & GV_BOUNDARY));
-		if (OGR_G_GetCoordinateDimension(Ogr_geometry) > 2)
-		    input3d = 1;
-	    }
-	    OGR_F_Destroy(Ogr_feature);
+
+            /* Geometry */
+#if GDAL_VERSION_NUM >= 1110000
+            for (i = 0; i < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); i++) {
+                if (igeom > -1 && i != igeom)
+                    continue; /* use only geometry defined via param.geom */
+            
+                Ogr_geometry = OGR_F_GetGeomFieldRef(Ogr_feature, i);
+#else
+                Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
+#endif
+                if (Ogr_geometry != NULL) {
+                    if (!flag.no_clean->answer)
+                        poly_count(Ogr_geometry, (type & GV_BOUNDARY));
+                    if (OGR_G_GetCoordinateDimension(Ogr_geometry) > 2)
+                        input3d = 1;
+                }
+#if GDAL_VERSION_NUM >= 1110000                
+            }
+#endif
+            OGR_F_Destroy(Ogr_feature);
 	}
 	G_percent(1, 1, 1);
     }
@@ -897,6 +937,12 @@ int main(int argc, char *argv[])
 	Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
 	Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
 
+        igeom = -1;
+#if GDAL_VERSION_NUM >= 1110000
+        if (param.geom->answer)
+            igeom = OGR_FD_GetGeomFieldIndex(Ogr_featuredefn, param.geom->answer);
+#endif
+        
         if (param.key->answer) {
             const char *fid_column;
             fid_column = OGR_L_GetFIDColumn(Ogr_layer);
@@ -1077,34 +1123,44 @@ int main(int argc, char *argv[])
 	    db_begin_transaction(driver);
 	}
 
-	/* Import feature */
+	/* Import features */
 	cat = 1;
 	nogeom = 0;
-	OGR_L_ResetReading(Ogr_layer);
-	n_features = feature_count = 0;
-
-	n_features = OGR_L_GetFeatureCount(Ogr_layer, 1);
+	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 */
-	    /* Geometry */
-	    Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
-	    if (Ogr_geometry == NULL) {
-		nogeom++;
-	    }
-	    else {
-                if (key_idx > -1)
-                    cat = OGR_F_GetFieldAsInteger(Ogr_feature, key_idx);
-                else if (key_idx == -1)
-                    cat = OGR_F_GetFID(Ogr_feature);
-                
-		geom(Ogr_geometry, Out, layer + 1, cat, min_area, type,
-		     flag.no_clean->answer);
-	    }
 
+            /* Geometry */
+#if GDAL_VERSION_NUM >= 1110000
+            for (i = 0; i < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); i++) {
+                if (igeom > -1 && i != igeom)
+                    continue; /* use only geometry defined via param.geom */
+            
+                Ogr_geometry = OGR_F_GetGeomFieldRef(Ogr_feature, i);
+#else
+                Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
+#endif                
+                if (Ogr_geometry == NULL) {
+                    nogeom++;
+                }
+                else {
+                    if (key_idx > -1)
+                        cat = OGR_F_GetFieldAsInteger(Ogr_feature, key_idx);
+                    else if (key_idx == -1)
+                        cat = OGR_F_GetFID(Ogr_feature);
+                    
+                    geom(Ogr_geometry, Out, layer + 1, cat, min_area, type,
+                         flag.no_clean->answer);
+                }
+#if GDAL_VERSION_NUM >= 1110000              
+            }
+#endif
 	    /* Attributes */
 	    if (!flag.notab->answer) {
 		sprintf(buf, "insert into %s values ( %d", Fi->table, cat);
@@ -1335,6 +1391,14 @@ int main(int argc, char *argv[])
 	    G_message(_("Finding centroids for OGR layer <%s>..."), layer_names[layer]);
 	    layer_id = layers[layer];
 	    Ogr_layer = OGR_DS_GetLayer(Ogr_ds, layer_id);
+            Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
+
+            igeom = -1;
+#if GDAL_VERSION_NUM >= 1110000
+            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);
 
@@ -1344,12 +1408,22 @@ int main(int argc, char *argv[])
 		cat++;
 		G_percent(cat, n_features, 2);
 		/* Geometry */
-		Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
-		if (Ogr_geometry != NULL) {
-		    centroid(Ogr_geometry, Centr, &si, layer + 1, cat,
-			     min_area, type);
-		}
-
+#if GDAL_VERSION_NUM >= 1110000
+                for (i = 0; i < OGR_FD_GetGeomFieldCount(Ogr_featuredefn); i++) {
+                    if (igeom > -1 && i != igeom)
+                        continue; /* use only geometry defined via param.geom */
+            
+                    Ogr_geometry = OGR_F_GetGeomFieldRef(Ogr_feature, i);
+#else
+                    Ogr_geometry = OGR_F_GetGeometryRef(Ogr_feature);
+#endif
+                    if (Ogr_geometry != NULL) {
+                        centroid(Ogr_geometry, Centr, &si, layer + 1, cat,
+                                 min_area, type);
+                    }
+#if GDAL_VERSION_NUM >= 1110000
+                }
+#endif
 		OGR_F_Destroy(Ogr_feature);
 	    }
 	}

+ 40 - 2
vector/v.in.ogr/v.in.ogr.html

@@ -149,6 +149,13 @@ categories. This column must be integer. If not specified, categories
 numbers are generated starting with 1 and stored in the column named
 &quot;cat&quot;.
 
+<p>
+Starting with GDAL 1.11 the library supports multiple geometry columns
+in OGR. By default <em>v.in.ogr</em> reads all geometry columns from
+given layer. The user can choose desired geometry column
+by <b>geometry</b> option,
+see <a href="#multiple-geometry-columns">example bellow</a>.
+
 <h2>EXAMPLES</h2>
 
 The command imports various vector formats:
@@ -269,6 +276,35 @@ db.select table=river
 </pre></div>
 -->
 
+<h3>Multiple geometry columns</h3>
+
+This example shows how to work with data which contain multiple
+geometry per feature. The number of geometry columns per feature can
+be checked by <em><a href="v.external.html">v.external</a></em>
+together with <b>-t</b> flag.
+                  
+<div class="code"><pre>
+v.external -t input=20141130_ST_UKSH.xml.gz
+...
+Okresy,point,1,DefinicniBod
+Okresy,multipolygon,1,OriginalniHranice
+Okresy,multipolygon,1,GeneralizovaneHranice
+...
+</pre></div>      
+
+In our example layer &quot;Okresy&quot; has three geometry columns:
+&quot;DefinicniBod&quot;, &quot;OriginalniHranice&quot; and
+&quot;GeneralizovanaHranice&quot;. By default <em>v.in.ogr</em> reads data from
+all three geometry columns. The user can specify desired geometry
+column by <b>geometry</b> option, in this case the module will read
+geometry only from the specified geometry column. In the example bellow,
+the output vector map will contain only geometry saved in
+&quot;OriginalniHranice&quot; geometry column.
+
+<div class="code"><pre>
+v.in.ogr input=20141130_ST_UKSH.xml.gz layer=Okresy geometry=OriginalniHranice
+</pre></div>      
+
 <h2>WARNINGS</h2>
 
 If a message like &quot;WARNING: Area size 1.3e-06, area not
@@ -323,11 +359,13 @@ with <em><a href="v.proj.html">v.proj</a></em>.</dd>
 
 <h2>AUTHORS</h2>
 
-Radim Blazek, ITC-irst, Trento, Italy
+Original author: Radim Blazek, ITC-irst, Trento, Italy
 <br>
 Location and spatial extent support by Markus Neteler and Paul Kelly
 <br>
-Markus Metz
+Various improvements by Markus Metz
+<br>
+Multiple geometry columns support by Martin Landa, OSGeoREL, Czech Technical University in Prague, Czech Republic
 
 <p>
 <i>Last changed: $Date$</i>