]> granicus.if.org Git - postgis/commitdiff
Add in support for magic srid numbers that will always be available for UTM WGS84...
authorPaul Ramsey <pramsey@cleverelephant.ca>
Sun, 18 Oct 2009 21:15:32 +0000 (21:15 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Sun, 18 Oct 2009 21:15:32 +0000 (21:15 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@4663 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_transform.c

index e2474b9063f47f947d4a14f1ee60dd15abb7de83..8fcc10373dbb0762c96b82093a0bad2fceb6c2d0 100644 (file)
@@ -75,7 +75,6 @@ typedef struct struct_PROJ4PortalCache
 }
 PROJ4PortalCache;
 
-
 /**
  * Backend projPJ hash table
  *
@@ -345,27 +344,18 @@ GetProjectionFromPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid)
        return NULL;
 }
 
-
-/**
- * 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
-AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
+static char* GetProj4StringSPI(int srid)
 {
-       MemoryContext PJMemoryContext;
+       static int maxproj4len = 512;
        int spi_result;
-       projPJ projection = NULL;
-       char *proj_str;
+       char *proj_str = palloc(maxproj4len);
        char proj4_spi_buffer[256];
-       int* pj_errno_ref;
 
        /* Connect */
        spi_result = SPI_connect();
        if (spi_result != SPI_OK_CONNECT)
        {
-               elog(ERROR, "AddToPROJ4SRSCache: Could not connect to database using SPI");
+               elog(ERROR, "GetProj4StringSPI: Could not connect to database using SPI");
        }
 
        /* Execute the lookup query */
@@ -379,86 +369,159 @@ AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
                TupleDesc tupdesc = SPI_tuptable->tupdesc;
                SPITupleTable *tuptable = SPI_tuptable;
                HeapTuple tuple = tuptable->vals[0];
-
+       
                /* Make a projection object out of it */
-               proj_str = palloc(strlen(SPI_getvalue(tuple, tupdesc, 1)) + 1);
-               strcpy(proj_str, SPI_getvalue(tuple, tupdesc, 1));
-               projection = make_project(proj_str);
+               strncpy(proj_str, SPI_getvalue(tuple, tupdesc, 1), maxproj4len - 1);
+       }
+       else
+       {
+               elog(ERROR, "GetProj4StringSPI: Cannot find SRID (%d) in spatial_ref_sys", srid);
+       }
 
