Skip to content

Commit

Permalink
Add method to retrieve datum transform ID from a proj string
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 15, 2017
1 parent 43d8a6b commit 3187352
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 1 deletion.
10 changes: 10 additions & 0 deletions python/core/qgscoordinatetransform.sip
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgscoordinatetransform.cpp
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions src/core/qgscoordinatetransform.h
Expand Up @@ -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
Expand Down
56 changes: 56 additions & 0 deletions src/core/qgscoordinatetransform_p.cpp
Expand Up @@ -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
{
Expand Down
15 changes: 14 additions & 1 deletion src/core/qgscoordinatetransform_p.h
Expand Up @@ -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:

Expand Down
13 changes: 13 additions & 0 deletions tests/src/python/test_qgscoordinatetransform.py
Expand Up @@ -218,6 +218,19 @@ def testTransformInfo(self):
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()

0 comments on commit 3187352

Please sign in to comment.