Skip to content

Commit 95c0d4f

Browse files
committedApr 5, 2019
Port QgsCoordinateTransform to proj 6 API
Sponsored by ICSM
1 parent eabf56b commit 95c0d4f

File tree

3 files changed

+98
-25
lines changed

3 files changed

+98
-25
lines changed
 

‎src/core/qgscoordinatetransform.cpp

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@
3232
#include <QStringList>
3333
#include <QVector>
3434

35-
extern "C"
36-
{
37-
#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
38-
#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
39-
#endif
35+
#if PROJ_VERSION_MAJOR>=6
36+
#include <proj.h>
37+
#include "qgsprojutils.h"
38+
#else
4039
#include <proj_api.h>
41-
}
40+
#endif
41+
4242
#include <sqlite3.h>
4343

4444
// if defined shows all information about transform to stdout
@@ -625,21 +625,36 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
625625

626626
// if the source/destination projection is lat/long, convert the points to radians
627627
// prior to transforming
628-
QPair<projPJ, projPJ> projData = d->threadLocalProjData();
628+
ProjData projData = d->threadLocalProjData();
629+
#if PROJ_VERSION_MAJOR<6
630+
bool sourceIsLatLong = false;
631+
bool destIsLatLong = false;
632+
629633
projPJ sourceProj = projData.first;
630634
projPJ destProj = projData.second;
635+
sourceIsLatLong = pj_is_latlong( sourceProj );
636+
destIsLatLong = pj_is_latlong( destProj );
631637

632-
if ( ( pj_is_latlong( destProj ) && ( direction == ReverseTransform ) )
633-
|| ( pj_is_latlong( sourceProj ) && ( direction == ForwardTransform ) ) )
638+
if ( ( destIsLatLong && ( direction == ReverseTransform ) )
639+
|| ( sourceIsLatLong && ( direction == ForwardTransform ) ) )
634640
{
635641
for ( int i = 0; i < numPoints; ++i )
636642
{
637643
x[i] *= DEG_TO_RAD;
638644
y[i] *= DEG_TO_RAD;
639645
}
640-
641646
}
642-
int projResult;
647+
#endif
648+
649+
int projResult = 0;
650+
#if PROJ_VERSION_MAJOR>=6
651+
proj_trans_generic( projData, direction == ForwardTransform ? PJ_FWD : PJ_INV,
652+
x, sizeof( double ), numPoints,
653+
y, sizeof( double ), numPoints,
654+
z, sizeof( double ), numPoints,
655+
nullptr, sizeof( double ), 0 );
656+
projResult = proj_errno( projData );
657+
#else
643658
if ( direction == ReverseTransform )
644659
{
645660
projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
@@ -650,6 +665,7 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
650665
Q_ASSERT( destProj );
651666
projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
652667
}
668+
#endif
653669

654670
if ( projResult != 0 )
655671
{
@@ -664,12 +680,30 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
664680
}
665681
else
666682
{
683+
#if PROJ_VERSION_MAJOR>=6
684+
points += QStringLiteral( "(%1, %2)\n" ).arg( x[i], 0, 'f' ).arg( y[i], 0, 'f' );
685+
#else
667686
points += QStringLiteral( "(%1, %2)\n" ).arg( x[i] * RAD_TO_DEG, 0, 'f' ).arg( y[i] * RAD_TO_DEG, 0, 'f' );
687+
#endif
668688
}
669689
}
670690

671691
QString dir = ( direction == ForwardTransform ) ? QObject::tr( "forward transform" ) : QObject::tr( "inverse transform" );
672692

693+
#if PROJ_VERSION_MAJOR>=6
694+
PJ *src = proj_get_source_crs( QgsProjContext::get(), projData );
695+
PJ *dest = proj_get_source_crs( QgsProjContext::get(), projData );
696+
QString msg = QObject::tr( "%1 of\n"
697+
"%2"
698+
"PROJ: %3\n"
699+
"Error: %4" )
700+
.arg( dir,
701+
points,
702+
proj_as_proj_string( QgsProjContext::get(), projData, PJ_PROJ_5, nullptr ),
703+
QString::fromUtf8( proj_errno_string( projResult ) ) );
704+
proj_destroy( src );
705+
proj_destroy( dest );
706+
#else
673707
char *srcdef = pj_get_def( sourceProj, 0 );
674708
char *dstdef = pj_get_def( destProj, 0 );
675709

