[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha3-18-g4cc9d7a

git at osgeo.org git at osgeo.org
Sun Nov 29 17:32:48 PST 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  4cc9d7adb122726047646648bd75e2972cd6c7b4 (commit)
       via  1d03bb67e1ce84c65b14c62eaa239d88f0dff86b (commit)
       via  dad434d9795682a3751c801cfc46b748d76ad385 (commit)
      from  ed1de589b145cf1b02f68c2a04b6d211f0c62889 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 4cc9d7adb122726047646648bd75e2972cd6c7b4
Merge: ed1de58 1d03bb6
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Sun Nov 29 17:32:40 2020 -0800

    Merge branch 'rouault-fix_ST_GeomFromGML'


commit 1d03bb67e1ce84c65b14c62eaa239d88f0dff86b
Merge: ed1de58 dad434d
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Sun Nov 29 17:28:10 2020 -0800

    Merge branch 'fix_ST_GeomFromGML' of https://github.com/rouault/postgis into rouault-fix_ST_GeomFromGML


commit dad434d9795682a3751c801cfc46b748d76ad385
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Fri Nov 27 19:07:11 2020 +0100

    ST_GeomFromGML(): fix axis order issue with urn:ogc:def:crs:EPSG:: syntax on projected CRS with northing,easting axis order
    
    It was assumed that coordinate swapping was only necessary on geographic CRS
    when srsName='urn:ogc:def:crs:EPSG::XXXX', but there are projected CRS such
    as EPSG:2393 that have a northing,easting axis order too.
    
    This is very similar to a TinyOWS fix I just did in
    https://github.com/MapServer/tinyows/pull/94

diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c
index f5028c6..eeb4356 100644
--- a/postgis/lwgeom_in_gml.c
+++ b/postgis/lwgeom_in_gml.c
@@ -384,25 +384,25 @@ gml_reproject_pa(POINTARRAY *pa, int32_t epsg_in, int32_t epsg_out)
 
 
 /**
- * Return 1 if given srid is planar (0 otherwise, i.e geocentric srid)
- * Return -1 if srid is not in spatial_ref_sys
+ * Return 1 if the SRS definition from the authority has a GIS friendly order,
+ * that is easting,northing. This is typically true for most projected CRS
+ * (but not all!), and this is false for EPSG geographic CRS.
  */
 static int
-gml_is_srid_planar(int32_t srid)
+gml_is_srs_axis_order_gis_friendly(int32_t srid)
 {
-	char *result;
+	char *srtext;
 	char query[256];
-	int is_planar, err;
+	int is_axis_order_gis_friendly, err;
 
 	if (SPI_OK_CONNECT != SPI_connect ())
-		lwpgerror("gml_is_srid_planar: could not connect to SPI manager");
+		lwpgerror("gml_is_srs_axis_order_gis_friendly: could not connect to SPI manager");
 
-	/* A way to find if this projection is planar or geocentric */
-	sprintf(query, "SELECT position('+units=m ' in proj4text) \
+	sprintf(query, "SELECT srtext \
                         FROM spatial_ref_sys WHERE srid='%d'", srid);
 
 	err = SPI_exec(query, 1);
-	if (err < 0) lwpgerror("gml_is_srid_planar: error executing query %d", err);
+	if (err < 0) lwpgerror("gml_is_srs_axis_order_gis_friendly: error executing query %d", err);
 
 	/* No entry in spatial_ref_sys */
 	if (SPI_processed <= 0)
@@ -411,11 +411,49 @@ gml_is_srid_planar(int32_t srid)
 		return -1;
 	}
 
-	result = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
-	is_planar = atoi(result);
+	srtext = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1);
+
+	is_axis_order_gis_friendly = 1;
+	if (srtext && srtext[0] != '\0')
+	{
+		char* ptr;
+		char* srtext_horizontal = (char*) malloc(strlen(srtext) + 1);
+		strcpy(srtext_horizontal, srtext);
+
+		/* Remove the VERT_CS part if we are in a COMPD_CS */
+		ptr = strstr(srtext_horizontal, ",VERT_CS[");
+		if (ptr)
+			*ptr = '\0';
+
+		if( strstr(srtext_horizontal, "AXIS[") == NULL &&
+		    strstr(srtext_horizontal, "GEOCCS[") == NULL )
+		{
+			/* If there is no axis definition, then due to how GDAL < 3
+			* generated the WKT, this means that the axis order is not
+			* GIS friendly */
+			is_axis_order_gis_friendly = 0;
+		}
+		else if( strstr(srtext_horizontal,
+		           "AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST]") != NULL )
+		{
+			is_axis_order_gis_friendly = 0;
+		}
+		else if( strstr(srtext_horizontal,
+		           "AXIS[\"Northing\",NORTH],AXIS[\"Easting\",EAST]") != NULL )
+		{
+			is_axis_order_gis_friendly = 0;
+		}
+		else if( strstr(srtext_horizontal,
+		           "AXIS[\"geodetic latitude (Lat)\",north,ORDER[1]") != NULL )
+		{
+			is_axis_order_gis_friendly = 0;
+		}
+
+		free(srtext_horizontal);
+	}
 	SPI_finish();
 
-	return is_planar;
+	return is_axis_order_gis_friendly;
 }
 
 
