Skip to content

Commit

Permalink
Upgrade QgsCoordinateTransformContext for proj 6
Browse files Browse the repository at this point in the history
This reworks (on proj 6 builds only!) QgsCoordinateTransformContext
to use proj strings of proj coordinate operations to handle the
users' preferred list of operations when transforming coordinates
between two CRSes.

Previously, the context heavily utilised internal transform ID
numbers, which were QGIS specific and relied on matching entries
from the QGIS srs.db file. This approach was undesirable because
it meant QGIS had to maintain and carry it's own table of
possible transform pathways between CRS pairs (which was difficult
to update, impossible to track, and most likely severely out of
date).

Now we can utilse Proj 6's (wonderful!) logic for determining the
best coordinate operation to utilise between two CRSes. All the
old API has been deprecated and no longer works under proj 6, but
that's unavoidable (and unlikely to be in use by plugins anyway,
it's VERY low level stuff).

A further bonus of this work is that QgsCoordinateTransform no
longer relies on proj strings of the source/dest CRS to build
the transform -- the issue with that approach was that proj
strings are lossy (and not always possible to generate), so
now by default we are generating better pathways between CRS
pairs.

This resolves issues with transforms which rely on pivot datums,
such as GDA94 - GDA2020 conversions.

Sponsored by ICSM
  • Loading branch information
nyalldawson committed May 31, 2019
1 parent 0cf4ecf commit c82d3b6
Show file tree
Hide file tree
Showing 21 changed files with 969 additions and 192 deletions.
52 changes: 48 additions & 4 deletions python/core/auto_generated/qgscoordinatetransform.sip.in
Expand Up @@ -288,7 +288,43 @@ otherwise points are transformed from destination to source CRS.
Returns ``True`` if the transform short circuits because the source and destination are equivalent.
%End

int sourceDatumTransformId() const;
QString coordinateOperation() const;
%Docstring
Returns a Proj string representing the coordinate operation which will be used to transform
coordinates.

.. note::

Requires Proj 6.0 or later. Builds based on earlier Proj versions will always return
an empty string, and the deprecated sourceDatumTransformId() or destinationDatumTransformId() methods should be used instead.

.. seealso:: :py:func:`setCoordinateOperation`

.. versionadded:: 3.8
%End

void setCoordinateOperation( const QString &operation ) const;
%Docstring
Sets a Proj string representing the coordinate ``operation`` which will be used to transform
coordinates.

.. warning::

It is the caller's responsibility to ensure that ``operation`` is a valid Proj
coordinate operation string.

.. note::

Requires Proj 6.0 or later. Builds based on earlier Proj versions will ignore this setting,
and the deprecated setSourceDatumTransformId() or setDestinationDatumTransformId() methods should be used instead.


.. seealso:: :py:func:`coordinateOperation`

.. versionadded:: 3.8
%End

int sourceDatumTransformId() const /Deprecated/;
%Docstring
Returns the ID of the datum transform to use when projecting from the source
CRS.
Expand All @@ -301,9 +337,11 @@ but can be manually overwritten by a call to setSourceDatumTransformId().
.. seealso:: :py:func:`setSourceDatumTransformId`

.. seealso:: :py:func:`destinationDatumTransformId`

.. deprecated:: Unused on builds based on Proj 6.0 or later
%End

void setSourceDatumTransformId( int datumId );
void setSourceDatumTransformId( int datumId ) /Deprecated/;
%Docstring
Sets the ``datumId`` ID of the datum transform to use when projecting from the source
CRS.
Expand All @@ -316,9 +354,11 @@ Calling this method will overwrite any automatically calculated datum transform.
.. seealso:: :py:func:`sourceDatumTransformId`

.. seealso:: :py:func:`setDestinationDatumTransformId`

.. deprecated:: Unused on builds based on Proj 6.0 or later
%End

int destinationDatumTransformId() const;
int destinationDatumTransformId() const /Deprecated/;
%Docstring
Returns the ID of the datum transform to use when projecting to the destination
CRS.
Expand All @@ -331,9 +371,11 @@ but can be manually overwritten by a call to setDestinationDatumTransformId().
.. seealso:: :py:func:`setDestinationDatumTransformId`

.. seealso:: :py:func:`sourceDatumTransformId`

.. deprecated:: Unused on builds based on Proj 6.0 or later
%End

void setDestinationDatumTransformId( int datumId );
void setDestinationDatumTransformId( int datumId ) /Deprecated/;
%Docstring
Sets the ``datumId`` ID of the datum transform to use when projecting to the destination
CRS.
Expand All @@ -346,6 +388,8 @@ Calling this method will overwrite any automatically calculated datum transform.
.. seealso:: :py:func:`destinationDatumTransformId`

.. seealso:: :py:func:`setSourceDatumTransformId`

.. deprecated:: Unused on builds based on Proj 6.0 or later
%End

static void invalidateCache();
Expand Down
84 changes: 73 additions & 11 deletions python/core/auto_generated/qgscoordinatetransformcontext.sip.in
Expand Up @@ -80,7 +80,30 @@ required for transformations for that source or destination.
.. seealso:: :py:func:`addSourceDestinationDatumTransform`