@@ -684,24 +718,27 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
684718

685719
pj_dalloc( srcdef );
686720
pj_dalloc( dstdef );
721+
#endif
687722

688723
QgsDebugMsg( "Projection failed emitting invalid transform signal: " + msg );
689724
QgsDebugMsg( QStringLiteral( "throwing exception" ) );
690725

691726
throw QgsCsException( msg );
692727
}
693728

729+
#if PROJ_VERSION_MAJOR<6
694730
// if the result is lat/long, convert the results from radians back
695731
// to degrees
696-
if ( ( pj_is_latlong( destProj ) && ( direction == ForwardTransform ) )
697-
|| ( pj_is_latlong( sourceProj ) && ( direction == ReverseTransform ) ) )
732+
if ( ( destIsLatLong && ( direction == ForwardTransform ) )
733+
|| ( sourceIsLatLong && ( direction == ReverseTransform ) ) )
698734
{
699735
for ( int i = 0; i < numPoints; ++i )
700736
{
701737
x[i] *= RAD_TO_DEG;
702738
y[i] *= RAD_TO_DEG;
703739
}
704740
}
741+
#endif
705742
#ifdef COORDINATE_TRANSFORM_VERBOSE
706743
QgsDebugMsg( QStringLiteral( "[[[[[[ Projected %1, %2 to %3, %4 ]]]]]]" )
707744
.arg( xorg, 0, 'g', 15 ).arg( yorg, 0, 'g', 15 )

‎src/core/qgscoordinatetransform_p.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@
2020
#include "qgsapplication.h"
2121
#include "qgsreadwritelocker.h"
2222

23-
extern "C"
24-
{
25-
#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
26-
#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
27-
#endif
23+
#if PROJ_VERSION_MAJOR>=6
24+
#include "qgsprojutils.h"
25+
#include <proj.h>
26+
#else
2827
#include <proj_api.h>
29-
}
28+
#endif
29+
3030
#include <sqlite3.h>
3131

3232
#include <QStringList>
3333

3434
/// @cond PRIVATE
3535

36+
#if PROJ_VERSION_MAJOR<6
3637
#ifdef USE_THREAD_LOCAL
3738
thread_local QgsProjContextStore QgsCoordinateTransformPrivate::mProjContext;
3839
#else
@@ -49,6 +50,8 @@ QgsProjContextStore::~QgsProjContextStore()
4950
pj_ctx_free( context );
5051
}
5152

53+
#endif
54+
5255
QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate()
5356
{
5457
setFinder();
@@ -163,17 +166,22 @@ bool QgsCoordinateTransformPrivate::initialize()
163166
}
164167

165168
// create proj projections for current thread
166-
QPair<projPJ, projPJ> res = threadLocalProjData();
169+
ProjData res = threadLocalProjData();
167170

168171
#ifdef COORDINATE_TRANSFORM_VERBOSE
169172
QgsDebugMsg( "From proj : " + mSourceCRS.toProj4() );
170173
QgsDebugMsg( "To proj : " + mDestCRS.toProj4() );
171174
#endif
172175

176+
#if PROJ_VERSION_MAJOR>=6
177+
if ( !res )
178+
mIsValid = false;
179+
#else
173180
if ( !res.first || !res.second )
174181
{
175182
mIsValid = false;
176183
}
184+
#endif
177185

178186
#ifdef COORDINATE_TRANSFORM_VERBOSE
179187
if ( mIsValid )
@@ -224,10 +232,14 @@ void QgsCoordinateTransformPrivate::calculateTransforms( const QgsCoordinateTran
224232
mDestinationDatumTransform = transforms.destinationTransformId;
225233
}
226234

227-
QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
235+
ProjData QgsCoordinateTransformPrivate::threadLocalProjData()
228236
{
229237
QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Read );
230238

239+
#if PROJ_VERSION_MAJOR>=6
240+
PJ_CONTEXT *context = QgsProjContext::get();
241+
QMap < uintptr_t, ProjData >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( context ) );
242+
#else
231243
#ifdef USE_THREAD_LOCAL
232244
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( mProjContext.get() ) );
233245
#else
@@ -242,17 +254,22 @@ QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
242254
pContext = mProjContext.localData()->get();
243255
}
244256
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( pContext ) );
257+
#endif
245258
#endif
246259

