[GRASS-SVN] r71873 - grass/trunk/vector/v.out.ogr

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Nov 29 13:20:50 PST 2017


Author: mmetz
Date: 2017-11-29 13:20:50 -0800 (Wed, 29 Nov 2017)
New Revision: 71873

Modified:
   grass/trunk/vector/v.out.ogr/export_areas.c
   grass/trunk/vector/v.out.ogr/local_proto.h
   grass/trunk/vector/v.out.ogr/main.c
Log:
v.out.ogr: adjust polygon ring orientation to match OGC specs except for known exceptions

Modified: grass/trunk/vector/v.out.ogr/export_areas.c
===================================================================
--- grass/trunk/vector/v.out.ogr/export_areas.c	2017-11-29 20:53:00 UTC (rev 71872)
+++ grass/trunk/vector/v.out.ogr/export_areas.c	2017-11-29 21:20:50 UTC (rev 71873)
@@ -6,20 +6,43 @@
                                OGRFeatureDefnH, OGRLayerH,
                                struct field_info *, dbDriver *, int, int *, 
                                const char **, int, int,
-                               int *, int *);
+                               int *, int *, int);
 static int export_areas_multi(struct Map_info *, int, int, 
                               OGRFeatureDefnH, OGRLayerH,
                               struct field_info *, dbDriver *, int, int *, 
                               const char **, int, int,
-                              int *, int *);
-static OGRGeometryH create_polygon(struct Map_info *, int, struct line_pnts *);
+                              int *, int *, int);
+static OGRGeometryH create_polygon(struct Map_info *, int, struct line_pnts *, int);
 
+/* maybe useful */
+void reverse_points(struct line_pnts *Points)
+{
+    int i, j, nhalf;
+    double tmp;
+    
+    nhalf = Points->n_points / 2;
+    
+    for (i = 0, j = Points->n_points - 1; i < nhalf; i++, j--) {
+	tmp = Points->x[i];
+	Points->x[i] = Points->x[j];
+	Points->x[j] = tmp;
+
+	tmp = Points->y[i];
+	Points->y[i] = Points->y[j];
+	Points->y[j] = tmp;
+
+	tmp = Points->z[i];
+	Points->z[i] = Points->z[j];
+	Points->z[j] = tmp;
+    }
+}
+
 /* export areas as single/multi-polygons */
 int export_areas(struct Map_info *In, int field, int multi, int donocat,
                  OGRFeatureDefnH Ogr_featuredefn,OGRLayerH Ogr_layer,
                  struct field_info *Fi, dbDriver *driver, int ncol, int *colctype,
                  const char **colname, int doatt, int nocat,
-                 int *noatt, int *fout)
+                 int *noatt, int *fout, int outer_ring_ccw)
 {
     if (multi)
         /* export as multi-polygons */
@@ -27,21 +50,21 @@
                                   Ogr_featuredefn, Ogr_layer,
                                   Fi, driver, ncol, colctype, 
                                   colname, doatt, nocat,
-                                  noatt, fout);
+                                  noatt, fout, outer_ring_ccw);
     
     /* export as polygons */
     return export_areas_single(In, field, donocat,
                                Ogr_featuredefn, Ogr_layer,
                                Fi, driver, ncol, colctype, 
                                colname, doatt, nocat,
-                               noatt, fout);
+                               noatt, fout, outer_ring_ccw);
 }
 
 int export_areas_single(struct Map_info *In, int field, int donocat,
                         OGRFeatureDefnH Ogr_featuredefn,OGRLayerH Ogr_layer,
                         struct field_info *Fi, dbDriver *driver, int ncol, int *colctype,
                         const char **colname, int doatt, int nocat,
-                        int *n_noatt, int *n_nocat)
+                        int *n_noatt, int *n_nocat, int outer_ring_ccw)
 {
     int i;
     int cat, area, n_areas;
@@ -76,7 +99,7 @@
         }
 
         /* create polygon from area */
-        Ogr_geometry = create_polygon(In, area, Points);
+        Ogr_geometry = create_polygon(In, area, Points, outer_ring_ccw);
 
         /* add feature */
         Ogr_feature = OGR_F_Create(Ogr_featuredefn);
@@ -116,7 +139,7 @@
                        OGRFeatureDefnH Ogr_featuredefn,OGRLayerH Ogr_layer,
                        struct field_info *Fi, dbDriver *driver, int ncol, int *colctype,
                        const char **colname, int doatt, int nocat,
-                       int *n_noatt, int *n_nocat)
+                       int *n_noatt, int *n_nocat, int outer_ring_ccw)
 {
     int i, n_exported, area;
     int cat, ncats_field, line, type, findex, ipart;
@@ -183,7 +206,7 @@
                 continue;
                 
             /* create polygon from area */
-            Ogr_geometry_part = create_polygon(In, area, Points);
+            Ogr_geometry_part = create_polygon(In, area, Points, outer_ring_ccw);
 
             /* add part */
             OGR_G_AddGeometryDirectly(Ogr_geometry, Ogr_geometry_part);
@@ -230,7 +253,7 @@
         }
 
         /* create polygon from area */
-        Ogr_geometry_part = create_polygon(In, area, Points);
+        Ogr_geometry_part = create_polygon(In, area, Points, outer_ring_ccw);
         
         /* add part */
         OGR_G_AddGeometryDirectly(Ogr_geometry, Ogr_geometry_part);
