[postgis-tickets] [SCM] PostGIS branch main updated. 3.1.0rc1-365-g0981555

git at osgeo.org git at osgeo.org
Wed Jul 28 13:23:31 PDT 2021


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, main has been updated
       via  0981555c35abb4a0c6984e302f399cea95ecc64b (commit)
      from  ff9de2c109dccd338ed5678bd334cbfe797cee8f (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 0981555c35abb4a0c6984e302f399cea95ecc64b
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Wed Jul 28 13:20:38 2021 -0700

    Replace home-grown axis swapping code with the proj_normalize_for_visualization()
    function from proj. This moves responsibility for maintaining "gis friendly"
    coordinates, with eastings in X and northings in Y (longitude first, latitude second)
    to proj, for proj versions 6.1 and greater. This means that proj 6.0 is
    demoted to using the old proj4 proj_api.h header, but otherwise we
    lose a bunch of code to maintain, and there should be no major changes in
    behaviour.

diff --git a/.gitignore b/.gitignore
index 14d4342..4c5328e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+*~
 *.a
 *.la
 .libs
@@ -29,7 +30,6 @@ doc/html/docbook.css
 doc/Makefile
 doc/Makefile.comments
 doc/po/*/*.xml
-doc/po/*/*.po~
 doc/po/*/html
 doc/po/*/xsl
 doc/po/*/*_comments.sql
diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index a48921f..f2a148c 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -35,7 +35,11 @@
 
 #include "../postgis_config.h"
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
+
+/* For Proj 6.0 use of old API */
+#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
+
 #include "proj_api.h"
 typedef struct PJ
 {
@@ -53,16 +57,12 @@ typedef PJ LWPROJ;
  */
 typedef struct LWPROJ
 {
-	PJ* pj;
-        /* CRSs are swapped: Used in transformation calls */
-	uint8_t source_swapped;
-	uint8_t target_swapped;
-        /* Source crs is geographic: Used in geography calls (source srid == dst srid) */
-        uint8_t source_is_latlong;
-
-        /* Source ellipsoid parameters */
-        double source_semi_major_metre;
-        double source_semi_minor_metre;
+    PJ* pj;
+    /* Source crs is geographic: Used in geography calls (source srid == dst srid) */
+    uint8_t source_is_latlong;
+    /* Source ellipsoid parameters */
+    double source_semi_major_metre;
+    double source_semi_minor_metre;
 } LWPROJ;
 #endif
 
@@ -2450,8 +2450,15 @@ int lwgeom_is_simple(const LWGEOM *lwgeom);
  ******************************************************************************/
 
 int lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr);
+/**
+ * Transform (reproject) a geometry in-place.
+ * @param geom the geometry to transform
+ * @param pj the transformation
+ */
+int lwgeom_transform(LWGEOM *geom, LWPROJ* pj);
+int ptarray_transform(POINTARRAY *pa, LWPROJ* pj);
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 /**
  * Get a projection from a string representation
  *
@@ -2459,23 +2466,14 @@ int lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outst
  */
 projPJ projpj_from_string(const char* txt);
 
-#endif
-/**
- * Transform (reproject) a geometry in-place.
- * @param geom the geometry to transform
- * @param pj the input and output
- */
-int lwgeom_transform(LWGEOM *geom, LWPROJ* pj);
-int ptarray_transform(POINTARRAY *pa, LWPROJ* pj);
-
-#if POSTGIS_PROJ_VERSION >= 60
+#else // POSTGIS_PROJ_VERSION >= 61
 
 /**
  * Allocate a new LWPROJ containing the reference to the PROJ's PJ
  * If extra_geography_data is true, it will generate the following values for
  * the source srs: is_latlong (geometric or not) and spheroid values
  */
-LWPROJ *lwproj_from_PJ(PJ *pj, int8_t extra_geography_data);
+LWPROJ *lwproj_from_str(const char* str_in, const char* str_out);
 
 #endif
 
diff --git a/liblwgeom/lwgeom_transform.c b/liblwgeom/lwgeom_transform.c
index 3bc3799..f2bcb84 100644
--- a/liblwgeom/lwgeom_transform.c
+++ b/liblwgeom/lwgeom_transform.c
@@ -46,7 +46,7 @@ to_dec(POINT4D *pt)
 
 /***************************************************************************/
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 
 static int
 point4d_transform(POINT4D *pt, LWPROJ *pj)
@@ -136,66 +136,7 @@ lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr)
 	return rv;
 }
 
