From 318735271e5118889b3b995612edfc3f4fe89a66 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 15 Dec 2017 16:42:40 +1000 Subject: [PATCH] Add method to retrieve datum transform ID from a proj string --- python/core/qgscoordinatetransform.sip | 10 ++++ src/core/qgscoordinatetransform.cpp | 5 ++ src/core/qgscoordinatetransform.h | 9 +++ src/core/qgscoordinatetransform_p.cpp | 56 +++++++++++++++++++ src/core/qgscoordinatetransform_p.h | 15 ++++- .../src/python/test_qgscoordinatetransform.py | 13 +++++ 6 files changed, 107 insertions(+), 1 deletion(-) diff --git a/python/core/qgscoordinatetransform.sip b/python/core/qgscoordinatetransform.sip index bf4b83b13b2..02b0151684a 100644 --- a/python/core/qgscoordinatetransform.sip +++ b/python/core/qgscoordinatetransform.sip @@ -281,9 +281,19 @@ Default constructor, creates an invalid QgsCoordinateTransform. Returns a proj string representing the specified ``datumTransformId`` datum transform ID. .. seealso:: :py:func:`datumTransformations()` .. seealso:: :py:func:`datumTransformInfo()` +.. seealso:: :py:func:`projStringToDatumTransformId()` :rtype: str %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 + :rtype: int +%End + struct TransformInfo { int datumTransformId; diff --git a/src/core/qgscoordinatetransform.cpp b/src/core/qgscoordinatetransform.cpp index 2e05b530403..7ba55baec8e 100644 --- a/src/core/qgscoordinatetransform.cpp +++ b/src/core/qgscoordinatetransform.cpp @@ -816,6 +816,11 @@ QString QgsCoordinateTransform::datumTransformToProj( int datumTransform ) return QgsCoordinateTransformPrivate::datumTransformString( datumTransform ); } +int QgsCoordinateTransform::projStringToDatumTransformId( const QString &string ) +{ + return QgsCoordinateTransformPrivate::transformIdFromString( string ); +} + QgsCoordinateTransform::TransformInfo QgsCoordinateTransform::datumTransformInfo( int datumTransform ) { TransformInfo info; diff --git a/src/core/qgscoordinatetransform.h b/src/core/qgscoordinatetransform.h index 2b21cb1c7f3..a287694328f 100644 --- a/src/core/qgscoordinatetransform.h +++ b/src/core/qgscoordinatetransform.h @@ -363,9 +363,18 @@ class CORE_EXPORT QgsCoordinateTransform * 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 ); + /** * Contains datum transform information. * \since QGIS 3.0 diff --git a/src/core/qgscoordinatetransform_p.cpp b/src/core/qgscoordinatetransform_p.cpp index ca3803ea719..1f5fee3cf81 100644 --- a/src/core/qgscoordinatetransform_p.cpp +++ b/src/core/qgscoordinatetransform_p.cpp @@ -341,6 +341,62 @@ QString QgsCoordinateTransformPrivate::datumTransformString( int datumTransform 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 90bb5cf798c..112a0ba5254 100644 --- a/src/core/qgscoordinatetransform_p.h +++ b/src/core/qgscoordinatetransform_p.h @@ -135,7 +135,20 @@ class QgsCoordinateTransformPrivate : public QSharedData QReadWriteLock mProjLock; QMap < uintptr_t, QPair< projPJ, projPJ > > mProjProjections; - static QString datumTransformString( int datumTransform ); + /** + * 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: diff --git a/tests/src/python/test_qgscoordinatetransform.py b/tests/src/python/test_qgscoordinatetransform.py index 8d937041072..ba6bbb19753 100644 --- a/tests/src/python/test_qgscoordinatetransform.py +++ b/tests/src/python/test_qgscoordinatetransform.py @@ -218,6 +218,19 @@ class TestQgsCoordinateTransform(unittest.TestCase): self.assertIn('EPSG:4326', [QgsCoordinateTransform.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) + test_string = '+towgs84=-403,684,41' + id = QgsCoordinateTransform.projStringToDatumTransformId(test_string) + self.assertNotEqual(id, -1) + string = QgsCoordinateTransform.datumTransformToProj(id) + self.assertEqual(string, test_string) + self.assertEqual(QgsCoordinateTransform.projStringToDatumTransformId(test_string.upper()), id) + if __name__ == '__main__': unittest.main()