]> granicus.if.org Git - postgis/commitdiff
Make transformation and projection cache API available (ticket #1053)
authorSandro Santilli <strk@keybit.net>
Fri, 12 Aug 2011 17:25:01 +0000 (17:25 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 12 Aug 2011 17:25:01 +0000 (17:25 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@7734 b70326c6-7e19-0410-871a-916f4a2858ee

20 files changed:
.gitignore
GNUmakefile.in
configure.ac
liblwgeom/Makefile.in
liblwgeom/liblwgeom.h
liblwgeom/lwgeom_transform.c [new file with mode: 0644]
libpgcommon/Makefile.in [new file with mode: 0644]
libpgcommon/common.h [moved from postgis/lwgeom_transform.h with 60% similarity]
libpgcommon/cunit/Makefile.in [new file with mode: 0644]
libpgcommon/gserialized.h [moved from postgis/gserialized.h with 100% similarity]
libpgcommon/lwgeom_pg.c [moved from postgis/lwgeom_pg.c with 100% similarity]
libpgcommon/lwgeom_pg.h [moved from postgis/lwgeom_pg.h with 100% similarity]
libpgcommon/lwgeom_transform.c [moved from postgis/lwgeom_transform.c with 83% similarity]
libpgcommon/lwgeom_transform.h [new file with mode: 0644]
libpgcommon/pgsql_compat.h [moved from postgis/pgsql_compat.h with 100% similarity]
postgis/Makefile.in
postgis/lwgeom_in_gml.c
raster/rt_pg/Makefile.in
raster/rt_pg/rt_pg.h
raster/rt_pg/rtpostgis.sql.in.c

index a4c85cfcf458eba624e754f6fe973746f8e19d4c..20431e59341f2435a0c2469e6c8bd3eef6eec0f9 100644 (file)
@@ -40,6 +40,8 @@ macros/ltversion.m4
 *.o
 postgis_config.h
 postgis/Makefile
+postgis/legacy_compatibility_layer.sql
+postgis/legacy_compatibility_layer.sql.in
 postgis/legacy.sql
 postgis/legacy.sql.in
 postgis/postgis.sql
@@ -49,6 +51,8 @@ postgis/postgis_upgrade_14_to_15.sql
 postgis/postgis_upgrade_15_minor.sql
 postgis/postgis_upgrade_20_minor.sql
 postgis/sqldefines.h
+postgis/uninstall_legacy.sql
+postgis/uninstall_legacy.sql.in
 postgis/uninstall_postgis.sql
 postgis/uninstall_postgis.sql.in
 raster/Makefile
@@ -77,3 +81,5 @@ topology/test/topo_predicates.sql
 topology/topology.sql
 topology/topology.sql.in
 authors.git
+libpgcommon/Makefile
+libpgcommon/cunit/Makefile
index daf8d77dd9d3e2af1fbe739fa17543eba1fd36c9..ae890d16ecffc76c4f9f27d98620a4e00dd680a1 100644 (file)
@@ -5,7 +5,7 @@
 #-----------------------------------------------------
 
 # todo: add all subdirs
-SUBDIRS = liblwgeom regress postgis loader utils @RASTER@ @TOPOLOGY@
+SUBDIRS = liblwgeom libpgcommon regress postgis loader utils @RASTER@ @TOPOLOGY@
 
 # todo: add more rules here, like uninstall, clean...
 all install uninstall noop clean distclean check:
index 9a679c6b364c3636ede957238f9d2150bbd1f81b..624e633ee8e61dca363112f53741c5f7aae99790 100644 (file)
@@ -357,6 +357,11 @@ PGSQL_FE_CPPFLAGS=-I`$PGCONFIG --includedir`
 AC_SUBST([PGSQL_FE_LDFLAGS])
 AC_SUBST([PGSQL_FE_CPPFLAGS])
 
+dnl Extract the include flags for the backend (libpgcommon)
+PGSQL_BE_CPPFLAGS=-I`$PGCONFIG --includedir-server`
+
+AC_SUBST([PGSQL_BE_CPPFLAGS])
+
 dnl Extract the documentation and man page directories
 PGSQL_DOCDIR=`$PGCONFIG --docdir`
 PGSQL_MANDIR=`$PGCONFIG --mandir`
@@ -589,6 +594,9 @@ AC_DEFINE_UNQUOTED([POSTGIS_PROJ_VERSION], [$POSTGIS_PROJ_VERSION], [PROJ librar
 AC_SUBST([POSTGIS_PROJ_VERSION])
 CPPFLAGS="$CPPFLAGS_SAVE"
 
+AC_SUBST([PROJ_CPPFLAGS])
+AC_SUBST([PROJ_LDFLAGS])
+
 dnl Ensure that we are using PROJ >= 4.5.0 (requires pj_set_searchpath) 
 if test ! "$POSTGIS_PROJ_VERSION" -ge 45; then
        AC_MSG_ERROR([PostGIS requires PROJ >= 4.5.0])
@@ -778,10 +786,14 @@ if test "x$RASTER" = "xraster"; then dnl # {
     POSTGIS_SRCDIR=`$PWDREGRESS`
     LIBLWGEOM_CFLAGS="-I${POSTGIS_SRCDIR}/liblwgeom"
     LIBLWGEOM_LDFLAGS="${POSTGIS_SRCDIR}/liblwgeom/liblwgeom.a"
+    LIBPGCOMMON_CFLAGS="-I${POSTGIS_SRCDIR}/libpgcommon"
+    LIBPGCOMMON_LDFLAGS="${POSTGIS_SRCDIR}/libpgcommon/libpgcommon.a"
 
     AC_SUBST([POSTGIS_SRCDIR])
     AC_SUBST([LIBLWGEOM_CFLAGS])
     AC_SUBST([LIBLWGEOM_LDFLAGS])
+    AC_SUBST([LIBPGCOMMON_CFLAGS])
+    AC_SUBST([LIBPGCOMMON_LDFLAGS])
 
     dnl ========================================================================
     dnl Determine GDAL Support
@@ -910,6 +922,7 @@ fi dnl # }
 dnl Output the relevant files
 AC_OUTPUT([GNUmakefile 
         liblwgeom/Makefile liblwgeom/cunit/Makefile postgis/Makefile
+        libpgcommon/Makefile libpgcommon/cunit/Makefile
         postgis/sqldefines.h loader/Makefile loader/cunit/Makefile
         topology/Makefile regress/Makefile doc/Makefile doc/Makefile.comments
         doc/html/image_src/Makefile $RT_MAKEFILE_LIST])
index ce451838a55bd997ae8fa34f4ada94f044be4ee3..5d1956dac975295783ecab8a70f2a74987201255 100644 (file)
 # **********************************************************************
 
 CC = @CC@
-CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ -DPOSTGIS_GEOS_VERSION=@POSTGIS_GEOS_VERSION@
-LDFLAGS = @GEOS_LDFLAGS@ -lgeos_c
+CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ \
+         @GEOS_CPPFLAGS@ -DPOSTGIS_GEOS_VERSION=@POSTGIS_GEOS_VERSION@ \
+         @PROJ_CPPFLAGS@ -DPOSTGIS_PROJ_VERSION=@POSTGIS_PROJ_VERSION@
+LDFLAGS = @GEOS_LDFLAGS@ @PROJ_LDFLAGS@ -lgeos_c
 NUMERICFLAGS = @NUMERICFLAGS@
 top_builddir = @top_builddir@
 prefix = @prefix@
@@ -76,7 +78,8 @@ SA_OBJS = \
        lwout_x3d.o \
        lwgeom_geos.o \
        lwgeom_geos_clean.o \
-       lwgeom_geos_split.o
+       lwgeom_geos_split.o \
+       lwgeom_transform.o
 
 NM_OBJS = \
        lwspheroid.o 
index 9d42b492233b09f301f5367f9024ed316467b547..4fa724aa508385f5b1b7e20a3ea6f38f721d695b 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include "proj_api.h"
 
 /**
 * @file liblwgeom.h
@@ -2187,6 +2188,19 @@ LWGEOM* lwgeom_snap(const LWGEOM* geom1, const LWGEOM* geom2, double tolerance);
 LWGEOM* lwgeom_sharedpaths(const LWGEOM* geom1, const LWGEOM* geom2);
 
 
+/*******************************************************************************
+ * PROJ4-dependent extra functions on LWGEOM
+ ******************************************************************************/
+/**
+ * Transform (reproject) a geometry in-place.
+ * @param geom the geometry to transform
+ * @param inpj the input (or current, or source) projection
+ * @param outpj the output (or destination) projection
+ */
+int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj) ;
+int point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj) ;
+
+
 /*******************************************************************************
  * GEOS-dependent extra functions on LWGEOM
  ******************************************************************************/
diff --git a/liblwgeom/lwgeom_transform.c b/liblwgeom/lwgeom_transform.c
new file mode 100644 (file)
index 0000000..661d607
--- /dev/null
@@ -0,0 +1,151 @@
+/**********************************************************************
+ * $Id:$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2003 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "proj_api.h"
+#include "liblwgeom.h"
+#include <math.h>
+
+
+/** convert decimal degress to radians */
+static void
+to_rad(POINT4D *pt)
+{
+       pt->x *= M_PI/180.0;
+       pt->y *= M_PI/180.0;
+}
+
+/** convert radians to decimal degress */
+static void
+to_dec(POINT4D *pt)
+{
+       pt->x *= 180.0/M_PI;
+       pt->y *= 180.0/M_PI;
+}
+
+
+/**
+ * Transform given SERIALIZED geometry
+ * from inpj projection to outpj projection
+ */
+int
+lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj)
+{
+       int j, i;
+       int type = geom->type;
+       POINT4D p;
+       POINTARRAY *pa;
+
+       /* No points to transform in an empty! */
+       if ( lwgeom_is_empty(geom) )
+               return LW_SUCCESS;
+
+       switch(type)
+       {
+               case POINTTYPE:
+               case LINETYPE:
+               case CIRCSTRINGTYPE:
+               case TRIANGLETYPE:
+               {
+                       LWLINE *g = (LWLINE*)geom;
+                       pa = g->points;
+                       for ( i = 0; i < pa->npoints; i++ )
+                       {
+                               getPoint4d_p(pa, i, &p);
+                               point4d_transform(&p, inpj, outpj);
+                               ptarray_set_point4d(pa, i, &p);
+                       }
+                       break;
+               }
+               case POLYGONTYPE:
+               {
+                       LWPOLY *g = (LWPOLY*)geom;
+                       for ( j = 0; j < g->nrings; j++ )
+                       {
+                               pa = g->rings[j];
+                               for ( i = 0; i < pa->npoints; i++ )
+                               {
+                                       getPoint4d_p(pa, i, &p);
+                                       point4d_transform(&p, inpj, outpj);
+                                       ptarray_set_point4d(pa, i, &p);
+                               }
+                       }
+                       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++ )
+                       {
+                               lwgeom_transform(g->geoms[i], inpj, outpj);
+                       }
+                       break;
+               }
+               default:
+               {
+                       lwerror("lwgeom_transform: Cannot handle type '%s'", lwtype_name(type));
+                       return LW_FAILURE;
+               }
+       }
+       return LW_SUCCESS;
+
+}
+
+int
+point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj)
+{
+       int* pj_errno_ref;
+       POINT4D orig_pt;
+
+       /* Make a copy of the input point so we can report the original should an error occur */
+       orig_pt.x = pt->x;
+       orig_pt.y = pt->y;
+       orig_pt.z = pt->z;
+
+       if (pj_is_latlong(srcpj)) to_rad(pt) ;
+
+       LWDEBUGF(4, "transforming POINT(%f %f) from '%s' to '%s'", orig_pt.x, orig_pt.y, pj_get_def(srcpj,0), pj_get_def(dstpj,0));
+
+       /* Perform the transform */
+       pj_transform(srcpj, dstpj, 1, 0, &(pt->x), &(pt->y), &(pt->z));
+
+       /* For NAD grid-shift errors, display an error message with an additional hint */
+       pj_errno_ref = pj_get_errno_ref();
+
+       if (*pj_errno_ref != 0)
+       {
+               if (*pj_errno_ref == -38)
+               {
+                       LWDEBUGF(0, "transform: couldn't project point (%g %g %g): %s (%d)",
+                                orig_pt.x, orig_pt.y, orig_pt.z, pj_strerrno(*pj_errno_ref), *pj_errno_ref) ;
+                       LWDEBUG(0, "HINT: PostGIS was unable to transform the point because either no grid shift files were found, or the point does not lie within the range for which the grid shift is defined. Refer to the ST_Transform() section of the PostGIS manual for details on how to configure PostGIS to alter this behaviour.") ;
+                       return 0;
+               }
+               else
+               {
+                       LWDEBUGF(0, "transform: couldn't project point (%g %g %g): %s (%d)",
+                            orig_pt.x, orig_pt.y, orig_pt.z, pj_strerrno(*pj_errno_ref), *pj_errno_ref);
+                       return 0;
+               }
+       }
+
+       if (pj_is_latlong(dstpj)) to_dec(pt);
+       return 1;
+}
diff --git a/libpgcommon/Makefile.in b/libpgcommon/Makefile.in
new file mode 100644 (file)
index 0000000..eadae7c
--- /dev/null
@@ -0,0 +1,60 @@
+# **********************************************************************
+# * $Id: Makefile.in 
+# *
+# * PostGIS - Spatial Types for PostgreSQL
+# * http://postgis.refractions.net
+# * Copyright 2008 Mark Cave-Ayland
+# *
+# * This is free software; you can redistribute and/or modify it under
+# * the terms of the GNU General Public Licence. See the COPYING file.
+# *
+# **********************************************************************
+
+CC=@CC@
+CFLAGS=@CFLAGS@ @PGSQL_BE_CPPFLAGS@ -I../liblwgeom @PICFLAGS@ @WARNFLAGS@ 
+NUMERICFLAGS=@NUMERICFLAGS@
+
+YACC=@YACC@
+LEX=@LEX@
+
+# Standalone COMMON objects
+SA_OBJS = \
+       lwgeom_transform.o \
+       lwgeom_pg.o
+
+
+SA_HEADERS = \
+       lwgeom_pg.h \
+       lwgeom_transform.h \
+       pgsql_compat.h
+
+all: libpgcommon.a
+
+# nothing to install or uninstall
+install uninstall:
+
+libpgcommon.a: $(SA_OBJS) $(SA_HEADERS)
+       ar rs libpgcommon.a $(SA_OBJS) 
+
+maintainer-clean: clean
+
+clean: 
+       $(MAKE) -C cunit clean
+       rm -f $(SA_OBJS) 
+       rm -f $(NM_OBJS) 
+       rm -f libpgcommon.a 
+
+# Nothing specific in distclean (will be done by clean)
+distclean:
+
+check: libpgcommon.a
+       make -C cunit check
+
+# Command to build each of the .o files
+$(SA_OBJS): %.o: %.c 
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+
+  
+
+
similarity index 60%
rename from postgis/lwgeom_transform.h
rename to libpgcommon/common.h
index 6cfd2242da5b3de3060913abead4db6fce8882b7..452c696035370e69641c7f89bf3082322677b3cc 100644 (file)
@@ -1,20 +1,20 @@
 /**********************************************************************
- * $Id
+ * $Id: $
  *
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
+ * Copyright 2011 OSGeo
  *
  * This is free software; you can redistribute and/or modify it under
  * the terms of the GNU General Public Licence. See the COPYING file.
  *
  **********************************************************************/
 