-/**
- * Transform given LWGEOM geometry
- * from inpj projection to outpj projection
- */
-int
-lwgeom_transform(LWGEOM *geom, LWPROJ *pj)
-{
-	uint32_t i;
 
-	/* No points to transform in an empty! */
-	if ( lwgeom_is_empty(geom) )
-		return LW_SUCCESS;
-
-	switch(geom->type)
-	{
-		case POINTTYPE:
-		case LINETYPE:
-		case CIRCSTRINGTYPE:
-		case TRIANGLETYPE:
-		{
-			LWLINE *g = (LWLINE*)geom;
-			if ( ! ptarray_transform(g->points, pj) ) return LW_FAILURE;
-			break;
-		}
-		case POLYGONTYPE:
-		{
-			LWPOLY *g = (LWPOLY*)geom;
-			for ( i = 0; i < g->nrings; i++ )
-			{
-				if ( ! ptarray_transform(g->rings[i], pj) ) return LW_FAILURE;
-			}
-			break;
-		}
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-		case COMPOUNDTYPE:
-		case CURVEPOLYTYPE:
-		case MULTICURVETYPE:
-		case MULTISURFACETYPE:
-		case POLYHEDRALSURFACETYPE:
-		case TINTYPE:
-		{
-			LWCOLLECTION *g = (LWCOLLECTION*)geom;
-			for ( i = 0; i < g->ngeoms; i++ )
-			{
-				if ( ! lwgeom_transform(g->geoms[i], pj) ) return LW_FAILURE;
-			}
-			break;
-		}
-		default:
-		{
-			lwerror("lwgeom_transform: Cannot handle type '%s'",
-			          lwtype_name(geom->type));
-			return LW_FAILURE;
-		}
-	}
-	return LW_SUCCESS;
-}
 
 projPJ
 projpj_from_string(const char *str1)
@@ -209,202 +150,94 @@ projpj_from_string(const char *str1)
 
 /***************************************************************************/
 
-#else /* POSTGIS_PROJ_VERION >= 60 */
-
-static PJ *
-proj_cs_get_simplecs(const PJ *pj_crs)
-{
-	PJ *pj_sub = NULL;
-	if (proj_get_type(pj_crs) == PJ_TYPE_COMPOUND_CRS)
-	{
-		/* Sub-CRS[0] is the horizontal component */
-		pj_sub = proj_crs_get_sub_crs(NULL, pj_crs, 0);
-		if (!pj_sub)
-			lwerror("%s: proj_crs_get_sub_crs(0) returned NULL", __func__);
-	}
-	else if (proj_get_type(pj_crs) == PJ_TYPE_BOUND_CRS)
-	{
-		pj_sub = proj_get_source_crs(NULL, pj_crs);
-		if (!pj_sub)
-			lwerror("%s: proj_get_source_crs returned NULL", __func__);
-	}
-	else
-	{
-		/* If this works, we have a CS so we can return */
-		pj_sub = proj_crs_get_coordinate_system(NULL, pj_crs);
-		if (pj_sub)
-			return pj_sub;
-	}
-
-	/* Only sub-components of the Compound or Bound CRS's get here */
-	/* If we failed to get sub-components, or we failed to extract */
-	/* a CS from a generic CRS, then this is another case we don't */
-	/* handle */
-	if (!pj_sub)
-		lwerror("%s: %s", __func__, proj_errno_string(proj_context_errno(NULL)));
-
-	/* If the components are usable, we can extract the CS and return */
-	int pj_type = proj_get_type(pj_sub);
-	if (pj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS || pj_type == PJ_TYPE_PROJECTED_CRS)
-	{
-		PJ *pj_2d = proj_crs_get_coordinate_system(NULL, pj_sub);
-		proj_destroy(pj_sub);
-		return pj_2d;
-	}
-
-	/* If the components are *themselves* Bound/Compound, we can recurse */
-	if (pj_type == PJ_TYPE_COMPOUND_CRS || pj_type == PJ_TYPE_BOUND_CRS)
-		return proj_cs_get_simplecs(pj_sub);
-
-	/* This is a case we don't know how to handle */
-	lwerror("%s: un-handled CRS sub-type: %s", __func__, pj_type);
-	return NULL;
-}
-
-static uint8_t
-proj_crs_is_swapped(const PJ *pj_crs)
-{
-	int axis_count;
-	PJ *pj_cs = proj_cs_get_simplecs(pj_crs);
-	if (!pj_cs)
-		lwerror("%s: proj_cs_get_simplecs returned NULL", __func__);
-
-	axis_count = proj_cs_get_axis_count(NULL, pj_cs);
-	if (axis_count >= 2)
-	{
-		const char *out_name1, *out_abbrev1, *out_direction1;
-		const char *out_name2, *out_abbrev2, *out_direction2;
-		/* Read first axis */
-		proj_cs_get_axis_info(NULL,
-			pj_cs, 0,
-			&out_name1, &out_abbrev1, &out_direction1,
-			NULL, NULL, NULL, NULL);
-		/* Read second axis */
-		proj_cs_get_axis_info(NULL,
-			pj_cs, 1,
-			&out_name2, &out_abbrev2, &out_direction2,
-			NULL, NULL, NULL, NULL);
-
-		proj_destroy(pj_cs);
-
-		/* Directions agree, this is a northing/easting CRS, so reverse it */
-		if(out_direction1 && STR_IEQUALS(out_direction1, "north") &&
-		   out_direction2 && STR_IEQUALS(out_direction2, "east") )
-		{
-			return LW_TRUE;
-		}
-
-		/* Oddball case? Both axes north / both axes south, swap */
-		if(out_direction1 && out_direction2 &&
-		   ((STR_IEQUALS(out_direction1, "north") && STR_IEQUALS(out_direction2, "north")) ||
-		    (STR_IEQUALS(out_direction1, "south") && STR_IEQUALS(out_direction2, "south"))) &&
-		   out_name1 && STR_ISTARTS(out_name1, "northing")  &&
-		   out_name2 && STR_ISTARTS(out_name2, "easting"))
-		{
-			return LW_TRUE;
-		}
-
-		/* Any lat/lon system with Lat in first axis gets swapped */
-		if (STR_ISTARTS(out_abbrev1, "Lat"))
-			return LW_TRUE;
-
-		return LW_FALSE;
-	}
-
-	/* Failed the axis count test, leave quietly */
-	proj_destroy(pj_cs);
-	return LW_FALSE;
-}
+#else /* POSTGIS_PROJ_VERION >= 61 */
 
 LWPROJ *
