root/trunk/gdal/ogr/ogrct.cpp

Revision 15384, 24.7 kB (checked in by dron, 2 months ago)

Use proper PROJ.4 name in MinGW environment ("libproj-0.dll" instead
of "proj.dll").

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  * $Id$
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$");
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
51 #define RAD_TO_DEG      57.29577951308232
52 #define DEG_TO_RAD      .0174532925199432958
53
54 #endif
55
56 static void *hPROJMutex = NULL;
57
58 static projPJ       (*pfn_pj_init_plus)(const char *) = NULL;
59 static projPJ       (*pfn_pj_init)(int, char**) = NULL;
60 static projUV       (*pfn_pj_fwd)(projUV, projPJ) = NULL;
61 static projUV       (*pfn_pj_inv)(projUV, projPJ) = NULL;
62 static void     (*pfn_pj_free)(projPJ) = NULL;
63 static int      (*pfn_pj_transform)(projPJ, projPJ, long, int,
64                                     double *, double *, double * ) = NULL;
65 static int         *(*pfn_pj_get_errno_ref)(void) = NULL;
66 static char        *(*pfn_pj_strerrno)(int) = NULL;
67 static char        *(*pfn_pj_get_def)(projPJ,int) = NULL;
68 static void         (*pfn_pj_dalloc)(void *) = NULL;
69
70 #if (defined(WIN32) || defined(WIN32CE)) && !defined(__MINGW32__)
71 define LIBNAME      "proj.dll"
72 #elif defined(__CYGWIN__) || defined(__MINGW32__)
73 // XXX: If PROJ.4 library was properly built using libtool in Cygwin or MinGW
74 // environments it has the interface version number embedded in the file name
75 // (it is CURRENT-AGE number). If DLL came somewhere else (e.g. from MSVC
76 // build) it can be named either way, so use PROJSO environment variable to
77 // specify the right library name. By default assume that in Cygwin/MinGW all
78 // components were buit in the same way.
79 # define LIBNAME      "libproj-0.dll"
80 #elif defined(__APPLE__)
81 define LIBNAME      "libproj.dylib"
82 #else
83 define LIBNAME      "libproj.so"
84 #endif
85
86 /************************************************************************/
87 /*                              OGRProj4CT                              */
88 /************************************************************************/
89
90 class OGRProj4CT : public OGRCoordinateTransformation
91 {
92     OGRSpatialReference *poSRSSource;
93     void        *psPJSource;
94     int         bSourceLatLong;
95     double      dfSourceToRadians;
96     double      dfSourceFromRadians;
97     int         bSourceWrap;
98     double      dfSourceWrapLong;
99    
100
101     OGRSpatialReference *poSRSTarget;
102     void        *psPJTarget;
103     int         bTargetLatLong;
104     double      dfTargetToRadians;
105     double      dfTargetFromRadians;
106     int         bTargetWrap;
107     double      dfTargetWrapLong;
108
109     int         nErrorCount;
110
111 public:
112                 OGRProj4CT();
113     virtual     ~OGRProj4CT();
114
115     int         Initialize( OGRSpatialReference *poSource,
116                             OGRSpatialReference *poTarget );
117
118     virtual OGRSpatialReference *GetSourceCS();
119     virtual OGRSpatialReference *GetTargetCS();
120     virtual int Transform( int nCount,
121                            double *x, double *y, double *z = NULL );
122     virtual int TransformEx( int nCount,
123                              double *x, double *y, double *z = NULL,
124                              int *panSuccess = NULL );
125
126 };
127
128 /************************************************************************/
129 /*                        GetProjLibraryName()                          */
130 /************************************************************************/
131
132 static const char* GetProjLibraryName()
133 {
134     const char *pszLibName = LIBNAME;
135 #if !defined(WIN32CE)
136     if( CPLGetConfigOption("PROJSO",NULL) != NULL )
137         pszLibName = CPLGetConfigOption("PROJSO",NULL);
138 #endif
139     return pszLibName;
140 }
141
142 /************************************************************************/
143 /*                          LoadProjLibrary()                           */
144 /************************************************************************/
145
146 static int LoadProjLibrary()
147
148 {
149     CPLMutexHolderD( &hPROJMutex );
150     static int  bTriedToLoad = FALSE;
151     const char *pszLibName;
152    
153     if( bTriedToLoad )
154         return( pfn_pj_transform != NULL );
155
156     bTriedToLoad = TRUE;
157
158     pszLibName = GetProjLibraryName();
159
160 #ifdef PROJ_STATIC
161     pfn_pj_init = pj_init;
162     pfn_pj_init_plus = pj_init_plus;
163     pfn_pj_fwd = pj_fwd;
164     pfn_pj_inv = pj_inv;
165     pfn_pj_free = pj_free;
166     pfn_pj_transform = pj_transform;
167     pfn_pj_get_errno_ref = (int *(*)(void)) pj_get_errno_ref;
168     pfn_pj_strerrno = pj_strerrno;
169     pfn_pj_dalloc = pj_dalloc;
170 #if PJ_VERSION >= 446
171     pfn_pj_get_def = pj_get_def;
172 #endif   
173 #else
174     CPLPushErrorHandler( CPLQuietErrorHandler );
175
176     pfn_pj_init = (projPJ (*)(int, char**)) CPLGetSymbol( pszLibName,
177                                                        "pj_init" );
178     CPLPopErrorHandler();
179    
180     if( pfn_pj_init == NULL )
181        return( FALSE );
182
183     pfn_pj_init_plus = (projPJ (*)(const char *))
184         CPLGetSymbol( pszLibName, "pj_init_plus" );
185     pfn_pj_fwd = (projUV (*)(projUV,projPJ))
186         CPLGetSymbol( pszLibName, "pj_fwd" );
187     pfn_pj_inv = (projUV (*)(projUV,projPJ))
188         CPLGetSymbol( pszLibName, "pj_inv" );
189     pfn_pj_free = (void (*)(projPJ))
190         CPLGetSymbol( pszLibName, "pj_free" );
191     pfn_pj_transform = (int (*)(projPJ,projPJ,long,int,double*,
192                                 double*,double*))
193                         CPLGetSymbol( pszLibName, "pj_transform" );
194     pfn_pj_get_errno_ref = (int *(*)(void))
195         CPLGetSymbol( pszLibName, "pj_get_errno_ref" );
196     pfn_pj_strerrno = (char *(*)(int))
197         CPLGetSymbol( pszLibName, "pj_strerrno" );
198
199     CPLPushErrorHandler( CPLQuietErrorHandler );
200     pfn_pj_get_def = (char *(*)(projPJ,int))
201         CPLGetSymbol( pszLibName, "pj_get_def" );
202     pfn_pj_dalloc = (void (*)(void*))
203         CPLGetSymbol( pszLibName, "pj_dalloc" );
204     CPLPopErrorHandler();
205
206 #endif
207
208     if( pfn_pj_transform == NULL )
209     {
210         CPLError( CE_Failure, CPLE_AppDefined,
211                   "Attempt to load %s, but couldn't find pj_transform.\n"
212                   "Please upgrade to PROJ 4.1.2 or later.",
213                   pszLibName );
214
215         return FALSE;
216     }
217
218     return( TRUE );
219 }
220
221 /************************************************************************/
222 /*                         OCTProj4Normalize()                          */
223 /*                                                                      */
224 /*      This function is really just here since we already have all     */
225 /*      the code to load libproj.so.  It is intended to "normalize"     */
226 /*      a proj.4 definition, expanding +init= definitions and so        */
227 /*      forth as possible.                                              */
228 /************************************************************************/
229
230 char *OCTProj4Normalize( const char *pszProj4Src )
231
232 {
233     char        *pszNewProj4Def, *pszCopy;
234     projPJ      psPJSource = NULL;
235     CPLMutexHolderD( &hPROJMutex );
236
237     if( !LoadProjLibrary() || pfn_pj_dalloc == NULL || pfn_pj_get_def == NULL )
238         return CPLStrdup( pszProj4Src );
239
240     psPJSource = pfn_pj_init_plus( pszProj4Src );
241
242     if( psPJSource == NULL )
243         return CPLStrdup( pszProj4Src );
244
245     pszNewProj4Def = pfn_pj_get_def( psPJSource, 0 );
246
247     pfn_pj_free( psPJSource );
248
249     if( pszNewProj4Def == NULL )
250         return CPLStrdup( pszProj4Src );
251
252     pszCopy = CPLStrdup( pszNewProj4Def );
253     pfn_pj_dalloc( pszNewProj4Def );
254
255     return pszCopy;
256 }
257
258 /************************************************************************/
259 /*                 OCTDestroyCoordinateTransformation()                 */
260 /************************************************************************/
261
262 void CPL_STDCALL
263 OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
264
265 {
266     delete (OGRCoordinateTransformation *) hCT;
267 }
268
269 /************************************************************************/
270 /*                 OGRCreateCoordinateTransformation()                  */
271 /************************************************************************/
272
273 /**
274  * Create transformation object.
275  *
276  * This is the same as the C function OCTNewCoordinateTransformation().
277  *
278  * Input spatial reference system objects are assigned
279  * by copy (calling clone() method) and no ownership transfer occurs.
280  *
281  * The delete operator, or OCTDestroyCoordinateTransformation() should
282  * be used to destroy transformation objects.
283  *
284  * @param poSource source spatial reference system.
285  * @param poTarget target spatial reference system.
286  * @return NULL on failure or a ready to use transformation object.
287  */
288
289 OGRCoordinateTransformation* 
290 OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
291                                    OGRSpatialReference *poTarget )
292
293 {
294     OGRProj4CT  *poCT;
295
296     if( !LoadProjLibrary() )
297     {
298         CPLError( CE_Failure, CPLE_NotSupported,
299                   "Unable to load PROJ.4 library (%s), creation of\n"
300                   "OGRCoordinateTransformation failed.",
301                   GetProjLibraryName() );
302         return NULL;
303     }
304
305     poCT = new OGRProj4CT();
306    
307     if( !poCT->Initialize( poSource, poTarget ) )
308     {
309         delete poCT;
310         return NULL;
311     }
312     else
313     {
314         return poCT;
315     }
316 }
317
318 /************************************************************************/
319 /*                   OCTNewCoordinateTransformation()                   */
320 /************************************************************************/
321
322 OGRCoordinateTransformationH CPL_STDCALL
323 OCTNewCoordinateTransformation(
324     OGRSpatialReferenceH hSourceSRS, OGRSpatialReferenceH hTargetSRS )
325
326 {
327     return (OGRCoordinateTransformationH)
328         OGRCreateCoordinateTransformation(
329             (OGRSpatialReference *) hSourceSRS,
330             (OGRSpatialReference *) hTargetSRS );
331 }
332
333 /************************************************************************/
334 /*                             OGRProj4CT()                             */
335 /************************************************************************/
336
337 OGRProj4CT::OGRProj4CT()
338
339 {
340     poSRSSource = NULL;
341     poSRSTarget = NULL;
342     psPJSource = NULL;
343     psPJTarget = NULL;
344    
345     nErrorCount = 0;
346 }
347
348 /************************************************************************/
349 /*                            ~OGRProj4CT()                             */
350 /************************************************************************/
351
352 OGRProj4CT::~OGRProj4CT()
353
354 {
355     if( poSRSSource != NULL )
356     {
357         if( poSRSSource->Dereference() <= 0 )
358             delete poSRSSource;
359     }
360
361     if( poSRSTarget != NULL )
362     {
363         if( poSRSTarget->Dereference() <= 0 )
364             delete poSRSTarget;
365     }
366
367     CPLMutexHolderD( &hPROJMutex );
368
369     if( psPJSource != NULL )
370         pfn_pj_free( psPJSource );
371
372     if( psPJTarget != NULL )
373         pfn_pj_free( psPJTarget );
374 }
375
376 /************************************************************************/
377 /*                             Initialize()                             */
378 /************************************************************************/
379
380 int OGRProj4CT::Initialize( OGRSpatialReference * poSourceIn,
381                             OGRSpatialReference * poTargetIn )
382
383 {
384     CPLMutexHolderD( &hPROJMutex );
385
386     if( poSourceIn == NULL || poTargetIn == NULL )
387         return FALSE;
388
389     poSRSSource = poSourceIn->Clone();
390     poSRSTarget = poTargetIn->Clone();
391
392     bSourceLatLong = poSRSSource->IsGeographic();
393     bTargetLatLong = poSRSTarget->IsGeographic();
394
395 /* -------------------------------------------------------------------- */
396 /*      Setup source and target translations to radians for lat/long    */
397 /*      systems.                                                        */
398 /* -------------------------------------------------------------------- */
399     dfSourceToRadians = DEG_TO_RAD;
400     dfSourceFromRadians = RAD_TO_DEG;
401     bSourceWrap = FALSE;
402     dfSourceWrapLong = 0.0;
403
404     if( bSourceLatLong )
405     {
406         OGR_SRSNode *poUNITS = poSRSSource->GetAttrNode( "GEOGCS|UNIT" );
407         if( poUNITS && poUNITS->GetChildCount() >= 2 )
408         {
409             dfSourceToRadians = atof(poUNITS->GetChild(1)->GetValue());
410             if( dfSourceToRadians == 0.0 )
411                 dfSourceToRadians = DEG_TO_RAD;
412             else
413                 dfSourceFromRadians = 1 / dfSourceToRadians;
414         }
415     }
416
417     dfTargetToRadians = DEG_TO_RAD;
418     dfTargetFromRadians = RAD_TO_DEG;
419     bTargetWrap = FALSE;
420     dfTargetWrapLong = 0.0;
421
422     if( bTargetLatLong )
423     {
424         OGR_SRSNode *poUNITS = poSRSTarget->GetAttrNode( "GEOGCS|UNIT" );
425         if( poUNITS && poUNITS->GetChildCount() >= 2 )
426         {
427             dfTargetToRadians = atof(poUNITS->GetChild(1)->GetValue());
428             if( dfTargetToRadians == 0.0 )
429                 dfTargetToRadians = DEG_TO_RAD;
430             else
431                 dfTargetFromRadians = 1 / dfTargetToRadians;
432         }
433     }
434
435 /* -------------------------------------------------------------------- */
436 /*      Preliminary logic to setup wrapping.                            */
437 /* -------------------------------------------------------------------- */
438     const char *pszCENTER_LONG;
439
440     if( CPLGetConfigOption( "CENTER_LONG", NULL ) != NULL )
441     {
442         bSourceWrap = bTargetWrap = TRUE;
443         dfSourceWrapLong = dfTargetWrapLong =
444             atof(CPLGetConfigOption( "CENTER_LONG", "" ));
445         CPLDebug( "OGRCT", "Wrap at %g.", dfSourceWrapLong );
446     }
447
448     pszCENTER_LONG = poSRSSource->GetExtension( "GEOGCS", "CENTER_LONG" );
449     if( pszCENTER_LONG != NULL )
450     {
451         dfSourceWrapLong = atof(pszCENTER_LONG);
452         bSourceWrap = TRUE;
453         CPLDebug( "OGRCT", "Wrap source at %g.", dfSourceWrapLong );
454     }
455
456     pszCENTER_LONG = poSRSTarget->GetExtension( "GEOGCS", "CENTER_LONG" );
457     if( pszCENTER_LONG != NULL )
458     {
459         dfTargetWrapLong = atof(pszCENTER_LONG);
460         bTargetWrap = TRUE;
461         CPLDebug( "OGRCT", "Wrap target at %g.", dfTargetWrapLong );
462     }
463
464 /* -------------------------------------------------------------------- */
465 /*      Establish PROJ.4 handle for source if projection.               */
466 /* -------------------------------------------------------------------- */
467     // OGRThreadSafety: The following variable is not a thread safety issue
468     // since the only issue is incrementing while accessing which at worse
469     // means debug output could be one "increment" late.
470     static int   nDebugReportCount = 0;
471
472     char        *pszProj4Defn = NULL;
473
474     if( poSRSSource->exportToProj4( &pszProj4Defn ) != OGRERR_NONE )
475     {
476         CPLFree( pszProj4Defn );
477         return FALSE;
478     }
479
480     if( strlen(pszProj4Defn) == 0 )
481     {
482         CPLFree( pszProj4Defn );
483         CPLError( CE_Failure, CPLE_AppDefined,
484                   "No PROJ.4 translation for source SRS, coordinate\n"
485                   "transformation initialization has failed." );
486         return FALSE;
487     }
488
489     psPJSource = pfn_pj_init_plus( pszProj4Defn );
490    
491     if( psPJSource == NULL )
492     {
493         if( pfn_pj_get_errno_ref != NULL
494             && pfn_pj_strerrno != NULL )
495         {
496             int *p_pj_errno = pfn_pj_get_errno_ref();
497
498             CPLError( CE_Failure, CPLE_NotSupported,
499                       "Failed to initialize PROJ.4 with `%s'.\n%s",
500                       pszProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
501         }
502         else
503         {
504             CPLError( CE_Failure, CPLE_NotSupported,
505                       "Failed to initialize PROJ.4 with `%s'.\n",
506                       pszProj4Defn );
507         }
508     }
509    
510     if( nDebugReportCount < 10 )
511         CPLDebug( "OGRCT", "Source: %s", pszProj4Defn );
512    
513     CPLFree( pszProj4Defn );
514
515     if( psPJSource == NULL )
516         return FALSE;
517
518 /* -------------------------------------------------------------------- */
519 /*      Establish PROJ.4 handle for target if projection.               */
520 /* -------------------------------------------------------------------- */
521     pszProj4Defn = NULL;
522
523     if( poSRSTarget->exportToProj4( &pszProj4Defn ) != OGRERR_NONE )
524     {
525         CPLFree( pszProj4Defn );
526         return FALSE;
527     }
528
529     if( strlen(pszProj4Defn) == 0 )
530     {
531         CPLFree( pszProj4Defn );
532         CPLError( CE_Failure, CPLE_AppDefined,
533                   "No PROJ.4 translation for destination SRS, coordinate\n"
534                   "transformation initialization has failed." );
535         return FALSE;
536     }
537
538     psPJTarget = pfn_pj_init_plus( pszProj4Defn );
539    
540     if( psPJTarget == NULL )
541         CPLError( CE_Failure, CPLE_NotSupported,
542                   "Failed to initialize PROJ.4 with `%s'.",
543                   pszProj4Defn );
544    
545     if( nDebugReportCount < 10 )
546     {
547         CPLDebug( "OGRCT", "Target: %s", pszProj4Defn );
548         nDebugReportCount++;
549     }
550
551     CPLFree( pszProj4Defn );
552    
553     if( psPJTarget == NULL )
554         return FALSE;
555
556     return TRUE;
557 }
558
559 /************************************************************************/
560 /*                            GetSourceCS()                             */
561 /************************************************************************/
562
563 OGRSpatialReference *OGRProj4CT::GetSourceCS()
564
565 {
566     return poSRSSource;
567 }
568
569 /************************************************************************/
570 /*                            GetTargetCS()                             */
571 /************************************************************************/
572
573 OGRSpatialReference *OGRProj4CT::GetTargetCS()
574
575 {
576     return poSRSTarget;
577 }
578
579 /************************************************************************/
580 /*                             Transform()                              */
581 /*                                                                      */
582 /*      This is a small wrapper for the extended transform version.     */
583 /************************************************************************/
584
585 int OGRProj4CT::Transform( int nCount, double *x, double *y, double *z )
586
587 {
588     int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
589     int bOverallSuccess, i;
590
591     bOverallSuccess = TransformEx( nCount, x, y, z, pabSuccess );
592
593     for( i = 0; i < nCount; i++ )
594     {
595         if( !pabSuccess[i] )
596         {
597             bOverallSuccess = FALSE;
598             break;
599         }
600     }
601
602     CPLFree( pabSuccess );
603
604     return bOverallSuccess;
605 }
606
607 /************************************************************************/
608 /*                            OCTTransform()                            */
609 /************************************************************************/
610
611 int CPL_STDCALL OCTTransform( OGRCoordinateTransformationH hTransform,
612                               int nCount, double *x, double *y, double *z )
613
614 {
615     return ((OGRCoordinateTransformation*) hTransform)->
616         Transform( nCount, x, y,z );
617 }
618
619 /************************************************************************/
620 /*                            TransformEx()                             */
621 /************************************************************************/
622
623 int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
624                              int *pabSuccess )
625
626 {
627     int   err, i;
628
629 /* -------------------------------------------------------------------- */
630 /*      Potentially transform to radians.                               */
631 /* -------------------------------------------------------------------- */
632     if( bSourceLatLong )
633     {
634         if( bSourceWrap )
635         {
636             for( i = 0; i < nCount; i++ )
637             {
638                 if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
639                 {
640                     if( x[i] < dfSourceWrapLong - 180.0 )
641                         x[i] += 360.0;
642                     else if( x[i] > dfSourceWrapLong + 180 )
643                         x[i] -= 360.0;
644                 }
645             }
646         }
647
648         for( i = 0; i < nCount; i++ )
649         {
650             if( x[i] != HUGE_VAL )
651             {
652                 x[i] *= dfSourceToRadians;
653                 y[i] *= dfSourceToRadians;
654             }
655         }
656     }
657
658 /* -------------------------------------------------------------------- */
659 /*      Do the transformation using PROJ.4.                             */
660 /* -------------------------------------------------------------------- */
661     CPLMutexHolderD( &hPROJMutex );
662     err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z );
663
664 /* -------------------------------------------------------------------- */
665 /*      Try to report an error through CPL.  Get proj.4 error string    */
666 /*      if possible.  Try to avoid reporting thousands of error         */
667 /*      ... supress further error reporting on this OGRProj4CT if we    */
668 /*      have already reported 20 errors.                                */
669 /* -------------------------------------------------------------------- */
670     if( err != 0 )
671     {
672         if( pabSuccess )
673             memset( pabSuccess, 0, sizeof(int) * nCount );
674
675         if( ++nErrorCount < 20 )
676         {
677             const char *pszError = NULL;
678             if( pfn_pj_strerrno != NULL )
679                 pszError = pfn_pj_strerrno( err );
680            
681             if( pszError == NULL )
682                 CPLError( CE_Failure, CPLE_AppDefined,
683                           "Reprojection failed, err = %d",
684                           err );
685             else
686                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
687         }
688         else if( nErrorCount == 20 )
689         {
690             CPLError( CE_Failure, CPLE_AppDefined,
691                       "Reprojection failed, err = %d, further errors will be supressed on the transform object.",
692                       err );
693         }
694
695         return FALSE;
696     }
697
698 /* -------------------------------------------------------------------- */
699 /*      Potentially transform back to degrees.                          */
700 /* -------------------------------------------------------------------- */
701     if( bTargetLatLong )
702     {
703         for( i = 0; i < nCount; i++ )
704         {
705             if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
706             {
707                 x[i] *= dfTargetFromRadians;
708                 y[i] *= dfTargetFromRadians;
709             }
710         }
711
712         if( bTargetWrap )
713         {
714             for( i = 0; i < nCount; i++ )
715             {
716                 if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
717                 {
718                     if( x[i] < dfTargetWrapLong - 180.0 )
719                         x[i] += 360.0;
720                     else if( x[i] > dfTargetWrapLong + 180 )
721                         x[i] -= 360.0;
722                 }
723             }
724         }
725     }
726
727 /* -------------------------------------------------------------------- */
728 /*      Establish error information if pabSuccess provided.             */
729 /* -------------------------------------------------------------------- */
730     if( pabSuccess )
731     {
732         for( i = 0; i < nCount; i++ )
733         {
734             if( x[i] == HUGE_VAL || y[i] == HUGE_VAL )
735                 pabSuccess[i] = FALSE;
736             else
737                 pabSuccess[i] = TRUE;
738         }
739     }
740
741     return TRUE;
742 }
743
744 /************************************************************************/
745 /*                           OCTTransformEx()                           */
746 /************************************************************************/
747
748 int CPL_STDCALL OCTTransformEx( OGRCoordinateTransformationH hTransform,
749                                 int nCount, double *x, double *y, double *z,
750                                 int *pabSuccess )
751
752 {
753     return ((OGRCoordinateTransformation*) hTransform)->
754         TransformEx( nCount, x, y, z, pabSuccess );
755 }
756
Note: See TracBrowser for help on using the browser.