-#include "postgres.h"
-#include "liblwgeom.h"
+#ifndef PG_LIBCOMMON_H
+#define PG_LIBCOMMON_H
+
+#include "pgsql_compat.h"
 #include "lwgeom_pg.h"
-#include "proj_api.h"
+#include "lwgeom_transform.h"
 
-projPJ make_project(char *str1);
-int transform_point(POINT4D *pt, projPJ srcdefn, projPJ dstdefn);
-char* GetProj4StringSPI(int srid);
+#endif /* PG_LIBCOMMON_H */
diff --git a/libpgcommon/cunit/Makefile.in b/libpgcommon/cunit/Makefile.in
new file mode 100644 (file)
index 0000000..76e688a
--- /dev/null
@@ -0,0 +1,13 @@
+# **********************************************************************
+# * $Id: Makefile.in 
+# *
+# * PostGIS - Spatial Types for PostgreSQL
+# * http://postgis.refractions.net
+# * Copyright 2008 Mark Cave-Ayland
+# *
+# * This is free software; you can redistribute and/or modify it under
+# * the terms of the GNU General Public Licence. See the COPYING file.
+# *
+# **********************************************************************
+
+all check clean : 
\ No newline at end of file
similarity index 100%
rename from postgis/lwgeom_pg.c
rename to libpgcommon/lwgeom_pg.c
similarity index 100%
rename from postgis/lwgeom_pg.h
rename to libpgcommon/lwgeom_pg.h
similarity index 83%
rename from postgis/lwgeom_transform.c
rename to libpgcommon/lwgeom_transform.c
index d01627433e8c79f01bb2f875c4c026f889e32796..9a9f05fda27f3adbb12a365b87add304469f38c3 100644 (file)
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id$
+ * $Id: lwgeom_transform.c -1M 2011-08-11 09:54:25Z (local) $
  *
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
@@ -37,10 +37,7 @@ Datum postgis_proj_version(PG_FUNCTION_ARGS);
 #include "lwgeom_transform.h"
 
 projPJ make_project(char *str1);
