28 #include <QStringList> 32 #ifdef USE_THREAD_LOCAL 33 thread_local QgsProjContextStore QgsCoordinateTransformPrivate::mProjContext;
35 QThreadStorage< QgsProjContextStore * > QgsCoordinateTransformPrivate::mProjContext;
38 QgsProjContextStore::QgsProjContextStore()
40 context = pj_ctx_alloc();
43 QgsProjContextStore::~QgsProjContextStore()
45 pj_ctx_free( context );
48 QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate()
56 : mSourceCRS( source )
57 , mDestCRS( destination )
60 calculateTransforms( context );
64 : mSourceCRS( source )
65 , mDestCRS( destination )
66 , mSourceDatumTransform( sourceDatumTransform )
67 , mDestinationDatumTransform( destDatumTransform )
72 QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate(
const QgsCoordinateTransformPrivate &other )
73 : QSharedData( other )
74 , mIsValid( other.mIsValid )
75 , mShortCircuit( other.mShortCircuit )
76 , mSourceCRS( other.mSourceCRS )
77 , mDestCRS( other.mDestCRS )
78 , mSourceDatumTransform( other.mSourceDatumTransform )
79 , mDestinationDatumTransform( other.mDestinationDatumTransform )
85 QgsCoordinateTransformPrivate::~QgsCoordinateTransformPrivate()
91 bool QgsCoordinateTransformPrivate::checkValidity()
93 if ( !mSourceCRS.isValid() || !mDestCRS.isValid() )
101 void QgsCoordinateTransformPrivate::invalidate()
103 mShortCircuit =
true;
107 bool QgsCoordinateTransformPrivate::initialize()
110 if ( !mSourceCRS.isValid() )
118 if ( !mDestCRS.isValid() )
122 mDestCRS = mSourceCRS;
129 int sourceDatumTransform = mSourceDatumTransform;
130 int destDatumTransform = mDestinationDatumTransform;
131 bool useDefaultDatumTransform = ( sourceDatumTransform == - 1 && destDatumTransform == -1 );
136 mSourceProjString = mSourceCRS.toProj4();
137 if ( !useDefaultDatumTransform )
139 mSourceProjString = stripDatumTransform( mSourceProjString );
141 if ( sourceDatumTransform != -1 )
146 mDestProjString = mDestCRS.toProj4();
147 if ( !useDefaultDatumTransform )
149 mDestProjString = stripDatumTransform( mDestProjString );
151 if ( destDatumTransform != -1 )
156 if ( !useDefaultDatumTransform )
158 addNullGridShifts( mSourceProjString, mDestProjString, sourceDatumTransform, destDatumTransform );
162 QPair<projPJ, projPJ> res = threadLocalProjData();
164 #ifdef COORDINATE_TRANSFORM_VERBOSE 165 QgsDebugMsg(
"From proj : " + mSourceCRS.toProj4() );
169 if ( !res.first || !res.second )
174 #ifdef COORDINATE_TRANSFORM_VERBOSE 177 QgsDebugMsg(
"------------------------------------------------------------" );
178 QgsDebugMsg(
"The OGR Coordinate transformation for this layer was set to" );
179 QgsLogger::debug<QgsCoordinateReferenceSystem>(
"Input", mSourceCRS, __FILE__, __FUNCTION__, __LINE__ );
180 QgsLogger::debug<QgsCoordinateReferenceSystem>(
"Output", mDestCRS, __FILE__, __FUNCTION__, __LINE__ );
181 QgsDebugMsg(
"------------------------------------------------------------" );
185 QgsDebugMsg(
"------------------------------------------------------------" );
186 QgsDebugMsg(
"The OGR Coordinate transformation FAILED TO INITIALIZE!" );
187 QgsDebugMsg(
"------------------------------------------------------------" );
192 QgsDebugMsg(
"Coordinate transformation failed to initialize!" );
199 if ( mSourceCRS == mDestCRS )
203 mShortCircuit =
true;
209 mShortCircuit =
false;
210 QgsDebugMsgLevel(
"Source/Dest CRS not equal, shortcircuit is not set.", 3 );
223 QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
225 mProjLock.lockForRead();
227 #ifdef USE_THREAD_LOCAL 228 QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( mProjContext.get() ) );
230 projCtx pContext =
nullptr;
231 if ( mProjContext.hasLocalData() )
233 pContext = mProjContext.localData()->get();
237 mProjContext.setLocalData(
new QgsProjContextStore() );
238 pContext = mProjContext.localData()->get();
240 QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( pContext ) );
243 if ( it != mProjProjections.constEnd() )
245 QPair<projPJ, projPJ> res = it.value();
252 mProjLock.lockForWrite();
254 #ifdef USE_THREAD_LOCAL 255 QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( mProjContext.get(), mSourceProjString.toUtf8() ),
256 pj_init_plus_ctx( mProjContext.get(), mDestProjString.toUtf8() ) );
257 mProjProjections.insert( reinterpret_cast< uintptr_t>( mProjContext.get() ), res );
259 QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( pContext, mSourceProjString.toUtf8() ),
260 pj_init_plus_ctx( pContext, mDestProjString.toUtf8() ) );
261 mProjProjections.insert( reinterpret_cast< uintptr_t>( pContext ), res );
267 QString QgsCoordinateTransformPrivate::stripDatumTransform(
const QString &proj4 )
const 269 QStringList parameterSplit = proj4.split(
'+', QString::SkipEmptyParts );
270 QString currentParameter;
271 QString newProjString;
273 for (
int i = 0; i < parameterSplit.size(); ++i )
275 currentParameter = parameterSplit.at( i );
276 if ( !currentParameter.startsWith( QLatin1String(
"towgs84" ), Qt::CaseInsensitive )
277 && !currentParameter.startsWith( QLatin1String(
"nadgrids" ), Qt::CaseInsensitive ) )
279 newProjString.append(
'+' );
280 newProjString.append( currentParameter );
281 newProjString.append(
' ' );
284 return newProjString;
287 void QgsCoordinateTransformPrivate::addNullGridShifts( QString &srcProjString, QString &destProjString,
288 int sourceDatumTransform,
int destinationDatumTransform )
const 291 if ( destinationDatumTransform == -1 && srcProjString.contains( QLatin1String(
"+nadgrids" ) ) )
293 destProjString += QLatin1String(
" +nadgrids=@null" );
296 if ( sourceDatumTransform == -1 && destProjString.contains( QLatin1String(
"+nadgrids" ) ) )
298 srcProjString += QLatin1String(
" +nadgrids=@null" );
304 if ( mSourceCRS.authid().compare( QLatin1String(
"EPSG:3857" ), Qt::CaseInsensitive ) == 0 && sourceDatumTransform == -1 )
306 srcProjString += QLatin1String(
" +nadgrids=@null" );
308 if ( mDestCRS.authid().compare( QLatin1String(
"EPSG:3857" ), Qt::CaseInsensitive ) == 0 && destinationDatumTransform == -1 )
310 destProjString += QLatin1String(
" +nadgrids=@null" );
314 void QgsCoordinateTransformPrivate::setFinder()
330 void QgsCoordinateTransformPrivate::freeProj()
332 mProjLock.lockForWrite();
333 QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constBegin();
334 for ( ; it != mProjProjections.constEnd(); ++it )
336 pj_free( it.value().first );
337 pj_free( it.value().second );
339 mProjProjections.clear();
#define QgsDebugMsgLevel(str, level)
Contains information about the context in which a coordinate transform is executed.
QgsDatumTransform::TransformPair calculateDatumTransforms(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns the pair of source and destination datum transforms to use for a transform from the specified...
This class represents a coordinate reference system (CRS).