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 );
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
QString authid() const
Returns the authority identifier for the CRS.
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Contains information about the context in which a coordinate transform is executed.
void clear()
Clears all stored transform information from the context.
bool allowFallbackTransform(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns true if approximate "ballpark" transforms may be used when transforming between a source and ...
QString calculateCoordinateOperation(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns the Proj coordinate operation string to use when transforming from the specified source CRS t...
void readSettings()
Reads the context's state from application settings.
void writeSettings()
Write the context's state to application settings.
Q_DECL_DEPRECATED bool addSourceDestinationDatumTransform(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransformId, int destinationTransformId)
Adds a new sourceTransform and destinationTransform to use when projecting coordinates from the speci...
QMap< QPair< QString, QString >, QString > coordinateOperations() const
Returns the stored mapping for source to destination CRS pairs to associated coordinate operation to ...
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes the context's state to a DOM element.
Q_DECL_DEPRECATED 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...
Q_DECL_DEPRECATED QMap< QPair< QString, QString >, QgsDatumTransform::TransformPair > sourceDestinationDatumTransforms() const
Returns the stored mapping for source to destination CRS pairs to associated datum transforms to use.
~QgsCoordinateTransformContext()
bool readXml(const QDomElement &element, const QgsReadWriteContext &context, QStringList &missingTransforms)
Reads the context's state from a DOM element.
bool addCoordinateOperation(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString, bool allowFallback=true)
Adds a new coordinateOperationProjString to use when projecting coordinates from the specified source...
void removeCoordinateOperation(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs)
Removes the coordinate operation for the specified sourceCrs and destinationCrs.
QgsCoordinateTransformContext()
Constructor for QgsCoordinateTransformContext.
bool hasTransform(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns true if the context has a valid coordinate operation to use when transforming from the specif...
bool mustReverseCoordinateOperation(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns true if the coordinate operation returned by calculateCoordinateOperation() for the source to...
bool operator==(const QgsCoordinateTransformContext &rhs) const
Q_DECL_DEPRECATED void removeSourceDestinationDatumTransform(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs)
Removes the source to destination datum transform pair for the specified sourceCrs and destinationCrs...
QgsCoordinateTransformContext & operator=(const QgsCoordinateTransformContext &rhs)
Assignment operator.
The class is used as a container of context for various read/write operations on other objects.
This class is a composition of two QSettings instances:
void endGroup()
Resets the group to what it was before the corresponding beginGroup() call.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
void remove(const QString &key, QgsSettings::Section section=QgsSettings::NoSection)
Removes the setting key and any sub-settings of key in a section.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QStringList allKeys() const
Returns a list of all keys, including subkeys, that can be read using the QSettings object.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QString crsToKey(const QgsCoordinateReferenceSystem &crs)
const QgsCoordinateReferenceSystem & crs