-lwproj_from_PJ(PJ *pj, int8_t extra_geography_data)
+lwproj_from_str(const char* str_in, const char* str_out)
 {
-	PJ *pj_source_crs = proj_get_source_crs(NULL, pj);
 	uint8_t source_is_latlong = LW_FALSE;
-	double out_semi_major_metre = DBL_MAX, out_semi_minor_metre = DBL_MAX;
+	double semi_major_metre = DBL_MAX, semi_minor_metre = DBL_MAX;
 
-	if (!pj_source_crs)
-	{
-		lwerror("%s: unable to access source crs", __func__);
+	/* Usable inputs? */
+	if (! (str_in && str_out))
 		return NULL;
-	}
-	uint8_t source_swapped = proj_crs_is_swapped(pj_source_crs);
 
-	/* We only care about the extra values if there is no transformation */
-	if (!extra_geography_data)
-	{
-		proj_destroy(pj_source_crs);
-	}
-	else
+	PJ* pj = proj_create_crs_to_crs(PJ_DEFAULT_CTX, str_in, str_out, NULL);
+	if (!pj)
+		return NULL;
+
+	/* Fill in geodetic parameter information when a null-transform */
+	/* is passed, because that's how we signal we want to store */
+	/* that info in the cache */
+	if (strcmp(str_in, str_out) == 0)
 	{
+		PJ *pj_source_crs = proj_get_source_crs(PJ_DEFAULT_CTX, pj);
 		PJ *pj_ellps;
-		double out_inv_flattening;
-		int out_is_semi_minor_computed;
-
 		PJ_TYPE pj_type = proj_get_type(pj_source_crs);
 		if (pj_type == PJ_TYPE_UNKNOWN)
 		{
-			proj_destroy(pj_source_crs);
+			proj_destroy(pj);
 			lwerror("%s: unable to access source crs type", __func__);
 			return NULL;
 		}
 		source_is_latlong = (pj_type == PJ_TYPE_GEOGRAPHIC_2D_CRS) || (pj_type == PJ_TYPE_GEOGRAPHIC_3D_CRS);
 
-		pj_ellps = proj_get_ellipsoid(NULL, pj_source_crs);
+		pj_ellps = proj_get_ellipsoid(PJ_DEFAULT_CTX, pj_source_crs);
 		proj_destroy(pj_source_crs);
 		if (!pj_ellps)
 		{
+			proj_destroy(pj);
 			lwerror("%s: unable to access source crs ellipsoid", __func__);
 			return NULL;
 		}
-		if (!proj_ellipsoid_get_parameters(NULL,
+		if (!proj_ellipsoid_get_parameters(PJ_DEFAULT_CTX,
 						   pj_ellps,
-						   &out_semi_major_metre,
-						   &out_semi_minor_metre,
-						   &out_is_semi_minor_computed,
-						   &out_inv_flattening))
+						   &semi_major_metre,
+						   &semi_minor_metre,
+						   NULL,
+						   NULL))
 		{
 			proj_destroy(pj_ellps);
+			proj_destroy(pj);
 			lwerror("%s: unable to access source crs ellipsoid parameters", __func__);
 			return NULL;
 		}
 		proj_destroy(pj_ellps);
 	}
 
-	PJ *pj_target_crs = proj_get_target_crs(NULL, pj);
-	if (!pj_target_crs)
-	{
-		lwerror("%s: unable to access target crs", __func__);
-		return NULL;
-	}
-	uint8_t target_swapped = proj_crs_is_swapped(pj_target_crs);
-	proj_destroy(pj_target_crs);
+	/* Add in an axis swap if necessary */
+	PJ* pj_norm = proj_normalize_for_visualization(PJ_DEFAULT_CTX, pj);
+	/* Swap failed for some reason? Fall back to coordinate operation */
+	if (!pj_norm)
+		pj_norm = pj;
+	/* Swap is not a copy of input? Clean up input */
+	else if (pj != pj_norm)
+		proj_destroy(pj);
 
+	/* Allocate and populate return value */
 	LWPROJ *lp = lwalloc(sizeof(LWPROJ));
-	lp->pj = pj;
-	lp->source_swapped = source_swapped;
-	lp->target_swapped = target_swapped;
+	lp->pj = pj_norm; /* Caller is going to have to explicitly proj_destroy this */
+	lp->source_is_latlong = LW_FALSE;
 	lp->source_is_latlong = source_is_latlong;
-	lp->source_semi_major_metre = out_semi_major_metre;
-	lp->source_semi_minor_metre = out_semi_minor_metre;
-
+	lp->source_semi_major_metre = semi_major_metre;
+	lp->source_semi_minor_metre = semi_minor_metre;
 	return lp;
 }
 
 int
 lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr)
 {
-	PJ *pj = proj_create_crs_to_crs(NULL, instr, outstr, NULL);
-	if (!pj)
+	LWPROJ *lp = lwproj_from_str(instr, outstr);
+	if (!lp)
 	{
-		PJ *pj_in = proj_create(NULL, instr);
+		PJ *pj_in = proj_create(PJ_DEFAULT_CTX, instr);
 		if (!pj_in)
 		{
 			lwerror("could not parse proj string '%s'", instr);
 		}
 		proj_destroy(pj_in);
 
-		PJ *pj_out = proj_create(NULL, outstr);
+		PJ *pj_out = proj_create(PJ_DEFAULT_CTX, outstr);
 		if (!pj_out)
 		{
 			lwerror("could not parse proj string '%s'", outstr);
@@ -413,78 +246,12 @@ lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr)
 		lwerror("%s: Failed to transform", __func__);
 		return LW_FAILURE;
 	}
-
-	LWPROJ *lp = lwproj_from_PJ(pj, LW_FALSE);
-
 	int ret = lwgeom_transform(geom, lp);
-
-	proj_destroy(pj);
-	lwfree(lp);
-
+	proj_destroy(lp->pj);
 	return ret;
 }
 
 int
