LTP GCOV extension - code coverage report
Current view: directory - ogr - ogrct.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 306
Code covered: 73.5 % Executed lines: 225

       1                 : /******************************************************************************
       2                 :  * $Id: ogrct.cpp 19939 2010-06-27 21:06:56Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  The OGRSCoordinateTransformation class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2000, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_spatialref.h"
      31                 : #include "cpl_port.h"
      32                 : #include "cpl_error.h"
      33                 : #include "cpl_conv.h"
      34                 : #include "cpl_string.h"
      35                 : #include "cpl_multiproc.h"
      36                 : 
      37                 : #ifdef PROJ_STATIC
      38                 : #include "proj_api.h"
      39                 : #endif
      40                 : 
      41                 : CPL_CVSID("$Id: ogrct.cpp 19939 2010-06-27 21:06:56Z rouault $");
      42                 : 
      43                 : /* ==================================================================== */
      44                 : /*      PROJ.4 interface stuff.                                         */
      45                 : /* ==================================================================== */
      46                 : #ifndef PROJ_STATIC
      47                 : typedef struct { double u, v; } projUV;
      48                 : 
      49                 : #define projPJ void *
      50                 : #define projCtx void *
      51                 : #define RAD_TO_DEG      57.29577951308232
      52                 : #define DEG_TO_RAD      .0174532925199432958
      53                 : 
      54                 : #else
      55                 : 
      56                 : #if PJ_VERSION < 480
      57                 : #define projCtx void *
      58                 : #endif
      59                 : 
      60                 : #endif
      61                 : 
      62                 : static void *hPROJMutex = NULL;
      63                 : 
      64                 : static projPJ       (*pfn_pj_init_plus)(const char *) = NULL;
      65                 : static projPJ       (*pfn_pj_init)(int, char**) = NULL;
      66                 : static void     (*pfn_pj_free)(projPJ) = NULL;
      67                 : static int      (*pfn_pj_transform)(projPJ, projPJ, long, int, 
      68                 :                                     double *, double *, double * ) = NULL;
      69                 : static int         *(*pfn_pj_get_errno_ref)(void) = NULL;
      70                 : static char        *(*pfn_pj_strerrno)(int) = NULL;
      71                 : static char        *(*pfn_pj_get_def)(projPJ,int) = NULL;
      72                 : static void         (*pfn_pj_dalloc)(void *) = NULL;
      73                 : 
      74                 : static projPJ (*pfn_pj_init_plus_ctx)( projCtx, const char * ) = NULL;
      75                 : static int (*pfn_pj_ctx_get_errno)( projCtx ) = NULL;
      76                 : static projCtx (*pfn_pj_ctx_alloc)(void) = NULL;
      77                 : static void    (*pfn_pj_ctx_free)( projCtx ) = NULL;
      78                 : 
      79                 : #if (defined(WIN32) || defined(WIN32CE)) && !defined(__MINGW32__)
      80                 : #  define LIBNAME      "proj.dll"
      81                 : #elif defined(__MINGW32__)
      82                 : // XXX: If PROJ.4 library was properly built using libtool in Cygwin or MinGW
      83                 : // environments it has the interface version number embedded in the file name
      84                 : // (it is CURRENT-AGE number). If DLL came somewhere else (e.g. from MSVC
      85                 : // build) it can be named either way, so use PROJSO environment variable to
      86                 : // specify the right library name. By default assume that in Cygwin/MinGW all
      87                 : // components were buit in the same way.
      88                 : #  define LIBNAME      "libproj-0.dll"
      89                 : #elif defined(__CYGWIN__)
      90                 : #  define LIBNAME      "cygproj-0.dll"
      91                 : #elif defined(__APPLE__)
      92                 : #  define LIBNAME      "libproj.dylib"
      93                 : #else
      94                 : #  define LIBNAME      "libproj.so"
      95                 : #endif
      96                 : 
      97                 : /************************************************************************/
      98                 : /*                              OGRProj4CT                              */
      99                 : /************************************************************************/
     100                 : 
     101                 : class OGRProj4CT : public OGRCoordinateTransformation
     102                 : {
     103                 :     OGRSpatialReference *poSRSSource;
     104                 :     void        *psPJSource;
     105                 :     int         bSourceLatLong;
     106                 :     double      dfSourceToRadians;
     107                 :     double      dfSourceFromRadians;
     108                 :     int         bSourceWrap;
     109                 :     double      dfSourceWrapLong;
     110                 :     
     111                 : 
     112                 :     OGRSpatialReference *poSRSTarget;
     113                 :     void        *psPJTarget;
     114                 :     int         bTargetLatLong;
     115                 :     double      dfTargetToRadians;
     116                 :     double      dfTargetFromRadians;
     117                 :     int         bTargetWrap;
     118                 :     double      dfTargetWrapLong;
     119                 : 
     120                 :     int         nErrorCount;
     121                 :     
     122                 :     int         bCheckWithInvertProj;
     123                 :     double      dfThreshold;
     124                 :     
     125                 :     projCtx     pjctx;
     126                 : 
     127                 :     int         InitializeNoLock( OGRSpatialReference *poSource, 
     128                 :                                   OGRSpatialReference *poTarget );
     129                 : public:
     130                 :                 OGRProj4CT();
     131                 :     virtual     ~OGRProj4CT();
     132                 : 
     133                 :     int         Initialize( OGRSpatialReference *poSource, 
     134                 :                             OGRSpatialReference *poTarget );
     135                 : 
     136                 :     virtual OGRSpatialReference *GetSourceCS();
     137                 :     virtual OGRSpatialReference *GetTargetCS();
     138                 :     virtual int Transform( int nCount, 
     139                 :                            double *x, double *y, double *z = NULL );
     140                 :     virtual int TransformEx( int nCount, 
     141                 :                              double *x, double *y, double *z = NULL,
     142                 :                              int *panSuccess = NULL );
     143                 : 
     144                 : };
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                        GetProjLibraryName()                          */
     148                 : /************************************************************************/
     149                 : 
     150              28 : static const char* GetProjLibraryName()
     151                 : {
     152              28 :     const char *pszLibName = LIBNAME;
     153                 : #if !defined(WIN32CE)
     154              28 :     if( CPLGetConfigOption("PROJSO",NULL) != NULL )
     155               0 :         pszLibName = CPLGetConfigOption("PROJSO",NULL);
     156                 : #endif
     157              28 :     return pszLibName;
     158                 : }
     159                 : 
     160                 : /************************************************************************/
     161                 : /*                          LoadProjLibrary()                           */
     162                 : /************************************************************************/
     163                 : 
     164             144 : static int LoadProjLibrary()
     165                 : 
     166                 : {
     167             144 :     CPLMutexHolderD( &hPROJMutex );
     168                 :     static int  bTriedToLoad = FALSE;
     169                 :     const char *pszLibName;
     170                 :     
     171             144 :     if( bTriedToLoad )
     172             116 :         return( pfn_pj_transform != NULL );
     173                 : 
     174              28 :     bTriedToLoad = TRUE;
     175                 : 
     176              28 :     pszLibName = GetProjLibraryName();
     177                 : 
     178                 : #ifdef PROJ_STATIC
     179                 :     pfn_pj_init = pj_init;
     180                 :     pfn_pj_init_plus = pj_init_plus;
     181                 :     pfn_pj_free = pj_free;
     182                 :     pfn_pj_transform = pj_transform;
     183                 :     pfn_pj_get_errno_ref = (int *(*)(void)) pj_get_errno_ref;
     184                 :     pfn_pj_strerrno = pj_strerrno;
     185                 :     pfn_pj_dalloc = pj_dalloc;
     186                 : #if PJ_VERSION >= 446
     187                 :     pfn_pj_get_def = pj_get_def;
     188                 : #endif
     189                 : #if PJ_VERSION >= 480
     190                 :     pfn_pj_ctx_alloc = pj_ctx_alloc;
     191                 :     pfn_pj_ctx_free = pj_ctx_free;
     192                 :     pfn_pj_init_plus_ctx = pj_init_plus_ctx;
     193                 :     pfn_pj_ctx_get_errno = pj_ctx_get_errno;
     194                 : #endif
     195                 : #else
     196              28 :     CPLPushErrorHandler( CPLQuietErrorHandler );
     197                 : 
     198                 :     pfn_pj_init = (projPJ (*)(int, char**)) CPLGetSymbol( pszLibName,
     199              28 :                                                        "pj_init" );
     200              28 :     CPLPopErrorHandler();
     201                 :     
     202              28 :     if( pfn_pj_init == NULL )
     203               0 :        return( FALSE );
     204                 : 
     205                 :     pfn_pj_init_plus = (projPJ (*)(const char *)) 
     206              28 :         CPLGetSymbol( pszLibName, "pj_init_plus" );
     207                 :     pfn_pj_free = (void (*)(projPJ)) 
     208              28 :         CPLGetSymbol( pszLibName, "pj_free" );
     209                 :     pfn_pj_transform = (int (*)(projPJ,projPJ,long,int,double*,
     210                 :                                 double*,double*))
     211              28 :                         CPLGetSymbol( pszLibName, "pj_transform" );
     212                 :     pfn_pj_get_errno_ref = (int *(*)(void))
     213              28 :         CPLGetSymbol( pszLibName, "pj_get_errno_ref" );
     214                 :     pfn_pj_strerrno = (char *(*)(int))
     215              28 :         CPLGetSymbol( pszLibName, "pj_strerrno" );
     216                 : 
     217              28 :     CPLPushErrorHandler( CPLQuietErrorHandler );
     218                 :     pfn_pj_get_def = (char *(*)(projPJ,int))
     219              28 :         CPLGetSymbol( pszLibName, "pj_get_def" );
     220                 :     pfn_pj_dalloc = (void (*)(void*))
     221              28 :         CPLGetSymbol( pszLibName, "pj_dalloc" );
     222                 : 
     223                 :     /* PROJ 4.8.0 symbols */
     224                 :     pfn_pj_ctx_alloc = (projCtx (*)( void ))
     225              28 :         CPLGetSymbol( pszLibName, "pj_ctx_alloc" );
     226                 :     pfn_pj_ctx_free = (void (*)( projCtx ))
     227              28 :         CPLGetSymbol( pszLibName, "pj_ctx_free" );
     228                 :     pfn_pj_init_plus_ctx = (projPJ (*)( projCtx, const char * ))
     229              28 :         CPLGetSymbol( pszLibName, "pj_init_plus_ctx" );
     230                 :     pfn_pj_ctx_get_errno = (int (*)( projCtx ))
     231              28 :         CPLGetSymbol( pszLibName, "pj_ctx_get_errno" );
     232                 : 
     233              28 :     CPLPopErrorHandler();
     234              28 :     CPLErrorReset();
     235                 : #endif
     236                 : 
     237              28 :     if (pfn_pj_ctx_alloc != NULL &&
     238                 :         pfn_pj_ctx_free != NULL &&
     239                 :         pfn_pj_init_plus_ctx != NULL &&
     240                 :         pfn_pj_ctx_get_errno != NULL &&
     241                 :         CSLTestBoolean(CPLGetConfigOption("USE_PROJ_480_FEATURES", "YES")))
     242                 :     {
     243              28 :         CPLDebug("OGRCT", "PROJ >= 4.8.0 features enabled");
     244                 :     }
     245                 :     else
     246                 :     {
     247               0 :         pfn_pj_ctx_alloc = NULL;
     248               0 :         pfn_pj_ctx_free = NULL;
     249               0 :         pfn_pj_init_plus_ctx = NULL;
     250               0 :         pfn_pj_ctx_get_errno = NULL;
     251                 :     }
     252                 : 
     253              28 :     if( pfn_pj_transform == NULL )
     254                 :     {
     255                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     256                 :                   "Attempt to load %s, but couldn't find pj_transform.\n"
     257                 :                   "Please upgrade to PROJ 4.1.2 or later.", 
     258               0 :                   pszLibName );
     259                 : 
     260               0 :         return FALSE;
     261                 :     }
     262                 : 
     263              28 :     return( TRUE );
     264                 : }
     265                 : 
     266                 : /************************************************************************/
     267                 : /*                         OCTProj4Normalize()                          */
     268                 : /*                                                                      */
     269                 : /*      This function is really just here since we already have all     */
     270                 : /*      the code to load libproj.so.  It is intended to "normalize"     */
     271                 : /*      a proj.4 definition, expanding +init= definitions and so        */
     272                 : /*      forth as possible.                                              */
     273                 : /************************************************************************/
     274                 : 
     275             120 : char *OCTProj4Normalize( const char *pszProj4Src )
     276                 : 
     277                 : {
     278                 :     char        *pszNewProj4Def, *pszCopy;
     279             120 :     projPJ      psPJSource = NULL;
     280                 : 
     281             120 :     CPLMutexHolderD( &hPROJMutex );
     282                 : 
     283             120 :     if( !LoadProjLibrary() || pfn_pj_dalloc == NULL || pfn_pj_get_def == NULL )
     284               0 :         return CPLStrdup( pszProj4Src );
     285                 : 
     286             120 :     psPJSource = pfn_pj_init_plus( pszProj4Src );
     287                 : 
     288             120 :     if( psPJSource == NULL )
     289              71 :         return CPLStrdup( pszProj4Src );
     290                 : 
     291              49 :     pszNewProj4Def = pfn_pj_get_def( psPJSource, 0 );
     292                 : 
     293              49 :     pfn_pj_free( psPJSource );
     294                 : 
     295              49 :     if( pszNewProj4Def == NULL )
     296               0 :         return CPLStrdup( pszProj4Src );
     297                 : 
     298              49 :     pszCopy = CPLStrdup( pszNewProj4Def );
     299              49 :     pfn_pj_dalloc( pszNewProj4Def );
     300                 : 
     301              49 :     return pszCopy;
     302                 : }
     303                 : 
     304                 : /************************************************************************/
     305                 : /*                 OCTDestroyCoordinateTransformation()                 */
     306                 : /************************************************************************/
     307                 : 
     308                 : /**
     309                 :  * \brief OGRCoordinateTransformation destructor. 
     310                 :  *
     311                 :  * This function is the same as OGRCoordinateTransformation::DestroyCT()
     312                 :  *
     313                 :  * @param hCT the object to delete
     314                 :  */
     315                 :  
     316                 : void CPL_STDCALL
     317              54 : OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
     318                 : 
     319                 : {
     320              54 :     delete (OGRCoordinateTransformation *) hCT;
     321              54 : }
     322                 : 
     323                 : /************************************************************************/
     324                 : /*                             DestroyCT()                              */
     325                 : /************************************************************************/
     326                 : 
     327                 : /**
     328                 :  * \brief OGRCoordinateTransformation destructor. 
     329                 :  *
     330                 :  * This function is the same as OGRCoordinateTransformation::~OGRCoordinateTransformation()
     331                 :  * and OCTDestroyCoordinateTransformation()
     332                 :  *
     333                 :  * This static method will destroy a OGRCoordinateTransformation.  It is
     334                 :  * equivalent to calling delete on the object, but it ensures that the
     335                 :  * deallocation is properly executed within the OGR libraries heap on
     336                 :  * platforms where this can matter (win32).  
     337                 :  *
     338                 :  * @param poCT the object to delete
     339                 :  *
     340                 :  * @since GDAL 1.7.0
     341                 :  */
     342                 :  
     343              34 : void OGRCoordinateTransformation::DestroyCT(OGRCoordinateTransformation* poCT)
     344                 : {
     345              34 :     delete poCT;
     346              34 : }
     347                 : 
     348                 : /************************************************************************/
     349                 : /*                 OGRCreateCoordinateTransformation()                  */
     350                 : /************************************************************************/
     351                 : 
     352                 : /**
     353                 :  * Create transformation object.
     354                 :  *
     355                 :  * This is the same as the C function OCTNewCoordinateTransformation().
     356                 :  *
     357                 :  * Input spatial reference system objects are assigned 
     358                 :  * by copy (calling clone() method) and no ownership transfer occurs.
     359                 :  *
     360                 :  * The delete operator, or OCTDestroyCoordinateTransformation() should
     361                 :  * be used to destroy transformation objects. 
     362                 :  *
     363                 :  * The PROJ.4 library must be available at run-time.
     364                 :  *
     365                 :  * @param poSource source spatial reference system. 
     366                 :  * @param poTarget target spatial reference system. 
     367                 :  * @return NULL on failure or a ready to use transformation object.
     368                 :  */
     369                 : 
     370                 : OGRCoordinateTransformation*  
     371                 : OGRCreateCoordinateTransformation( OGRSpatialReference *poSource, 
     372             172 :                                    OGRSpatialReference *poTarget )
     373                 : 
     374                 : {
     375                 :     OGRProj4CT  *poCT;
     376                 : 
     377             172 :     if( pfn_pj_init == NULL && !LoadProjLibrary() )
     378                 :     {
     379                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     380                 :                   "Unable to load PROJ.4 library (%s), creation of\n"
     381                 :                   "OGRCoordinateTransformation failed.",
     382               0 :                   GetProjLibraryName() );
     383               0 :         return NULL;
     384                 :     }
     385                 : 
     386             172 :     poCT = new OGRProj4CT();
     387                 :     
     388             172 :     if( !poCT->Initialize( poSource, poTarget ) )
     389                 :     {
     390               0 :         delete poCT;
     391               0 :         return NULL;
     392                 :     }
     393                 :     else
     394                 :     {
     395             172 :         return poCT;
     396                 :     }
     397                 : }
     398                 : 
     399                 : /************************************************************************/
     400                 : /*                   OCTNewCoordinateTransformation()                   */
     401                 : /************************************************************************/
     402                 : 
     403                 : /**
     404                 :  * Create transformation object.
     405                 :  *
     406                 :  * This is the same as the C++ function OGRCreateCoordinateTransformation().
     407                 :  *
     408                 :  * Input spatial reference system objects are assigned 
     409                 :  * by copy (calling clone() method) and no ownership transfer occurs.
     410                 :  *
     411                 :  * OCTDestroyCoordinateTransformation() should
     412                 :  * be used to destroy transformation objects. 
     413                 :  *
     414                 :  * The PROJ.4 library must be available at run-time.
     415                 :  *
     416                 :  * @param hSourceSRS source spatial reference system. 
     417                 :  * @param hTargetSRS target spatial reference system. 
     418                 :  * @return NULL on failure or a ready to use transformation object.
     419                 :  */
     420                 :  
     421                 : OGRCoordinateTransformationH CPL_STDCALL 
     422                 : OCTNewCoordinateTransformation(
     423              51 :     OGRSpatialReferenceH hSourceSRS, OGRSpatialReferenceH hTargetSRS )
     424                 : 
     425                 : {
     426                 :     return (OGRCoordinateTransformationH) 
     427                 :         OGRCreateCoordinateTransformation( 
     428                 :             (OGRSpatialReference *) hSourceSRS,
     429              51 :             (OGRSpatialReference *) hTargetSRS );
     430                 : }
     431                 : 
     432                 : /************************************************************************/
     433                 : /*                             OGRProj4CT()                             */
     434                 : /************************************************************************/
     435                 : 
     436             172 : OGRProj4CT::OGRProj4CT()
     437                 : 
     438                 : {
     439             172 :     poSRSSource = NULL;
     440             172 :     poSRSTarget = NULL;
     441             172 :     psPJSource = NULL;
     442             172 :     psPJTarget = NULL;
     443                 :     
     444             172 :     nErrorCount = 0;
     445                 :     
     446             172 :     bCheckWithInvertProj = FALSE;
     447             172 :     dfThreshold = 0;
     448                 :     
     449             172 :     if (pfn_pj_ctx_alloc != NULL)
     450             172 :         pjctx = pfn_pj_ctx_alloc();
     451                 :     else
     452               0 :         pjctx = NULL;
     453             172 : }
     454                 : 
     455                 : /************************************************************************/
     456                 : /*                            ~OGRProj4CT()                             */
     457                 : /************************************************************************/
     458                 : 
     459             172 : OGRProj4CT::~OGRProj4CT()
     460                 : 
     461                 : {
     462             172 :     if( poSRSSource != NULL )
     463                 :     {
     464             172 :         if( poSRSSource->Dereference() <= 0 )
     465             172 :             delete poSRSSource;
     466                 :     }
     467                 : 
     468             172 :     if( poSRSTarget != NULL )
     469                 :     {
     470             172 :         if( poSRSTarget->Dereference() <= 0 )
     471             170 :             delete poSRSTarget;
     472                 :     }
     473                 : 
     474             172 :     if (pjctx != NULL)
     475                 :     {
     476             172 :         pfn_pj_ctx_free(pjctx);
     477                 : 
     478             172 :         if( psPJSource != NULL )
     479             172 :             pfn_pj_free( psPJSource );
     480                 : 
     481             172 :         if( psPJTarget != NULL )
     482             172 :             pfn_pj_free( psPJTarget );
     483                 :     }
     484                 :     else
     485                 :     {
     486               0 :         CPLMutexHolderD( &hPROJMutex );
     487                 : 
     488               0 :         if( psPJSource != NULL )
     489               0 :             pfn_pj_free( psPJSource );
     490                 : 
     491               0 :         if( psPJTarget != NULL )
     492               0 :             pfn_pj_free( psPJTarget );
     493                 :     }
     494             172 : }
     495                 : 
     496                 : /************************************************************************/
     497                 : /*                             Initialize()                             */
     498                 : /************************************************************************/
     499                 : 
     500                 : int OGRProj4CT::Initialize( OGRSpatialReference * poSourceIn, 
     501             172 :                             OGRSpatialReference * poTargetIn )
     502                 : 
     503                 : {
     504             172 :     if (pjctx != NULL)
     505                 :     {
     506             172 :         return InitializeNoLock(poSourceIn, poTargetIn);
     507                 :     }
     508                 : 
     509               0 :     CPLMutexHolderD( &hPROJMutex );
     510               0 :     return InitializeNoLock(poSourceIn, poTargetIn);
     511                 : }
     512                 : 
     513                 : /************************************************************************/
     514                 : /*                         InitializeNoLock()                           */
     515                 : /************************************************************************/
     516                 : 
     517                 : int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn, 
     518             172 :                                   OGRSpatialReference * poTargetIn )
     519                 : 
     520                 : {
     521             172 :     if( poSourceIn == NULL || poTargetIn == NULL )
     522               0 :         return FALSE;
     523                 : 
     524             172 :     poSRSSource = poSourceIn->Clone();
     525             172 :     poSRSTarget = poTargetIn->Clone();
     526                 : 
     527             172 :     bSourceLatLong = poSRSSource->IsGeographic();
     528             172 :     bTargetLatLong = poSRSTarget->IsGeographic();
     529                 : 
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Setup source and target translations to radians for lat/long    */
     532                 : /*      systems.                                                        */
     533                 : /* -------------------------------------------------------------------- */
     534             172 :     dfSourceToRadians = DEG_TO_RAD;
     535             172 :     dfSourceFromRadians = RAD_TO_DEG;
     536             172 :     bSourceWrap = FALSE;
     537             172 :     dfSourceWrapLong = 0.0;
     538                 : 
     539             172 :     if( bSourceLatLong )
     540                 :     {
     541              85 :         OGR_SRSNode *poUNITS = poSRSSource->GetAttrNode( "GEOGCS|UNIT" );
     542              85 :         if( poUNITS && poUNITS->GetChildCount() >= 2 )
     543                 :         {
     544              85 :             dfSourceToRadians = atof(poUNITS->GetChild(1)->GetValue());
     545              85 :             if( dfSourceToRadians == 0.0 )
     546               0 :                 dfSourceToRadians = DEG_TO_RAD;
     547                 :             else
     548              85 :                 dfSourceFromRadians = 1 / dfSourceToRadians;
     549                 :         }
     550                 :     }
     551                 : 
     552             172 :     dfTargetToRadians = DEG_TO_RAD;
     553             172 :     dfTargetFromRadians = RAD_TO_DEG;
     554             172 :     bTargetWrap = FALSE;
     555             172 :     dfTargetWrapLong = 0.0;
     556                 : 
     557             172 :     if( bTargetLatLong )
     558                 :     {
     559              90 :         OGR_SRSNode *poUNITS = poSRSTarget->GetAttrNode( "GEOGCS|UNIT" );
     560              90 :         if( poUNITS && poUNITS->GetChildCount() >= 2 )
     561                 :         {
     562              90 :             dfTargetToRadians = atof(poUNITS->GetChild(1)->GetValue());
     563              90 :             if( dfTargetToRadians == 0.0 )
     564               0 :                 dfTargetToRadians = DEG_TO_RAD;
     565                 :             else
     566              90 :                 dfTargetFromRadians = 1 / dfTargetToRadians;
     567                 :         }
     568                 :     }
     569                 : 
     570                 : /* -------------------------------------------------------------------- */
     571                 : /*      Preliminary logic to setup wrapping.                            */
     572                 : /* -------------------------------------------------------------------- */
     573                 :     const char *pszCENTER_LONG;
     574                 : 
     575             172 :     if( CPLGetConfigOption( "CENTER_LONG", NULL ) != NULL )
     576                 :     {
     577               0 :         bSourceWrap = bTargetWrap = TRUE;
     578                 :         dfSourceWrapLong = dfTargetWrapLong = 
     579               0 :             atof(CPLGetConfigOption( "CENTER_LONG", "" ));
     580               0 :         CPLDebug( "OGRCT", "Wrap at %g.", dfSourceWrapLong );
     581                 :     }
     582                 : 
     583             172 :     pszCENTER_LONG = poSRSSource->GetExtension( "GEOGCS", "CENTER_LONG" );
     584             172 :     if( pszCENTER_LONG != NULL )
     585                 :     {
     586              37 :         dfSourceWrapLong = atof(pszCENTER_LONG);
     587              37 :         bSourceWrap = TRUE;
     588              37 :         CPLDebug( "OGRCT", "Wrap source at %g.", dfSourceWrapLong );
     589                 :     }
     590                 : 
     591             172 :     pszCENTER_LONG = poSRSTarget->GetExtension( "GEOGCS", "CENTER_LONG" );
     592             172 :     if( pszCENTER_LONG != NULL )
     593                 :     {
     594              37 :         dfTargetWrapLong = atof(pszCENTER_LONG);
     595              37 :         bTargetWrap = TRUE;
     596              37 :         CPLDebug( "OGRCT", "Wrap target at %g.", dfTargetWrapLong );
     597                 :     }
     598                 :     
     599             172 :     bCheckWithInvertProj = CSLTestBoolean(CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", "NO" ));
     600                 :     
     601                 :     /* The threshold is rather experimental... Works well with the cases of ticket #2305 */
     602             172 :     if (bSourceLatLong)
     603              85 :         dfThreshold = atof(CPLGetConfigOption( "THRESHOLD", ".1" ));
     604                 :     else
     605                 :         /* 1 works well for most projections, except for +proj=aeqd that requires */
     606                 :         /* a tolerance of 10000 */
     607              87 :         dfThreshold = atof(CPLGetConfigOption( "THRESHOLD", "10000" ));
     608                 : 
     609                 : /* -------------------------------------------------------------------- */
     610                 : /*      Establish PROJ.4 handle for source if projection.               */
     611                 : /* -------------------------------------------------------------------- */
     612                 :     // OGRThreadSafety: The following variable is not a thread safety issue 
     613                 :     // since the only issue is incrementing while accessing which at worse 
     614                 :     // means debug output could be one "increment" late. 
     615                 :     static int   nDebugReportCount = 0;
     616                 : 
     617             172 :     char        *pszProj4Defn = NULL;
     618                 : 
     619             172 :     if( poSRSSource->exportToProj4( &pszProj4Defn ) != OGRERR_NONE )
     620                 :     {
     621               0 :         CPLFree( pszProj4Defn );
     622               0 :         return FALSE;
     623                 :     }
     624                 : 
     625             172 :     if( strlen(pszProj4Defn) == 0 )
     626                 :     {
     627               0 :         CPLFree( pszProj4Defn );
     628                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     629                 :                   "No PROJ.4 translation for source SRS, coordinate\n"
     630               0 :                   "transformation initialization has failed." );
     631               0 :         return FALSE;
     632                 :     }
     633                 : 
     634             172 :     if (pjctx)
     635             172 :         psPJSource = pfn_pj_init_plus_ctx( pjctx, pszProj4Defn );
     636                 :     else
     637               0 :         psPJSource = pfn_pj_init_plus( pszProj4Defn );
     638                 :     
     639             172 :     if( psPJSource == NULL )
     640                 :     {
     641               0 :         if( pjctx != NULL)
     642                 :         {
     643               0 :             int pj_errno = pfn_pj_ctx_get_errno(pjctx);
     644                 : 
     645                 :             /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
     646               0 :             CPLMutexHolderD(&hPROJMutex);
     647                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     648                 :                       "Failed to initialize PROJ.4 with `%s'.\n%s", 
     649               0 :                       pszProj4Defn, pfn_pj_strerrno(pj_errno) );
     650                 :         }
     651               0 :         else if( pfn_pj_get_errno_ref != NULL
     652                 :             && pfn_pj_strerrno != NULL )
     653                 :         {
     654               0 :             int *p_pj_errno = pfn_pj_get_errno_ref();
     655                 : 
     656                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     657                 :                       "Failed to initialize PROJ.4 with `%s'.\n%s", 
     658               0 :                       pszProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
     659                 :         }
     660                 :         else
     661                 :         {
     662                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     663                 :                       "Failed to initialize PROJ.4 with `%s'.\n", 
     664               0 :                       pszProj4Defn );
     665                 :         }
     666                 :     }
     667                 :     
     668             172 :     if( nDebugReportCount < 10 )
     669              83 :         CPLDebug( "OGRCT", "Source: %s", pszProj4Defn );
     670                 :     
     671             172 :     CPLFree( pszProj4Defn );
     672                 : 
     673             172 :     if( psPJSource == NULL )
     674               0 :         return FALSE;
     675                 : 
     676                 : /* -------------------------------------------------------------------- */
     677                 : /*      Establish PROJ.4 handle for target if projection.               */
     678                 : /* -------------------------------------------------------------------- */
     679             172 :     pszProj4Defn = NULL;
     680                 : 
     681             172 :     if( poSRSTarget->exportToProj4( &pszProj4Defn ) != OGRERR_NONE )
     682                 :     {
     683               0 :         CPLFree( pszProj4Defn );
     684               0 :         return FALSE;
     685                 :     }
     686                 : 
     687             172 :     if( strlen(pszProj4Defn) == 0 )
     688                 :     {
     689               0 :         CPLFree( pszProj4Defn );
     690                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     691                 :                   "No PROJ.4 translation for destination SRS, coordinate\n"
     692               0 :                   "transformation initialization has failed." );
     693               0 :         return FALSE;
     694                 :     }
     695                 : 
     696             172 :     if (pjctx)
     697             172 :         psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszProj4Defn );
     698                 :     else
     699               0 :         psPJTarget = pfn_pj_init_plus( pszProj4Defn );
     700                 :     
     701             172 :     if( psPJTarget == NULL )
     702                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     703                 :                   "Failed to initialize PROJ.4 with `%s'.", 
     704               0 :                   pszProj4Defn );
     705                 :     
     706             172 :     if( nDebugReportCount < 10 )
     707                 :     {
     708              83 :         CPLDebug( "OGRCT", "Target: %s", pszProj4Defn );
     709              83 :         nDebugReportCount++;
     710                 :     }
     711                 : 
     712             172 :     CPLFree( pszProj4Defn );
     713                 :     
     714             172 :     if( psPJTarget == NULL )
     715               0 :         return FALSE;
     716                 : 
     717             172 :     return TRUE;
     718                 : }
     719                 : 
     720                 : /************************************************************************/
     721                 : /*                            GetSourceCS()                             */
     722                 : /************************************************************************/
     723                 : 
     724               0 : OGRSpatialReference *OGRProj4CT::GetSourceCS()
     725                 : 
     726                 : {
     727               0 :     return poSRSSource;
     728                 : }
     729                 : 
     730                 : /************************************************************************/
     731                 : /*                            GetTargetCS()                             */
     732                 : /************************************************************************/
     733                 : 
     734              46 : OGRSpatialReference *OGRProj4CT::GetTargetCS()
     735                 : 
     736                 : {
     737              46 :     return poSRSTarget;
     738                 : }
     739                 : 
     740                 : /************************************************************************/
     741                 : /*                             Transform()                              */
     742                 : /*                                                                      */
     743                 : /*      This is a small wrapper for the extended transform version.     */
     744                 : /************************************************************************/
     745                 : 
     746             198 : int OGRProj4CT::Transform( int nCount, double *x, double *y, double *z )
     747                 : 
     748                 : {
     749             198 :     int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
     750                 :     int bOverallSuccess, i;
     751                 : 
     752             198 :     bOverallSuccess = TransformEx( nCount, x, y, z, pabSuccess );
     753                 : 
     754             872 :     for( i = 0; i < nCount; i++ )
     755                 :     {
     756             674 :         if( !pabSuccess[i] )
     757                 :         {
     758               0 :             bOverallSuccess = FALSE;
     759               0 :             break;
     760                 :         }
     761                 :     }
     762                 : 
     763             198 :     CPLFree( pabSuccess );
     764                 : 
     765             198 :     return bOverallSuccess;
     766                 : }
     767                 : 
     768                 : /************************************************************************/
     769                 : /*                            OCTTransform()                            */
     770                 : /************************************************************************/
     771                 : 
     772                 : int CPL_STDCALL OCTTransform( OGRCoordinateTransformationH hTransform,
     773             158 :                               int nCount, double *x, double *y, double *z )
     774                 : 
     775                 : {
     776                 :     return ((OGRCoordinateTransformation*) hTransform)->
     777             158 :         Transform( nCount, x, y,z );
     778                 : }
     779                 : 
     780                 : /************************************************************************/
     781                 : /*                            TransformEx()                             */
     782                 : /************************************************************************/
     783                 : 
     784                 : int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
     785           31208 :                              int *pabSuccess )
     786                 : 
     787                 : {
     788                 :     int   err, i;
     789                 : 
     790                 : /* -------------------------------------------------------------------- */
     791                 : /*      Potentially transform to radians.                               */
     792                 : /* -------------------------------------------------------------------- */
     793           31208 :     if( bSourceLatLong )
     794                 :     {
     795            7347 :         if( bSourceWrap )
     796                 :         {
     797           19771 :             for( i = 0; i < nCount; i++ )
     798                 :             {
     799           14068 :                 if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
     800                 :                 {
     801           13285 :                     if( x[i] < dfSourceWrapLong - 180.0 )
     802               0 :                         x[i] += 360.0;
     803           13285 :                     else if( x[i] > dfSourceWrapLong + 180 )
     804               0 :                         x[i] -= 360.0;
     805                 :                 }
     806                 :             }
     807                 :         }
     808                 : 
     809         1495914 :         for( i = 0; i < nCount; i++ )
     810                 :         {
     811         1488567 :             if( x[i] != HUGE_VAL )
     812                 :             {
     813         1487784 :                 x[i] *= dfSourceToRadians;
     814         1487784 :                 y[i] *= dfSourceToRadians;
     815                 :             }
     816                 :         }
     817                 :     }
     818                 :     
     819                 : /* -------------------------------------------------------------------- */
     820                 : /*      Do the transformation using PROJ.4.                             */
     821                 : /* -------------------------------------------------------------------- */
     822           31208 :     if (pjctx == NULL)
     823                 :     {
     824                 :         /* The mutex has already been created */
     825               0 :         CPLAssert(hPROJMutex != NULL);
     826               0 :         CPLAcquireMutex(hPROJMutex, 1000.0);
     827                 :     }
     828                 :         
     829           31208 :     if (bCheckWithInvertProj)
     830                 :     {
     831                 :         /* For some projections, we cannot detect if we are trying to reproject */
     832                 :         /* coordinates outside the validity area of the projection. So let's do */
     833                 :         /* the reverse reprojection and compare with the source coordinates */
     834                 :         
     835            9834 :         double *ori_x = NULL;
     836            9834 :         double *ori_y = NULL;
     837            9834 :         double *ori_z = NULL;
     838            9834 :         ori_x = (double*)CPLMalloc(sizeof(double)*nCount);
     839            9834 :         memcpy(ori_x, x, sizeof(double)*nCount);
     840            9834 :         ori_y = (double*)CPLMalloc(sizeof(double)*nCount);
     841            9834 :         memcpy(ori_y, y, sizeof(double)*nCount);
     842            9834 :         if (z)
     843                 :         {
     844            9834 :             ori_z = (double*)CPLMalloc(sizeof(double)*nCount);
     845            9834 :             memcpy(ori_z, z, sizeof(double)*nCount);
     846                 :         }
     847            9834 :         err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z );
     848            9834 :         if (err == 0)
     849                 :         {
     850            9834 :             double* target_x = (double*)CPLMalloc(sizeof(double)*nCount);
     851            9834 :             double* target_y = (double*)CPLMalloc(sizeof(double)*nCount);
     852            9834 :             double* target_z = NULL;
     853            9834 :             memcpy(target_x, x, sizeof(double)*nCount);
     854            9834 :             memcpy(target_y, y, sizeof(double)*nCount);
     855            9834 :             if (z)
     856                 :             {
     857            9834 :                 target_z = (double*)CPLMalloc(sizeof(double)*nCount);
     858            9834 :                 memcpy(target_z, z, sizeof(double)*nCount);
     859                 :             }
     860                 :             
     861                 :             err = pfn_pj_transform( psPJTarget, psPJSource , nCount, 1,
     862            9834 :                                     target_x, target_y, target_z );
     863            9834 :             if (err == 0)
     864                 :             {
     865          767888 :                 for( i = 0; i < nCount; i++ )
     866                 :                 {
     867          758054 :                     if ( x[i] != HUGE_VAL && y[i] != HUGE_VAL &&
     868                 :                         (fabs(target_x[i] - ori_x[i]) > dfThreshold ||
     869                 :                          fabs(target_y[i] - ori_y[i]) > dfThreshold) )
     870                 :                     {
     871          158741 :                         x[i] = HUGE_VAL;
     872          158741 :                         y[i] = HUGE_VAL;
     873                 :                     }
     874                 :                 }
     875                 :             }
     876                 :             
     877            9834 :             CPLFree(target_x);
     878            9834 :             CPLFree(target_y);
     879            9834 :             CPLFree(target_z);
     880                 :         }
     881            9834 :         CPLFree(ori_x);
     882            9834 :         CPLFree(ori_y);
     883            9834 :         CPLFree(ori_z);
     884                 :     }
     885                 :     else
     886                 :     {
     887           21374 :         err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z );
     888                 :     }
     889                 : 
     890                 : /* -------------------------------------------------------------------- */
     891                 : /*      Try to report an error through CPL.  Get proj.4 error string    */
     892                 : /*      if possible.  Try to avoid reporting thousands of error         */
     893                 : /*      ... supress further error reporting on this OGRProj4CT if we    */
     894                 : /*      have already reported 20 errors.                                */
     895                 : /* -------------------------------------------------------------------- */
     896           31208 :     if( err != 0 )
     897                 :     {
     898               0 :         if( pabSuccess )
     899               0 :             memset( pabSuccess, 0, sizeof(int) * nCount );
     900                 : 
     901               0 :         if( ++nErrorCount < 20 )
     902                 :         {
     903               0 :             if (pjctx != NULL)
     904                 :                 /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
     905               0 :                 CPLAcquireMutex(hPROJMutex, 1000.0);
     906                 : 
     907               0 :             const char *pszError = NULL;
     908               0 :             if( pfn_pj_strerrno != NULL )
     909               0 :                 pszError = pfn_pj_strerrno( err );
     910                 :             
     911               0 :             if( pszError == NULL )
     912                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     913                 :                           "Reprojection failed, err = %d", 
     914               0 :                           err );
     915                 :             else
     916               0 :                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
     917                 : 
     918               0 :             if (pjctx != NULL)
     919                 :                 /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
     920               0 :                 CPLReleaseMutex(hPROJMutex);
     921                 :         }
     922               0 :         else if( nErrorCount == 20 )
     923                 :         {
     924                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     925                 :                       "Reprojection failed, err = %d, further errors will be supressed on the transform object.", 
     926               0 :                       err );
     927                 :         }
     928                 : 
     929               0 :         if (pjctx == NULL)
     930               0 :             CPLReleaseMutex(hPROJMutex);
     931               0 :         return FALSE;
     932                 :     }
     933                 : 
     934           31208 :     if (pjctx == NULL)
     935               0 :         CPLReleaseMutex(hPROJMutex);
     936                 : 
     937                 : /* -------------------------------------------------------------------- */
     938                 : /*      Potentially transform back to degrees.                          */
     939                 : /* -------------------------------------------------------------------- */
     940           31208 :     if( bTargetLatLong )
     941                 :     {
     942         2239148 :         for( i = 0; i < nCount; i++ )
     943                 :         {
     944         2229354 :             if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
     945                 :             {
     946         2071472 :                 x[i] *= dfTargetFromRadians;
     947         2071472 :                 y[i] *= dfTargetFromRadians;
     948                 :             }
     949                 :         }
     950                 : 
     951            9794 :         if( bTargetWrap )
     952                 :         {
     953         2238356 :             for( i = 0; i < nCount; i++ )
     954                 :             {
     955         2228721 :                 if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
     956                 :                 {
     957         2070839 :                     if( x[i] < dfTargetWrapLong - 180.0 )
     958             808 :                         x[i] += 360.0;
     959         2070031 :                     else if( x[i] > dfTargetWrapLong + 180 )
     960               0 :                         x[i] -= 360.0;
     961                 :                 }
     962                 :             }
     963                 :         }
     964                 :     }
     965                 : 
     966                 : /* -------------------------------------------------------------------- */
     967                 : /*      Establish error information if pabSuccess provided.             */
     968                 : /* -------------------------------------------------------------------- */
     969           31208 :     if( pabSuccess )
     970                 :     {
     971         2319856 :         for( i = 0; i < nCount; i++ )
     972                 :         {
     973         2448350 :             if( x[i] == HUGE_VAL || y[i] == HUGE_VAL )
     974          159702 :                 pabSuccess[i] = FALSE;
     975                 :             else
     976         2128946 :                 pabSuccess[i] = TRUE;
     977                 :         }
     978                 :     }
     979                 : 
     980           31208 :     return TRUE;
     981                 : }
     982                 : 
     983                 : /************************************************************************/
     984                 : /*                           OCTTransformEx()                           */
     985                 : /************************************************************************/
     986                 : 
     987                 : int CPL_STDCALL OCTTransformEx( OGRCoordinateTransformationH hTransform,
     988                 :                                 int nCount, double *x, double *y, double *z,
     989               0 :                                 int *pabSuccess )
     990                 : 
     991                 : {
     992                 :     return ((OGRCoordinateTransformation*) hTransform)->
     993               0 :         TransformEx( nCount, x, y, z, pabSuccess );
     994                 : }
     995                 : 

Generated by: LTP GCOV extension version 1.5