Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

gdalprojdef.cpp

00001 /******************************************************************************
00002  * $Id: gdalprojdef_cpp-source.html,v 1.1 2000/09/25 20:50:11 warmerda Exp $
00003  *
00004  * Name:     gdalprojdef.cpp
00005  * Project:  GDAL Core Projections
00006  * Purpose:  Implementation of the GDALProjDef class, a class abstracting
00007  *           the interface to PROJ.4 projection services.
00008  * Author:   Frank Warmerdam, warmerda@home.com
00009  *
00010  ******************************************************************************
00011  * Copyright (c) 1999, Frank Warmerdam
00012  *
00013  * Permission is hereby granted, free of charge, to any person obtaining a
00014  * copy of this software and associated documentation files (the "Software"),
00015  * to deal in the Software without restriction, including without limitation
00016  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00017  * and/or sell copies of the Software, and to permit persons to whom the
00018  * Software is furnished to do so, subject to the following conditions:
00019  *
00020  * The above copyright notice and this permission notice shall be included
00021  * in all copies or substantial portions of the Software.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00024  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00025  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00026  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00027  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00028  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00029  * DEALINGS IN THE SOFTWARE.
00030  ******************************************************************************
00031  *
00032  * $Log: gdalprojdef_cpp-source.html,v $
00032  * Revision 1.1  2000/09/25 20:50:11  warmerda
00032  * New
00032  *
00033  * Revision 1.7  2000/01/12 19:41:04  warmerda
00034  * Ensure lat/long projections handled properly, especially for OGC
00035  * definitions.
00036  *
00037  * Revision 1.6  2000/01/10 17:36:56  warmerda
00038  * Avoid errors when looking for the libproj.so.
00039  *
00040  * Revision 1.5  1999/07/29 19:09:23  warmerda
00041  * added windows support for proj.dll
00042  *
00043  * Revision 1.4  1999/07/29 18:01:31  warmerda
00044  * added support for translation of OGIS WKT projdefs to proj.4
00045  *
00046  * Revision 1.3  1999/03/02 21:09:48  warmerda
00047  * add GDALDecToDMS()
00048  *
00049  * Revision 1.2  1999/01/27 20:28:01  warmerda
00050  * Don't call CPLGetsymbol() for every function if first fails.
00051  *
00052  * Revision 1.1  1999/01/11 15:36:26  warmerda
00053  * New
00054  *
00055  */
00056 
00057 #include "gdal_priv.h"
00058 #include "cpl_conv.h"
00059 #include "cpl_string.h"
00060 #include "ogr_spatialref.h"
00061 
00062 typedef struct { double u, v; } UV;
00063 
00064 #define PJ void
00065 
00066 static PJ       *(*pfn_pj_init)(int, char**) = NULL;
00067 static UV       (*pfn_pj_fwd)(UV, PJ *) = NULL;
00068 static UV       (*pfn_pj_inv)(UV, PJ *) = NULL;
00069 static void     (*pfn_pj_free)(PJ *) = NULL;
00070 
00071 #define RAD_TO_DEG      57.29577951308232
00072 #define DEG_TO_RAD      .0174532925199432958
00073 
00074 #ifdef WIN32
00075 #  define LIBNAME      "proj.dll"
00076 #else
00077 #  define LIBNAME      "libproj.so"
00078 #endif
00079 
00080 /************************************************************************/
00081 /*                          LoadProjLibrary()                           */
00082 /************************************************************************/
00083 
00084 static int LoadProjLibrary()
00085 
00086 {
00087     static int  bTriedToLoad = FALSE;
00088     
00089     if( bTriedToLoad )
00090         return( pfn_pj_init != NULL );
00091 
00092     bTriedToLoad = TRUE;
00093 
00094     CPLPushErrorHandler( CPLQuietErrorHandler );
00095     pfn_pj_init = (PJ *(*)(int, char**)) CPLGetSymbol( LIBNAME,
00096                                                        "pj_init" );
00097     CPLPopErrorHandler();
00098     
00099     if( pfn_pj_init == NULL )
00100        return( FALSE );
00101 
00102     pfn_pj_fwd = (UV (*)(UV,PJ*)) CPLGetSymbol( LIBNAME, "pj_fwd" );
00103     pfn_pj_inv = (UV (*)(UV,PJ*)) CPLGetSymbol( LIBNAME, "pj_inv" );
00104     pfn_pj_free = (void (*)(PJ*)) CPLGetSymbol( LIBNAME, "pj_free" );
00105 
00106     return( TRUE );
00107 }
00108 
00109 /************************************************************************/
00110 /*                            GDALProjDef()                             */
00111 /************************************************************************/
00112 
00113 GDALProjDef::GDALProjDef( const char * pszProjectionIn )
00114 
00115 {
00116     if( pszProjectionIn == NULL )
00117         pszProjection = CPLStrdup( "" );
00118     else
00119         pszProjection = CPLStrdup( pszProjectionIn );
00120 
00121     psPJ = NULL;
00122 
00123     SetProjectionString( pszProjectionIn );
00124 }
00125 
00126 /************************************************************************/
00127 /*                         GDALCreateProjDef()                          */
00128 /************************************************************************/
00129 
00130 GDALProjDefH GDALCreateProjDef( const char * pszProjection )
00131 
00132 {
00133     return( (GDALProjDefH) (new GDALProjDef( pszProjection )) );
00134 }
00135 
00136 /************************************************************************/
00137 /*                            ~GDALProjDef()                            */
00138 /************************************************************************/
00139 
00140 GDALProjDef::~GDALProjDef()
00141 
00142 {
00143     CPLFree( pszProjection );
00144     if( psPJ != NULL )
00145         pfn_pj_free( psPJ );
00146 }
00147 
00148 /************************************************************************/
00149 /*                         GDALDestroyProjDef()                         */
00150 /************************************************************************/
00151 
00152 void GDALDestroyProjDef( GDALProjDefH hProjDef )
00153 
00154 {
00155     delete (GDALProjDef *) hProjDef;
00156 }
00157 
00158 /************************************************************************/
00159 /*                        SetProjectionString()                         */
00160 /************************************************************************/
00161 
00162 CPLErr GDALProjDef::SetProjectionString( const char * pszProjectionIn )
00163 
00164 {
00165     char        **args;
00166 
00167     if( psPJ != NULL && pfn_pj_free != NULL )
00168     {
00169         pfn_pj_free( psPJ );
00170         psPJ = NULL;
00171     }
00172 
00173     if( pszProjection != NULL )
00174         CPLFree( pszProjection );
00175     
00176     pszProjection = CPLStrdup( pszProjectionIn );
00177 
00178     if( !LoadProjLibrary() )
00179     {
00180         return CE_Failure;
00181     }
00182 
00183 /* -------------------------------------------------------------------- */
00184 /*      If this is an OGIS string we will try and translate it to       */
00185 /*      PROJ.4 format.                                                  */
00186 /* -------------------------------------------------------------------- */
00187     char        *pszProj4Projection = NULL;
00188     
00189     if( EQUALN(pszProjection,"PROJCS",6) || EQUALN(pszProjection,"GEOGCS",6) )
00190     {
00191         OGRSpatialReference     oSRS;
00192         char                    *pszProjRef = pszProjection;
00193 
00194         if( oSRS.importFromWkt( &pszProjRef ) != OGRERR_NONE
00195             || oSRS.exportToProj4( &pszProj4Projection ) != OGRERR_NONE )
00196             return CE_Failure;
00197     }
00198     else
00199     {
00200         pszProj4Projection = CPLStrdup( pszProjection );
00201     }
00202 
00203 /* -------------------------------------------------------------------- */
00204 /*      Tokenize, and pass tokens to PROJ.4 initialization function.    */
00205 /* -------------------------------------------------------------------- */
00206     args = CSLTokenizeStringComplex( pszProj4Projection, " +", TRUE, FALSE );
00207 
00208     psPJ = pfn_pj_init( CSLCount(args), args );
00209 
00210 /* -------------------------------------------------------------------- */
00211 /*      Cleanup.                                                        */
00212 /* -------------------------------------------------------------------- */
00213     CSLDestroy( args );
00214     CPLFree( pszProj4Projection );
00215 
00216     if( psPJ == NULL )
00217         return CE_Failure;
00218     else
00219         return CE_None;
00220 }
00221 
00222 /************************************************************************/
00223 /*                             ToLongLat()                              */
00224 /************************************************************************/
00225 
00226 CPLErr GDALProjDef::ToLongLat( double * padfX, double * padfY )
00227 
00228 {
00229     UV          uv;
00230     
00231     CPLAssert( padfX != NULL && padfY != NULL );
00232     
00233     if( strstr(pszProjection,"+proj=longlat") != NULL
00234         || strstr(pszProjection,"+proj=latlong") != NULL
00235         || EQUALN(pszProjection,"GEOGCS",6) )
00236         return CE_None;
00237 
00238     if( psPJ == NULL )
00239         return CE_Failure;
00240 
00241     uv.u = *padfX;
00242     uv.v = *padfY;
00243 
00244     uv = pfn_pj_inv( uv, psPJ );
00245 
00246     *padfX = uv.u * RAD_TO_DEG;
00247     *padfY = uv.v * RAD_TO_DEG;
00248     
00249     return( CE_None );
00250 }
00251 
00252 /************************************************************************/
00253 /*                       GDALReprojectToLongLat()                       */
00254 /************************************************************************/
00255 
00256 CPLErr GDALReprojectToLongLat( GDALProjDefH hProjDef,
00257                                double * padfX, double * padfY )
00258 
00259 {
00260     return( ((GDALProjDef *) hProjDef)->ToLongLat(padfX, padfY) );
00261 }
00262 
00263 /************************************************************************/
00264 /*                            FromLongLat()                             */
00265 /************************************************************************/
00266 
00267 CPLErr GDALProjDef::FromLongLat( double * padfX, double * padfY )
00268 
00269 {
00270     UV          uv;
00271     
00272     CPLAssert( padfX != NULL && padfY != NULL );
00273     
00274     if( strstr(pszProjection,"+proj=longlat") != NULL
00275         || strstr(pszProjection,"+proj=latlong") != NULL 
00276         || EQUALN(pszProjection,"GEOGCS",6) )
00277         return CE_None;
00278 
00279     if( psPJ == NULL )
00280         return CE_Failure;
00281 
00282     uv.u = *padfX * DEG_TO_RAD;
00283     uv.v = *padfY * DEG_TO_RAD;
00284 
00285     uv = pfn_pj_fwd( uv, psPJ );
00286 
00287     *padfX = uv.u;
00288     *padfY = uv.v;
00289     
00290     return( CE_None );
00291 }
00292 
00293 /************************************************************************/
00294 /*                      GDALReprojectFromLongLat()                      */
00295 /************************************************************************/
00296 
00297 CPLErr GDALReprojectFromLongLat( GDALProjDefH hProjDef,
00298                                  double * padfX, double * padfY )
00299 
00300 {
00301     return( ((GDALProjDef *) hProjDef)->FromLongLat(padfX, padfY) );
00302 }
00303 
00304 /************************************************************************/
00305 /*                            GDALDecToDMS()                            */
00306 /*                                                                      */
00307 /*      Translate a decimal degrees value to a DMS string with          */
00308 /*      hemisphere.                                                     */
00309 /************************************************************************/
00310 
00311 const char *GDALDecToDMS( double dfAngle, const char * pszAxis,
00312                           int nPrecision )
00313 
00314 {
00315     int         nDegrees, nMinutes;
00316     double      dfSeconds;
00317     char        szFormat[30];
00318     static char szBuffer[50];
00319     const char  *pszHemisphere;
00320     
00321 
00322     nDegrees = (int) ABS(dfAngle);
00323     nMinutes = (int) ((ABS(dfAngle) - nDegrees) * 60);
00324     dfSeconds = (ABS(dfAngle) * 3600 - nDegrees*3600 - nMinutes*60);
00325 
00326     if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
00327         pszHemisphere = "W";
00328     else if( EQUAL(pszAxis,"Long") )
00329         pszHemisphere = "E";
00330     else if( dfAngle < 0.0 )
00331         pszHemisphere = "S";
00332     else
00333         pszHemisphere = "N";
00334 
00335     sprintf( szFormat, "%%3dd%%2d\'%%.%df\"%s", nPrecision, pszHemisphere );
00336     sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
00337 
00338     return( szBuffer );
00339 }
00340 

doxygen1.2.2 Dimitri van Heesch, © 1997-2000