-lwgeom_transform(LWGEOM *geom, LWPROJ *pj)
-{
-	uint32_t i;
-
-	/* No points to transform in an empty! */
-	if (lwgeom_is_empty(geom))
-		return LW_SUCCESS;
-
-	switch(geom->type)
-	{
-		case POINTTYPE:
-		case LINETYPE:
-		case CIRCSTRINGTYPE:
-		case TRIANGLETYPE:
-		{
-			LWLINE *g = (LWLINE*)geom;
-			if (!ptarray_transform(g->points, pj))
-				return LW_FAILURE;
-			break;
-		}
-		case POLYGONTYPE:
-		{
-			LWPOLY *g = (LWPOLY*)geom;
-			for (i = 0; i < g->nrings; i++)
-			{
-				if (!ptarray_transform(g->rings[i], pj))
-					return LW_FAILURE;
-			}
-			break;
-		}
-		case MULTIPOINTTYPE:
-		case MULTILINETYPE:
-		case MULTIPOLYGONTYPE:
-		case COLLECTIONTYPE:
-		case COMPOUNDTYPE:
-		case CURVEPOLYTYPE:
-		case MULTICURVETYPE:
-		case MULTISURFACETYPE:
-		case POLYHEDRALSURFACETYPE:
-		case TINTYPE:
-		{
-			LWCOLLECTION *g = (LWCOLLECTION*)geom;
-			for (i = 0; i < g->ngeoms; i++)
-			{
-				if (!lwgeom_transform(g->geoms[i], pj))
-					return LW_FAILURE;
-			}
-			break;
-		}
-		default:
-		{
-			lwerror("lwgeom_transform: Cannot handle type '%s'",
-			          lwtype_name(geom->type));
-			return LW_FAILURE;
-		}
-	}
-	return LW_SUCCESS;
-}
-
-int
 ptarray_transform(POINTARRAY *pa, LWPROJ *pj)
 {
 	uint32_t i;
@@ -505,9 +272,6 @@ ptarray_transform(POINTARRAY *pa, LWPROJ *pj)
 		}
 	}
 