-void to_rad(POINT4D *pt);
-void to_dec(POINT4D *pt);
 int pj_transform_nodatum(projPJ srcdefn, projPJ dstdefn, long point_count, int point_offset, double *x, double *y, double *z );
-int transform_point(POINT4D *pt, projPJ srcdefn, projPJ dstdefn);
 
 
 
@@ -104,11 +101,12 @@ static void AddPJHashEntry(MemoryContext mcxt, projPJ projection);
 static projPJ GetPJHashEntry(MemoryContext mcxt);
 static void DeletePJHashEntry(MemoryContext mcxt);
 
-/* Cache API */
-bool IsInPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
-projPJ GetProjectionFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
-void AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid);
-void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
+/* Internal Cache API */
+static PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfoData *fcinfo) ;
+static bool IsInPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
+static projPJ GetProjectionFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
+static void AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid);
+static void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid);
 
 /* Search path for PROJ.4 library */
 static bool IsPROJ4LibPathSet = false;
@@ -300,12 +298,16 @@ static void DeletePJHashEntry(MemoryContext mcxt)
                elog(ERROR, "DeletePJHashEntry: There was an error removing the PROJ4 projection object from this MemoryContext (%p)", (void *)mcxt);
 }
 
+bool
+IsInPROJ4Cache(Proj4Cache PROJ4Cache, int srid) {
+       return IsInPROJ4SRSCache((PROJ4PortalCache *)PROJ4Cache, srid) ;
+}
 
 /*
  * Per-cache management functions
  */
 