-               pj_errno_ref = pj_get_errno_ref();
-               if ( (projection == NULL) || (*pj_errno_ref))
+       spi_result = SPI_finish();
+       if (spi_result != SPI_OK_FINISH)
+       {
+               elog(ERROR, "GetProj4StringSPI: Could not disconnect from database using SPI");
+       }
+       
+       return proj_str;        
+}
+
+
+/**
+*  Given an SRID, return the proj4 text. If the integer is less than zero, 
+*  and one of the "well known" projections we support 
+*  (WGS84 UTM N/S, Polar Stereographic N/S), return the proj4text
+*  for those.
+*/
+static char* GetProj4String(int srid) 
+{
+       static int maxproj4len = 512;
+
+       /* SRIDs in SPATIAL_REF_SYS */
+       if( srid > 0 )
+       {
+               return GetProj4StringSPI(srid);
+       }
+       /* Automagic SRIDs ( < 0, using abs(srid) = epsg# ) */
+       else
+       {
+               char *proj_str = palloc(maxproj4len);
+               int id = abs(srid);
+               /* UTM North */
+               if( id >= 32601 && id <= 32660 )
                {
-                       /* we need this for error reporting */
-                       /*pfree(projection); */
-                       elog(ERROR, "AddToPROJ4SRSCache: couldn't parse proj4 string: '%s': %s", proj_str, pj_strerrno(*pj_errno_ref));
+                       snprintf(proj_str, maxproj4len, "+proj=utm +zone=%d +ellps=WGS84 +datum=WGS84 +units=m +no_defs", id - 32600);
                }
-
-               /*
-                * If the cache is already full then find the first entry
-                * that doesn't contain other_srid and use this as the
-                * subsequent value of PROJ4SRSCacheCount
-                */
-               if (PROJ4Cache->PROJ4SRSCacheCount == PROJ4_CACHE_ITEMS)
+               /* UTM South */
+               if( id >= 32701 && id <= 32760 )
                {
-                       bool found = false;
-                       int i;
+                       snprintf(proj_str, maxproj4len, "+proj=utm +zone=%d +south +ellps=WGS84 +datum=WGS84 +units=m +no_defs", id - 32700);
+               }
+               /* Polar Sterographic South */
+               if( id == 3031 )
+               {
+                       strncpy(proj_str, "+proj=stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len);
+               }
+               /* Polar Stereographic North */
+               if( id == 3995 )
+               {
+                       strncpy(proj_str, "+proj=stere +lat_0=90 +lat_ts=71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs", maxproj4len );
+               }               
 
-                       for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
+               POSTGIS_DEBUGF(3, "returning on SRID=%d: %s", srid, proj_str);
+               return proj_str;
+       }
+}
+
+
+/**
+ * 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
+AddToPROJ4SRSCache(PROJ4PortalCache *PROJ4Cache, int srid, int other_srid)
+{
+       MemoryContext PJMemoryContext;
+       projPJ projection = NULL;
+       char *proj_str;
+       int* pj_errno_ref;
+
+       /* 
+       ** Turn the SRID number into a proj4 string, by reading from spatial_ref_sys
+       ** or instantiating a magical value from a negative srid. 
+       */
+       proj_str = GetProj4String(srid);
+       if( ! proj_str )
+       {
+               elog(ERROR, "GetProj4String returned NULL for SRID (%d)", srid);
+       }
+
+       projection = make_project(proj_str);
+
+       pj_errno_ref = pj_get_errno_ref();
+       if ( (projection == NULL) || (*pj_errno_ref))
+       {
+               /* we need this for error reporting */
+               /*pfree(projection); */
+               elog(ERROR, "AddToPROJ4SRSCache: couldn't parse proj4 string: '%s': %s", proj_str, pj_strerrno(*pj_errno_ref));
+       }
+
+       /*
+        * If the cache is already full then find the first entry
+        * that doesn't contain other_srid and use this as the
+        * subsequent value of PROJ4SRSCacheCount
+        */
+       if (PROJ4Cache->PROJ4SRSCacheCount == PROJ4_CACHE_ITEMS)
+       {
+               bool found = false;
+               int i;
+
+               for (i = 0; i < PROJ4_CACHE_ITEMS; i++)
+               {
+                       if (PROJ4Cache->PROJ4SRSCache[i].srid != other_srid && found == false)
                        {
-                               if (PROJ4Cache->PROJ4SRSCache[i].srid != other_srid && found == false)
-                               {
-                                       LWDEBUGF(3, "choosing to remove item from query cache with SRID %d and index %d", PROJ4Cache->PROJ4SRSCache[i].srid, i);
+                               LWDEBUGF(3, "choosing to remove item from query cache with SRID %d and index %d", PROJ4Cache->PROJ4SRSCache[i].srid, i);
 
-                                       DeleteFromPROJ4SRSCache(PROJ4Cache, PROJ4Cache->PROJ4SRSCache[i].srid);
-                                       PROJ4Cache->PROJ4SRSCacheCount = i;
+                               DeleteFromPROJ4SRSCache(PROJ4Cache, PROJ4Cache->PROJ4SRSCache[i].srid);
+                               PROJ4Cache->PROJ4SRSCacheCount = i;
 
-                                       found = true;
-                               }
+                               found = true;
                        }
                }
+       }
 
-               /*
-                * Now create a memory context for this projection and
-                * store it in the backend hash
-                */
-               LWDEBUGF(3, "adding SRID %d with proj4text \"%s\" to query cache at index %d", srid, proj_str, PROJ4Cache->PROJ4SRSCacheCount);
-
-               PJMemoryContext = MemoryContextCreate(T_AllocSetContext, 8192,
-                                                     &PROJ4SRSCacheContextMethods,
-                                                     PROJ4Cache->PROJ4SRSCacheContext,
-                                                     "PostGIS PROJ4 PJ Memory Context");
+       /*
+        * Now create a memory context for this projection and
+        * store it in the backend hash
+        */
+       LWDEBUGF(3, "adding SRID %d with proj4text \"%s\" to query cache at index %d", srid, proj_str, PROJ4Cache->PROJ4SRSCacheCount);
 
-               /* Create the backend hash if it doesn't already exist */
-               if (!PJHash)
-                       PJHash = CreatePJHash();
+       PJMemoryContext = MemoryContextCreate(T_AllocSetContext, 8192,
+                                             &PROJ4SRSCacheContextMethods,
+                                             PROJ4Cache->PROJ4SRSCacheContext,
+                                             "PostGIS PROJ4 PJ Memory Context");
 
-               /*
-                * Add the MemoryContext to the backend hash so we can
-                * clean up upon portal shutdown
-                */
-               LWDEBUGF(3, "adding projection object (%p) to hash table with MemoryContext key (%p)", projection, PJMemoryContext);
+       /* Create the backend hash if it doesn't already exist */
+       if (!PJHash)
+               PJHash = CreatePJHash();
 
-               AddPJHashEntry(PJMemoryContext, projection);
+       /*
+        * Add the MemoryContext to the backend hash so we can
+        * clean up upon portal shutdown
+        */
+       LWDEBUGF(3, "adding projection object (%p) to hash table with MemoryContext key (%p)", projection, PJMemoryContext);
 
-               PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].srid = srid;
-               PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection = projection;
-               PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection_mcxt = PJMemoryContext;
-               PROJ4Cache->PROJ4SRSCacheCount++;
+       AddPJHashEntry(PJMemoryContext, projection);
 
-               /* Free the projection string */
-               pfree(proj_str);
-       }
-       else
-       {
-               elog(ERROR, "AddToPROJ4SRSCache: Cannot find SRID (%d) in spatial_ref_sys", srid);
-       }
+       PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].srid = srid;
+       PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection = projection;
+       PROJ4Cache->PROJ4SRSCache[PROJ4Cache->PROJ4SRSCacheCount].projection_mcxt = PJMemoryContext;
+       PROJ4Cache->PROJ4SRSCacheCount++;
 
-       /* Close the connection */
-       spi_result = SPI_finish();
-       if (spi_result != SPI_OK_FINISH)
-       {
-               elog(ERROR, "AddToPROJ4SRSCache: Could not disconnect from database using SPI");
-       }
+       /* Free the projection string */
+       pfree(proj_str);
 
 }