-	if (pj->source_swapped)
-		ptarray_swap_ordinates(pa, LWORD_X, LWORD_Y);
-
 	if (n_points == 1)
 	{
 		/* For single points it's faster to call proj_trans */
@@ -567,9 +331,6 @@ ptarray_transform(POINTARRAY *pa, LWPROJ *pj)
 		}
 	}
 
-	if (pj->target_swapped)
-		ptarray_swap_ordinates(pa, LWORD_X, LWORD_Y);
-
 	/* Convert radians to degrees if necessary */
 	if (proj_angular_output(pj->pj, PJ_FWD))
 	{
@@ -584,3 +345,64 @@ ptarray_transform(POINTARRAY *pa, LWPROJ *pj)
 }
 
 #endif
+
+/**
+ * Transform given LWGEOM geometry
+ * from inpj projection to outpj projection
+ */
+int
+lwgeom_transform(LWGEOM *geom, LWPROJ *pj)
+{
+	uint32_t i;
+
+	/* No points to transform in an empty! */
+	if ( lwgeom_is_empty(geom) )
+		return LW_SUCCESS;
+
+	switch(geom->type)
+	{
+		case POINTTYPE:
+		case LINETYPE:
+		case CIRCSTRINGTYPE:
+		case TRIANGLETYPE:
+		{
+			LWLINE *g = (LWLINE*)geom;
+			if ( ! ptarray_transform(g->points, pj) ) return LW_FAILURE;
+			break;
+		}
+		case POLYGONTYPE:
+		{
+			LWPOLY *g = (LWPOLY*)geom;
+			for ( i = 0; i < g->nrings; i++ )
+			{
+				if ( ! ptarray_transform(g->rings[i], pj) ) return LW_FAILURE;
+			}
+			break;
+		}
+		case MULTIPOINTTYPE:
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case COLLECTIONTYPE:
+		case COMPOUNDTYPE:
+		case CURVEPOLYTYPE:
+		case MULTICURVETYPE:
+		case MULTISURFACETYPE:
+		case POLYHEDRALSURFACETYPE:
+		case TINTYPE:
+		{
+			LWCOLLECTION *g = (LWCOLLECTION*)geom;
+			for ( i = 0; i < g->ngeoms; i++ )
+			{
+				if ( ! lwgeom_transform(g->geoms[i], pj) ) return LW_FAILURE;
+			}
+			break;
+		}
+		default:
+		{
+			lwerror("lwgeom_transform: Cannot handle type '%s'",
+			          lwtype_name(geom->type));
+			return LW_FAILURE;
+		}
+	}
+	return LW_SUCCESS;
+}
diff --git a/libpgcommon/lwgeom_transform.c b/libpgcommon/lwgeom_transform.c
index 23f20da..8fff336 100644
--- a/libpgcommon/lwgeom_transform.c
+++ b/libpgcommon/lwgeom_transform.c
@@ -67,8 +67,8 @@ static void
 PROJSRSDestroyPJ(void *projection)
 {
 	LWPROJ *pj = (LWPROJ *)projection;
-#if POSTGIS_PROJ_VERSION < 60
-/* Ape the Proj 6+ API for versions < 6 */
+#if POSTGIS_PROJ_VERSION < 61
+/* Ape the Proj 6+ API for versions < 6.1 */
 	if (pj->pj_from)
 	{
 		pj_free(pj->pj_from);
@@ -359,7 +359,7 @@ pjstrs_pfree(PjStrs *strs)
 		pfree(strs->srtext);
 }
 
-#if POSTGIS_PROJ_VERSION >= 60
+#if POSTGIS_PROJ_VERSION >= 61
 static char*
 pgstrs_get_entry(const PjStrs *strs, int n)
 {
@@ -377,7 +377,7 @@ pgstrs_get_entry(const PjStrs *strs, int n)
 }
 #endif
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 /*
 * Utility function for GML reader that still
 * needs proj4text access
@@ -421,7 +421,7 @@ AddToPROJSRSCache(PROJSRSCache *PROJCache, int32_t srid_from, int32_t srid_to)
 
 	oldContext = MemoryContextSwitchTo(PROJCache->PROJSRSCacheContext);
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 	PJ *projection = palloc(sizeof(PJ));
 	pj_from_str = from_strs.proj4text;
 	pj_to_str = to_strs.proj4text;
@@ -438,7 +438,8 @@ AddToPROJSRSCache(PROJSRSCache *PROJCache, int32_t srid_from, int32_t srid_to)
 		    "could not form projection from 'srid=%d' to 'srid=%d'",
 		    srid_from, srid_to);
 #else
-	PJ *projpj = NULL;
+
+	LWPROJ *projection = NULL;
 	/* Try combinations of ESPG/SRTEXT/PROJ4TEXT until we find */
 	/* one that gives us a usable transform. Note that we prefer */
 	/* EPSG numbers over SRTEXT and SRTEXT over PROJ4TEXT */
@@ -450,16 +451,11 @@ AddToPROJSRSCache(PROJSRSCache *PROJCache, int32_t srid_from, int32_t srid_to)
 		pj_to_str   = pgstrs_get_entry(&to_strs,   i % 3);
 		if (!(pj_from_str && pj_to_str))
 			continue;
-		projpj = proj_create_crs_to_crs(NULL, pj_from_str, pj_to_str, NULL);
-		if (projpj && !proj_errno(projpj))
+
+		projection = lwproj_from_str(pj_from_str, pj_to_str);
+		if (projection)
 			break;
 	}