-bool
+static bool
 IsInPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid)
 {
        /*
@@ -318,19 +320,23 @@ IsInPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid)
        for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
        {
                if (PROJ4Cache->PROJ4SRSCache[i].srid == srid)
-                       return true;
+                       return 1;
        }
 
        /* Otherwise not found */
-       return false;
+       return 0;
 }
 
+projPJ GetProjectionFromPROJ4Cache(Proj4Cache cache, int srid)
+{
+       return GetProjectionFromPROJ4SRSCache((PROJ4PortalCache *)cache, srid) ;
+}
 
 /**
  * Return the projection object from the cache (we should
  * already have checked it exists using IsInPROJ4SRSCache first)
  */
-projPJ
+static projPJ
 GetProjectionFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid)
 {
        int i;
@@ -454,13 +460,17 @@ static char* GetProj4String(int srid)
        }
 }
 
+void AddToPROJ4Cache(Proj4Cache cache, int srid, int other_srid) {
+       AddToPROJ4SRSCache((PROJ4PortalCache *)cache, srid, other_srid) ;
+}
+
 
 /**
  * Add an entry to the local PROJ4 SRS cache. If we need to wrap around then
  * we must make sure the entry we choose to delete does not contain other_srid
  * which is the definition for the other half of the transformation.
  */
