Skip to content
Permalink
Browse files

Merge pull request #5906 from nyalldawson/datum

Datum fixes and cleanups
  • Loading branch information
nyalldawson committed Dec 19, 2017
2 parents 13a888d + a77b5b6 commit 48e6ec58e8691514b82d0712cf39e97c9749ac80
@@ -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()
@@ -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
@@ -82,7 +86,7 @@ and it is used to retrieve the project's transform context only.
%Docstring
Constructs a QgsCoordinateTransform to transform from the ``source``
to ``destination`` coordinate reference system, with the specified
datum transforms.
datum transforms (see QgsDatumTransform).

.. versionadded:: 3.0
%End
@@ -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;
@@ -303,6 +266,8 @@ CRS.
This is usually calculated automatically from the transform's QgsCoordinateTransformContext,
but can be manually overwritten by a call to setSourceDatumTransformId().

.. seealso:: :py:class:`QgsDatumTransform`

.. seealso:: :py:func:`setSourceDatumTransformId()`

.. seealso:: :py:func:`destinationDatumTransformId()`
@@ -318,6 +283,8 @@ CRS.
This is usually calculated automatically from the transform's QgsCoordinateTransformContext.
Calling this method will overwrite any automatically calculated datum transform.

.. seealso:: :py:class:`QgsDatumTransform`

.. seealso:: :py:func:`sourceDatumTransformId()`

.. seealso:: :py:func:`setDestinationDatumTransformId()`
@@ -333,6 +300,8 @@ CRS.
This is usually calculated automatically from the transform's QgsCoordinateTransformContext,
but can be manually overwritten by a call to setDestinationDatumTransformId().

.. seealso:: :py:class:`QgsDatumTransform`

.. seealso:: :py:func:`setDestinationDatumTransformId()`

.. seealso:: :py:func:`sourceDatumTransformId()`
@@ -348,6 +317,8 @@ CRS.
This is usually calculated automatically from the transform's QgsCoordinateTransformContext.
Calling this method will overwrite any automatically calculated datum transform.

.. seealso:: :py:class:`QgsDatumTransform`

.. seealso:: :py:func:`destinationDatumTransformId()`

.. seealso:: :py:func:`setSourceDatumTransformId()`
@@ -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

@@ -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

};

/************************************************************************
@@ -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() );
}
@@ -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:
@@ -161,6 +161,7 @@ SET(QGIS_CORE_SRCS
qgsdatasourceuri.cpp
qgsdataprovider.cpp
qgsdatetimestatisticalsummary.cpp
qgsdatumtransform.cpp
qgsdbfilterproxymodel.cpp
qgsdefaultvalue.cpp
qgsdiagramrenderer.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<int> 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<int> 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<int> 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<int> 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;

0 comments on commit 48e6ec5

Please sign in to comment.
You can’t perform that action at this time.