@@ -425,10 +463,10 @@ gml_is_srid_planar(int32_t srid)
 static void parse_gml_srs(xmlNodePtr xnode, gmlSrs *srs)
 {
 	char *p;
-	int is_planar;
+	int is_axis_order_gis_friendly;
 	xmlNodePtr node;
 	xmlChar *srsname;
-	bool latlon = false;
+	bool honours_authority_axis_order = false;
 	char sep = ':';
 
 	node = xnode;
@@ -466,20 +504,20 @@ static void parse_gml_srs(xmlNodePtr xnode, gmlSrs *srs)
 		if (!strncmp((char *) srsname, "EPSG:", 5))
 		{
 			sep = ':';
-			latlon = false;
+			honours_authority_axis_order = false;
 		}
 		else if (!strncmp((char *) srsname, "urn:ogc:def:crs:EPSG:", 21)
 		         || !strncmp((char *) srsname, "urn:x-ogc:def:crs:EPSG:", 23)
 		         || !strncmp((char *) srsname, "urn:EPSG:geographicCRS:", 23))
 		{
 			sep = ':';
-			latlon = true;
+			honours_authority_axis_order = true;
 		}
 		else if (!strncmp((char *) srsname,
 		                  "http://www.opengis.net/gml/srs/epsg.xml#", 40))
 		{
 			sep = '#';
-			latlon = false;
+			honours_authority_axis_order = false;
 		}
 		else gml_lwpgerror("unknown spatial reference system", 4);
 
@@ -491,12 +529,14 @@ static void parse_gml_srs(xmlNodePtr xnode, gmlSrs *srs)
 		srs->srid = atoi(++p);
 
 		/* Check into spatial_ref_sys that this SRID really exist */
-		is_planar = gml_is_srid_planar(srs->srid);
-		if (srs->srid == SRID_UNKNOWN || is_planar == -1)
+		is_axis_order_gis_friendly = gml_is_srs_axis_order_gis_friendly(srs->srid);
+		if (srs->srid == SRID_UNKNOWN || is_axis_order_gis_friendly == -1)
 			gml_lwpgerror("unknown spatial reference system", 6);
 
-		/* About lat/lon issue, Cf: http://tinyurl.com/yjpr55z */
-		srs->reverse_axis = !is_planar && latlon;
+		/* Reverse axis order if the srsName is meant to honour the axis
+		   order defined by the authority and if that axis order is not
+		   the GIS friendly one. */
+		srs->reverse_axis = !is_axis_order_gis_friendly && honours_authority_axis_order;
 
 		xmlFree(srsname);
 		return;
diff --git a/regress/core/in_gml.sql b/regress/core/in_gml.sql
index 3b0dec6..0c6867c 100644
--- a/regress/core/in_gml.sql
+++ b/regress/core/in_gml.sql
@@ -636,6 +636,30 @@ SELECT 'srs_16', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="EPSG:-1"><gml:pos
 -- Reverse axis with all kind of simples geometry types
 SELECT 'srs_17', ST_AsEWKT(ST_GeomFromGML('<gml:MultiGeometry srsName="urn:ogc:def:crs:EPSG::4326"><gml:geometryMember><gml:Point><gml:pos srsDimension="2">1 2</gml:pos></gml:Point></gml:geometryMember><gml:geometryMember><gml:LineString><gml:posList srsDimension="2">3 4 5 6</gml:posList></gml:LineString></gml:geometryMember><gml:geometryMember><gml:Curve><gml:segments><gml:LineStringSegment><gml:posList srsDimension="2">7 8 9 10</gml:posList></gml:LineStringSegment></gml:segments></gml:Curve></gml:geometryMember><gml:geometryMember><gml:Polygon><gml:exterior><gml:LinearRing><gml:posList srsDimension="2">11 12 13 14 15 16 11 12</gml:posList></gml:LinearRing></gml:exterior><gml:interior><gml:LinearRing><gml:posList srsDimension="2">17 18 19 20 21 22 17 18</gml:posList></gml:LinearRing></gml:interior></gml:Polygon></gml:geometryMember><gml:geometryMember><gml:Surface><gml:patches><gml:PolygonPatch><gml:exterior><gml:LinearRing><gml:posList srsDimension="2">23 24 25 26 27 28 23 24</gml
 :posList></gml:LinearRing></gml:exterior><gml:interior><gml:LinearRing><gml:posList srsDimension="2">25 26 27 28 29 30 25 26</gml:posList></gml:LinearRing></gml:interior></gml:PolygonPatch></gml:patches></gml:Surface></gml:geometryMember></gml:MultiGeometry>'));
 
+-- Projected CRS with AXIS["Easting",EAST],AXIS["Northing",NORTH]. No coordinate swapping
+SELECT 'srs_18', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::32631"><gml:pos>500000 0</gml:pos></gml:Point>'));
+
+-- Projected CRS with northing, easting axis order, but with no explicit AXIS (EPSG 2393: KKJ / Finland Uniform Coordinate System). We must swap the coordinates
+SELECT 'srs_19', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::2393"><gml:pos>6000000 3500000</gml:pos></gml:Point>'));
+
+-- Geocentric CRS with explicit geocentric AXIS (WGS 84 geocentric). No coordinate swapping
+SELECT 'srs_20', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::4978"><gml:pos srsDimension="3">1 2 3</gml:pos></gml:Point>'));
+
+-- Geographic 3D CRS with AXIS["geodetic latitude (Lat)",north,ORDER[1],...] (WGS 84 with ellipsoidal height). We must swap coordinates
+SELECT 'srs_21', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::4979"><gml:pos srsDimension="3">49 2 3</gml:pos></gml:Point>'));
+
+-- BoundCRS of a Geographic 2D CRS with AXIS["latitude",north,ORDER[1],...] (EPSG 4985: WGS 72 BE). We must swap coordinates
+SELECT 'srs_22', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::4985"><gml:pos>49 2</gml:pos></gml:Point>'));
+
+-- Projected CRS with empty srtext (EPSG 8857 : WGS 84 / Equal Earth Greenwich). We assume GIS friendly order (which is the case here)
+SELECT 'srs_23', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::8857"><gml:pos>1 2</gml:pos></gml:Point>'));
+
+-- CompoundCRS of a Geographic CRS (EPSG 8360 : ETRS89 + Baltic 1957 height). We must swap coordinates
+SELECT 'srs_24', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::8360"><gml:pos srsDimension="3">49 2 3</gml:pos></gml:Point>'));
+
+-- Projected CRS with AXIS["Northing",NORTH],AXIS["Easting",EAST] in its definition (EPSG 8433 : Macao 1920 / Macao Grid). We must swap coordinates
+SELECT 'srs_25', ST_AsEWKT(ST_GeomFromGML('<gml:Point srsName="urn:ogc:def:crs:EPSG::8433"><gml:pos>2 1</gml:pos></gml:Point>'));
+
 -- Reverse axis with severals multi geometry types
 -- TODO
 
diff --git a/regress/core/in_gml_expected b/regress/core/in_gml_expected
index 9c88d5a..ecf9ae9 100644
--- a/regress/core/in_gml_expected
+++ b/regress/core/in_gml_expected
@@ -215,6 +215,14 @@ ERROR:  unknown spatial reference system
 ERROR:  unknown spatial reference system
 ERROR:  unknown spatial reference system
 srs_17|SRID=4326;GEOMETRYCOLLECTION(POINT(2 1),LINESTRING(4 3,6 5),LINESTRING(8 7,10 9),POLYGON((12 11,14 13,16 15,12 11),(18 17,20 19,22 21,18 17)),POLYGON((24 23,26 25,28 27,24 23),(26 25,28 27,30 29,26 25)))
+srs_18|SRID=32631;POINT(500000 0)
+srs_19|SRID=2393;POINT(3500000 6000000)
+srs_20|SRID=4978;POINT(1 2 3)
+srs_21|SRID=4979;POINT(2 49 3)
+srs_22|SRID=4985;POINT(2 49)
+srs_23|SRID=8857;POINT(1 2)
+srs_24|SRID=8360;POINT(2 49 3)
+srs_25|SRID=8433;POINT(1 2)
 ns_1|POINT(1 2)
 ns_2|POINT(1 2)
 ns_3|POINT(1 2)

-----------------------------------------------------------------------

Summary of changes:
 postgis/lwgeom_in_gml.c      | 82 ++++++++++++++++++++++++++++++++------------
 regress/core/in_gml.sql      | 24 +++++++++++++
 regress/core/in_gml_expected |  8 +++++
 3 files changed, 93 insertions(+), 21 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list