-void
+static void
 AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
 {
        MemoryContext PJMemoryContext;
@@ -545,8 +555,12 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
 
 }
 
+void DeleteFromPROJ4Cache(Proj4Cache cache, int srid) {
+       DeleteFromPROJ4SRSCache((PROJ4PortalCache *)cache, srid) ;
+}
+
 
-void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid)
+static void DeleteFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid)
 {
        /*
         * Delete the SRID entry from the cache
@@ -590,40 +604,28 @@ void SetPROJ4LibPath(void)
        char *path;
        const char **proj_lib_path;
 
-       /*
-        * Get the sharepath and append /contrib/postgis/proj to form a suitable
-        * directory in which to store the grid shift files
-        */
-       proj_lib_path = palloc(sizeof(char *));
-       path = palloc(MAXPGPATH);
-       *proj_lib_path = path;
+       if (!IsPROJ4LibPathSet) {
 
-       get_share_path(my_exec_path, path);
-       strncat(path, "/contrib/postgis/proj", MAXPGPATH - strlen(path) - 1);
+               /*
+                * Get the sharepath and append /contrib/postgis/proj to form a suitable
+                * directory in which to store the grid shift files
+                */
+               proj_lib_path = palloc(sizeof(char *));
+               path = palloc(MAXPGPATH);
+               *proj_lib_path = path;
 
-       /* Set the search path for PROJ.4 */
-       pj_set_searchpath(1, proj_lib_path);
-
-       /* Ensure we only do this once... */
-       IsPROJ4LibPathSet = true;
-}
+               get_share_path(my_exec_path, path);
+               strncat(path, "/contrib/postgis/proj", MAXPGPATH - strlen(path) - 1);
 
+               /* Set the search path for PROJ.4 */
+               pj_set_searchpath(1, proj_lib_path);
 
-/** convert decimal degress to radians */
-void
-to_rad(POINT4D *pt)
-{
-       pt->x *= M_PI/180.0;
-       pt->y *= M_PI/180.0;
+               /* Ensure we only do this once... */
+               IsPROJ4LibPathSet = true;
+       }
 }
 
-/** convert radians to decimal degress */
-void
-to_dec(POINT4D *pt)
-{
-       pt->x *= 180.0/M_PI;
-       pt->y *= 180.0/M_PI;
-}
+
 
 /** given a string, make a PJ object */
 projPJ
@@ -673,84 +675,55 @@ make_project(char *str1)
 }
 
 