247260
if ( it != mProjProjections.constEnd() )
248261
{
249-
QPair<projPJ, projPJ> res = it.value();
262+
ProjData res = it.value();
250263
return res;
251264
}
252265

253266
// proj projections don't exist yet, so we need to create
254267
locker.changeMode( QgsReadWriteLocker::Write );
255268

269+
#if PROJ_VERSION_MAJOR>=6
270+
ProjData res = proj_create_crs_to_crs( context, mSourceProjString.toUtf8(), mDestProjString.toUtf8(), nullptr );
271+
mProjProjections.insert( reinterpret_cast< uintptr_t>( context ), res );
272+
#else
256273
#ifdef USE_THREAD_LOCAL
257274
QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( mProjContext.get(), mSourceProjString.toUtf8() ),
258275
pj_init_plus_ctx( mProjContext.get(), mDestProjString.toUtf8() ) );
@@ -261,6 +278,7 @@ QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
261278
QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( pContext, mSourceProjString.toUtf8() ),
262279
pj_init_plus_ctx( pContext, mDestProjString.toUtf8() ) );
263280
mProjProjections.insert( reinterpret_cast< uintptr_t>( pContext ), res );
281+
#endif
264282
#endif
265283
return res;
266284
}
@@ -331,11 +349,15 @@ void QgsCoordinateTransformPrivate::setFinder()
331349
void QgsCoordinateTransformPrivate::freeProj()
332350
{
333351
QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Write );
334-
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constBegin();
352+
QMap < uintptr_t, ProjData >::const_iterator it = mProjProjections.constBegin();
335353
for ( ; it != mProjProjections.constEnd(); ++it )
336354
{
355+
#if PROJ_VERSION_MAJOR>=6
356+
proj_destroy( it.value() );
357+
#else
337358
pj_free( it.value().first );
338359
pj_free( it.value().second );
360+
#endif
339361
}
340362
mProjProjections.clear();
341363
}

‎src/core/qgscoordinatetransform_p.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,21 @@
3333

3434
#include <QSharedData>
3535

36+
#if PROJ_VERSION_MAJOR<6
3637
#ifndef USE_THREAD_LOCAL
3738
#include <QThreadStorage>
3839
#endif
40+
typedef QPair< projPJ, projPJ > ProjData;
41+
#else
42+
struct PJconsts;
43+
typedef struct PJconsts PJ;
44+
typedef PJ *ProjData;
45+
#endif
3946

4047
#include "qgscoordinatereferencesystem.h"
4148
#include "qgscoordinatetransformcontext.h"
4249

50+
#if PROJ_VERSION_MAJOR<6
4351
typedef void *projPJ;
4452
typedef void *projCtx;
4553

@@ -61,6 +69,8 @@ class QgsProjContextStore
6169
projCtx context;
6270
};
6371

72+
#endif
73+
6474
class QgsCoordinateTransformPrivate : public QSharedData
6575
{
6676

@@ -89,7 +99,7 @@ class QgsCoordinateTransformPrivate : public QSharedData
8999

90100
void calculateTransforms( const QgsCoordinateTransformContext &context );
91101

92-
QPair< projPJ, projPJ > threadLocalProjData();
102+
ProjData threadLocalProjData();
93103

94104
/**
95105
* Flag to indicate whether the transform is valid (ie has a valid
@@ -115,6 +125,8 @@ class QgsCoordinateTransformPrivate : public QSharedData
115125
int mSourceDatumTransform = -1;
116126
int mDestinationDatumTransform = -1;
117127

128+
#if PROJ_VERSION_MAJOR<6
129+
118130
/**
119131
* Thread local proj context storage. A new proj context will be created
120132
* for every thread.
@@ -124,9 +136,11 @@ class QgsCoordinateTransformPrivate : public QSharedData
124136
#else
125137
static QThreadStorage< QgsProjContextStore * > mProjContext;
126138
#endif
139+
#endif
140+
127141

128142
QReadWriteLock mProjLock;
129-
QMap < uintptr_t, QPair< projPJ, projPJ > > mProjProjections;
143+
QMap < uintptr_t, ProjData > mProjProjections;
130144

131145
private:
132146

0 commit comments

Comments
 (0)
Please sign in to comment.