.. deprecated:: Has no effect on builds based on Proj 6.0 or later
.. deprecated:: Has no effect on builds based on Proj 6.0 or later, use coordinateOperations() instead.
%End

QMap< QPair< QString, QString>, QString > coordinateOperations() const;
%Docstring
Returns the stored mapping for source to destination CRS pairs to associated coordinate operation to use
(as a proj string). The map keys will be :py:func:`QgsCoordinateReferenceSystems.authid()`s.

.. warning::

This method should not be used to calculate the corresponding coordinate operation
to use for a coordinate transform. Instead, always use calculateCoordinateOperation()
to determine this.

.. seealso:: :py:func:`addCoordinateOperation`


.. note::

Requires Proj 6.0 or later. Builds based on earlier Proj versions will always return an empty list,
and the deprecated sourceDestinationDatumTransforms() method must be used instead.


.. versionadded:: 3.8
%End

bool addSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransformId, int destinationTransformId ) /Deprecated/;
Expand All @@ -93,17 +116,35 @@ required for transformations for that source or destination.

Returns ``True`` if the new transform pair was added successfully.

.. note::

Transforms set using this method will override any specific source or destination
transforms set by addSourceDatumTransform() or addDestinationDatumTransform().

.. seealso:: :py:func:`sourceDestinationDatumTransforms`

.. seealso:: :py:func:`removeSourceDestinationDatumTransform`

.. deprecated:: Has no effect on builds based on Proj 6.0 or later, use addCoordinateOperation() instead.
%End

bool addCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString );
%Docstring
Adds a new ``coordinateOperationProjString`` to use when projecting coordinates
from the specified ``sourceCrs`` to the specified ``destinationCrs``.

``coordinateOperationProjString`` should be set to a valid Proj coordinate operation
string. If ``coordinateOperationProjString`` is empty, then the default Proj operation
will be used when transforming between the coordinate reference systems.

.. deprecated:: Has no effect on builds based on Proj 6.0 or later
Returns ``True`` if the new coordinate operation was added successfully.

.. seealso:: :py:func:`coordinateOperations`

.. seealso:: :py:func:`removeCoordinateOperation`

.. note::

Requires Proj 6.0 or later. Builds based on earlier Proj versions will ignore this setting,
and the deprecated addSourceDestinationDatumTransform() method must be used instead.


.. versionadded:: 3.8
%End

void removeSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs ) /Deprecated/;
Expand All @@ -118,16 +159,15 @@ Removes the source to destination datum transform pair for the specified ``sourc

void removeCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs );
%Docstring
Removes the source to destination datum coordinated operation for the specified ``sourceCrs`` and
``destinationCrs``.
Removes the coordinate operation for the specified ``sourceCrs`` and ``destinationCrs``.

.. versionadded:: 3.8
%End

bool hasTransform( const QgsCoordinateReferenceSystem &source,
const QgsCoordinateReferenceSystem &destination ) const;
%Docstring
Returns ``True`` if the context has a valid datum transform to use
Returns ``True`` if the context has a valid coordinate operation to use
when transforming from the specified ``source`` CRS to ``destination`` CRS.

.. note::
Expand All @@ -147,7 +187,29 @@ destination.

source and destination are reversible.

.. deprecated:: Has no effect on builds based on Proj 6.0 or later
.. deprecated:: Has no effect on builds based on Proj 6.0 or later. Use calculateCoordinateOperation() instead.
%End

QString calculateCoordinateOperation( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const;
%Docstring
Returns the Proj coordinate operation string to use when transforming
from the specified ``source`` CRS to ``destination`` CRS.

Returns an empty string if no specific coordinate operation is set for the source to
destination pair, in which case the default Proj coordinate operation should
be used.

.. note::

source and destination are reversible.

.. note::

Requires Proj 6.0 or later. Builds based on earlier Proj versions will always return
an empty string, and the deprecated calculateDatumTransforms() method should be used instead.


.. versionadded:: 3.8
%End

bool readXml( const QDomElement &element, const QgsReadWriteContext &context, QStringList &missingTransforms /Out/ );
Expand Down
3 changes: 0 additions & 3 deletions python/core/auto_generated/raster/qgsrasterviewport.sip.in
Expand Up @@ -29,9 +29,6 @@ struct QgsRasterViewPort

QgsCoordinateReferenceSystem mDestCRS;

int mSrcDatumTransform;
int mDestDatumTransform;

QgsCoordinateTransformContext mTransformContext;
};

Expand Down
4 changes: 2 additions & 2 deletions src/core/qgscoordinatereferencesystem_p.h
Expand Up @@ -76,8 +76,8 @@ class QgsCoordinateReferenceSystemPrivate : public QSharedData
, mAxisInverted( other.mAxisInverted )
{
#if PROJ_VERSION_MAJOR>=6
if ( mIsValid && mPj.get() )
mPj.reset( proj_clone( QgsProjContext::get(), mPj.get() ) );
if ( mIsValid && other.mPj )
mPj.reset( proj_clone( QgsProjContext::get(), other.mPj.get() ) );
#else
if ( mIsValid )
{
Expand Down

0 comments on commit c82d3b6

Please sign in to comment.