-/**
- * Transform given SERIALIZED geometry
- * from inpj projection to outpj projection
- */
-static int
-lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj)
+
+Proj4Cache GetPROJ4Cache(FunctionCallInfoData *fcinfo) {
+       return (Proj4Cache)GetPROJ4SRSCache(fcinfo) ;
+}
+
+static PROJ4PortalCache *GetPROJ4SRSCache(FunctionCallInfoData *fcinfo)
 {
-       int j, i;
-       int type = geom->type;
-       POINT4D p;
-       POINTARRAY *pa;
-       
-       /* No points to transform in an empty! */
-       if ( lwgeom_is_empty(geom) )
-               return LW_SUCCESS;
-       
-       switch(type) 
+       PROJ4PortalCache *PROJ4Cache ;
+
+       /*
+        * If we have not already created PROJ4 cache for this portal
+        * then create it
+        */
+       if (fcinfo->flinfo->fn_extra == NULL)
        {
-               case POINTTYPE:
-               case LINETYPE:
-               case CIRCSTRINGTYPE:
-               case TRIANGLETYPE:
-               {
-                       LWLINE *g = (LWLINE*)geom;
-                       pa = g->points;
-                       for ( i = 0; i < pa->npoints; i++ )
-                       {
-                               getPoint4d_p(pa, i, &p);
-                               transform_point(&p, inpj, outpj);
-                               ptarray_set_point4d(pa, i, &p);
-                       }
-                       break;
-               }
-               case POLYGONTYPE:
-               {
-                       LWPOLY *g = (LWPOLY*)geom;
-                       for ( j = 0; j < g->nrings; j++ )
-                       {
-                               pa = g->rings[j];
-                               for ( i = 0; i < pa->npoints; i++ )
-                               {
-                                       getPoint4d_p(pa, i, &p);
-                                       transform_point(&p, inpj, outpj);
-                                       ptarray_set_point4d(pa, i, &p);
-                               }
-                       }
-                       break;
-               }
-               case MULTIPOINTTYPE:
-               case MULTILINETYPE:
-               case MULTIPOLYGONTYPE:
-               case COLLECTIONTYPE:
-               case COMPOUNDTYPE:
-               case CURVEPOLYTYPE:
-               case MULTICURVETYPE:
-               case MULTISURFACETYPE:
-               case POLYHEDRALSURFACETYPE:
-               case TINTYPE:
+               MemoryContext old_context;
+
+               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
+               PROJ4Cache = palloc(sizeof(PROJ4PortalCache));
+               MemoryContextSwitchTo(old_context);
+
+               if (PROJ4Cache)
                {
-                       LWCOLLECTION *g = (LWCOLLECTION*)geom;
-                       for ( i = 0; i < g->ngeoms; i++ )
+                       int i;
+
+                       POSTGIS_DEBUGF(3, "Allocating PROJ4Cache for portal with transform() MemoryContext %p", fcinfo->flinfo->fn_mcxt);
+                       /* Put in any required defaults */
+                       for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
                        {
-                               lwgeom_transform(g->geoms[i], inpj, outpj);
+                               PROJ4Cache->PROJ4SRSCache[i].srid = SRID_UNKNOWN;
+                               PROJ4Cache->PROJ4SRSCache[i].projection = NULL;
+                               PROJ4Cache->PROJ4SRSCache[i].projection_mcxt = NULL;
                        }
-                       break;
-               }
-               default:
-               {
-                       lwerror("lwgeom_transform: Cannot handle type '%s'", lwtype_name(type));
-                       return LW_FAILURE;
+                       PROJ4Cache->PROJ4SRSCacheCount = 0;
+                       PROJ4Cache->PROJ4SRSCacheContext = fcinfo->flinfo->fn_mcxt;
+
+                       /* Store the pointer in fcinfo->flinfo->fn_extra */
+                       fcinfo->flinfo->fn_extra = PROJ4Cache;
                }
        }
-       return LW_SUCCESS;
+       else
+       {
+               /* Use the existing cache */
+               PROJ4Cache = fcinfo->flinfo->fn_extra;
+       }
 
+       return PROJ4Cache ;
 }
 
-
-
 /**
  * transform( GEOMETRY, INT (output srid) )
  * tmpPts - if there is a nadgrid error (-38), we re-try the transform
@@ -798,42 +771,8 @@ Datum transform(PG_FUNCTION_ARGS)
                PG_RETURN_POINTER(PG_GETARG_DATUM(0));
        }
 
-       /*
-        * If we have not already created PROJ4 cache for this portal
-        * then create it
-        */
-       if (fcinfo->flinfo->fn_extra == NULL)
-       {
-               MemoryContext old_context;
-
-               old_context = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
-               PROJ4Cache = palloc(sizeof(PROJ4PortalCache));
-               MemoryContextSwitchTo(old_context);
-
-               if (PROJ4Cache)
-               {
-                       int i;
-
-                       POSTGIS_DEBUGF(3, "Allocating PROJ4Cache for portal with transform() MemoryContext %p", fcinfo->flinfo->fn_mcxt);
-                       /* Put in any required defaults */
-                       for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
-                       {
-                               PROJ4Cache->PROJ4SRSCache[i].srid = SRID_UNKNOWN;
-                               PROJ4Cache->PROJ4SRSCache[i].projection = NULL;
-                               PROJ4Cache->PROJ4SRSCache[i].projection_mcxt = NULL;
-                       }
-                       PROJ4Cache->PROJ4SRSCacheCount = 0;
-                       PROJ4Cache->PROJ4SRSCacheContext = fcinfo->flinfo->fn_mcxt;
-
-                       /* Store the pointer in fcinfo->flinfo->fn_extra */
-                       fcinfo->flinfo->fn_extra = PROJ4Cache;
-               }
-       }
-       else
-       {
-               /* Use the existing cache */
-               PROJ4Cache = fcinfo->flinfo->fn_extra;
-       }
+       /* get or initialize the cache for this round */
+       PROJ4Cache = GetPROJ4SRSCache(fcinfo) ;
 
        /* Add the output srid to the cache if it's not already there */
        if (!IsInPROJ4SRSCache(PROJ4Cache, result_srid))
