30 bool qMapLessThanKey<QPair<QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem>>(
const QPair<QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem> &key1,
31 const QPair<QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem> &key2 )
33 const QPair< QString, QString > key1String = qMakePair(
crsToKey( key1.first ),
crsToKey( key1.second ) );
34 const QPair< QString, QString > key2String = qMakePair(
crsToKey( key2.first ),
crsToKey( key2.second ) );
35 return key1String < key2String;
39 : d( new QgsCoordinateTransformContextPrivate() )
59 d->mLock.lockForRead();
60 rhs.d->mLock.lockForRead();
61 bool equal = d->mSourceDestDatumTransforms == rhs.d->mSourceDestDatumTransforms;
63 rhs.d->mLock.unlock();
71 d->mLock.lockForWrite();
72 d->mSourceDestDatumTransforms.clear();
78 #if PROJ_VERSION_MAJOR>=6
81 d->mLock.lockForRead();
82 auto res = d->mSourceDestDatumTransforms;
91 #if PROJ_VERSION_MAJOR>=6
92 d->mLock.lockForRead();
93 auto res = d->mSourceDestDatumTransforms;
96 QMap<QPair<QString, QString>, QString> results;
97 for (
auto it = res.constBegin(); it != res.constEnd(); ++it )
98 results.insert( qMakePair( it.key().first.authid(), it.key().second.authid() ), it.value().operation );
102 return QMap<QPair<QString, QString>, QString>();
110 #if PROJ_VERSION_MAJOR>=6
111 Q_UNUSED( sourceTransform )
112 Q_UNUSED( destinationTransform )
116 d->mLock.lockForWrite();
127 #if PROJ_VERSION_MAJOR>=6
129 d->mLock.lockForWrite();
130 QgsCoordinateTransformContextPrivate::OperationDetails details;
131 details.operation = coordinateOperationProjString;
132 details.allowFallback = allowFallback;
133 d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs, destinationCrs ), details );
137 Q_UNUSED( coordinateOperationProjString )
138 Q_UNUSED( allowFallback )
150 #if PROJ_VERSION_MAJOR>=6
151 d->mSourceDestDatumTransforms.remove( qMakePair( sourceCrs, destinationCrs ) );
153 d->mSourceDestDatumTransforms.remove( qMakePair( sourceCrs.
authid(), destinationCrs.
authid() ) );
159 #if PROJ_VERSION_MAJOR>=6
167 return t.sourceTransformId != -1 || t.destinationTransformId != -1;
173 #if PROJ_VERSION_MAJOR>=6
175 Q_UNUSED( destination )
178 QString srcKey = source.
authid();
179 QString destKey = destination.
authid();
181 d->mLock.lockForRead();
197 #if PROJ_VERSION_MAJOR>=6
201 d->mLock.lockForRead();
202 QgsCoordinateTransformContextPrivate::OperationDetails res = d->mSourceDestDatumTransforms.value( qMakePair( source, destination ), QgsCoordinateTransformContextPrivate::OperationDetails() );
203 if ( res.operation.isEmpty() )
206 res = d->mSourceDestDatumTransforms.value( qMakePair( destination, source ), QgsCoordinateTransformContextPrivate::OperationDetails() );
209 return res.operation;
212 Q_UNUSED( destination )
219 #if PROJ_VERSION_MAJOR>=6
223 d->mLock.lockForRead();
224 QgsCoordinateTransformContextPrivate::OperationDetails res = d->mSourceDestDatumTransforms.value( qMakePair( source, destination ), QgsCoordinateTransformContextPrivate::OperationDetails() );
225 if ( res.operation.isEmpty() )
228 res = d->mSourceDestDatumTransforms.value( qMakePair( destination, source ), QgsCoordinateTransformContextPrivate::OperationDetails() );
231 return res.allowFallback;
234 Q_UNUSED( destination )
241 #if PROJ_VERSION_MAJOR>=6
245 d->mLock.lockForRead();
246 QgsCoordinateTransformContextPrivate::OperationDetails res = d->mSourceDestDatumTransforms.value( qMakePair( source, destination ), QgsCoordinateTransformContextPrivate::OperationDetails() );
247 if ( !res.operation.isEmpty() )
253 res = d->mSourceDestDatumTransforms.value( qMakePair( destination, source ), QgsCoordinateTransformContextPrivate::OperationDetails() );
254 if ( !res.operation.isEmpty() )
264 Q_UNUSED( destination )
272 d->mLock.lockForWrite();
274 d->mSourceDestDatumTransforms.clear();
276 const QDomNodeList contextNodes = element.elementsByTagName( QStringLiteral(
"transformContext" ) );
277 if ( contextNodes.count() < 1 )
283 missingTransforms.clear();
286 const QDomElement contextElem = contextNodes.at( 0 ).toElement();
289 const QDomNodeList srcDestNodes = contextElem.elementsByTagName( QStringLiteral(
"srcDest" ) );
290 for (
int i = 0; i < srcDestNodes.size(); ++i )
292 const QDomElement transformElem = srcDestNodes.at( i ).toElement();
294 #if PROJ_VERSION_MAJOR>=6
295 const QDomElement srcElem = transformElem.firstChildElement( QStringLiteral(
"src" ) );
296 const QDomElement destElem = transformElem.firstChildElement( QStringLiteral(
"dest" ) );
300 if ( !srcElem.isNull() && !destElem.isNull() )
308 const QString key1 = transformElem.attribute( QStringLiteral(
"source" ) );
309 const QString key2 = transformElem.attribute( QStringLiteral(
"dest" ) );
317 const QString coordinateOp = transformElem.attribute( QStringLiteral(
"coordinateOp" ) );
318 const bool allowFallback = transformElem.attribute( QStringLiteral(
"allowFallback" ), QStringLiteral(
"1" ) ).toInt();
321 if ( !QgsProjUtils::coordinateOperationIsAvailable( coordinateOp ) )
328 QgsCoordinateTransformContextPrivate::OperationDetails deets;
329 deets.operation = coordinateOp;
330 deets.allowFallback = allowFallback;
331 d->mSourceDestDatumTransforms.insert( qMakePair( srcCrs, destCrs ), deets );
333 const QString key1 = transformElem.attribute( QStringLiteral(
"source" ) );
334 const QString key2 = transformElem.attribute( QStringLiteral(
"dest" ) );
336 QString value1 = transformElem.attribute( QStringLiteral(
"sourceTransform" ) );
337 QString value2 = transformElem.attribute( QStringLiteral(
"destTransform" ) );
343 if ( !value1.isEmpty() )
349 missingTransforms << value1;
352 if ( !value2.isEmpty() )
358 missingTransforms << value2;
373 d->mLock.lockForRead();
375 QDomDocument doc = element.ownerDocument();
377 QDomElement contextElem = doc.createElement( QStringLiteral(
"transformContext" ) );
380 for (
auto it = d->mSourceDestDatumTransforms.constBegin(); it != d->mSourceDestDatumTransforms.constEnd(); ++ it )
382 QDomElement transformElem = doc.createElement( QStringLiteral(
"srcDest" ) );
383 #if PROJ_VERSION_MAJOR>=6
384 QDomElement srcElem = doc.createElement( QStringLiteral(
"src" ) );
385 QDomElement destElem = doc.createElement( QStringLiteral(
"dest" ) );
387 it.key().first.writeXml( srcElem, doc );
388 it.key().second.writeXml( destElem, doc );
390 transformElem.appendChild( srcElem );
391 transformElem.appendChild( destElem );
393 transformElem.setAttribute( QStringLiteral(
"coordinateOp" ), it.value().operation );
394 transformElem.setAttribute( QStringLiteral(
"allowFallback" ), it.value().allowFallback ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
396 transformElem.setAttribute( QStringLiteral(
"source" ), it.key().first );
397 transformElem.setAttribute( QStringLiteral(
"dest" ), it.key().second );
401 transformElem.setAttribute( QStringLiteral(
"destTransform" ), it.value().destinationTransformId < 0 ? QString() :
QgsDatumTransform::datumTransformToProj( it.value().destinationTransformId ) );
404 contextElem.appendChild( transformElem );
407 element.appendChild( contextElem );
414 d->mLock.lockForWrite();
416 d->mSourceDestDatumTransforms.clear();
419 settings.
beginGroup( QStringLiteral(
"/Projections" ) );
420 QStringList projectionKeys = settings.
allKeys();
423 #if PROJ_VERSION_MAJOR>=6
424 QMap< QPair< QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem >, QgsCoordinateTransformContextPrivate::OperationDetails > transforms;
426 QMap< QPair< QString, QString >, QPair< int, int > > transforms;
428 QStringList::const_iterator pkeyIt = projectionKeys.constBegin();
429 for ( ; pkeyIt != projectionKeys.constEnd(); ++pkeyIt )
431 #if PROJ_VERSION_MAJOR>=6
432 if ( pkeyIt->contains( QLatin1String(
"coordinateOp" ) ) )
434 QStringList split = pkeyIt->split(
'/' );
435 QString srcAuthId, destAuthId;
436 if ( ! split.isEmpty() )
438 srcAuthId = split.at( 0 );
440 if ( split.size() > 1 )
442 destAuthId = split.at( 1 ).split(
'_' ).at( 0 );
445 if ( srcAuthId.isEmpty() || destAuthId.isEmpty() )
448 const QString proj = settings.
value( *pkeyIt ).toString();
449 const bool allowFallback = settings.
value( QStringLiteral(
"%1//%2_allowFallback" ).arg( srcAuthId, destAuthId ) ).toBool();
450 QgsCoordinateTransformContextPrivate::OperationDetails deets;
451 deets.operation = proj;
452 deets.allowFallback = allowFallback;
456 if ( pkeyIt->contains( QLatin1String(
"srcTransform" ) ) || pkeyIt->contains( QLatin1String(
"destTransform" ) ) )
458 QStringList split = pkeyIt->split(
'/' );
459 QString srcAuthId, destAuthId;
460 if ( ! split.isEmpty() )
462 srcAuthId = split.at( 0 );
464 if ( split.size() > 1 )
466 destAuthId = split.at( 1 ).split(
'_' ).at( 0 );
469 QString proj = settings.
value( *pkeyIt ).toString();
473 if ( pkeyIt->contains( QLatin1String(
"srcTransform" ) ) )
475 transforms[ qMakePair( srcAuthId, destAuthId )].first = datumId;
477 else if ( pkeyIt->contains( QLatin1String(
"destTransform" ) ) )
479 transforms[ qMakePair( srcAuthId, destAuthId )].second = datumId;
486 auto transformIt = transforms.constBegin();
487 for ( ; transformIt != transforms.constEnd(); ++transformIt )
489 #if PROJ_VERSION_MAJOR>=6
490 d->mSourceDestDatumTransforms.insert( transformIt.key(), transformIt.value() );
503 settings.
beginGroup( QStringLiteral(
"/Projections" ) );
504 QStringList groupKeys = settings.
allKeys();
505 QStringList::const_iterator groupKeyIt = groupKeys.constBegin();
506 for ( ; groupKeyIt != groupKeys.constEnd(); ++groupKeyIt )
508 if ( groupKeyIt->contains( QLatin1String(
"srcTransform" ) ) || groupKeyIt->contains( QLatin1String(
"destTransform" ) ) || groupKeyIt->contains( QLatin1String(
"coordinateOp" ) ) )
510 settings.
remove( *groupKeyIt );
514 for (
auto transformIt = d->mSourceDestDatumTransforms.constBegin(); transformIt != d->mSourceDestDatumTransforms.constEnd(); ++transformIt )
516 #if PROJ_VERSION_MAJOR>=6
517 const QString srcAuthId = transformIt.key().first.authid();
518 const QString destAuthId = transformIt.key().second.authid();
520 const QString srcAuthId = transformIt.key().first;
521 const QString destAuthId = transformIt.key().second;
524 if ( srcAuthId.isEmpty() || destAuthId.isEmpty() )
527 #if PROJ_VERSION_MAJOR>=6
528 const QString proj = transformIt.value().operation;
529 const bool allowFallback = transformIt.value().allowFallback;
530 settings.
setValue( srcAuthId +
"//" + destAuthId +
"_coordinateOp", proj );
531 settings.
setValue( srcAuthId +
"//" + destAuthId +
"_allowFallback", allowFallback );
533 int sourceDatumTransform = transformIt.value().sourceTransformId;
534 QString sourceDatumProj;
536 if ( sourceDatumTransform >= 0 )
538 int destinationDatumTransform = transformIt.value().destinationTransformId;
539 QString destinationDatumProj;
540 if ( destinationDatumTransform >= 0 )
544 settings.
setValue( srcAuthId +
"//" + destAuthId +
"_srcTransform", sourceDatumProj );
545 settings.
setValue( srcAuthId +
"//" + destAuthId +
"_destTransform", destinationDatumProj );