-	if (!projpj)
-	{
-		elog(ERROR, "could not form projection (PJ) from 'srid=%d' to 'srid=%d'", srid_from, srid_to);
-		return NULL;
-	}
-	LWPROJ *projection = lwproj_from_PJ(projpj, srid_from == srid_to);
 	if (!projection)
 	{
 		elog(ERROR, "could not form projection (LWPROJ) from 'srid=%d' to 'srid=%d'", srid_from, srid_to);
@@ -557,7 +553,7 @@ GetLWPROJ(int32_t srid_from, int32_t srid_to, LWPROJ **pj)
 static int
 proj_pj_is_latlong(const LWPROJ *pj)
 {
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 	return pj_is_latlong(pj->pj_from);
 #else
 	return pj->source_is_latlong;
@@ -611,14 +607,14 @@ int
 spheroid_init_from_srid(int32_t srid, SPHEROID *s)
 {
 	LWPROJ *pj;
-#if POSTGIS_PROJ_VERSION >= 48 && POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION >= 48 && POSTGIS_PROJ_VERSION < 61
 	double major_axis, minor_axis, eccentricity_squared;
 #endif
 
 	if ( GetLWPROJ(srid, srid, &pj) == LW_FAILURE)
 		return LW_FAILURE;
 
-#if POSTGIS_PROJ_VERSION >= 60
+#if POSTGIS_PROJ_VERSION >= 61
 	if (!pj->source_is_latlong)
 		return LW_FAILURE;
 	spheroid_init(s, pj->source_semi_major_metre, pj->source_semi_minor_metre);
diff --git a/libpgcommon/lwgeom_transform.h b/libpgcommon/lwgeom_transform.h
index f2a65e5..db58c64 100644
--- a/libpgcommon/lwgeom_transform.h
+++ b/libpgcommon/lwgeom_transform.h
@@ -56,7 +56,7 @@ typedef struct srs_precision
 	int precision_m;
 } srs_precision;
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 /* Needs to call postgis_initialize_cache first */
 char *GetProj4String(int32_t srid);
 #endif
diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c
index 664ed93..8b3238e 100644
--- a/postgis/lwgeom_in_gml.c
+++ b/postgis/lwgeom_in_gml.c
@@ -112,7 +112,7 @@ Datum geom_from_gml(PG_FUNCTION_ARGS)
 	/* Zero for undefined */
 	root_srid = PG_GETARG_INT32(1);
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 	/* Internally lwgeom_from_gml calls gml_reproject_pa which, for PROJ before 6, called GetProj4String.
 	 * That function requires access to spatial_ref_sys, so in order to have it ready we need to ensure
 	 * the internal cache is initialized
@@ -303,12 +303,12 @@ static xmlNodePtr get_xlink_node(xmlNodePtr xnode)
  * Use Proj to reproject a given POINTARRAY
  */
 
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 
 static POINTARRAY *
 gml_reproject_pa(POINTARRAY *pa, int32_t srid_in, int32_t srid_out)
 {
-	PJ pj;
+	LWPROJ pj;
 	char *text_in, *text_out;
 
 	if (srid_in == SRID_UNKNOWN) return pa; /* nothing to do */
@@ -333,16 +333,12 @@ gml_reproject_pa(POINTARRAY *pa, int32_t srid_in, int32_t srid_out)
 
 	return pa;
 }
-#else
-/*
- * TODO: rework GML projection handling to skip the spatial_ref_sys
- * lookups, and use the Proj 6+ EPSG catalogue and built-in SRID
- * lookups directly. Drop this ugly hack.
- */
+
+#else /* POSTGIS_PROJ_VERSION >= 61 */
+
 static POINTARRAY *
 gml_reproject_pa(POINTARRAY *pa, int32_t epsg_in, int32_t epsg_out)
 {
-	PJ *pj;
 	LWPROJ *lwp;
 	char text_in[16];
 	char text_out[16];
@@ -358,27 +354,26 @@ gml_reproject_pa(POINTARRAY *pa, int32_t epsg_in, int32_t epsg_out)
 
 	snprintf(text_in, 16, "EPSG:%d", epsg_in);
 	snprintf(text_out, 16, "EPSG:%d", epsg_out);
-	pj = proj_create_crs_to_crs(NULL, text_in, text_out, NULL);
 
-	lwp = lwproj_from_PJ(pj, LW_FALSE);
+
+	lwp = lwproj_from_str(text_in, text_out);
 	if (!lwp)
 	{
-		proj_destroy(pj);
 		gml_lwpgerror("Could not create LWPROJ*", 57);
 		return NULL;
 	}
 
 	if (ptarray_transform(pa, lwp) == LW_FAILURE)
 	{
-		proj_destroy(pj);
 		elog(ERROR, "gml_reproject_pa: reprojection failed");
 		return NULL;
 	}
-	proj_destroy(pj);
+	proj_destroy(lwp->pj);
 	pfree(lwp);
 
 	return pa;
 }
+
 #endif /* POSTGIS_PROJ_VERSION */
 
 
diff --git a/postgis/lwgeom_transform.c b/postgis/lwgeom_transform.c
index fbd3d89..80f7b25 100644
--- a/postgis/lwgeom_transform.c
+++ b/postgis/lwgeom_transform.c
@@ -152,7 +152,7 @@ Datum transform_geom(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(postgis_proj_version);
 Datum postgis_proj_version(PG_FUNCTION_ARGS)
 {
-#if POSTGIS_PROJ_VERSION < 60
+#if POSTGIS_PROJ_VERSION < 61
 	const char *ver = pj_get_release();
 	text *result = cstring_to_text(ver);
 #else

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

Summary of changes:
 .gitignore                     |   2 +-
 liblwgeom/liblwgeom.h.in       |  44 +++--
 liblwgeom/lwgeom_transform.c   | 384 +++++++++++------------------------------
 libpgcommon/lwgeom_transform.c |  30 ++--
 libpgcommon/lwgeom_transform.h |   2 +-
 postgis/lwgeom_in_gml.c        |  25 ++-
 postgis/lwgeom_transform.c     |   2 +-
 7 files changed, 150 insertions(+), 339 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list