Commit 25ce5fde authored by Paul Ramsey's avatar Paul Ramsey

Support new Proj6 API

Closes #4322


git-svn-id: http://svn.osgeo.org/postgis/trunk@17274 b70326c6-7e19-0410-871a-916f4a2858ee
parent 1f30f436
Pipeline #48821353 passed with stage
in 28 minutes and 48 seconds
......@@ -868,10 +868,13 @@ fi
dnl Check that we can find the proj_api.h header file
CPPFLAGS_SAVE="$CPPFLAGS"
CPPFLAGS="$PROJ_CPPFLAGS"
AC_CHECK_HEADER([proj_api.h], [], [AC_MSG_ERROR([could not find proj_api.h - you may need to specify the directory of a PROJ.4 installation using --with-projdir])],
[
#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1
])
AC_CHECK_HEADER([proj_api.h],
[],
[AC_CHECK_HEADER([proj.h],
[],
[AC_MSG_ERROR([could not find proj.h or proj_api.h - you may need to specify the directory of a PROJ installation using --with-projdir])]
)]
)
dnl Return the PROJ.4 version number
AC_PROJ_VERSION([POSTGIS_PROJ_VERSION])
......@@ -879,11 +882,6 @@ AC_DEFINE_UNQUOTED([POSTGIS_PROJ_VERSION], [$POSTGIS_PROJ_VERSION], [PROJ librar
AC_SUBST([POSTGIS_PROJ_VERSION])
CPPFLAGS="$CPPFLAGS_SAVE"
dnl For PROJ 6 add the ACCEPT_USE_OF_DEPRECATED_PROJ_API_H definition
if test "$POSTGIS_PROJ_VERSION" -ge 60 && test "$POSTGIS_PROJ_VERSION" -lt 70; then
AC_DEFINE([ACCEPT_USE_OF_DEPRECATED_PROJ_API_H], [1], [Define to use the old PROJ API])
fi
dnl Ensure that we are using PROJ >= 4.6.0 (requires pj_set_searchpath)
if test ! "$POSTGIS_PROJ_VERSION" -ge 46; then
AC_MSG_ERROR([PostGIS requires PROJ >= 4.6.0])
......@@ -897,7 +895,7 @@ LIBS_SAVE="$LIBS"
LIBS="$PROJ_LDFLAGS"
AC_CHECK_LIB([proj], [pj_get_release],
[],
[AC_MSG_ERROR([could not find libproj - you may need to specify the directory of a PROJ.4 installation using --with-projdir])],
[AC_MSG_ERROR([could not find libproj - you may need to specify the directory of a PROJ installation using --with-projdir])],
[])
LIBS="$LIBS_SAVE"
......
......@@ -1276,7 +1276,7 @@ static void test_spheroid_distance(void)
{
GEOGRAPHIC_POINT g1, g2;
double d;
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
double epsilon; /* irregular */
#else
const double epsilon = 1e-8; /* at least 10 nm precision */
......@@ -1291,7 +1291,7 @@ static void test_spheroid_distance(void)
point_set(0.0, 0.0, &g1);
point_set(0.0, 1.0, &g2);
d = spheroid_distance(&g1, &g2, &s);
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
epsilon = 1e-6;
#endif
CU_ASSERT_DOUBLE_EQUAL(d, 110574.3885577987957342, epsilon);
......@@ -1301,7 +1301,7 @@ static void test_spheroid_distance(void)
point_set(-10.0, 0.0, &g1);
point_set(0.0, 0.0, &g2);
d = spheroid_distance(&g1, &g2, &s);
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
epsilon = 1e-3;
#endif
CU_ASSERT_DOUBLE_EQUAL(d, 1113194.9079327357264771, epsilon);
......@@ -1311,7 +1311,7 @@ static void test_spheroid_distance(void)
point_set(-1.0, 0.0, &g1);
point_set(0.0, 0.0, &g2);
d = spheroid_distance(&g1, &g2, &s);
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
epsilon = 1e-4;
#endif
CU_ASSERT_DOUBLE_EQUAL(d, 111319.4907932735726477, epsilon);
......@@ -1321,7 +1321,7 @@ static void test_spheroid_distance(void)
point_set(-180.0, 0.0, &g1);
point_set(0.0, 1.0, &g2);
d = spheroid_distance(&g1, &g2, &s);
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
epsilon = 1e-5;
#endif
CU_ASSERT_DOUBLE_EQUAL(d, 19893357.0700676468277450, epsilon);
......@@ -1331,7 +1331,7 @@ static void test_spheroid_distance(void)
point_set(-180.0, 0.0, &g1);
point_set(0.0, 90.0, &g2);
d = spheroid_distance(&g1, &g2, &s);
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
epsilon = 1e-6;
#endif
CU_ASSERT_DOUBLE_EQUAL(d, 10001965.7293127228117396, epsilon);
......@@ -1372,7 +1372,7 @@ static void test_spheroid_area(void)
a1 = lwgeom_area_sphere(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a1, 12341436880.106982993974659, 0.1);
/* spheroid: Planimeter -E -p 20 -r --input-string "3 -2;4 -2;4 -1;3 -1" */
#if PROJ_GEODESIC
#ifdef PROJ_GEODESIC
a2 = lwgeom_area_spheroid(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a2, 12286884908.946891319597874, 0.1);
#endif
......@@ -1385,7 +1385,7 @@ static void test_spheroid_area(void)
a1 = lwgeom_area_sphere(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a1, 12360265021.368023059138681, 0.1);
/* spheroid: Planimeter -E -p 20 --input-string "2 8.5;1 8.5;1 9.5;2 9.5" */
#if PROJ_GEODESIC
#ifdef PROJ_GEODESIC
a2 = lwgeom_area_spheroid(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a2, 12305128751.042900673161556, 0.1);
#endif
......@@ -1398,7 +1398,7 @@ static void test_spheroid_area(void)
a1 = lwgeom_area_sphere(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a1, 12360265021.368023059138681, 0.1);
/* spheroid: Planimeter -E -p 20 -r --input-string "2 179.5;1 179.5;1 178.5;2 178.5" */
#if PROJ_GEODESIC
#ifdef PROJ_GEODESIC
a2 = lwgeom_area_spheroid(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a2, 12305128751.042900673161556, 0.1);
#endif
......@@ -1411,7 +1411,7 @@ static void test_spheroid_area(void)
a1 = lwgeom_area_sphere(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a1, 12360265021.368023059138681, 0.1);
/* spheroid: Planimeter -E -p 20 --input-string "2 179.5;1 179.5;1 -179.5;2 -179.5" */
#if PROJ_GEODESIC
#ifdef PROJ_GEODESIC
a2 = lwgeom_area_spheroid(lwg, &s);
CU_ASSERT_DOUBLE_EQUAL(a2, 12305128751.042900673161556, 0.1);
#endif
......
......@@ -10,6 +10,8 @@
*
**********************************************************************/
#include <stdlib.h>
#include "CUnit/Basic.h"
#include "../lwgeom_log.h"
......
......@@ -390,11 +390,11 @@ GBOX* gbox_from_string(const char *str)
char* gbox_to_string(const GBOX *gbox)
{
static int sz = 138;
const size_t sz = 138;
char *str = NULL;
if ( ! gbox )
return strdup("NULL POINTER");
return lwstrdup("NULL POINTER");
str = (char*)lwalloc(sz);
......
This diff is collapsed.
......@@ -38,13 +38,14 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
#if HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#include <float.h>
#include "liblwgeom.h"
/**
......@@ -348,11 +349,6 @@ char lwtriangle_same(const LWTRIANGLE *p1, const LWTRIANGLE *p2);
char lwcollection_same(const LWCOLLECTION *p1, const LWCOLLECTION *p2);
char lwcircstring_same(const LWCIRCSTRING *p1, const LWCIRCSTRING *p2);
/*
* Transform
*/
int point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj);
/*
* Shift
*/
......@@ -488,5 +484,6 @@ int ptarray_npoints_in_rect(const POINTARRAY *pa, const GBOX *gbox);
int gbox_contains_point2d(const GBOX *g, const POINT2D *p);
int lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt);
POINT4D* lwmpoint_extract_points_4d(const LWMPOINT* g, uint32_t* npoints, int* input_empty);
char* lwstrdup(const char* a);
#endif /* _LIBLWGEOM_INTERNAL_H */
This diff is collapsed.
......@@ -25,6 +25,8 @@
#include <assert.h>
#include <string.h>
#include <math.h>
#include "liblwgeom.h"
#include "../postgis_config.h"
......
......@@ -28,8 +28,8 @@
#include "lwgeodetic.h"
#include "lwgeom_log.h"
/* GeographicLib */
#if PROJ_GEODESIC
/* In proj4.9, GeographicLib is in special header */
#ifdef PROJ_GEODESIC
#include <geodesic.h>
#endif
......@@ -45,7 +45,7 @@ void spheroid_init(SPHEROID *s, double a, double b)
s->radius = (2.0 * a + b ) / 3.0;
}
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
static double spheroid_mu2(double alpha, const SPHEROID *s)
{
double b2 = POW2(s->b);
......@@ -64,7 +64,7 @@ static double spheroid_big_b(double u2)
#endif /* ! PROJ_GEODESIC */
#if PROJ_GEODESIC
#ifdef PROJ_GEODESIC
/**
* Computes the shortest distance along the surface of the spheroid
......@@ -165,7 +165,7 @@ static double ptarray_area_spheroid(const POINTARRAY *pa, const SPHEROID *sphero
return fabs(area);
}
/* Above use GeographicLib */
/* Above use Proj GeographicLib */
#else /* ! PROJ_GEODESIC */
/* Below use pre-version 2.2 geodesic functions */
......
......@@ -26,6 +26,7 @@
#include "liblwgeom.h"
#include "lwunionfind.h"
#include <string.h>
#include <stdlib.h>
static int cmp_int(const void *a, const void *b);
static int cmp_int_ptr(const void *a, const void *b);
......
......@@ -244,6 +244,15 @@ lwfree(void *mem)
lwfree_var(mem);
}
char *
lwstrdup(const char* a)
{
size_t l = strlen(a)+1;
char *b = lwalloc(l);
strncpy(b, a, l);
return b;
}
/*
* Returns a new string which contains a maximum of maxlength characters starting
* from startpos and finishing at endpos (0-based indexing). If the string is
......
......@@ -26,6 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../postgis_config.h"
/*#define POSTGIS_DEBUG_LEVEL 4*/
......@@ -378,8 +379,8 @@ ptarray_swap_ordinates(POINTARRAY *pa, LWORD o1, LWORD o2)
double d, *dp1, *dp2;
POINT4D p;
dp1 = ((double*)&p)+(unsigned)o1;
dp2 = ((double*)&p)+(unsigned)o2;
dp1 = ((double*)&p)+(unsigned)o1;
dp2 = ((double*)&p)+(unsigned)o2;
for (i=0 ; i < pa->npoints ; i++)
{
getPoint4d_p(pa, i, &p);
......
......@@ -77,35 +77,36 @@ GetGenericCacheCollection(FunctionCallInfo fcinfo)
/**
* Get the Proj4 entry from the generic cache if one exists.
* Get the Proj entry from the generic cache if one exists.
* If it doesn't exist, make a new empty one and return it.
*/
PROJ4PortalCache *
GetPROJ4SRSCache(FunctionCallInfo fcinfo)
PROJPortalCache *
GetPROJSRSCache(FunctionCallInfo fcinfo)
{
GenericCacheCollection* generic_cache = GetGenericCacheCollection(fcinfo);
PROJ4PortalCache* cache = (PROJ4PortalCache*)(generic_cache->entry[PROJ_CACHE_ENTRY]);
PROJPortalCache* cache = (PROJPortalCache*)(generic_cache->entry[PROJ_CACHE_ENTRY]);
if ( ! cache )
{
/* Allocate in the upper context */
cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(PROJ4PortalCache));
cache = MemoryContextAlloc(FIContext(fcinfo), sizeof(PROJPortalCache));
if (cache)
{
int i;
POSTGIS_DEBUGF(3, "Allocating PROJ4Cache for portal with transform() MemoryContext %p", FIContext(fcinfo));
POSTGIS_DEBUGF(3, "Allocating PROJCache for portal with transform() MemoryContext %p", FIContext(fcinfo));
/* Put in any required defaults */
for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
for (i = 0; i < PROJ_CACHE_ITEMS; i++)
{
cache->PROJ4SRSCache[i].srid = SRID_UNKNOWN;
cache->PROJ4SRSCache[i].projection = NULL;
cache->PROJ4SRSCache[i].projection_mcxt = NULL;
cache->PROJSRSCache[i].srid_from = SRID_UNKNOWN;
cache->PROJSRSCache[i].srid_to = SRID_UNKNOWN;
cache->PROJSRSCache[i].projection = NULL;
cache->PROJSRSCache[i].projection_mcxt = NULL;
}
cache->type = PROJ_CACHE_ENTRY;
cache->PROJ4SRSCacheCount = 0;
cache->PROJ4SRSCacheContext = FIContext(fcinfo);
cache->PROJSRSCacheCount = 0;
cache->PROJSRSCacheContext = FIContext(fcinfo);
/* Store the pointer in GenericCache */
generic_cache->entry[PROJ_CACHE_ENTRY] = (GenericCache*)cache;
......
......@@ -62,31 +62,32 @@ typedef struct {
* fcinfo->flinfo->fn_extra to avoid collisions.
*/
/* An entry in the PROJ4 SRS cache */
typedef struct struct_PROJ4SRSCacheItem
/* An entry in the PROJ SRS cache */
typedef struct struct_PROJSRSCacheItem
{
int srid;
projPJ projection;
int srid_from;
int srid_to;
PJ* projection;
MemoryContext projection_mcxt;
}
PROJ4SRSCacheItem;
PROJSRSCacheItem;
/* PROJ 4 lookup transaction cache methods */
#define PROJ4_CACHE_ITEMS 8
#define PROJ_CACHE_ITEMS 8
/*
* The proj4 cache holds a fixed number of reprojection
* entries. In normal usage we don't expect it to have
* many entries, so we always linearly scan the list.
*/
typedef struct struct_PROJ4PortalCache
typedef struct struct_PROJPortalCache
{
int type;
PROJ4SRSCacheItem PROJ4SRSCache[PROJ4_CACHE_ITEMS];
int PROJ4SRSCacheCount;
MemoryContext PROJ4SRSCacheContext;
PROJSRSCacheItem PROJSRSCache[PROJ_CACHE_ITEMS];
int PROJSRSCacheCount;
MemoryContext PROJSRSCacheContext;
}
PROJ4PortalCache;
PROJPortalCache;
/**
* Generic signature for functions to manage a geometry
......@@ -103,7 +104,7 @@ typedef struct
/*
* Cache retrieval functions
*/
PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfo fcinfo);
PROJPortalCache *GetPROJSRSCache(FunctionCallInfo fcinfo);
GeomCache *GetGeomCache(FunctionCallInfo fcinfo,
const GeomCacheMethods *cache_methods,
const GSERIALIZED *g1,
......
This diff is collapsed.
......@@ -10,9 +10,10 @@
**********************************************************************/
#include "postgres.h"
#include "liblwgeom.h"
#include "liblwgeom_internal.h"
#include "lwgeom_pg.h"
typedef struct srs_precision
{
int precision_xy;
......@@ -20,23 +21,19 @@ typedef struct srs_precision
int precision_m;
} srs_precision;
char* GetProj4StringSPI(int srid);
void SetPROJ4LibPath(void) ;
char * GetProj4String(int srid);
/**
* Opaque type to use in the projection cache API.
*/
typedef void *Proj4Cache ;
void SetPROJ4LibPath(void);
Proj4Cache GetPROJ4Cache(FunctionCallInfo fcinfo) ;
bool IsInPROJ4Cache(Proj4Cache cache, int srid) ;
void AddToPROJ4Cache(Proj4Cache cache, int srid, int other_srid);
void DeleteFromPROJ4Cache(Proj4Cache cache, int srid) ;
projPJ GetProjectionFromPROJ4Cache(Proj4Cache cache, int srid);
int GetProjectionsUsingFCInfo(FunctionCallInfo fcinfo, int srid1, int srid2, projPJ *pj1, projPJ *pj2);
typedef void *ProjCache ;
void SetPROJLibPath(void);
bool IsInPROJCache(ProjCache cache, int srid_from, int srid_to);
PJ* GetPJFromPROJCache(ProjCache cache, int srid_from, int srid_to);
int GetPJUsingFCInfo(FunctionCallInfo fcinfo, int srid_from, int srid_to, PJ** pj);
int spheroid_init_from_srid(FunctionCallInfo fcinfo, int srid, SPHEROID *s);
void srid_is_latlong(FunctionCallInfo fcinfo, int srid);
void srid_check_latlong(FunctionCallInfo fcinfo, int srid);
srs_precision srid_axis_precision(FunctionCallInfo fcinfo, int srid, int precision);
/**
......
......@@ -14,29 +14,53 @@ dnl Return the PROJ.4 version number
dnl
AC_DEFUN([AC_PROJ_VERSION], [
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([
#ifdef HAVE_STDINT_H
#include <stdio.h>
#endif
#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 1
#include "proj_api.h"
],
[
FILE *fp;
fp = fopen("conftest.out", "w");
fprintf(fp, "%d\n", PJ_VERSION);
fclose(fp)])
],
[
dnl The program ran successfully, so return the version number in the form MAJORMINOR
$1=`cat conftest.out | sed 's/\([[0-9]]\)\([[0-9]]\)\([[0-9]]\)/\1\2/'`
],
[
dnl The program failed so return an empty variable
$1=""
]
)
AC_CHECK_HEADER([proj.h], [
dnl Proj >= 6 include and version string
AC_RUN_IFELSE([
AC_LANG_PROGRAM([
#ifdef HAVE_STDINT_H
#include <stdio.h>
#endif
#include "proj.h"
],[
FILE *fp;
int vernum;
fp = fopen("conftest.out", "w");
vernum = (100 * PROJ_VERSION_MAJOR) + (10 * PROJ_VERSION_MINOR) + PROJ_VERSION_PATCH;
fprintf(fp, "%d\n", vernum);
fclose(fp);
])
],[
dnl The program ran successfully, so return the version number in the form MAJORMINOR
$1=`cat conftest.out | sed 's/\([[0-9]]\)\([[0-9]]\)\([[0-9]]\)/\1\2/'`
],[
dnl The program failed so return an empty variable
$1=""
])
],[
dnl Proj < 6 include and version string
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([
#ifdef HAVE_STDINT_H
#include <stdio.h>
#endif
#include "proj_api.h"
],[
FILE *fp;
fp = fopen("conftest.out", "w");
fprintf(fp, "%d\n", PJ_VERSION);
fclose(fp);
])
],[
dnl The program ran successfully, so return the version number in the form MAJORMINOR
$1=`cat conftest.out | sed 's/\([[0-9]]\)\([[0-9]]\)\([[0-9]]\)/\1\2/'`
],[
dnl The program failed so return an empty variable
$1=""
])
])
])
......@@ -171,7 +171,7 @@ Datum geography_in(PG_FUNCTION_ARGS)
}
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
srid_check_latlong(fcinfo, lwgeom->srid);
/* Convert to gserialized */
g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
......@@ -563,7 +563,7 @@ Datum geography_from_text(PG_FUNCTION_ARGS)
PG_PARSER_ERROR(lwg_parser_result);
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwg_parser_result.geom->srid);
srid_check_latlong(fcinfo, lwg_parser_result.geom->srid);
/* Clean up string */
pfree(wkt);
......@@ -591,7 +591,7 @@ Datum geography_from_binary(PG_FUNCTION_ARGS)
lwpgerror("Unable to parse WKB");
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
srid_check_latlong(fcinfo, lwgeom->srid);
gser = gserialized_geography_from_lwgeom(lwgeom, -1);
lwgeom_free(lwgeom);
......@@ -617,7 +617,7 @@ Datum geography_from_geometry(PG_FUNCTION_ARGS)
}
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
srid_check_latlong(fcinfo, lwgeom->srid);
/* Force the geometry to have valid geodetic coordinate range. */
lwgeom_nudge_geodetic(lwgeom);
......@@ -681,7 +681,7 @@ Datum geography_recv(PG_FUNCTION_ARGS)
lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL);
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
srid_check_latlong(fcinfo, lwgeom->srid);
g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
......
......@@ -39,7 +39,7 @@
#include "geography_measurement_trees.h" /* For circ_tree caching */
#include "lwgeom_transform.h" /* For SRID functions */
#if PROJ_GEODESIC
#ifdef PROJ_GEODESIC
/* round to 10 nm precision */
#define INVMINDIST 1.0e8
#else
......@@ -531,7 +531,7 @@ Datum geography_area(PG_FUNCTION_ARGS)
else
lwgeom_calculate_gbox_geodetic(lwgeom, &gbox);
#if ! PROJ_GEODESIC
#ifndef PROJ_GEODESIC
/* Test for cases that are currently not handled by spheroid code */
if ( use_spheroid )
{
......@@ -542,7 +542,7 @@ Datum geography_area(PG_FUNCTION_ARGS)
if ( gbox.zmax > 0.0 && gbox.zmin < 0.0 )
use_spheroid = LW_FALSE;
}
#endif /* if ! PROJ_GEODESIC */
#endif /* ifndef PROJ_GEODESIC */
/* User requests spherical calculation, turn our spheroid into a sphere */
if ( ! use_spheroid )
......
......@@ -52,6 +52,7 @@
#include <float.h> /* For FLT_MAX */
#include <math.h>
/*
** When is a node split not so good? If more than 90% of the entries
......
......@@ -49,6 +49,7 @@
#include "geography.h"
#include <assert.h>
#include <math.h>
/*
** When is a node split not so good? If more than 90% of the entries
......
......@@ -82,6 +82,7 @@
#include "lwgeom_pg.h" /* For debugging macros. */
#include <gserialized_gist.h> /* For utility functions. */
#include <lwgeom_pg.h> /* For debugging macros. */
#include <math.h>
/*
** SP-GiST 2D index function prototypes
......
......@@ -294,7 +294,7 @@ Datum geography_typmod_in(PG_FUNCTION_ARGS)
int32 typmod = gserialized_typmod_in(arr, LW_TRUE);
int srid = TYPMOD_GET_SRID(typmod);
/* Check the SRID is legal (geographic coordinates) */
srid_is_latlong(fcinfo, srid);
srid_check_latlong(fcinfo, srid);
PG_RETURN_INT32(typmod);
}
......
......@@ -292,36 +292,68 @@ static xmlNodePtr get_xlink_node(xmlNodePtr xnode)
}
/**
* Use Proj4 to reproject a given POINTARRAY
* Use Proj to reproject a given POINTARRAY
*/
#if POSTGIS_PROJ_VERSION < 60
static POINTARRAY* gml_reproject_pa(POINTARRAY *pa, int srid_in, int srid_out)
{
projPJ in_pj, out_pj;
PJ pj;
char *text_in, *text_out;
if (srid_in == SRID_UNKNOWN) return pa; /* nothing to do */
if (srid_out == SRID_UNKNOWN) gml_lwpgerror("invalid GML representation", 3);
text_in = GetProj4StringSPI(srid_in);
text_out = GetProj4StringSPI(srid_out);
text_in = GetProj4String(srid_in);
text_out = GetProj4String(srid_out);
in_pj = lwproj_from_string(text_in);
out_pj = lwproj_from_string(text_out);
pj.pj_from = lwproj_from_string(text_in);
pj.pj_to = lwproj_from_string(text_out);
lwfree(text_in);
lwfree(text_out);
if ( ptarray_transform(pa, in_pj, out_pj) == LW_FAILURE )
if ( ptarray_transform(pa, &pj) == LW_FAILURE )
{
elog(ERROR, "gml_reproject_pa: reprojection failed");
}
pj_free(in_pj);
pj_free(out_pj);
pj_free(pj.pj_from);
pj_free(pj.pj_to);
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.
*/
static POINTARRAY* gml_reproject_pa(POINTARRAY *pa, int srid_in, int srid_out)
{
PJ *pj;
char text_in[32];
char text_out[32];
if (srid_in == SRID_UNKNOWN) return pa; /* nothing to do */
if (srid_out == SRID_UNKNOWN) gml_lwpgerror("invalid GML representation", 3);
snprintf(text_in, 32, "EPSG:%d", srid_in);
snprintf(text_out, 32, "EPSG:%d", srid_out);
pj = proj_create_crs_to_crs(NULL, text_in, text_out, NULL);
if (ptarray_transform(pa, pj) == LW_FAILURE)
{
elog(ERROR, "gml_reproject_pa: reprojection failed");
}
proj_destroy(pj);
return pa;
}
#endif /* POSTGIS_PROJ_VERSION */
/**
......
......@@ -439,7 +439,7 @@ Datum LWGEOM_length_ellipsoid_linestring(PG_FUNCTION_ARGS)
* (if deltaX is 1 degrees, then that distance represents 1/360 of a circle of radius S.)
*
*
* Parts taken from PROJ4 - geodetic_to_geocentric() (for calculating Rn)
* Parts taken from PROJ - geodetic_to_geocentric() (for calculating Rn)
*
* remember that lat1/long1/lat2/long2 are comming in a *RADIANS* not degrees.
*
......
......@@ -44,23 +44,23 @@ Datum postgis_proj_version(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(transform);
Datum transform(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom;
GSERIALIZED *result=NULL;
LWGEOM *lwgeom;
projPJ input_pj, output_pj;
int32 output_srid, input_srid;
output_srid = PG_GETARG_INT32(1);
if (output_srid == SRID_UNKNOWN)
GSERIALIZED* geom;
GSERIALIZED* result=NULL;
LWGEOM* lwgeom;
PJ* pj;
int32 srid_to, srid_from;
srid_to = PG_GETARG_INT32(1);
if (srid_to == SRID_UNKNOWN)
{
elog(ERROR, "%d is an invalid target SRID", SRID_UNKNOWN);
PG_RETURN_NULL();
}
geom = PG_GETARG_GSERIALIZED_P_COPY(0);
input_srid = gserialized_get_srid(geom);
srid_from = gserialized_get_srid(geom);
if ( input_srid == SRID_UNKNOWN )
if ( srid_from == SRID_UNKNOWN )
{
PG_FREE_IF_COPY(geom, 0);
elog(ERROR, "Input geometry has unknown (%d) SRID", SRID_UNKNOWN);
......@@ -68,10 +68,10 @@ Datum transform(PG_FUNCTION_ARGS)
}
/* Input SRID and output SRID are equal, noop */
if ( input_srid == output_srid )