diff --git a/doc/api_break.dox b/doc/api_break.dox index cf852046924..13d4364bbba 100644 --- a/doc/api_break.dox +++ b/doc/api_break.dox @@ -935,9 +935,9 @@ plugins calling these methods will need to be updated. - 'theNode', 'theDoc' parameters in readXML and writeXML have been renamed to 'node' and 'document' respectively - readXML() and writeXML() have been removed. - initialize() was removed. -- datumTransformations() now returns a list of QgsCoordinateTransform.TransformPair instead of a list of lists. -- datumTransformString() was renamed to datumTransformToProj() -- datumTransformCrsInfo() was renamed to datumTransformInfo(), and now returns a QgsCoordinateTransform.TransformInfo object. +- datumTransformations() was moved to QgsDatumTransform, and now returns a list of QgsDatumTransform.TransformPair instead of a list of lists. +- datumTransformString() was moved to QgsDatumTransform and renamed to datumTransformToProj() +- datumTransformCrsInfo() was moved to QgsDatumTransform and renamed to datumTransformInfo(), and now returns a QgsDatumTransform.TransformInfo object. - sourceDatumTransform() was renamed to sourceDatumTransformId() - setSourceDatumTransform() was renamed to setSourceDatumTransformId() - destinationDatumTransform() was renamed to destinationDatumTransformId() diff --git a/python/core/qgscoordinatetransform.sip b/python/core/qgscoordinatetransform.sip index 9da72d9a718..32c3ecb18a3 100644 --- a/python/core/qgscoordinatetransform.sip +++ b/python/core/qgscoordinatetransform.sip @@ -28,6 +28,10 @@ transforms coordinates from the layer's coordinate system to the map canvas. .. note:: Since QGIS 3.0 QgsCoordinateReferenceSystem objects are implicitly shared. + +.. seealso:: :py:class:`QgsDatumTransform` + +.. seealso:: :py:class:`QgsCoordinateTransformContext` %End %TypeHeaderCode @@ -252,47 +256,6 @@ otherwise points are transformed from destination to source CRS. bool isShortCircuited() const; %Docstring Returns true if the transform short circuits because the source and destination are equivalent. -%End - - 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. - -.. seealso:: :py:func:`datumTransformToProj()` - -.. seealso:: :py:func:`datumTransformInfo()` -%End - - static QString datumTransformToProj( int datumTransformId ); -%Docstring -Returns a proj string representing the specified ``datumTransformId`` datum transform ID. - -.. seealso:: :py:func:`datumTransformations()` - -.. seealso:: :py:func:`datumTransformInfo()` - -.. seealso:: :py:func:`projStringToDatumTransformId()` -%End - - static int projStringToDatumTransformId( const QString &string ); -%Docstring -Returns the datum transform ID corresponding to a specified proj ``string``. -Returns -1 if matching datum ID was not found. - -.. seealso:: :py:func:`datumTransformToProj()` - -.. versionadded:: 3.0 -%End - - 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 --1 will be returned. - -.. seealso:: :py:func:`datumTransformations()` - -.. seealso:: :py:func:`datumTransformToProj()` %End int sourceDatumTransformId() const; diff --git a/python/core/qgscoordinatetransformcontext.sip b/python/core/qgscoordinatetransformcontext.sip index bc6fe437e83..1bd94b2eaa3 100644 --- a/python/core/qgscoordinatetransformcontext.sip +++ b/python/core/qgscoordinatetransformcontext.sip @@ -37,6 +37,11 @@ applies for destination CRS transforms set using addDestinationDatumTransform(). QgsCoordinateTransformContext objects are implicitly shared. +.. seealso:: :py:class:`QgsDatumTransform` + +.. seealso:: :py:class:`QgsCoordinateTransform` + + .. versionadded:: 3.0 %End diff --git a/python/core/qgsdatumtransform.sip b/python/core/qgsdatumtransform.sip index 4ffffd34048..d6548fcd6a9 100644 --- a/python/core/qgsdatumtransform.sip +++ b/python/core/qgsdatumtransform.sip @@ -8,11 +8,17 @@ + + class QgsDatumTransform { %Docstring Contains methods and classes relating the datum transformations. +.. seealso:: :py:class:`QgsCoordinateTransformContext` + +.. seealso:: :py:class:`QgsCoordinateTransform` + .. versionadded:: 3.0 %End @@ -103,6 +109,46 @@ True if transform is deprecated %End }; + + 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. + +.. seealso:: :py:func:`datumTransformToProj()` + +.. seealso:: :py:func:`datumTransformInfo()` +%End + + static QString datumTransformToProj( int datumTransformId ); +%Docstring +Returns a proj string representing the specified ``datumTransformId`` datum transform ID. + +.. seealso:: :py:func:`datumTransformations()` + +.. seealso:: :py:func:`datumTransformInfo()` + +.. seealso:: :py:func:`projStringToDatumTransformId()` +%End + + static int projStringToDatumTransformId( const QString &string ); +%Docstring +Returns the datum transform ID corresponding to a specified proj ``string``. +Returns -1 if matching datum ID was not found. + +.. seealso:: :py:func:`datumTransformToProj()` +%End + + 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 +-1 will be returned. + +.. seealso:: :py:func:`datumTransformations()` + +.. seealso:: :py:func:`datumTransformToProj()` +%End + }; /************************************************************************ diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 5d022da2f41..73eeedbcb8b 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -9151,7 +9151,7 @@ void QgisApp::projectCrsChanged() if ( !transformsToAskFor.contains( it.value()->crs() ) && it.value()->crs() != QgsProject::instance()->crs() && !QgsProject::instance()->transformContext().hasTransform( it.value()->crs(), QgsProject::instance()->crs() ) && - QgsCoordinateTransform::datumTransformations( it.value()->crs(), QgsProject::instance()->crs() ).count() > 1 ) + QgsDatumTransform::datumTransformations( it.value()->crs(), QgsProject::instance()->crs() ).count() > 1 ) { transformsToAskFor.append( it.value()->crs() ); } diff --git a/src/app/qgsdatumtransformtablewidget.cpp b/src/app/qgsdatumtransformtablewidget.cpp index 364c5b68d36..11854eb360a 100644 --- a/src/app/qgsdatumtransformtablewidget.cpp +++ b/src/app/qgsdatumtransformtablewidget.cpp @@ -110,7 +110,7 @@ QVariant QgsDatumTransformTableModel::data( const QModelIndex &index, int role ) case SourceTransformColumn: if ( sourceTransform != -1 ) { - return QgsCoordinateTransform::datumTransformToProj( sourceTransform ); + return QgsDatumTransform::datumTransformToProj( sourceTransform ); } break; case DestinationCrsColumn: @@ -119,7 +119,7 @@ QVariant QgsDatumTransformTableModel::data( const QModelIndex &index, int role ) case DestinationTransformColumn: if ( destinationTransform != -1 ) { - return QgsCoordinateTransform::datumTransformToProj( destinationTransform ); + return QgsDatumTransform::datumTransformToProj( destinationTransform ); } break; default: diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a18fb5c01b8..ab95bc81c5b 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -161,6 +161,7 @@ SET(QGIS_CORE_SRCS qgsdatasourceuri.cpp qgsdataprovider.cpp qgsdatetimestatisticalsummary.cpp + qgsdatumtransform.cpp qgsdbfilterproxymodel.cpp qgsdefaultvalue.cpp qgsdiagramrenderer.cpp diff --git a/src/core/qgscoordinatetransform.cpp b/src/core/qgscoordinatetransform.cpp index ea6e41ec725..26eacbb9620 100644 --- a/src/core/qgscoordinatetransform.cpp +++ b/src/core/qgscoordinatetransform.cpp @@ -700,97 +700,6 @@ const char *finder( const char *name ) return proj.toUtf8(); } - - -QList< QgsDatumTransform::TransformPair > QgsCoordinateTransform::datumTransformations( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS ) -{ - QList< QgsDatumTransform::TransformPair > transformations; - - QString srcGeoId = srcCRS.geographicCrsAuthId(); - QString destGeoId = destCRS.geographicCrsAuthId(); - - if ( srcGeoId.isEmpty() || destGeoId.isEmpty() ) - { - return transformations; - } - - QStringList srcSplit = srcGeoId.split( ':' ); - QStringList destSplit = destGeoId.split( ':' ); - - if ( srcSplit.size() < 2 || destSplit.size() < 2 ) - { - return transformations; - } - - int srcAuthCode = srcSplit.at( 1 ).toInt(); - int destAuthCode = destSplit.at( 1 ).toInt(); - - if ( srcAuthCode == destAuthCode ) - { - return transformations; //crs have the same datum - } - - QList directTransforms; - searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code=%1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( destAuthCode ), - directTransforms ); - QList reverseDirectTransforms; - searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code = %1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( srcAuthCode ), - reverseDirectTransforms ); - QList srcToWgs84; - searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( 4326 ), - srcToWgs84 ); - QList destToWgs84; - searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( 4326 ), - destToWgs84 ); - - //add direct datum transformations - for ( int transform : qgis::as_const( directTransforms ) ) - { - transformations.push_back( QgsDatumTransform::TransformPair( transform, -1 ) ); - } - - //add direct datum transformations - for ( int transform : qgis::as_const( directTransforms ) ) - { - transformations.push_back( QgsDatumTransform::TransformPair( -1, transform ) ); - } - - for ( int srcTransform : qgis::as_const( srcToWgs84 ) ) - { - for ( int destTransform : qgis::as_const( destToWgs84 ) ) - { - transformations.push_back( QgsDatumTransform::TransformPair( srcTransform, destTransform ) ); - } - } - - return transformations; -} - -void QgsCoordinateTransform::searchDatumTransform( const QString &sql, QList< int > &transforms ) -{ - sqlite3_database_unique_ptr database; - int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); - if ( openResult != SQLITE_OK ) - { - return; - } - - sqlite3_statement_unique_ptr statement; - int prepareRes; - statement = database.prepare( sql, prepareRes ); - if ( prepareRes != SQLITE_OK ) - { - return; - } - - QString cOpCode; - while ( statement.step() == SQLITE_ROW ) - { - cOpCode = statement.columnAsText( 0 ); - transforms.push_back( cOpCode.toInt() ); - } -} - bool QgsCoordinateTransform::setFromCache( const QgsCoordinateReferenceSystem &src, const QgsCoordinateReferenceSystem &dest, int srcDatumTransform, int destDatumTransform ) { if ( !src.isValid() || !dest.isValid() ) @@ -833,61 +742,6 @@ void QgsCoordinateTransform::addToCache() sCacheLock.unlock(); } -QString QgsCoordinateTransform::datumTransformToProj( int datumTransform ) -{ - return QgsCoordinateTransformPrivate::datumTransformString( datumTransform ); -} - -int QgsCoordinateTransform::projStringToDatumTransformId( const QString &string ) -{ - return QgsCoordinateTransformPrivate::transformIdFromString( string ); -} - -QgsDatumTransform::TransformInfo QgsCoordinateTransform::datumTransformInfo( int datumTransform ) -{ - QgsDatumTransform::TransformInfo info; - - sqlite3_database_unique_ptr database; - int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); - if ( openResult != SQLITE_OK ) - { - return info; - } - - sqlite3_statement_unique_ptr statement; - QString sql = QStringLiteral( "SELECT epsg_nr,source_crs_code,target_crs_code,remarks,scope,preferred,deprecated FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( datumTransform ); - int prepareRes; - statement = database.prepare( sql, prepareRes ); - if ( prepareRes != SQLITE_OK ) - { - return info; - } - - int srcCrsId, destCrsId; - if ( statement.step() != SQLITE_ROW ) - { - return info; - } - - info.datumTransformId = datumTransform; - info.epsgCode = statement.columnAsInt64( 0 ); - srcCrsId = statement.columnAsInt64( 1 ); - destCrsId = statement.columnAsInt64( 2 ); - info.remarks = statement.columnAsText( 3 ); - info.scope = statement.columnAsText( 4 ); - info.preferred = statement.columnAsInt64( 5 ) != 0; - info.deprecated = statement.columnAsInt64( 6 ) != 0; - - QgsCoordinateReferenceSystem srcCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:%1" ).arg( srcCrsId ) ); - info.sourceCrsDescription = srcCrs.description(); - info.sourceCrsAuthId = srcCrs.authid(); - QgsCoordinateReferenceSystem destCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:%1" ).arg( destCrsId ) ); - info.destinationCrsDescription = destCrs.description(); - info.destinationCrsAuthId = destCrs.authid(); - - return info; -} - int QgsCoordinateTransform::sourceDatumTransformId() const { return d->mSourceDatumTransform; diff --git a/src/core/qgscoordinatetransform.h b/src/core/qgscoordinatetransform.h index d9e35c07bc7..806a834699f 100644 --- a/src/core/qgscoordinatetransform.h +++ b/src/core/qgscoordinatetransform.h @@ -44,6 +44,9 @@ class QgsProject; * operations are from the perspective of the layer. For example, a forward transformation * transforms coordinates from the layer's coordinate system to the map canvas. * \note Since QGIS 3.0 QgsCoordinateReferenceSystem objects are implicitly shared. +* +* \see QgsDatumTransform +* \see QgsCoordinateTransformContext */ class CORE_EXPORT QgsCoordinateTransform { @@ -312,38 +315,6 @@ class CORE_EXPORT QgsCoordinateTransform */ bool isShortCircuited() const; - /** - * Returns a list of datum transformations which are available for the given \a source and \a destination CRS. - * \see datumTransformToProj() - * \see datumTransformInfo() - */ - static QList< QgsDatumTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ); - - /** - * Returns a proj string representing the specified \a datumTransformId datum transform ID. - * \see datumTransformations() - * \see datumTransformInfo() - * \see projStringToDatumTransformId() - */ - static QString datumTransformToProj( int datumTransformId ); - - /** - * Returns the datum transform ID corresponding to a specified proj \a string. - * Returns -1 if matching datum ID was not found. - * \see datumTransformToProj() - * \since QGIS 3.0 - */ - static int projStringToDatumTransformId( const QString &string ); - - /** - * Returns detailed information about the specified \a datumTransformId. - * If \a datumTransformId was not a valid transform ID, a TransformInfo with TransformInfo::datumTransformId of - * -1 will be returned. - * \see datumTransformations() - * \see datumTransformToProj() - */ - static QgsDatumTransform::TransformInfo datumTransformInfo( int datumTransformId ); - /** * Returns the ID of the datum transform to use when projecting from the source * CRS. @@ -406,8 +377,6 @@ class CORE_EXPORT QgsCoordinateTransform private: - static void searchDatumTransform( const QString &sql, QList< int > &transforms ); - mutable QExplicitlySharedDataPointer d; //! Transform context diff --git a/src/core/qgscoordinatetransform_p.cpp b/src/core/qgscoordinatetransform_p.cpp index 624ca6e29cd..6ca038c8545 100644 --- a/src/core/qgscoordinatetransform_p.cpp +++ b/src/core/qgscoordinatetransform_p.cpp @@ -140,7 +140,7 @@ bool QgsCoordinateTransformPrivate::initialize() } if ( sourceDatumTransform != -1 ) { - mSourceProjString += ( ' ' + datumTransformString( sourceDatumTransform ) ); + mSourceProjString += ( ' ' + QgsDatumTransform::datumTransformToProj( sourceDatumTransform ) ); } mDestProjString = mDestCRS.toProj4(); @@ -150,7 +150,7 @@ bool QgsCoordinateTransformPrivate::initialize() } if ( destDatumTransform != -1 ) { - mDestProjString += ( ' ' + datumTransformString( destDatumTransform ) ); + mDestProjString += ( ' ' + QgsDatumTransform::datumTransformToProj( destDatumTransform ) ); } if ( !useDefaultDatumTransform ) @@ -284,114 +284,6 @@ QString QgsCoordinateTransformPrivate::stripDatumTransform( const QString &proj4 return newProjString; } -QString QgsCoordinateTransformPrivate::datumTransformString( int datumTransform ) -{ - QString transformString; - - sqlite3_database_unique_ptr database; - int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); - if ( openResult != SQLITE_OK ) - { - return transformString; - } - - sqlite3_statement_unique_ptr statement; - QString sql = QStringLiteral( "SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7 FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( datumTransform ); - int prepareRes; - statement = database.prepare( sql, prepareRes ); - if ( prepareRes != SQLITE_OK ) - { - return transformString; - } - - if ( statement.step() == SQLITE_ROW ) - { - //coord_op_methode_code - int methodCode = statement.columnAsInt64( 0 ); - if ( methodCode == 9615 ) //ntv2 - { - transformString = "+nadgrids=" + statement.columnAsText( 1 ); - } - else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 ) - { - transformString += QLatin1String( "+towgs84=" ); - double p1 = statement.columnAsDouble( 1 ); - double p2 = statement.columnAsDouble( 2 ); - double p3 = statement.columnAsDouble( 3 ); - double p4 = statement.columnAsDouble( 4 ); - double p5 = statement.columnAsDouble( 5 ); - double p6 = statement.columnAsDouble( 6 ); - double p7 = statement.columnAsDouble( 7 ); - if ( methodCode == 9603 ) //3 parameter transformation - { - transformString += QStringLiteral( "%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) ); - } - else //7 parameter transformation - { - transformString += QStringLiteral( "%1,%2,%3,%4,%5,%6,%7" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ), QString::number( p4 ), QString::number( p5 ), QString::number( p6 ), QString::number( p7 ) ); - } - } - } - - return transformString; -} - -int QgsCoordinateTransformPrivate::transformIdFromString( const QString &string ) -{ - sqlite3_database_unique_ptr database; - int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); - if ( openResult != SQLITE_OK ) - { - return -1; - } - - sqlite3_statement_unique_ptr statement; - QString sql = QStringLiteral( "SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7,coord_op_code FROM tbl_datum_transform" ); - int prepareRes; - statement = database.prepare( sql, prepareRes ); - if ( prepareRes != SQLITE_OK ) - { - return -1; - } - - while ( statement.step() == SQLITE_ROW ) - { - QString transformString; - //coord_op_methode_code - int methodCode = statement.columnAsInt64( 0 ); - if ( methodCode == 9615 ) //ntv2 - { - transformString = "+nadgrids=" + statement.columnAsText( 1 ); - } - else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 ) - { - transformString += QLatin1String( "+towgs84=" ); - double p1 = statement.columnAsDouble( 1 ); - double p2 = statement.columnAsDouble( 2 ); - double p3 = statement.columnAsDouble( 3 ); - double p4 = statement.columnAsDouble( 4 ); - double p5 = statement.columnAsDouble( 5 ); - double p6 = statement.columnAsDouble( 6 ); - double p7 = statement.columnAsDouble( 7 ); - if ( methodCode == 9603 ) //3 parameter transformation - { - transformString += QStringLiteral( "%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) ); - } - else //7 parameter transformation - { - transformString += QStringLiteral( "%1,%2,%3,%4,%5,%6,%7" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ), QString::number( p4 ), QString::number( p5 ), QString::number( p6 ), QString::number( p7 ) ); - } - } - - if ( transformString.compare( string, Qt::CaseInsensitive ) == 0 ) - { - return statement.columnAsInt64( 8 ); - } - } - - return -1; -} - void QgsCoordinateTransformPrivate::addNullGridShifts( QString &srcProjString, QString &destProjString, int sourceDatumTransform, int destinationDatumTransform ) const { diff --git a/src/core/qgscoordinatetransform_p.h b/src/core/qgscoordinatetransform_p.h index 8e23b8b09ae..27063a17819 100644 --- a/src/core/qgscoordinatetransform_p.h +++ b/src/core/qgscoordinatetransform_p.h @@ -128,21 +128,6 @@ class QgsCoordinateTransformPrivate : public QSharedData QReadWriteLock mProjLock; QMap < uintptr_t, QPair< projPJ, projPJ > > mProjProjections; - /** - * Returns the proj transform string corresponding to a - * datum transform ID. - * \see transformIdFromString() - */ - static QString datumTransformString( int transformId ); - - /** - * Attempts to match a proj datum transform string to a datum ID. - * Returns -1 if datum ID was not found. - * \see datumTransformString() - * \since QGIS 3.0 - */ - static int transformIdFromString( const QString &string ); - private: //! Removes +nadgrids and +towgs84 from proj4 string diff --git a/src/core/qgscoordinatetransformcontext.cpp b/src/core/qgscoordinatetransformcontext.cpp index 22039d390b1..c816d900d59 100644 --- a/src/core/qgscoordinatetransformcontext.cpp +++ b/src/core/qgscoordinatetransformcontext.cpp @@ -203,7 +203,7 @@ bool QgsCoordinateTransformContext::readXml( const QDomElement &element, const Q //warn if value1 or value2 is non-empty, yet no matching transform was found if ( !value1.isEmpty() ) { - datumId1 = QgsCoordinateTransform::projStringToDatumTransformId( value1 ); + datumId1 = QgsDatumTransform::projStringToDatumTransformId( value1 ); if ( datumId1 < 0 ) { result = false; @@ -212,7 +212,7 @@ bool QgsCoordinateTransformContext::readXml( const QDomElement &element, const Q } if ( !value2.isEmpty() ) { - datumId2 = QgsCoordinateTransform::projStringToDatumTransformId( value2 ); + datumId2 = QgsDatumTransform::projStringToDatumTransformId( value2 ); if ( datumId2 < 0 ) { result = false; @@ -271,8 +271,8 @@ void QgsCoordinateTransformContext::writeXml( QDomElement &element, const QgsRea QDomElement transformElem = element.ownerDocument().createElement( QStringLiteral( "srcDest" ) ); transformElem.setAttribute( QStringLiteral( "source" ), it.key().first ); transformElem.setAttribute( QStringLiteral( "dest" ), it.key().second ); - transformElem.setAttribute( QStringLiteral( "sourceTransform" ), it.value().sourceTransformId < 0 ? QString() : QgsCoordinateTransform::datumTransformToProj( it.value().sourceTransformId ) ); - transformElem.setAttribute( QStringLiteral( "destTransform" ), it.value().destinationTransformId < 0 ? QString() : QgsCoordinateTransform::datumTransformToProj( it.value().destinationTransformId ) ); + transformElem.setAttribute( QStringLiteral( "sourceTransform" ), it.value().sourceTransformId < 0 ? QString() : QgsDatumTransform::datumTransformToProj( it.value().sourceTransformId ) ); + transformElem.setAttribute( QStringLiteral( "destTransform" ), it.value().destinationTransformId < 0 ? QString() : QgsDatumTransform::datumTransformToProj( it.value().destinationTransformId ) ); contextElem.appendChild( transformElem ); } @@ -334,7 +334,7 @@ void QgsCoordinateTransformContext::readSettings() } QString proj = settings.value( *pkeyIt ).toString(); - int datumId = QgsCoordinateTransform::projStringToDatumTransformId( proj ); + int datumId = QgsDatumTransform::projStringToDatumTransformId( proj ); if ( pkeyIt->contains( QLatin1String( "srcTransform" ) ) ) { transforms[ qMakePair( srcAuthId, destAuthId )].first = datumId; @@ -378,11 +378,11 @@ void QgsCoordinateTransformContext::writeSettings() int sourceDatumTransform = transformIt.value().sourceTransformId; QString sourceDatumProj; if ( sourceDatumTransform >= 0 ) - sourceDatumProj = QgsCoordinateTransform::datumTransformToProj( sourceDatumTransform ); + sourceDatumProj = QgsDatumTransform::datumTransformToProj( sourceDatumTransform ); int destinationDatumTransform = transformIt.value().destinationTransformId; QString destinationDatumProj; if ( destinationDatumTransform >= 0 ) - destinationDatumProj = QgsCoordinateTransform::datumTransformToProj( destinationDatumTransform ); + destinationDatumProj = QgsDatumTransform::datumTransformToProj( destinationDatumTransform ); settings.setValue( srcAuthId + "//" + destAuthId + "_srcTransform", sourceDatumProj ); settings.setValue( srcAuthId + "//" + destAuthId + "_destTransform", destinationDatumProj ); diff --git a/src/core/qgscoordinatetransformcontext.h b/src/core/qgscoordinatetransformcontext.h index de30edc9eab..e2ed59a6b22 100644 --- a/src/core/qgscoordinatetransformcontext.h +++ b/src/core/qgscoordinatetransformcontext.h @@ -53,6 +53,9 @@ class QDomElement; * * \note QgsCoordinateTransformContext objects are implicitly shared. * + * \see QgsDatumTransform + * \see QgsCoordinateTransform + * * \since QGIS 3.0 */ diff --git a/src/core/qgsdatumtransform.cpp b/src/core/qgsdatumtransform.cpp new file mode 100644 index 00000000000..d307f65ac10 --- /dev/null +++ b/src/core/qgsdatumtransform.cpp @@ -0,0 +1,263 @@ +/*************************************************************************** + qgsdatumtransform.cpp + ------------------------ + 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. * + * * + ***************************************************************************/ +#include "qgsdatumtransform.h" +#include "qgscoordinatereferencesystem.h" +#include "qgsapplication.h" +#include "qgssqliteutils.h" +#include + +QList< QgsDatumTransform::TransformPair > QgsDatumTransform::datumTransformations( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateReferenceSystem &destCRS ) +{ + QList< QgsDatumTransform::TransformPair > transformations; + + QString srcGeoId = srcCRS.geographicCrsAuthId(); + QString destGeoId = destCRS.geographicCrsAuthId(); + + if ( srcGeoId.isEmpty() || destGeoId.isEmpty() ) + { + return transformations; + } + + QStringList srcSplit = srcGeoId.split( ':' ); + QStringList destSplit = destGeoId.split( ':' ); + + if ( srcSplit.size() < 2 || destSplit.size() < 2 ) + { + return transformations; + } + + int srcAuthCode = srcSplit.at( 1 ).toInt(); + int destAuthCode = destSplit.at( 1 ).toInt(); + + if ( srcAuthCode == destAuthCode ) + { + return transformations; //crs have the same datum + } + + QList directTransforms; + searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code=%1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( destAuthCode ), + directTransforms ); + QList reverseDirectTransforms; + searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code = %1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( srcAuthCode ), + reverseDirectTransforms ); + QList srcToWgs84; + searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( 4326 ), + srcToWgs84 ); + QList destToWgs84; + searchDatumTransform( QStringLiteral( "SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( 4326 ), + destToWgs84 ); + + //add direct datum transformations + for ( int transform : qgis::as_const( directTransforms ) ) + { + transformations.push_back( QgsDatumTransform::TransformPair( transform, -1 ) ); + } + + //add direct datum transformations + for ( int transform : qgis::as_const( directTransforms ) ) + { + transformations.push_back( QgsDatumTransform::TransformPair( -1, transform ) ); + } + + for ( int srcTransform : qgis::as_const( srcToWgs84 ) ) + { + for ( int destTransform : qgis::as_const( destToWgs84 ) ) + { + transformations.push_back( QgsDatumTransform::TransformPair( srcTransform, destTransform ) ); + } + } + + return transformations; +} + +void QgsDatumTransform::searchDatumTransform( const QString &sql, QList< int > &transforms ) +{ + sqlite3_database_unique_ptr database; + int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); + if ( openResult != SQLITE_OK ) + { + return; + } + + sqlite3_statement_unique_ptr statement; + int prepareRes; + statement = database.prepare( sql, prepareRes ); + if ( prepareRes != SQLITE_OK ) + { + return; + } + + QString cOpCode; + while ( statement.step() == SQLITE_ROW ) + { + cOpCode = statement.columnAsText( 0 ); + transforms.push_back( cOpCode.toInt() ); + } +} + +QString QgsDatumTransform::datumTransformToProj( int datumTransform ) +{ + QString transformString; + + sqlite3_database_unique_ptr database; + int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); + if ( openResult != SQLITE_OK ) + { + return transformString; + } + + sqlite3_statement_unique_ptr statement; + QString sql = QStringLiteral( "SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7 FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( datumTransform ); + int prepareRes; + statement = database.prepare( sql, prepareRes ); + if ( prepareRes != SQLITE_OK ) + { + return transformString; + } + + if ( statement.step() == SQLITE_ROW ) + { + //coord_op_methode_code + int methodCode = statement.columnAsInt64( 0 ); + if ( methodCode == 9615 ) //ntv2 + { + transformString = "+nadgrids=" + statement.columnAsText( 1 ); + } + else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 ) + { + transformString += QLatin1String( "+towgs84=" ); + double p1 = statement.columnAsDouble( 1 ); + double p2 = statement.columnAsDouble( 2 ); + double p3 = statement.columnAsDouble( 3 ); + double p4 = statement.columnAsDouble( 4 ); + double p5 = statement.columnAsDouble( 5 ); + double p6 = statement.columnAsDouble( 6 ); + double p7 = statement.columnAsDouble( 7 ); + if ( methodCode == 9603 ) //3 parameter transformation + { + transformString += QStringLiteral( "%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) ); + } + else //7 parameter transformation + { + transformString += QStringLiteral( "%1,%2,%3,%4,%5,%6,%7" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ), QString::number( p4 ), QString::number( p5 ), QString::number( p6 ), QString::number( p7 ) ); + } + } + } + + return transformString; +} + +int QgsDatumTransform::projStringToDatumTransformId( const QString &string ) +{ + sqlite3_database_unique_ptr database; + int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); + if ( openResult != SQLITE_OK ) + { + return -1; + } + + sqlite3_statement_unique_ptr statement; + QString sql = QStringLiteral( "SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7,coord_op_code FROM tbl_datum_transform" ); + int prepareRes; + statement = database.prepare( sql, prepareRes ); + if ( prepareRes != SQLITE_OK ) + { + return -1; + } + + while ( statement.step() == SQLITE_ROW ) + { + QString transformString; + //coord_op_methode_code + int methodCode = statement.columnAsInt64( 0 ); + if ( methodCode == 9615 ) //ntv2 + { + transformString = "+nadgrids=" + statement.columnAsText( 1 ); + } + else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 ) + { + transformString += QLatin1String( "+towgs84=" ); + double p1 = statement.columnAsDouble( 1 ); + double p2 = statement.columnAsDouble( 2 ); + double p3 = statement.columnAsDouble( 3 ); + double p4 = statement.columnAsDouble( 4 ); + double p5 = statement.columnAsDouble( 5 ); + double p6 = statement.columnAsDouble( 6 ); + double p7 = statement.columnAsDouble( 7 ); + if ( methodCode == 9603 ) //3 parameter transformation + { + transformString += QStringLiteral( "%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) ); + } + else //7 parameter transformation + { + transformString += QStringLiteral( "%1,%2,%3,%4,%5,%6,%7" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ), QString::number( p4 ), QString::number( p5 ), QString::number( p6 ), QString::number( p7 ) ); + } + } + + if ( transformString.compare( string, Qt::CaseInsensitive ) == 0 ) + { + return statement.columnAsInt64( 8 ); + } + } + + return -1; +} + +QgsDatumTransform::TransformInfo QgsDatumTransform::datumTransformInfo( int datumTransform ) +{ + QgsDatumTransform::TransformInfo info; + + sqlite3_database_unique_ptr database; + int openResult = database.open_v2( QgsApplication::srsDatabaseFilePath(), SQLITE_OPEN_READONLY, nullptr ); + if ( openResult != SQLITE_OK ) + { + return info; + } + + sqlite3_statement_unique_ptr statement; + QString sql = QStringLiteral( "SELECT epsg_nr,source_crs_code,target_crs_code,remarks,scope,preferred,deprecated FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( datumTransform ); + int prepareRes; + statement = database.prepare( sql, prepareRes ); + if ( prepareRes != SQLITE_OK ) + { + return info; + } + + int srcCrsId, destCrsId; + if ( statement.step() != SQLITE_ROW ) + { + return info; + } + + info.datumTransformId = datumTransform; + info.epsgCode = statement.columnAsInt64( 0 ); + srcCrsId = statement.columnAsInt64( 1 ); + destCrsId = statement.columnAsInt64( 2 ); + info.remarks = statement.columnAsText( 3 ); + info.scope = statement.columnAsText( 4 ); + info.preferred = statement.columnAsInt64( 5 ) != 0; + info.deprecated = statement.columnAsInt64( 6 ) != 0; + + QgsCoordinateReferenceSystem srcCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:%1" ).arg( srcCrsId ) ); + info.sourceCrsDescription = srcCrs.description(); + info.sourceCrsAuthId = srcCrs.authid(); + QgsCoordinateReferenceSystem destCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:%1" ).arg( destCrsId ) ); + info.destinationCrsDescription = destCrs.description(); + info.destinationCrsAuthId = destCrs.authid(); + + return info; +} diff --git a/src/core/qgsdatumtransform.h b/src/core/qgsdatumtransform.h index cefa4a044d6..cfaee6baa41 100644 --- a/src/core/qgsdatumtransform.h +++ b/src/core/qgsdatumtransform.h @@ -20,9 +20,16 @@ #include "qgis_core.h" #include +class QgsCoordinateReferenceSystem; + + /** * Contains methods and classes relating the datum transformations. * \ingroup core + * + * \see QgsCoordinateTransformContext + * \see QgsCoordinateTransform + * * \since QGIS 3.0 */ class CORE_EXPORT QgsDatumTransform @@ -107,6 +114,43 @@ class CORE_EXPORT QgsDatumTransform bool deprecated = false; }; + + /** + * Returns a list of datum transformations which are available for the given \a source and \a destination CRS. + * \see datumTransformToProj() + * \see datumTransformInfo() + */ + static QList< QgsDatumTransform::TransformPair > datumTransformations( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ); + + /** + * Returns a proj string representing the specified \a datumTransformId datum transform ID. + * \see datumTransformations() + * \see datumTransformInfo() + * \see projStringToDatumTransformId() + */ + static QString datumTransformToProj( int datumTransformId ); + + /** + * Returns the datum transform ID corresponding to a specified proj \a string. + * Returns -1 if matching datum ID was not found. + * \see datumTransformToProj() + */ + static int projStringToDatumTransformId( const QString &string ); + + /** + * Returns detailed information about the specified \a datumTransformId. + * If \a datumTransformId was not a valid transform ID, a TransformInfo with TransformInfo::datumTransformId of + * -1 will be returned. + * \see datumTransformations() + * \see datumTransformToProj() + */ + static QgsDatumTransform::TransformInfo datumTransformInfo( int datumTransformId ); + + private: + + static void searchDatumTransform( const QString &sql, QList< int > &transforms ); + + }; #endif // QGSDATUMTRANSFORM_H diff --git a/src/gui/qgsdatumtransformdialog.cpp b/src/gui/qgsdatumtransformdialog.cpp index 709cf6f364b..111dd8a90b6 100644 --- a/src/gui/qgsdatumtransformdialog.cpp +++ b/src/gui/qgsdatumtransformdialog.cpp @@ -46,7 +46,7 @@ QgsDatumTransformDialog::QgsDatumTransformDialog( const QgsCoordinateReferenceSy //get list of datum transforms mSourceCrs = sourceCrs; mDestinationCrs = destinationCrs; - mDatumTransforms = QgsCoordinateTransform::datumTransformations( sourceCrs, destinationCrs ); + mDatumTransforms = QgsDatumTransform::datumTransformations( sourceCrs, destinationCrs ); QApplication::setOverrideCursor( Qt::ArrowCursor ); @@ -84,10 +84,10 @@ void QgsDatumTransformDialog::load( const QPair &selectedDatumTransfor if ( nr == -1 ) continue; - item->setText( i, QgsCoordinateTransform::datumTransformToProj( nr ) ); + item->setText( i, QgsDatumTransform::datumTransformToProj( nr ) ); //Describe datums in a tooltip - QgsDatumTransform::TransformInfo info = QgsCoordinateTransform::datumTransformInfo( nr ); + QgsDatumTransform::TransformInfo info = QgsDatumTransform::datumTransformInfo( nr ); if ( info.datumTransformId == -1 ) continue; @@ -266,7 +266,7 @@ void QgsDatumTransformDialog::mDatumTransformTreeWidget_currentItemChanged( QTre void QgsDatumTransformDialog::setSourceCrs( const QgsCoordinateReferenceSystem &sourceCrs ) { mSourceCrs = sourceCrs; - mDatumTransforms = QgsCoordinateTransform::datumTransformations( mSourceCrs, mDestinationCrs ); + mDatumTransforms = QgsDatumTransform::datumTransformations( mSourceCrs, mDestinationCrs ); load(); setOKButtonEnabled(); } @@ -274,7 +274,7 @@ void QgsDatumTransformDialog::setSourceCrs( const QgsCoordinateReferenceSystem & void QgsDatumTransformDialog::setDestinationCrs( const QgsCoordinateReferenceSystem &destinationCrs ) { mDestinationCrs = destinationCrs; - mDatumTransforms = QgsCoordinateTransform::datumTransformations( mSourceCrs, mDestinationCrs ); + mDatumTransforms = QgsDatumTransform::datumTransformations( mSourceCrs, mDestinationCrs ); load(); setOKButtonEnabled(); } diff --git a/tests/src/python/test_qgscoordinatetransform.py b/tests/src/python/test_qgscoordinatetransform.py index ba6bbb19753..6e1a47f6dbb 100644 --- a/tests/src/python/test_qgscoordinatetransform.py +++ b/tests/src/python/test_qgscoordinatetransform.py @@ -18,6 +18,7 @@ from qgis.core import (QgsRectangle, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsCoordinateTransformContext, + QgsDatumTransform, QgsProject) from qgis.testing import start_app, unittest @@ -209,27 +210,27 @@ class TestQgsCoordinateTransform(unittest.TestCase): def testTransformInfo(self): # hopefully this transform is available on all platforms! - transforms = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4613), QgsCoordinateReferenceSystem(4326)) + transforms = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4613), QgsCoordinateReferenceSystem(4326)) self.assertTrue(len(transforms) > 0) - self.assertIn('+towgs84=-403,684,41', [QgsCoordinateTransform.datumTransformToProj(t.sourceTransformId) for t in transforms]) - self.assertIn('+towgs84=-403,684,41', [QgsCoordinateTransform.datumTransformToProj(t.destinationTransformId) for t in transforms]) - self.assertIn('EPSG:4613', [QgsCoordinateTransform.datumTransformInfo(t.destinationTransformId).sourceCrsAuthId for t in + self.assertIn('+towgs84=-403,684,41', [QgsDatumTransform.datumTransformToProj(t.sourceTransformId) for t in transforms]) + self.assertIn('+towgs84=-403,684,41', [QgsDatumTransform.datumTransformToProj(t.destinationTransformId) for t in transforms]) + self.assertIn('EPSG:4613', [QgsDatumTransform.datumTransformInfo(t.destinationTransformId).sourceCrsAuthId for t in transforms]) - self.assertIn('EPSG:4326', [QgsCoordinateTransform.datumTransformInfo(t.destinationTransformId).destinationCrsAuthId for t in + self.assertIn('EPSG:4326', [QgsDatumTransform.datumTransformInfo(t.destinationTransformId).destinationCrsAuthId for t in transforms]) def testStringToTransformId(self): """ Test converting proj strings to corresponding datum IDs """ - self.assertEqual(QgsCoordinateTransform.projStringToDatumTransformId(''), -1) - self.assertEqual(QgsCoordinateTransform.projStringToDatumTransformId('not'), -1) + self.assertEqual(QgsDatumTransform.projStringToDatumTransformId(''), -1) + self.assertEqual(QgsDatumTransform.projStringToDatumTransformId('not'), -1) test_string = '+towgs84=-403,684,41' - id = QgsCoordinateTransform.projStringToDatumTransformId(test_string) + id = QgsDatumTransform.projStringToDatumTransformId(test_string) self.assertNotEqual(id, -1) - string = QgsCoordinateTransform.datumTransformToProj(id) + string = QgsDatumTransform.datumTransformToProj(id) self.assertEqual(string, test_string) - self.assertEqual(QgsCoordinateTransform.projStringToDatumTransformId(test_string.upper()), id) + self.assertEqual(QgsDatumTransform.projStringToDatumTransformId(test_string.upper()), id) if __name__ == '__main__': diff --git a/tests/src/python/test_qgscoordinatetransformcontext.py b/tests/src/python/test_qgscoordinatetransformcontext.py index 71848e8a803..7d0b6b89866 100644 --- a/tests/src/python/test_qgscoordinatetransformcontext.py +++ b/tests/src/python/test_qgscoordinatetransformcontext.py @@ -302,15 +302,15 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): # setup a context context = QgsCoordinateTransformContext() - source_id_1 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), - QgsCoordinateReferenceSystem(4326))[0].sourceTransformId - dest_id_1 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), - QgsCoordinateReferenceSystem(4326))[0].destinationTransformId + source_id_1 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), + QgsCoordinateReferenceSystem(4326))[0].sourceTransformId + dest_id_1 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), + QgsCoordinateReferenceSystem(4326))[0].destinationTransformId - source_id_2 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), - QgsCoordinateReferenceSystem(4326))[0].sourceTransformId - dest_id_2 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), - QgsCoordinateReferenceSystem(4326))[0].destinationTransformId + source_id_2 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), + QgsCoordinateReferenceSystem(4326))[0].sourceTransformId + dest_id_2 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), + QgsCoordinateReferenceSystem(4326))[0].destinationTransformId self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(4204), QgsCoordinateReferenceSystem(4326), source_id_1, dest_id_1)) @@ -373,15 +373,15 @@ class TestQgsCoordinateTransformContext(unittest.TestCase): context = QgsCoordinateTransformContext() context.readSettings() - source_id_1 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), - QgsCoordinateReferenceSystem(4326))[0].sourceTransformId - dest_id_1 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), - QgsCoordinateReferenceSystem(4326))[0].destinationTransformId + source_id_1 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), + QgsCoordinateReferenceSystem(4326))[0].sourceTransformId + dest_id_1 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4204), + QgsCoordinateReferenceSystem(4326))[0].destinationTransformId - source_id_2 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), - QgsCoordinateReferenceSystem(4326))[0].sourceTransformId - dest_id_2 = QgsCoordinateTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), - QgsCoordinateReferenceSystem(4326))[0].destinationTransformId + source_id_2 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), + QgsCoordinateReferenceSystem(4326))[0].sourceTransformId + dest_id_2 = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4205), + QgsCoordinateReferenceSystem(4326))[0].destinationTransformId # should be empty self.assertEqual(context.sourceDestinationDatumTransforms(), {})