@@ -983,49 +922,6 @@ Datum postgis_proj_version(PG_FUNCTION_ARGS)
 }
 
 
-int
-transform_point(POINT4D *pt, projPJ srcpj, projPJ dstpj)
-{
-       int* pj_errno_ref;
-       POINT4D orig_pt;
-
-       /* Make a copy of the input point so we can report the original should an error occur */
-       orig_pt.x = pt->x;
-       orig_pt.y = pt->y;
-       orig_pt.z = pt->z;
-
-       if (pj_is_latlong(srcpj)) to_rad(pt);
-
-       LWDEBUGF(4, "transforming POINT(%f %f) from '%s' to '%s'", orig_pt.x, orig_pt.y, pj_get_def(srcpj,0), pj_get_def(dstpj,0));
-       
-       /* Perform the transform */
-       pj_transform(srcpj, dstpj, 1, 0, &(pt->x), &(pt->y), &(pt->z));
-
-       /* For NAD grid-shift errors, display an error message with an additional hint */
-       pj_errno_ref = pj_get_errno_ref();
-
-       if (*pj_errno_ref != 0)
-       {
-               if (*pj_errno_ref == -38)
-               {
-                       ereport(ERROR, (
-                                   errmsg_internal("transform: couldn't project point (%g %g %g): %s (%d)",
-                                                   orig_pt.x, orig_pt.y, orig_pt.z, pj_strerrno(*pj_errno_ref), *pj_errno_ref),
-                                   errhint("PostGIS was unable to transform the point because either no grid shift files were found, or the point does not lie within the range for which the grid shift is defined. Refer to the ST_Transform() section of the PostGIS manual for details on how to configure PostGIS to alter this behaviour.")
-                               ));
-                       return 0;
-               }
-               else
-               {
-                       elog(ERROR, "transform: couldn't project point (%g %g %g): %s (%d)",
-                            orig_pt.x, orig_pt.y, orig_pt.z, pj_strerrno(*pj_errno_ref), *pj_errno_ref);
-                       return 0;
-               }
-       }
-
-       if (pj_is_latlong(dstpj)) to_dec(pt);
-       return 1;
-}
 
 
 
diff --git a/libpgcommon/lwgeom_transform.h b/libpgcommon/lwgeom_transform.h
new file mode 100644 (file)
index 0000000..c988dfd
--- /dev/null
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * $Id: lwgeom_transform.h -1M 2011-08-11 11:15:57Z (local) $ 
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2003 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include "postgres.h"
+#include "liblwgeom.h"
+#include "lwgeom_pg.h"
+#include "proj_api.h"
+
+projPJ make_project(char *str1);
+char* GetProj4StringSPI(int srid);
+
+/**
+ * Opaque type to use in the projection cache API.
+ */
+typedef void *Proj4Cache ;
+
+void SetPROJ4LibPath(void);
+Proj4Cache GetPROJ4Cache(FunctionCallInfoData *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);
+
+
index 1f0953cb37132a37c057c62b67e748c628645125..6e3934e07e63ae42e3591f22eeca98d190c6154a 100644 (file)
@@ -21,8 +21,7 @@ DATA=../spatial_ref_sys.sql
 SQL_OBJS=postgis.sql.in uninstall_postgis.sql.in legacy.sql.in uninstall_legacy.sql.in legacy_compatibility_layer.sql.in
 
 # PostgreSQL objects
-PG_OBJS=lwgeom_pg.o \
-       lwgeom_debug.o \
+PG_OBJS=lwgeom_debug.o \
        lwgeom_accum.o \
        lwgeom_spheroid.o \
        lwgeom_ogc.o \
@@ -32,7 +31,6 @@ PG_OBJS=lwgeom_pg.o \
        lwgeom_functions_basic.o \
        lwgeom_gist.o \
        lwgeom_btree.o \
-       lwgeom_transform.o \
        lwgeom_box.o \
        lwgeom_box3d.o \
        lwgeom_box2dfloat4.o \