@@ -268,7 +291,7 @@
 }
 
 OGRGeometryH create_polygon(struct Map_info *In, int area,
-                            struct line_pnts *Points)
+                            struct line_pnts *Points, int outer_ring_ccw)
 {
     int j, k;
     OGRGeometryH Ogr_geometry, ring;
@@ -279,29 +302,58 @@
     ring = OGR_G_CreateGeometry(wkbLinearRing);
     
     /* Area */
-    for (j = 0; j < Points->n_points; j++) {
-        if (Vect_is_3d(In))
-            OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
-                           Points->z[j]);
-	else
-            OGR_G_AddPoint_2D(ring, Points->x[j], Points->y[j]);
+    if (Vect_is_3d(In)) {
+	if (outer_ring_ccw) {
+	    for (j = Points->n_points - 1; j >= 0 ; j--)
+                OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
+                               Points->z[j]);
+	}
+	else {
+	    for (j = 0; j < Points->n_points; j++)
+                OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
+                               Points->z[j]);
+	}
     }
-    
+    else {
+	if (outer_ring_ccw) {
+	    for (j = Points->n_points - 1; j >= 0 ; j--)
+		OGR_G_AddPoint_2D(ring, Points->x[j], Points->y[j]);
+	}
+	else {
+	    for (j = 0; j < Points->n_points; j++)
+		OGR_G_AddPoint_2D(ring, Points->x[j], Points->y[j]);
+	}
+    }
+
     OGR_G_AddGeometryDirectly(Ogr_geometry, ring);
     
     /* Isles */
     for (k = 0; k < Vect_get_area_num_isles(In, area); k++) {
         Vect_get_isle_points(In, Vect_get_area_isle(In, area, k),
                              Points);
-        
         ring = OGR_G_CreateGeometry(wkbLinearRing);
-        for (j = 0; j < Points->n_points; j++) {
-	    if(Vect_is_3d(In))
-                OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
-                               Points->z[j]);
-	    else
-                OGR_G_AddPoint_2D(ring, Points->x[j], Points->y[j]);
-        }
+	if (Vect_is_3d(In)) {
+	    if (outer_ring_ccw) {
+		for (j = Points->n_points - 1; j >= 0 ; j--)
+		    OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
+				   Points->z[j]);
+	    }
+	    else {
+		for (j = 0; j < Points->n_points; j++)
+		    OGR_G_AddPoint(ring, Points->x[j], Points->y[j],
+				   Points->z[j]);
+	    }
+	}
+	else {
+	    if (outer_ring_ccw) {
+		for (j = Points->n_points - 1; j >= 0 ; j--)
+		    OGR_G_AddPoint_2D(ring, Points->x[j], Points->y[j]);
+	    }
+	    else {
+		for (j = 0; j < Points->n_points; j++)
+		    OGR_G_AddPoint_2D(ring, Points->x[j], Points->y[j]);
+	    }
+	}
         OGR_G_AddGeometryDirectly(Ogr_geometry, ring);
     }
 

Modified: grass/trunk/vector/v.out.ogr/local_proto.h
===================================================================
--- grass/trunk/vector/v.out.ogr/local_proto.h	2017-11-29 20:53:00 UTC (rev 71872)
+++ grass/trunk/vector/v.out.ogr/local_proto.h	2017-11-29 21:20:50 UTC (rev 71873)
@@ -73,4 +73,4 @@
                  OGRFeatureDefnH, OGRLayerH,
                  struct field_info *, dbDriver *, int, int *, 
                  const char **, int, int,
-                 int *, int *);
+                 int *, int *, int);

Modified: grass/trunk/vector/v.out.ogr/main.c
===================================================================
--- grass/trunk/vector/v.out.ogr/main.c	2017-11-29 20:53:00 UTC (rev 71872)
+++ grass/trunk/vector/v.out.ogr/main.c	2017-11-29 21:20:50 UTC (rev 71873)
@@ -74,6 +74,7 @@
     char **papszDSCO = NULL, **papszLCO = NULL;
     int num_types;
     char *dsn;
+    int outer_ring_ccw;
     
     G_gisinit(argv[0]);
 
@@ -262,7 +263,6 @@
     if (cellhd.proj != PROJECTION_XY) {
         const char *epsg;
 
-        Ogr_projection = NULL;
         /* try EPSG code first */
         epsg = G_database_epsg_code();
         if (!epsg) {
@@ -772,6 +772,19 @@
 
     if (OGR_L_TestCapability(Ogr_layer, OLCTransactions))
 	OGR_L_StartTransaction(Ogr_layer);
+
+    /* export polygons oriented according to OGC simple features standard 1.2.1
+     * outer rings are oriented counter-clockwise (CCW)
+     * inner rings are oriented clockwise (CW) */
+    outer_ring_ccw = 1;
+    /* some formats expect outer rings to be CW and inner rings to be CCW:
+     * ESRI Shapefile, PGeo, FileGDB, OpenFileGDB (all ESRI) */
+    if (strcmp(options.format->answer, "ESRI Shapefile") == 0 ||
+        strcmp(options.format->answer, "PGeo") == 0 ||
+        strcmp(options.format->answer, "FileGDB") == 0 ||
+        strcmp(options.format->answer, "OpenFileGDB") == 0) {
+	outer_ring_ccw = 0;
+    }
     
     /* Lines (run always to count features of different type) */
     if (otype & (GV_POINTS | GV_LINES | GV_KERNEL | GV_FACE)) {
@@ -799,7 +812,7 @@
                                Ogr_featuredefn, Ogr_layer,
                                Fi, Driver, ncol, colctype, 
                                colname, doatt, flags.nocat->answer ? TRUE : FALSE,
-                               &n_noatt, &n_nocat);
+                               &n_noatt, &n_nocat, outer_ring_ccw);
     }
 
     /*



More information about the grass-commit mailing list