From 1c7e1402632d3127178d265b063280f42987be0f Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 18 Dec 2017 18:07:49 +1000 Subject: [PATCH 1/5] Fix transform context not copied with render context copies --- src/core/qgsrendercontext.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index 5e5d53f0f1e..57bb9a3e91c 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -55,6 +55,10 @@ QgsRenderContext::QgsRenderContext( const QgsRenderContext &rh ) , mFeatureFilterProvider( rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr ) , mSegmentationTolerance( rh.mSegmentationTolerance ) , mSegmentationToleranceType( rh.mSegmentationToleranceType ) + , mTransformContext( rh.mTransformContext ) +#ifdef QGISDEBUG + , mHasTransformContext( rh.mHasTransformContext ) +#endif { } @@ -77,6 +81,11 @@ QgsRenderContext &QgsRenderContext::operator=( const QgsRenderContext &rh ) mSegmentationTolerance = rh.mSegmentationTolerance; mSegmentationToleranceType = rh.mSegmentationToleranceType; mDistanceArea = rh.mDistanceArea; + mTransformContext = rh.mTransformContext; +#ifdef QGISDEBUG + mHasTransformContext = rh.mHasTransformContext; +#endif + return *this; } From 25c3e135b07bbeafcc645e2a543bc2fe6d746048 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 18 Dec 2017 18:38:56 +1000 Subject: [PATCH 2/5] Move datum transform structs out to their own header, to avoid need to include private header file --- python/core/core_auto.sip | 1 + python/core/qgscoordinatetransform.sip | 87 +------------ python/core/qgscoordinatetransformcontext.sip | 4 +- python/core/qgsdatumtransform.sip | 114 +++++++++++++++++ src/app/qgsdatumtransformtablewidget.cpp | 2 +- src/core/CMakeLists.txt | 2 +- src/core/qgscoordinatetransform.cpp | 14 +-- src/core/qgscoordinatetransform.h | 82 +----------- src/core/qgscoordinatetransform_p.cpp | 4 +- src/core/qgscoordinatetransformcontext.cpp | 18 +-- src/core/qgscoordinatetransformcontext.h | 6 +- src/core/qgscoordinatetransformcontext_p.h | 4 +- src/core/qgsdatumtransform.h | 112 +++++++++++++++++ src/gui/qgsdatumtransformdialog.cpp | 4 +- src/gui/qgsdatumtransformdialog.h | 2 +- tests/src/core/testqgscoordinatetransform.cpp | 10 +- .../test_qgscoordinatetransformcontext.py | 119 +++++++++--------- 17 files changed, 326 insertions(+), 259 deletions(-) create mode 100644 python/core/qgsdatumtransform.sip create mode 100644 src/core/qgsdatumtransform.h diff --git a/python/core/core_auto.sip b/python/core/core_auto.sip index d171204bc9e..d49f11808ee 100644 --- a/python/core/core_auto.sip +++ b/python/core/core_auto.sip @@ -30,6 +30,7 @@ %Include qgsdataitemproviderregistry.sip %Include qgsdatasourceuri.sip %Include qgsdatetimestatisticalsummary.sip +%Include qgsdatumtransform.sip %Include qgsdbfilterproxymodel.sip %Include qgsdefaultvalue.sip %Include qgsdiagramrenderer.sip diff --git a/python/core/qgscoordinatetransform.sip b/python/core/qgscoordinatetransform.sip index 1c00caab7ac..9da72d9a718 100644 --- a/python/core/qgscoordinatetransform.sip +++ b/python/core/qgscoordinatetransform.sip @@ -254,36 +254,7 @@ otherwise points are transformed from destination to source CRS. Returns true if the transform short circuits because the source and destination are equivalent. %End - struct TransformPair - { - - TransformPair( int sourceTransformId = -1, int destinationTransformId = -1 ); -%Docstring -Constructor for a TransformPair with the specified ``sourceTransformId`` -and ``destinationTransformId`` transforms. -%End - - int sourceTransformId; -%Docstring -ID for the datum transform to use when projecting from the source CRS. - -.. seealso:: :py:func:`QgsCoordinateTransform.datumTransformCrsInfo()` -%End - - int destinationTransformId; -%Docstring -ID for the datum transform to use when projecting to the destination CRS. - -.. seealso:: :py:func:`QgsCoordinateTransform.datumTransformCrsInfo()` -%End - - bool operator==( const QgsCoordinateTransform::TransformPair &other ) const; - - bool operator!=( const QgsCoordinateTransform::TransformPair &other ) const; - - }; - - static QList< QgsCoordinateTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ); + static QList< QgsDatumTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ); %Docstring Returns a list of datum transformations which are available for the given ``source`` and ``destination`` CRS. @@ -313,61 +284,7 @@ Returns -1 if matching datum ID was not found. .. versionadded:: 3.0 %End - struct TransformInfo - { - int datumTransformId; -%Docstring -Datum transform ID -%End - - int epsgCode; -%Docstring -EPSG code for the transform, or 0 if not found in EPSG database -%End - - QString sourceCrsAuthId; -%Docstring -Source CRS auth ID -%End - - QString destinationCrsAuthId; -%Docstring -Destination CRS auth ID -%End - - QString sourceCrsDescription; -%Docstring -Source CRS description -%End - - QString destinationCrsDescription; -%Docstring -Destination CRS description -%End - - QString remarks; -%Docstring -Transform remarks -%End - - QString scope; -%Docstring -Scope of transform -%End - - bool preferred; -%Docstring -True if transform is the preferred transform to use for the source/destination CRS combination -%End - - bool deprecated; -%Docstring -True if transform is deprecated -%End - - }; - - static QgsCoordinateTransform::TransformInfo datumTransformInfo( int datumTransformId ); + static QgsDatumTransform::TransformInfo datumTransformInfo( int datumTransformId ); %Docstring Returns detailed information about the specified ``datumTransformId``. If ``datumTransformId`` was not a valid transform ID, a TransformInfo with TransformInfo.datumTransformId of diff --git a/python/core/qgscoordinatetransformcontext.sip b/python/core/qgscoordinatetransformcontext.sip index e47e1841c80..c51b0827e38 100644 --- a/python/core/qgscoordinatetransformcontext.sip +++ b/python/core/qgscoordinatetransformcontext.sip @@ -65,7 +65,7 @@ Clears all stored transform information from the context. - QMap< QPair< QString, QString>, QgsCoordinateTransform::TransformPair > sourceDestinationDatumTransforms() const; + QMap< QPair< QString, QString>, QgsDatumTransform::TransformPair > sourceDestinationDatumTransforms() const; %Docstring Returns the stored mapping for source to destination CRS pairs to associated datum transforms to use. The map keys will be QgsCoordinateReferenceSystems.authid()s. @@ -123,7 +123,7 @@ when transforming from the specified ``source`` CRS to ``destination`` CRS. source and destination are reversible. %End - QgsCoordinateTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, + QgsDatumTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const; %Docstring Returns the pair of source and destination datum transforms to use diff --git a/python/core/qgsdatumtransform.sip b/python/core/qgsdatumtransform.sip new file mode 100644 index 00000000000..4ffffd34048 --- /dev/null +++ b/python/core/qgsdatumtransform.sip @@ -0,0 +1,114 @@ +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/qgsdatumtransform.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ + + + +class QgsDatumTransform +{ +%Docstring +Contains methods and classes relating the datum transformations. + +.. versionadded:: 3.0 +%End + +%TypeHeaderCode +#include "qgsdatumtransform.h" +%End + public: + + struct TransformPair + { + + TransformPair( int sourceTransformId = -1, int destinationTransformId = -1 ); +%Docstring +Constructor for a TransformPair with the specified ``sourceTransformId`` +and ``destinationTransformId`` transforms. +%End + + int sourceTransformId; +%Docstring +ID for the datum transform to use when projecting from the source CRS. + +.. seealso:: :py:func:`QgsCoordinateTransform.datumTransformCrsInfo()` +%End + + int destinationTransformId; +%Docstring +ID for the datum transform to use when projecting to the destination CRS. + +.. seealso:: :py:func:`QgsCoordinateTransform.datumTransformCrsInfo()` +%End + + bool operator==( const QgsDatumTransform::TransformPair &other ) const; + + bool operator!=( const QgsDatumTransform::TransformPair &other ) const; + + }; + + struct TransformInfo + { + int datumTransformId; +%Docstring +Datum transform ID +%End + + int epsgCode; +%Docstring +EPSG code for the transform, or 0 if not found in EPSG database +%End + + QString sourceCrsAuthId; +%Docstring +Source CRS auth ID +%End + + QString destinationCrsAuthId; +%Docstring +Destination CRS auth ID +%End + + QString sourceCrsDescription; +%Docstring +Source CRS description +%End + + QString destinationCrsDescription; +%Docstring +Destination CRS description +%End + + QString remarks; +%Docstring +Transform remarks +%End + + QString scope; +%Docstring +Scope of transform +%End + + bool preferred; +%Docstring +True if transform is the preferred transform to use for the source/destination CRS combination +%End + + bool deprecated; +%Docstring +True if transform is deprecated +%End + + }; +}; + +/************************************************************************ + * This file has been generated automatically from * + * * + * src/core/qgsdatumtransform.h * + * * + * Do not edit manually ! Edit header and run scripts/sipify.pl again * + ************************************************************************/ diff --git a/src/app/qgsdatumtransformtablewidget.cpp b/src/app/qgsdatumtransformtablewidget.cpp index de8a49a7ff2..364c5b68d36 100644 --- a/src/app/qgsdatumtransformtablewidget.cpp +++ b/src/app/qgsdatumtransformtablewidget.cpp @@ -85,7 +85,7 @@ QVariant QgsDatumTransformTableModel::data( const QModelIndex &index, int role ) QPair< QString, QString> crses = mTransformContext.sourceDestinationDatumTransforms().keys().at( index.row() ); sourceCrs = crses.first; destinationCrs = crses.second; - const QgsCoordinateTransform::TransformPair transforms = mTransformContext.sourceDestinationDatumTransforms().value( crses ); + const QgsDatumTransform::TransformPair transforms = mTransformContext.sourceDestinationDatumTransforms().value( crses ); sourceTransform = transforms.sourceTransformId; destinationTransform = transforms.destinationTransformId; #ifdef singlesourcedest diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 97dac05f6ac..a18fb5c01b8 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -854,7 +854,6 @@ SET(QGIS_CORE_HDRS qgscoordinateformatter.h qgscoordinatetransform.h qgscoordinatetransformcontext.h - qgscoordinatetransformcontext_p.h qgscoordinateutils.h qgsdartmeasurement.h qgsdatadefinedsizelegend.h @@ -862,6 +861,7 @@ SET(QGIS_CORE_HDRS qgsdataitemproviderregistry.h qgsdatasourceuri.h qgsdatetimestatisticalsummary.h + qgsdatumtransform.h qgsdbfilterproxymodel.h qgsdefaultvalue.h qgsdiagramrenderer.h diff --git a/src/core/qgscoordinatetransform.cpp b/src/core/qgscoordinatetransform.cpp index 7ba55baec8e..78097497efb 100644 --- a/src/core/qgscoordinatetransform.cpp +++ b/src/core/qgscoordinatetransform.cpp @@ -691,9 +691,9 @@ const char *finder( const char *name ) -QList< QgsCoordinateTransform::TransformPair > QgsCoordinateTransform::datumTransformations( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS ) +QList< QgsDatumTransform::TransformPair > QgsCoordinateTransform::datumTransformations( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS ) { - QList< QgsCoordinateTransform::TransformPair > transformations; + QList< QgsDatumTransform::TransformPair > transformations; QString srcGeoId = srcCRS.geographicCrsAuthId(); QString destGeoId = destCRS.geographicCrsAuthId(); @@ -735,20 +735,20 @@ QList< QgsCoordinateTransform::TransformPair > QgsCoordinateTransform::datumTran //add direct datum transformations for ( int transform : qgis::as_const( directTransforms ) ) { - transformations.push_back( TransformPair( transform, -1 ) ); + transformations.push_back( QgsDatumTransform::TransformPair( transform, -1 ) ); } //add direct datum transformations for ( int transform : qgis::as_const( directTransforms ) ) { - transformations.push_back( TransformPair( -1, transform ) ); + transformations.push_back( QgsDatumTransform::TransformPair( -1, transform ) ); } for ( int srcTransform : qgis::as_const( srcToWgs84 ) ) { for ( int destTransform : qgis::as_const( destToWgs84 ) ) { - transformations.push_back( TransformPair( srcTransform, destTransform ) ); + transformations.push_back( QgsDatumTransform::TransformPair( srcTransform, destTransform ) ); } } @@ -821,9 +821,9 @@ int QgsCoordinateTransform::projStringToDatumTransformId( const QString &string return QgsCoordinateTransformPrivate::transformIdFromString( string ); } -QgsCoordinateTransform::TransformInfo QgsCoordinateTransform::datumTransformInfo( int datumTransform ) +QgsDatumTransform::TransformInfo QgsCoordinateTransform::datumTransformInfo( int datumTransform ) { - TransformInfo info; + QgsDatumTransform::TransformInfo info; sqlite3_database_unique_ptr database; int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); diff --git a/src/core/qgscoordinatetransform.h b/src/core/qgscoordinatetransform.h index 4d2bb70bbf2..54e3db47e21 100644 --- a/src/core/qgscoordinatetransform.h +++ b/src/core/qgscoordinatetransform.h @@ -312,52 +312,12 @@ class CORE_EXPORT QgsCoordinateTransform */ bool isShortCircuited() const; - /** - * Contains datum transform information. - * \since QGIS 3.0 - */ - struct TransformPair - { - - /** - * Constructor for a TransformPair with the specified \a sourceTransformId - * and \a destinationTransformId transforms. - */ - TransformPair( int sourceTransformId = -1, int destinationTransformId = -1 ) - : sourceTransformId( sourceTransformId ) - , destinationTransformId( destinationTransformId ) - {} - - /** - * ID for the datum transform to use when projecting from the source CRS. - * \see QgsCoordinateTransform::datumTransformCrsInfo() - */ - int sourceTransformId = -1; - - /** - * ID for the datum transform to use when projecting to the destination CRS. - * \see QgsCoordinateTransform::datumTransformCrsInfo() - */ - int destinationTransformId = -1; - - bool operator==( const QgsCoordinateTransform::TransformPair &other ) const - { - return other.sourceTransformId == sourceTransformId && other.destinationTransformId == destinationTransformId; - } - - bool operator!=( const QgsCoordinateTransform::TransformPair &other ) const - { - return other.sourceTransformId != sourceTransformId || other.destinationTransformId != destinationTransformId; - } - - }; - /** * Returns a list of datum transformations which are available for the given \a source and \a destination CRS. * \see datumTransformToProj() * \see datumTransformInfo() */ - static QList< QgsCoordinateTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ); + static QList< QgsDatumTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ); /** * Returns a proj string representing the specified \a datumTransformId datum transform ID. @@ -375,44 +335,6 @@ class CORE_EXPORT QgsCoordinateTransform */ static int projStringToDatumTransformId( const QString &string ); - /** - * Contains datum transform information. - * \since QGIS 3.0 - */ - struct TransformInfo - { - //! Datum transform ID - int datumTransformId = -1; - - //! EPSG code for the transform, or 0 if not found in EPSG database - int epsgCode = 0; - - //! Source CRS auth ID - QString sourceCrsAuthId; - - //! Destination CRS auth ID - QString destinationCrsAuthId; - - //! Source CRS description - QString sourceCrsDescription; - - //! Destination CRS description - QString destinationCrsDescription; - - //! Transform remarks - QString remarks; - - //! Scope of transform - QString scope; - - //! True if transform is the preferred transform to use for the source/destination CRS combination - bool preferred = false; - - //! True if transform is deprecated - bool deprecated = false; - - }; - /** * Returns detailed information about the specified \a datumTransformId. * If \a datumTransformId was not a valid transform ID, a TransformInfo with TransformInfo::datumTransformId of @@ -420,7 +342,7 @@ class CORE_EXPORT QgsCoordinateTransform * \see datumTransformations() * \see datumTransformToProj() */ - static QgsCoordinateTransform::TransformInfo datumTransformInfo( int datumTransformId ); + static QgsDatumTransform::TransformInfo datumTransformInfo( int datumTransformId ); /** * Returns the ID of the datum transform to use when projecting from the source diff --git a/src/core/qgscoordinatetransform_p.cpp b/src/core/qgscoordinatetransform_p.cpp index 1f5fee3cf81..436921907c1 100644 --- a/src/core/qgscoordinatetransform_p.cpp +++ b/src/core/qgscoordinatetransform_p.cpp @@ -217,10 +217,10 @@ bool QgsCoordinateTransformPrivate::initialize() return mIsValid; } -void QgsCoordinateTransformPrivate::calculateTransforms() +void QgsCoordinateTransformPrivate::calculateTransforms( const QgsCoordinateTransformContext &context ) { // recalculate datum transforms from context - QgsCoordinateTransform::TransformPair transforms = mContext.calculateDatumTransforms( mSourceCRS, mDestCRS ); + QgsDatumTransform::TransformPair transforms = context.calculateDatumTransforms( mSourceCRS, mDestCRS ); mSourceDatumTransform = transforms.sourceTransformId; mDestinationDatumTransform = transforms.destinationTransformId; } diff --git a/src/core/qgscoordinatetransformcontext.cpp b/src/core/qgscoordinatetransformcontext.cpp index 91e0eca0a7b..e26e2276c8c 100644 --- a/src/core/qgscoordinatetransformcontext.cpp +++ b/src/core/qgscoordinatetransformcontext.cpp @@ -102,7 +102,7 @@ void QgsCoordinateTransformContext::removeDestinationDatumTransform( const QgsCo #endif -QMap, QgsCoordinateTransform::TransformPair> QgsCoordinateTransformContext::sourceDestinationDatumTransforms() const +QMap, QgsDatumTransform::TransformPair> QgsCoordinateTransformContext::sourceDestinationDatumTransforms() const { d->mLock.lockForRead(); auto res = d->mSourceDestDatumTransforms; @@ -118,7 +118,7 @@ bool QgsCoordinateTransformContext::addSourceDestinationDatumTransform( const Qg d.detach(); d->mLock.lockForWrite(); - d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), QgsCoordinateTransform::TransformPair( sourceTransform, destinationTransform ) ); + d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), QgsDatumTransform::TransformPair( sourceTransform, destinationTransform ) ); d->mLock.unlock(); return true; } @@ -130,24 +130,24 @@ void QgsCoordinateTransformContext::removeSourceDestinationDatumTransform( const bool QgsCoordinateTransformContext::hasTransform( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const { - QgsCoordinateTransform::TransformPair t = calculateDatumTransforms( source, destination ); + QgsDatumTransform::TransformPair t = calculateDatumTransforms( source, destination ); // calculateDatumTransforms already takes care of switching source and destination return t.sourceTransformId != -1 || t.destinationTransformId != -1; } -QgsCoordinateTransform::TransformPair QgsCoordinateTransformContext::calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const +QgsDatumTransform::TransformPair QgsCoordinateTransformContext::calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const { QString srcKey = source.authid(); QString destKey = destination.authid(); d->mLock.lockForRead(); // highest priority is exact match for source/dest pair - QgsCoordinateTransform::TransformPair res = d->mSourceDestDatumTransforms.value( qMakePair( srcKey, destKey ), QgsCoordinateTransform::TransformPair( -1, -1 ) ); + QgsDatumTransform::TransformPair res = d->mSourceDestDatumTransforms.value( qMakePair( srcKey, destKey ), QgsDatumTransform::TransformPair( -1, -1 ) ); if ( res.sourceTransformId == -1 && res.destinationTransformId == -1 ) { // try to reverse - QgsCoordinateTransform::TransformPair res2 = d->mSourceDestDatumTransforms.value( qMakePair( destKey, srcKey ), QgsCoordinateTransform::TransformPair( -1, -1 ) ); - res = QgsCoordinateTransform::TransformPair( res2.destinationTransformId, res2.sourceTransformId ); + QgsDatumTransform::TransformPair res2 = d->mSourceDestDatumTransforms.value( qMakePair( destKey, srcKey ), QgsDatumTransform::TransformPair( -1, -1 ) ); + res = QgsDatumTransform::TransformPair( res2.destinationTransformId, res2.sourceTransformId ); } d->mLock.unlock(); return res; @@ -217,7 +217,7 @@ bool QgsCoordinateTransformContext::readXml( const QDomElement &element, const Q } } - d->mSourceDestDatumTransforms.insert( qMakePair( key1, key2 ), QgsCoordinateTransform::TransformPair( datumId1, datumId2 ) ); + d->mSourceDestDatumTransforms.insert( qMakePair( key1, key2 ), QgsDatumTransform::TransformPair( datumId1, datumId2 ) ); } #if 0 @@ -347,7 +347,7 @@ void QgsCoordinateTransformContext::readSettings() QMap< QPair< QString, QString >, QPair< int, int > >::const_iterator transformIt = transforms.constBegin(); for ( ; transformIt != transforms.constEnd(); ++transformIt ) { - d->mSourceDestDatumTransforms.insert( transformIt.key(), QgsCoordinateTransform::TransformPair( transformIt.value().first, transformIt.value().second ) ); + d->mSourceDestDatumTransforms.insert( transformIt.key(), QgsDatumTransform::TransformPair( transformIt.value().first, transformIt.value().second ) ); } d->mLock.unlock(); diff --git a/src/core/qgscoordinatetransformcontext.h b/src/core/qgscoordinatetransformcontext.h index 6d8dbdeabf7..24b4e4f5c3d 100644 --- a/src/core/qgscoordinatetransformcontext.h +++ b/src/core/qgscoordinatetransformcontext.h @@ -21,7 +21,7 @@ #include "qgis_core.h" #include "qgis.h" #include "qgscoordinatetransformcontext_p.h" -#include "qgscoordinatetransform.h" +#include "qgsdatumtransform.h" class QgsReadWriteContext; @@ -181,7 +181,7 @@ class CORE_EXPORT QgsCoordinateTransformContext * * \see addSourceDestinationDatumTransform() */ - QMap< QPair< QString, QString>, QgsCoordinateTransform::TransformPair > sourceDestinationDatumTransforms() const; + QMap< QPair< QString, QString>, QgsDatumTransform::TransformPair > sourceDestinationDatumTransforms() const; /** * Adds a new \a sourceTransform and \a destinationTransform to use when projecting coordinates @@ -228,7 +228,7 @@ class CORE_EXPORT QgsCoordinateTransformContext * * \note source and destination are reversible. */ - QgsCoordinateTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, + QgsDatumTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const; /** diff --git a/src/core/qgscoordinatetransformcontext_p.h b/src/core/qgscoordinatetransformcontext_p.h index ba45c02ade9..b37d1208d12 100644 --- a/src/core/qgscoordinatetransformcontext_p.h +++ b/src/core/qgscoordinatetransformcontext_p.h @@ -38,7 +38,7 @@ #define SIP_NO_FILE #include "qgscoordinatereferencesystem.h" -#include "qgscoordinatetransform.h" +#include "qgsdatumtransform.h" class QgsCoordinateTransformContextPrivate : public QSharedData { @@ -63,7 +63,7 @@ class QgsCoordinateTransformContextPrivate : public QSharedData * Mapping for datum transforms to use for source/destination CRS pairs. * Matching records from this map will take precedence over other transform maps. */ - QMap< QPair< QString, QString >, QgsCoordinateTransform::TransformPair > mSourceDestDatumTransforms; + QMap< QPair< QString, QString >, QgsDatumTransform::TransformPair > mSourceDestDatumTransforms; #if 0 //! Mapping for datum transforms to use for source CRS diff --git a/src/core/qgsdatumtransform.h b/src/core/qgsdatumtransform.h new file mode 100644 index 00000000000..cefa4a044d6 --- /dev/null +++ b/src/core/qgsdatumtransform.h @@ -0,0 +1,112 @@ +/*************************************************************************** + qgsdatumtransform.h + ------------------------ + begin : Dec 2017 + copyright : (C) 2017 Nyall Dawson + email : nyall dot dawson at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#ifndef QGSDATUMTRANSFORM_H +#define QGSDATUMTRANSFORM_H + +#include "qgis_core.h" +#include + +/** + * Contains methods and classes relating the datum transformations. + * \ingroup core + * \since QGIS 3.0 + */ +class CORE_EXPORT QgsDatumTransform +{ + + public: + + /** + * Contains datum transform information. + * \since QGIS 3.0 + */ + struct TransformPair + { + + /** + * Constructor for a TransformPair with the specified \a sourceTransformId + * and \a destinationTransformId transforms. + */ + TransformPair( int sourceTransformId = -1, int destinationTransformId = -1 ) + : sourceTransformId( sourceTransformId ) + , destinationTransformId( destinationTransformId ) + {} + + /** + * ID for the datum transform to use when projecting from the source CRS. + * \see QgsCoordinateTransform::datumTransformCrsInfo() + */ + int sourceTransformId = -1; + + /** + * ID for the datum transform to use when projecting to the destination CRS. + * \see QgsCoordinateTransform::datumTransformCrsInfo() + */ + int destinationTransformId = -1; + + bool operator==( const QgsDatumTransform::TransformPair &other ) const + { + return other.sourceTransformId == sourceTransformId && other.destinationTransformId == destinationTransformId; + } + + bool operator!=( const QgsDatumTransform::TransformPair &other ) const + { + return other.sourceTransformId != sourceTransformId || other.destinationTransformId != destinationTransformId; + } + + }; + + /** + * Contains datum transform information. + * \since QGIS 3.0 + */ + struct TransformInfo + { + //! Datum transform ID + int datumTransformId = -1; + + //! EPSG code for the transform, or 0 if not found in EPSG database + int epsgCode = 0; + + //! Source CRS auth ID + QString sourceCrsAuthId; + + //! Destination CRS auth ID + QString destinationCrsAuthId; + + //! Source CRS description + QString sourceCrsDescription; + + //! Destination CRS description + QString destinationCrsDescription; + + //! Transform remarks + QString remarks; + + //! Scope of transform + QString scope; + + //! True if transform is the preferred transform to use for the source/destination CRS combination + bool preferred = false; + + //! True if transform is deprecated + bool deprecated = false; + + }; +}; + +#endif // QGSDATUMTRANSFORM_H diff --git a/src/gui/qgsdatumtransformdialog.cpp b/src/gui/qgsdatumtransformdialog.cpp index 6df20b8b14f..709cf6f364b 100644 --- a/src/gui/qgsdatumtransformdialog.cpp +++ b/src/gui/qgsdatumtransformdialog.cpp @@ -71,7 +71,7 @@ void QgsDatumTransformDialog::load( const QPair &selectedDatumTransfor { mDatumTransformTreeWidget->clear(); - for ( const QgsCoordinateTransform::TransformPair &transform : qgis::as_const( mDatumTransforms ) ) + for ( const QgsDatumTransform::TransformPair &transform : qgis::as_const( mDatumTransforms ) ) { QTreeWidgetItem *item = new QTreeWidgetItem(); bool itemDisabled = false; @@ -87,7 +87,7 @@ void QgsDatumTransformDialog::load( const QPair &selectedDatumTransfor item->setText( i, QgsCoordinateTransform::datumTransformToProj( nr ) ); //Describe datums in a tooltip - QgsCoordinateTransform::TransformInfo info = QgsCoordinateTransform::datumTransformInfo( nr ); + QgsDatumTransform::TransformInfo info = QgsCoordinateTransform::datumTransformInfo( nr ); if ( info.datumTransformId == -1 ) continue; diff --git a/src/gui/qgsdatumtransformdialog.h b/src/gui/qgsdatumtransformdialog.h index 8ed5d423a47..6d8480ea7ee 100644 --- a/src/gui/qgsdatumtransformdialog.h +++ b/src/gui/qgsdatumtransformdialog.h @@ -71,7 +71,7 @@ class GUI_EXPORT QgsDatumTransformDialog : public QDialog, private Ui::QgsDatumT void setOKButtonEnabled(); - QList< QgsCoordinateTransform::TransformPair > mDatumTransforms; + QList< QgsDatumTransform::TransformPair > mDatumTransforms; QgsCoordinateReferenceSystem mSourceCrs; QgsCoordinateReferenceSystem mDestinationCrs; }; diff --git a/tests/src/core/testqgscoordinatetransform.cpp b/tests/src/core/testqgscoordinatetransform.cpp index 6c2d126ed25..056842bc434 100644 --- a/tests/src/core/testqgscoordinatetransform.cpp +++ b/tests/src/core/testqgscoordinatetransform.cpp @@ -188,8 +188,8 @@ void TestQgsCoordinateTransform::contextShared() original.addSourceDestinationDatumTransform( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), 1, 2 ); QgsCoordinateTransformContext copy( original ); - QMap< QPair< QString, QString >, QgsCoordinateTransform::TransformPair > expected; - expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsCoordinateTransform::TransformPair( 1, 2 ) ); + QMap< QPair< QString, QString >, QgsDatumTransform::TransformPair > expected; + expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsDatumTransform::TransformPair( 1, 2 ) ); QCOMPARE( original.sourceDestinationDatumTransforms(), expected ); QCOMPARE( copy.sourceDestinationDatumTransforms(), expected ); @@ -197,19 +197,19 @@ void TestQgsCoordinateTransform::contextShared() copy.addSourceDestinationDatumTransform( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), 3, 4 ); QCOMPARE( original.sourceDestinationDatumTransforms(), expected ); - expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsCoordinateTransform::TransformPair( 3, 4 ) ); + expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsDatumTransform::TransformPair( 3, 4 ) ); QCOMPARE( copy.sourceDestinationDatumTransforms(), expected ); // copy via assignment QgsCoordinateTransformContext copy2; copy2 = original; - expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsCoordinateTransform::TransformPair( 1, 2 ) ); + expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsDatumTransform::TransformPair( 1, 2 ) ); QCOMPARE( original.sourceDestinationDatumTransforms(), expected ); QCOMPARE( copy2.sourceDestinationDatumTransforms(), expected ); copy2.addSourceDestinationDatumTransform( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), 3, 4 ); QCOMPARE( original.sourceDestinationDatumTransforms(), expected ); - expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsCoordinateTransform::TransformPair( 3, 4 ) ); + expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QgsDatumTransform::TransformPair( 3, 4 ) ); QCOMPARE( copy2.sourceDestinationDatumTransforms(), expected ); } diff --git a/tests/src/python/test_qgscoordinatetransformcontext.py b/tests/src/python/test_qgscoordinatetransformcontext.py index b25d058e767..71848e8a803 100644 --- a/tests/src/python/test_qgscoordinatetransformcontext.py +++ b/tests/src/python/test_qgscoordinatetransformcontext.py @@ -17,6 +17,7 @@ import qgis # NOQA from qgis.core import (QgsCoordinateReferenceSystem, QgsCoordinateTransformContext, QgsCoordinateTransform, + QgsDatumTransform, QgsReadWriteContext, QgsProject, QgsSettings) @@ -114,79 +115,79 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4326'))) self.assertFalse( context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3113'), QgsCoordinateReferenceSystem('EPSG:4283'))) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2)}) self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem(4283), 3, 4)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4)}) self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem(28357), 7, 8)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(7, 8)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(7, 8)}) self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem('EPSG:28357'), 9, 11)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)}) # invalid additions self.assertFalse(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(), QgsCoordinateReferenceSystem('EPSG:28357'), 9, 11)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)}) self.assertFalse(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem(), 9, 11)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)}) # indicate no transform required self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(28357), QgsCoordinateReferenceSystem(28356), -1, -1)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11), - ('EPSG:28357', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, -1)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11), + ('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1)}) self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3111), QgsCoordinateReferenceSystem(28356), 17, -1)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11), - ('EPSG:28357', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, -1), - ('EPSG:3111', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(17, -1)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11), + ('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1), + ('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1)}) self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3113), QgsCoordinateReferenceSystem(28356), -1, 18)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11), - ('EPSG:28357', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, -1), - ('EPSG:3111', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(17, -1), - ('EPSG:3113', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, 18)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11), + ('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1), + ('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1), + ('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)}) # remove non-existing context.removeSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3113), QgsCoordinateReferenceSystem(3111)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2), - ('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11), - ('EPSG:28357', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, -1), - ('EPSG:3111', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(17, -1), - ('EPSG:3113', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, 18)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2), + ('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11), + ('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1), + ('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1), + ('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)}) # remove existing context.removeSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3111), QgsCoordinateReferenceSystem(4283)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11), - ('EPSG:28357', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, -1), - ('EPSG:3111', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(17, -1), - ('EPSG:3113', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, 18)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11), + ('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1), + ('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1), + ('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)}) context.removeSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3111), QgsCoordinateReferenceSystem(28356)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:28356', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(3, 4), - ('EPSG:28356', 'EPSG:28357'): QgsCoordinateTransform.TransformPair(9, 11), - ('EPSG:28357', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, -1), - ('EPSG:3113', 'EPSG:28356'): QgsCoordinateTransform.TransformPair(-1, 18)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4), + ('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11), + ('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1), + ('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)}) context.clear() self.assertEqual(context.sourceDestinationDatumTransforms(), {}) @@ -244,7 +245,7 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): #empty context self.assertEqual(context.calculateDatumTransforms(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4283')), - QgsCoordinateTransform.TransformPair(-1, -1)) + QgsDatumTransform.TransformPair(-1, -1)) #add specific source/dest pair - should take precedence context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'), @@ -252,17 +253,17 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): 3, 4) self.assertEqual(context.calculateDatumTransforms(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem('EPSG:4283')), - QgsCoordinateTransform.TransformPair(3, 4)) + QgsDatumTransform.TransformPair(3, 4)) self.assertEqual(context.calculateDatumTransforms(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4283')), - QgsCoordinateTransform.TransformPair(-1, -1)) + QgsDatumTransform.TransformPair(-1, -1)) self.assertEqual(context.calculateDatumTransforms(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem('EPSG:3111')), - QgsCoordinateTransform.TransformPair(-1, -1)) + QgsDatumTransform.TransformPair(-1, -1)) # check that reverse transforms are automatically supported self.assertEqual(context.calculateDatumTransforms(QgsCoordinateReferenceSystem('EPSG:4283'), QgsCoordinateReferenceSystem('EPSG:28356')), - QgsCoordinateTransform.TransformPair(4, 3)) + QgsDatumTransform.TransformPair(4, 3)) @unittest.skip('ifdefed out in c++ until required') def testWriteReadXmlSingleVariant(self): @@ -316,8 +317,8 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(4205), QgsCoordinateReferenceSystem(4326), source_id_2, dest_id_2)) - self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:4204', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_1, dest_id_1), - ('EPSG:4205', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_2, dest_id_2)}) + self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1), + ('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)}) # save to xml doc = QDomDocument("testdoc") @@ -329,8 +330,8 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): context2.readXml(elem, QgsReadWriteContext()) # check result - self.assertEqual(context2.sourceDestinationDatumTransforms(), {('EPSG:4204', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_1, dest_id_1), - ('EPSG:4205', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_2, dest_id_2)}) + self.assertEqual(context2.sourceDestinationDatumTransforms(), {('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1), + ('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)}) def testMissingTransforms(self): # fudge context xml with a missing transform @@ -366,7 +367,7 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): QgsCoordinateReferenceSystem('EPSG:4283'), 1, 2) project.setTransformContext(context) self.assertEqual(len(context_changed_spy), 1) - self.assertEqual(project.transformContext().sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsCoordinateTransform.TransformPair(1, 2)}) + self.assertEqual(project.transformContext().sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2)}) def testReadWriteSettings(self): context = QgsCoordinateTransformContext() @@ -391,8 +392,8 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): QgsCoordinateReferenceSystem(4326), source_id_2, dest_id_2)) self.assertEqual(context.sourceDestinationDatumTransforms(), - {('EPSG:4204', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_1, dest_id_1), - ('EPSG:4205', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_2, dest_id_2)}) + {('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1), + ('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)}) # save to settings context.writeSettings() @@ -404,8 +405,8 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): # check result self.assertEqual(context2.sourceDestinationDatumTransforms(), - {('EPSG:4204', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_1, dest_id_1), - ('EPSG:4205', 'EPSG:4326'): QgsCoordinateTransform.TransformPair(source_id_2, dest_id_2)}) + {('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1), + ('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)}) if __name__ == '__main__': From 9ba1d28aa4a7199ebd477b5951c9ce98edba2873 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 18 Dec 2017 18:39:49 +1000 Subject: [PATCH 3/5] Don't cache context along with QgsCoordinateTransforms This information should not be restored from the cache, since it's project specific yet the cache is not --- src/core/qgscoordinatetransform.cpp | 44 ++++++++++++++++------ src/core/qgscoordinatetransform.h | 9 ++++- src/core/qgscoordinatetransform_p.cpp | 7 +--- src/core/qgscoordinatetransform_p.h | 9 +---- src/core/qgscoordinatetransformcontext.cpp | 1 + 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/core/qgscoordinatetransform.cpp b/src/core/qgscoordinatetransform.cpp index 78097497efb..ea6e41ec725 100644 --- a/src/core/qgscoordinatetransform.cpp +++ b/src/core/qgscoordinatetransform.cpp @@ -65,9 +65,10 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, const QgsCoordinateTransformContext &context ) { - d = new QgsCoordinateTransformPrivate( source, destination, context ); + mContext = context; + d = new QgsCoordinateTransformPrivate( source, destination, mContext ); #ifdef QGISDEBUG - d->mHasContext = true; + mHasContext = true; #endif if ( !d->checkValidity() ) @@ -82,9 +83,11 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, const QgsProject *project ) { - d = new QgsCoordinateTransformPrivate( source, destination, project ? project->transformContext() : QgsCoordinateTransformContext() ); + mContext = project ? project->transformContext() : QgsCoordinateTransformContext(); + d = new QgsCoordinateTransformPrivate( source, destination, mContext ); #ifdef QGISDEBUG - d->mHasContext = true; + if ( project ) + mHasContext = true; #endif if ( !d->checkValidity() ) @@ -101,7 +104,7 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst { d = new QgsCoordinateTransformPrivate( source, destination, sourceDatumTransform, destinationDatumTransform ); #ifdef QGISDEBUG - d->mHasContext = true; // not strictly true, but we don't need to worry if datums have been explicitly set + mHasContext = true; // not strictly true, but we don't need to worry if datums have been explicitly set #endif if ( !d->checkValidity() ) @@ -115,6 +118,10 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst } QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateTransform &o ) + : mContext( o.mContext ) +#ifdef QGISDEBUG + , mHasContext( o.mHasContext ) +#endif { d = o.d; } @@ -122,6 +129,10 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateTransform &o QgsCoordinateTransform &QgsCoordinateTransform::operator=( const QgsCoordinateTransform &o ) //NOLINT { d = o.d; +#ifdef QGISDEBUG + mHasContext = o.mHasContext; +#endif + mContext = o.mContext; return *this; } @@ -134,7 +145,7 @@ void QgsCoordinateTransform::setSourceCrs( const QgsCoordinateReferenceSystem &c if ( !d->checkValidity() ) return; - d->calculateTransforms(); + d->calculateTransforms( mContext ); if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) ) { d->initialize(); @@ -148,7 +159,7 @@ void QgsCoordinateTransform::setDestinationCrs( const QgsCoordinateReferenceSyst if ( !d->checkValidity() ) return; - d->calculateTransforms(); + d->calculateTransforms( mContext ); if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) ) { d->initialize(); @@ -159,14 +170,14 @@ void QgsCoordinateTransform::setDestinationCrs( const QgsCoordinateReferenceSyst void QgsCoordinateTransform::setContext( const QgsCoordinateTransformContext &context ) { d.detach(); - d->mContext = context; + mContext = context; #ifdef QGISDEBUG - d->mHasContext = true; + mHasContext = true; #endif if ( !d->checkValidity() ) return; - d->calculateTransforms(); + d->calculateTransforms( mContext ); if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) ) { d->initialize(); @@ -575,7 +586,7 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double * #endif #ifdef QGISDEBUG - if ( !d->mHasContext ) + if ( !mHasContext ) qWarning( "No QgsCoordinateTransformContext context set for transform" ); #endif @@ -792,8 +803,19 @@ bool QgsCoordinateTransform::setFromCache( const QgsCoordinateReferenceSystem &s if ( ( *valIt ).sourceDatumTransformId() == srcDatumTransform && ( *valIt ).destinationDatumTransformId() == destDatumTransform ) { + // need to save, and then restore the context... we don't want this to be cached or to use the values from the cache + QgsCoordinateTransformContext context = mContext; +#ifdef QGISDEBUG + bool hasContext = mHasContext; +#endif *this = *valIt; sCacheLock.unlock(); + + mContext = context; +#ifdef QGISDEBUG + mHasContext = hasContext; +#endif + return true; } } diff --git a/src/core/qgscoordinatetransform.h b/src/core/qgscoordinatetransform.h index 54e3db47e21..d9e35c07bc7 100644 --- a/src/core/qgscoordinatetransform.h +++ b/src/core/qgscoordinatetransform.h @@ -22,12 +22,12 @@ #include "qgis_core.h" #include "qgis_sip.h" #include "qgscoordinatereferencesystem.h" +#include "qgscoordinatetransformcontext.h" class QgsCoordinateTransformPrivate; class QgsPointXY; class QgsRectangle; class QPolygonF; -class QgsCoordinateTransformContext; class QgsProject; /** @@ -410,6 +410,13 @@ class CORE_EXPORT QgsCoordinateTransform mutable QExplicitlySharedDataPointer d; + //! Transform context + QgsCoordinateTransformContext mContext; + +#ifdef QGISDEBUG + bool mHasContext = false; +#endif + bool setFromCache( const QgsCoordinateReferenceSystem &src, const QgsCoordinateReferenceSystem &dest, int srcDatumTransform, diff --git a/src/core/qgscoordinatetransform_p.cpp b/src/core/qgscoordinatetransform_p.cpp index 436921907c1..624ca6e29cd 100644 --- a/src/core/qgscoordinatetransform_p.cpp +++ b/src/core/qgscoordinatetransform_p.cpp @@ -55,10 +55,9 @@ QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinat const QgsCoordinateTransformContext &context ) : mSourceCRS( source ) , mDestCRS( destination ) - , mContext( context ) { setFinder(); - calculateTransforms(); + calculateTransforms( context ); } QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, int sourceDatumTransform, int destDatumTransform ) @@ -76,10 +75,6 @@ QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinat , mShortCircuit( other.mShortCircuit ) , mSourceCRS( other.mSourceCRS ) , mDestCRS( other.mDestCRS ) - , mContext( other.mContext ) -#ifdef QGISDEBUG - , mHasContext( other.mHasContext ) -#endif , mSourceDatumTransform( other.mSourceDatumTransform ) , mDestinationDatumTransform( other.mDestinationDatumTransform ) { diff --git a/src/core/qgscoordinatetransform_p.h b/src/core/qgscoordinatetransform_p.h index 112a0ba5254..8e23b8b09ae 100644 --- a/src/core/qgscoordinatetransform_p.h +++ b/src/core/qgscoordinatetransform_p.h @@ -87,7 +87,7 @@ class QgsCoordinateTransformPrivate : public QSharedData bool initialize(); - void calculateTransforms(); + void calculateTransforms( const QgsCoordinateTransformContext &context ); QPair< projPJ, projPJ > threadLocalProjData(); @@ -109,13 +109,6 @@ class QgsCoordinateTransformPrivate : public QSharedData //! QgsCoordinateReferenceSystem of the destination (map canvas) coordinate system QgsCoordinateReferenceSystem mDestCRS; - //! Transform context - QgsCoordinateTransformContext mContext; - -#ifdef QGISDEBUG - bool mHasContext = false; -#endif - QString mSourceProjString; QString mDestProjString; diff --git a/src/core/qgscoordinatetransformcontext.cpp b/src/core/qgscoordinatetransformcontext.cpp index e26e2276c8c..99d7a80ae4f 100644 --- a/src/core/qgscoordinatetransformcontext.cpp +++ b/src/core/qgscoordinatetransformcontext.cpp @@ -17,6 +17,7 @@ #include "qgscoordinatetransformcontext.h" #include "qgscoordinatetransformcontext_p.h" +#include "qgscoordinatetransform.h" #include "qgssettings.h" QgsCoordinateTransformContext::QgsCoordinateTransformContext() From 358c58d70b9f0fcbbec1072ea27af97d8e7316dc Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 18 Dec 2017 18:40:27 +1000 Subject: [PATCH 4/5] Fix bad merge --- src/core/layout/qgslayoutitemmap.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/layout/qgslayoutitemmap.cpp b/src/core/layout/qgslayoutitemmap.cpp index 6a2d1a0d439..895d636925f 100644 --- a/src/core/layout/qgslayoutitemmap.cpp +++ b/src/core/layout/qgslayoutitemmap.cpp @@ -1090,9 +1090,7 @@ QgsMapSettings QgsLayoutItemMap::mapSettings( const QgsRectangle &extent, QSizeF jobMapSettings.setFlag( QgsMapSettings::DrawEditingInfo, false ); jobMapSettings.setFlag( QgsMapSettings::DrawSelection, false ); jobMapSettings.setFlag( QgsMapSettings::UseAdvancedEffects, mLayout->context().flags() & QgsLayoutContext::FlagUseAdvancedEffects ); - - // todo datum nyall - //jobMapSettings.datumTransformStore().setDestinationCrs( renderCrs ); + jobMapSettings.setTransformContext( mLayout->project()->transformContext() ); jobMapSettings.setLabelingEngineSettings( mLayout->project()->labelingEngineSettings() ); From 198486f0e9eefdd8dfb1f2fff665a815d366ddf4 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 18 Dec 2017 21:18:51 +1000 Subject: [PATCH 5/5] Avoid including private header --- python/core/qgscoordinatetransformcontext.sip | 3 ++- src/core/qgscoordinatetransformcontext.cpp | 2 ++ src/core/qgscoordinatetransformcontext.h | 7 +++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/python/core/qgscoordinatetransformcontext.sip b/python/core/qgscoordinatetransformcontext.sip index c51b0827e38..bc6fe437e83 100644 --- a/python/core/qgscoordinatetransformcontext.sip +++ b/python/core/qgscoordinatetransformcontext.sip @@ -12,7 +12,6 @@ - class QgsCoordinateTransformContext { %Docstring @@ -51,6 +50,8 @@ applies for destination CRS transforms set using addDestinationDatumTransform(). Constructor for QgsCoordinateTransformContext. %End + ~QgsCoordinateTransformContext(); + QgsCoordinateTransformContext( const QgsCoordinateTransformContext &rhs ); %Docstring Copy constructor diff --git a/src/core/qgscoordinatetransformcontext.cpp b/src/core/qgscoordinatetransformcontext.cpp index 99d7a80ae4f..22039d390b1 100644 --- a/src/core/qgscoordinatetransformcontext.cpp +++ b/src/core/qgscoordinatetransformcontext.cpp @@ -24,6 +24,8 @@ QgsCoordinateTransformContext::QgsCoordinateTransformContext() : d( new QgsCoordinateTransformContextPrivate() ) {} +QgsCoordinateTransformContext::~QgsCoordinateTransformContext() = default; + QgsCoordinateTransformContext::QgsCoordinateTransformContext( const QgsCoordinateTransformContext &rhs ) //NOLINT : d( rhs.d ) {} diff --git a/src/core/qgscoordinatetransformcontext.h b/src/core/qgscoordinatetransformcontext.h index 24b4e4f5c3d..de30edc9eab 100644 --- a/src/core/qgscoordinatetransformcontext.h +++ b/src/core/qgscoordinatetransformcontext.h @@ -20,11 +20,12 @@ #include "qgis_core.h" #include "qgis.h" -#include "qgscoordinatetransformcontext_p.h" #include "qgsdatumtransform.h" +class QgsCoordinateReferenceSystem; class QgsReadWriteContext; - +class QgsCoordinateTransformContextPrivate; +class QDomElement; /*************************************************************************** * This class is considered CRITICAL and any change MUST be accompanied with @@ -64,6 +65,8 @@ class CORE_EXPORT QgsCoordinateTransformContext */ QgsCoordinateTransformContext(); + ~QgsCoordinateTransformContext(); + /** * Copy constructor */