@@ -69,8 +67,8 @@ OBJS=$(PG_OBJS)
 # to an existing liblwgeom.so in the PostgreSQL $libdir supplied by an
 # older version of PostGIS, rather than with the static liblwgeom.a 
 # supplied with newer versions of PostGIS
-PG_CPPFLAGS += @CPPFLAGS@ -I../liblwgeom
-SHLIB_LINK = ../liblwgeom/liblwgeom.a @SHLIB_LINK@ 
+PG_CPPFLAGS += @CPPFLAGS@ -I../liblwgeom -I../libpgcommon
+SHLIB_LINK = ../libpgcommon/libpgcommon.a ../liblwgeom/liblwgeom.a @SHLIB_LINK@ 
 
 # Extra files to remove during 'make clean'
 EXTRA_CLEAN=$(SQL_OBJS)
@@ -103,7 +101,7 @@ endif
 
 # Make all PostGIS objects depend upon liblwgeom, so that if an underlying
 # change is made, a PostGIS rebuild is triggered.
-$(PG_OBJS): ../liblwgeom/liblwgeom.a 
+$(PG_OBJS): ../liblwgeom/liblwgeom.a ../libpgcommon/libpgcommon.a
 
 # Borrow the $libdir substitution from PGXS but customise by adding the version number
 %.sql: %.sql.in
@@ -114,6 +112,6 @@ postgis_upgrade_20_minor.sql: postgis.sql
 
 # Generate any .sql.in files from .sql.in.c files by running them through the C pre-processor 
 $(SQL_OBJS): %.in: %.in.c
-       $(CPP) -traditional-cpp $< | grep -v '^#' > $@
+       $(CPP) -traditional-cpp -I../libpgcommon $< | grep -v '^#' > $@
 
 postgis.sql.in: geography.sql.in.c
index 66414334bf71cb79c5ba94e081c2150515548f64..201c9fdeae8eecf69798edef4746006566a1684a 100644 (file)
@@ -333,7 +333,7 @@ static POINTARRAY* gml_reproject_pa(POINTARRAY *pa, int srid_in, int srid_out)
        for (i=0 ; i < pa->npoints ; i++)
        {
                getPoint4d_p(pa, i, &p);
-               transform_point(&p, in_pj, out_pj);
+               point4d_transform(&p, in_pj, out_pj);
                ptarray_set_point4d(pa, i, &p);
        }
 
index a95c4bc2eee4eb1588bd4a8bd4607b183afbf795..f3abfa8bd08ee474bc1216ef6736fb1fef26f808 100644 (file)
@@ -32,11 +32,13 @@ OBJS=rt_pg.o
 
 LIBLWGEOM_LDFLAGS=@LIBLWGEOM_LDFLAGS@
 LIBLWGEOM_CFLAGS=@LIBLWGEOM_CFLAGS@
+LIBPGCOMMON_CFLAGS=@LIBPGCOMMON_CFLAGS@
+LIBPGCOMMON_LDFLAGS=@LIBPGCOMMON_LDFLAGS@
 LIBGDAL_CFLAGS=@LIBGDAL_CFLAGS@
 LIBGDAL_LDFLAGS=@LIBGDAL_LDFLAGS@
 
-PG_CPPFLAGS+=@CPPFLAGS@ $(LIBLWGEOM_CFLAGS) $(LIBGDAL_CFLAGS) -I../rt_core
-SHLIB_LINK+=@SHLIB_LINK@ ../rt_core/librtcore.a $(LIBLWGEOM_LDFLAGS) $(LIBGDAL_LDFLAGS)
+PG_CPPFLAGS+=@CPPFLAGS@ $(LIBLWGEOM_CFLAGS) $(LIBGDAL_CFLAGS) $(LIBPGCOMMON_CFLAGS) -I../rt_core
+SHLIB_LINK+=@SHLIB_LINK@ ../rt_core/librtcore.a $(LIBPGCOMMON_LDFLAGS) $(LIBLWGEOM_LDFLAGS) $(LIBGDAL_LDFLAGS)
 # Extra files to remove during 'make clean'
 EXTRA_CLEAN=$(SQL_OBJS) rtpostgis.sql
 
index 9bffaedf21a5c29d5540f756e9b7a95f722bf205..715a9533e59c96972d5fa02f35262bee4be8d9ac 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "rt_api.h"
 #include "../../postgis_config.h"
-#include "../../postgis/gserialized.h"
+#include "gserialized.h"
 
 /* Debugging macros */
 #if POSTGIS_DEBUG_LEVEL > 0
index 7c83d26eace27c9b123e2e7f8956d125b4897c6c..ebdc5acb96d0e69736e07f5f100b0ca1f297b1d8 100644 (file)
@@ -22,7 +22,7 @@
 --
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-#include "../../postgis/gserialized.h"
+#include "../../libpgcommon/gserialized.h"
 
 -- BEGIN;