mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Upgrade QgsCoordinateTransformContext for proj 6
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
This commit is contained in:
parent
0cf4ecf491
commit
c82d3b643f
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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();
|
||||
|
@ -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/;
|
||||
@ -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
|
||||
|
||||
.. deprecated:: Has no effect on builds based on Proj 6.0 or later
|
||||
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.
|
||||
|
||||
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/;
|
||||
@ -118,8 +159,7 @@ 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
|
||||
@ -127,7 +167,7 @@ Removes the source to destination datum coordinated operation for the specified
|
||||
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::
|
||||
@ -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/ );
|
||||
|
@ -29,9 +29,6 @@ struct QgsRasterViewPort
|
||||
|
||||
QgsCoordinateReferenceSystem mDestCRS;
|
||||
|
||||
int mSrcDatumTransform;
|
||||
int mDestDatumTransform;
|
||||
|
||||
QgsCoordinateTransformContext mTransformContext;
|
||||
};
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -63,7 +63,11 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
|
||||
if ( !d->checkValidity() )
|
||||
return;
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mProjCoordinateOperation ) )
|
||||
#else
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
|
||||
#endif
|
||||
{
|
||||
d->initialize();
|
||||
addToCache();
|
||||
@ -82,7 +86,11 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
|
||||
if ( !d->checkValidity() )
|
||||
return;
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mProjCoordinateOperation ) )
|
||||
#else
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
|
||||
#endif
|
||||
{
|
||||
d->initialize();
|
||||
addToCache();
|
||||
@ -99,7 +107,11 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
|
||||
if ( !d->checkValidity() )
|
||||
return;
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mProjCoordinateOperation ) )
|
||||
#else
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
|
||||
#endif
|
||||
{
|
||||
d->initialize();
|
||||
addToCache();
|
||||
@ -135,7 +147,11 @@ void QgsCoordinateTransform::setSourceCrs( const QgsCoordinateReferenceSystem &c
|
||||
return;
|
||||
|
||||
d->calculateTransforms( mContext );
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mProjCoordinateOperation ) )
|
||||
#else
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
|
||||
#endif
|
||||
{
|
||||
d->initialize();
|
||||
addToCache();
|
||||
@ -149,7 +165,11 @@ void QgsCoordinateTransform::setDestinationCrs( const QgsCoordinateReferenceSyst
|
||||
return;
|
||||
|
||||
d->calculateTransforms( mContext );
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mProjCoordinateOperation ) )
|
||||
#else
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
|
||||
#endif
|
||||
{
|
||||
d->initialize();
|
||||
addToCache();
|
||||
@ -167,7 +187,11 @@ void QgsCoordinateTransform::setContext( const QgsCoordinateTransformContext &co
|
||||
return;
|
||||
|
||||
d->calculateTransforms( mContext );
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mProjCoordinateOperation ) )
|
||||
#else
|
||||
if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
|
||||
#endif
|
||||
{
|
||||
d->initialize();
|
||||
addToCache();
|
||||
@ -757,6 +781,17 @@ bool QgsCoordinateTransform::isShortCircuited() const
|
||||
return !d->mIsValid || d->mShortCircuit;
|
||||
}
|
||||
|
||||
QString QgsCoordinateTransform::coordinateOperation() const
|
||||
{
|
||||
return d->mProjCoordinateOperation;
|
||||
}
|
||||
|
||||
void QgsCoordinateTransform::setCoordinateOperation( const QString &operation ) const
|
||||
{
|
||||
d.detach();
|
||||
d->mProjCoordinateOperation = operation;
|
||||
}
|
||||
|
||||
const char *finder( const char *name )
|
||||
{
|
||||
QString proj;
|
||||
@ -769,6 +804,46 @@ const char *finder( const char *name )
|
||||
return proj.toUtf8();
|
||||
}
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
bool QgsCoordinateTransform::setFromCache( const QgsCoordinateReferenceSystem &src, const QgsCoordinateReferenceSystem &dest, const QString &coordinateOperationProj )
|
||||
{
|
||||
if ( !src.isValid() || !dest.isValid() )
|
||||
return false;
|
||||
|
||||
const QString sourceKey = src.authid().isEmpty() ?
|
||||
src.toWkt() : src.authid();
|
||||
const QString destKey = dest.authid().isEmpty() ?
|
||||
dest.toWkt() : dest.authid();
|
||||
|
||||
if ( sourceKey.isEmpty() || destKey.isEmpty() )
|
||||
return false;
|
||||
|
||||
sCacheLock.lockForRead();
|
||||
const QList< QgsCoordinateTransform > values = sTransforms.values( qMakePair( src.authid(), dest.authid() ) );
|
||||
for ( auto valIt = values.constBegin(); valIt != values.constEnd(); ++valIt )
|
||||
{
|
||||
if ( ( *valIt ).coordinateOperation() == coordinateOperationProj )
|
||||
{
|
||||
// need to save, and then restore the context... we don't want this to be cached or to use the values from the cache
|
||||
QgsCoordinateTransformContext context = mContext;
|
||||
#ifdef QGISDEBUG
|
||||
bool hasContext = mHasContext;
|
||||
#endif
|
||||
*this = *valIt;
|
||||
sCacheLock.unlock();
|
||||
|
||||
mContext = context;
|
||||
#ifdef QGISDEBUG
|
||||
mHasContext = hasContext;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
sCacheLock.unlock();
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bool QgsCoordinateTransform::setFromCache( const QgsCoordinateReferenceSystem &src, const QgsCoordinateReferenceSystem &dest, int srcDatumTransform, int destDatumTransform )
|
||||
{
|
||||
if ( !src.isValid() || !dest.isValid() )
|
||||
@ -808,6 +883,7 @@ bool QgsCoordinateTransform::setFromCache( const QgsCoordinateReferenceSystem &s
|
||||
sCacheLock.unlock();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QgsCoordinateTransform::addToCache()
|
||||
{
|
||||
@ -829,24 +905,32 @@ void QgsCoordinateTransform::addToCache()
|
||||
|
||||
int QgsCoordinateTransform::sourceDatumTransformId() const
|
||||
{
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
return d->mSourceDatumTransform;
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
}
|
||||
|
||||
void QgsCoordinateTransform::setSourceDatumTransformId( int dt )
|
||||
{
|
||||
d.detach();
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
d->mSourceDatumTransform = dt;
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
}
|
||||
|
||||
int QgsCoordinateTransform::destinationDatumTransformId() const
|
||||
{
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
return d->mDestinationDatumTransform;
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
}
|
||||
|
||||
void QgsCoordinateTransform::setDestinationDatumTransformId( int dt )
|
||||
{
|
||||
d.detach();
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
d->mDestinationDatumTransform = dt;
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
}
|
||||
|
||||
void QgsCoordinateTransform::invalidateCache()
|
||||
|
@ -332,6 +332,33 @@ class CORE_EXPORT QgsCoordinateTransform
|
||||
*/
|
||||
bool isShortCircuited() const;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* \see setCoordinateOperation()
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
QString coordinateOperation() const;
|
||||
|
||||
/**
|
||||
* Sets a Proj string representing the coordinate \a operation which will be used to transform
|
||||
* coordinates.
|
||||
*
|
||||
* \warning It is the caller's responsibility to ensure that \a 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.
|
||||
*
|
||||
* \see coordinateOperation()
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
void setCoordinateOperation( const QString &operation ) const;
|
||||
|
||||
/**
|
||||
* Returns the ID of the datum transform to use when projecting from the source
|
||||
* CRS.
|
||||
@ -342,8 +369,10 @@ class CORE_EXPORT QgsCoordinateTransform
|
||||
* \see QgsDatumTransform
|
||||
* \see setSourceDatumTransformId()
|
||||
* \see destinationDatumTransformId()
|
||||
*
|
||||
* \deprecated Unused on builds based on Proj 6.0 or later
|
||||
*/
|
||||
int sourceDatumTransformId() const;
|
||||
Q_DECL_DEPRECATED int sourceDatumTransformId() const SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Sets the \a datumId ID of the datum transform to use when projecting from the source
|
||||
@ -355,8 +384,10 @@ class CORE_EXPORT QgsCoordinateTransform
|
||||
* \see QgsDatumTransform
|
||||
* \see sourceDatumTransformId()
|
||||
* \see setDestinationDatumTransformId()
|
||||
*
|
||||
* \deprecated Unused on builds based on Proj 6.0 or later
|
||||
*/
|
||||
void setSourceDatumTransformId( int datumId );
|
||||
Q_DECL_DEPRECATED void setSourceDatumTransformId( int datumId ) SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Returns the ID of the datum transform to use when projecting to the destination
|
||||
@ -368,8 +399,10 @@ class CORE_EXPORT QgsCoordinateTransform
|
||||
* \see QgsDatumTransform
|
||||
* \see setDestinationDatumTransformId()
|
||||
* \see sourceDatumTransformId()
|
||||
*
|
||||
* \deprecated Unused on builds based on Proj 6.0 or later
|
||||
*/
|
||||
int destinationDatumTransformId() const;
|
||||
Q_DECL_DEPRECATED int destinationDatumTransformId() const SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Sets the \a datumId ID of the datum transform to use when projecting to the destination
|
||||
@ -381,8 +414,10 @@ class CORE_EXPORT QgsCoordinateTransform
|
||||
* \see QgsDatumTransform
|
||||
* \see destinationDatumTransformId()
|
||||
* \see setSourceDatumTransformId()
|
||||
*
|
||||
* \deprecated Unused on builds based on Proj 6.0 or later
|
||||
*/
|
||||
void setDestinationDatumTransformId( int datumId );
|
||||
Q_DECL_DEPRECATED void setDestinationDatumTransformId( int datumId ) SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Clears the internal cache used to initialize QgsCoordinateTransform objects.
|
||||
@ -414,10 +449,16 @@ class CORE_EXPORT QgsCoordinateTransform
|
||||
bool mHasContext = false;
|
||||
#endif
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
bool setFromCache( const QgsCoordinateReferenceSystem &src,
|
||||
const QgsCoordinateReferenceSystem &dest,
|
||||
const QString &coordinateOperationProj );
|
||||
#else
|
||||
bool setFromCache( const QgsCoordinateReferenceSystem &src,
|
||||
const QgsCoordinateReferenceSystem &dest,
|
||||
int srcDatumTransform,
|
||||
int destDatumTransform );
|
||||
#endif
|
||||
void addToCache();
|
||||
|
||||
// cache
|
||||
|
@ -52,11 +52,14 @@ QgsProjContextStore::~QgsProjContextStore()
|
||||
|
||||
#endif
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH // because of deprecated members
|
||||
QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate()
|
||||
{
|
||||
setFinder();
|
||||
}
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH // because of deprecated members
|
||||
QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinateReferenceSystem &source,
|
||||
const QgsCoordinateReferenceSystem &destination,
|
||||
const QgsCoordinateTransformContext &context )
|
||||
@ -66,7 +69,9 @@ QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinat
|
||||
setFinder();
|
||||
calculateTransforms( context );
|
||||
}
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH // because of deprecated members
|
||||
QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, int sourceDatumTransform, int destDatumTransform )
|
||||
: mSourceCRS( source )
|
||||
, mDestCRS( destination )
|
||||
@ -90,12 +95,15 @@ QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinat
|
||||
//must reinitialize to setup mSourceProjection and mDestinationProjection
|
||||
initialize();
|
||||
}
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
QgsCoordinateTransformPrivate::~QgsCoordinateTransformPrivate()
|
||||
{
|
||||
// free the proj objects
|
||||
freeProj();
|
||||
}
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
bool QgsCoordinateTransformPrivate::checkValidity()
|
||||
{
|
||||
@ -135,14 +143,15 @@ bool QgsCoordinateTransformPrivate::initialize()
|
||||
|
||||
mIsValid = true;
|
||||
|
||||
// init the projections (destination and source)
|
||||
freeProj();
|
||||
|
||||
#if PROJ_VERSION_MAJOR < 6
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
int sourceDatumTransform = mSourceDatumTransform;
|
||||
int destDatumTransform = mDestinationDatumTransform;
|
||||
bool useDefaultDatumTransform = ( sourceDatumTransform == - 1 && destDatumTransform == -1 );
|
||||
|
||||
// init the projections (destination and source)
|
||||
freeProj();
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
mSourceProjString = mSourceCRS.toProj4();
|
||||
if ( !useDefaultDatumTransform )
|
||||
{
|
||||
@ -162,12 +171,13 @@ bool QgsCoordinateTransformPrivate::initialize()
|
||||
{
|
||||
mDestProjString += ( ' ' + QgsDatumTransform::datumTransformToProj( destDatumTransform ) );
|
||||
}
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
if ( !useDefaultDatumTransform )
|
||||
{
|
||||
addNullGridShifts( mSourceProjString, mDestProjString, sourceDatumTransform, destDatumTransform );
|
||||
}
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
#endif
|
||||
|
||||
// create proj projections for current thread
|
||||
ProjData res = threadLocalProjData();
|
||||
@ -244,11 +254,15 @@ bool QgsCoordinateTransformPrivate::initialize()
|
||||
void QgsCoordinateTransformPrivate::calculateTransforms( const QgsCoordinateTransformContext &context )
|
||||
{
|
||||
// recalculate datum transforms from context
|
||||
#if PROJ_VERSION_MAJOR >= 6
|
||||
mProjCoordinateOperation = context.calculateCoordinateOperation( mSourceCRS, mDestCRS );
|
||||
#else
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
QgsDatumTransform::TransformPair transforms = context.calculateDatumTransforms( mSourceCRS, mDestCRS );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
mSourceDatumTransform = transforms.sourceTransformId;
|
||||
mDestinationDatumTransform = transforms.destinationTransformId;
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
#endif
|
||||
}
|
||||
|
||||
ProjData QgsCoordinateTransformPrivate::threadLocalProjData()
|
||||
@ -287,7 +301,30 @@ ProjData QgsCoordinateTransformPrivate::threadLocalProjData()
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
#if PROJ_VERSION_MINOR>=1
|
||||
QgsProjUtils::proj_pj_unique_ptr transform( proj_create_crs_to_crs( context, mSourceProjString.toUtf8().constData(), mDestProjString.toUtf8().constData(), nullptr ) );
|
||||
QgsProjUtils::proj_pj_unique_ptr transform;
|
||||
if ( !mProjCoordinateOperation.isEmpty() )
|
||||
transform.reset( proj_create( context, mProjCoordinateOperation.toUtf8().constData() ) );
|
||||
|
||||
if ( !transform ) // fallback on default proj pathway
|
||||
{
|
||||
if ( !mSourceCRS.projObject() || ! mDestCRS.projObject() )
|
||||
return nullptr;
|
||||
|
||||
PJ_OPERATION_FACTORY_CONTEXT *operationContext = proj_create_operation_factory_context( context, nullptr );
|
||||
|
||||
// See https://lists.osgeo.org/pipermail/proj/2019-May/008604.html
|
||||
proj_operation_factory_context_set_spatial_criterion( context, operationContext, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION );
|
||||
|
||||
if ( PJ_OBJ_LIST *ops = proj_create_operations( context, mSourceCRS.projObject(), mDestCRS.projObject(), operationContext ) )
|
||||
{
|
||||
int count = proj_list_get_count( ops );
|
||||
if ( count > 0 )
|
||||
transform.reset( proj_list_get( context, ops, 0 ) );
|
||||
proj_list_destroy( ops );
|
||||
}
|
||||
proj_operation_factory_context_destroy( operationContext );
|
||||
}
|
||||
|
||||
if ( !transform )
|
||||
{
|
||||
// ouch!
|
||||
@ -317,6 +354,7 @@ ProjData QgsCoordinateTransformPrivate::threadLocalProjData()
|
||||
return res;
|
||||
}
|
||||
|
||||
#if PROJ_VERSION_MAJOR<6
|
||||
QString QgsCoordinateTransformPrivate::stripDatumTransform( const QString &proj4 ) const
|
||||
{
|
||||
QStringList parameterSplit = proj4.split( '+', QString::SkipEmptyParts );
|
||||
@ -363,6 +401,7 @@ void QgsCoordinateTransformPrivate::addNullGridShifts( QString &srcProjString, Q
|
||||
destProjString += QLatin1String( " +nadgrids=@null" );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void QgsCoordinateTransformPrivate::setFinder()
|
||||
{
|
||||
|
@ -120,11 +120,12 @@ class QgsCoordinateTransformPrivate : public QSharedData
|
||||
//! QgsCoordinateReferenceSystem of the destination (map canvas) coordinate system
|
||||
QgsCoordinateReferenceSystem mDestCRS;
|
||||
|
||||
QString mSourceProjString;
|
||||
QString mDestProjString;
|
||||
Q_DECL_DEPRECATED QString mSourceProjString;
|
||||
Q_DECL_DEPRECATED QString mDestProjString;
|
||||
|
||||
int mSourceDatumTransform = -1;
|
||||
int mDestinationDatumTransform = -1;
|
||||
Q_DECL_DEPRECATED int mSourceDatumTransform = -1;
|
||||
Q_DECL_DEPRECATED int mDestinationDatumTransform = -1;
|
||||
QString mProjCoordinateOperation;
|
||||
|
||||
bool mSourceAxisOrderSwapped = false;
|
||||
bool mDestAxisOrderSwapped = false;
|
||||
@ -148,11 +149,13 @@ class QgsCoordinateTransformPrivate : public QSharedData
|
||||
|
||||
private:
|
||||
|
||||
#if PROJ_VERSION_MAJOR<6
|
||||
//! Removes +nadgrids and +towgs84 from proj4 string
|
||||
QString stripDatumTransform( const QString &proj4 ) const;
|
||||
Q_DECL_DEPRECATED QString stripDatumTransform( const QString &proj4 ) const;
|
||||
|
||||
//! In certain situations, null grid shifts have to be added to src / dst proj string
|
||||
void addNullGridShifts( QString &srcProjString, QString &destProjString, int sourceDatumTransform, int destinationDatumTransform ) const;
|
||||
Q_DECL_DEPRECATED void addNullGridShifts( QString &srcProjString, QString &destProjString, int sourceDatumTransform, int destinationDatumTransform ) const;
|
||||
#endif
|
||||
|
||||
void setFinder();
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "qgscoordinatetransformcontext_p.h"
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsprojutils.h"
|
||||
|
||||
|
||||
QgsCoordinateTransformContext::QgsCoordinateTransformContext()
|
||||
: d( new QgsCoordinateTransformContextPrivate() )
|
||||
@ -60,23 +62,62 @@ void QgsCoordinateTransformContext::clear()
|
||||
|
||||
QMap<QPair<QString, QString>, QgsDatumTransform::TransformPair> QgsCoordinateTransformContext::sourceDestinationDatumTransforms() const
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
return QMap<QPair<QString, QString>, QgsDatumTransform::TransformPair>();
|
||||
#else
|
||||
d->mLock.lockForRead();
|
||||
auto res = d->mSourceDestDatumTransforms;
|
||||
res.detach();
|
||||
d->mLock.unlock();
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
QMap<QPair<QString, QString>, QString> QgsCoordinateTransformContext::coordinateOperations() const
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
d->mLock.lockForRead();
|
||||
auto res = d->mSourceDestDatumTransforms;
|
||||
res.detach();
|
||||
d->mLock.unlock();
|
||||
return res;
|
||||
#else
|
||||
return QMap<QPair<QString, QString>, QgsDatumTransform::TransformDetails>();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QgsCoordinateTransformContext::addSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransform, int destinationTransform )
|
||||
{
|
||||
if ( !sourceCrs.isValid() || !destinationCrs.isValid() )
|
||||
return false;
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
Q_UNUSED( sourceTransform )
|
||||
Q_UNUSED( destinationTransform )
|
||||
return false;
|
||||
#else
|
||||
d.detach();
|
||||
d->mLock.lockForWrite();
|
||||
d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), QgsDatumTransform::TransformPair( sourceTransform, destinationTransform ) );
|
||||
d->mLock.unlock();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QgsCoordinateTransformContext::addCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString )
|
||||
{
|
||||
if ( !sourceCrs.isValid() || !destinationCrs.isValid() )
|
||||
return false;
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
d.detach();
|
||||
d->mLock.lockForWrite();
|
||||
d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), coordinateOperationProjString );
|
||||
d->mLock.unlock();
|
||||
return true;
|
||||
#else
|
||||
Q_UNUSED( sourceTransform )
|
||||
Q_UNUSED( destinationTransform )
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void QgsCoordinateTransformContext::removeSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs )
|
||||
@ -91,15 +132,25 @@ void QgsCoordinateTransformContext::removeCoordinateOperation( const QgsCoordina
|
||||
|
||||
bool QgsCoordinateTransformContext::hasTransform( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
const QString t = calculateCoordinateOperation( source, destination );
|
||||
return !t.isEmpty();
|
||||
#else
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
QgsDatumTransform::TransformPair t = calculateDatumTransforms( source, destination );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
// calculateDatumTransforms already takes care of switching source and destination
|
||||
return t.sourceTransformId != -1 || t.destinationTransformId != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
QgsDatumTransform::TransformPair QgsCoordinateTransformContext::calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
Q_UNUSED( source )
|
||||
Q_UNUSED( destination )
|
||||
return QgsDatumTransform::TransformPair( -1, -1 );
|
||||
#else
|
||||
QString srcKey = source.authid();
|
||||
QString destKey = destination.authid();
|
||||
|
||||
@ -114,6 +165,29 @@ QgsDatumTransform::TransformPair QgsCoordinateTransformContext::calculateDatumTr
|
||||
}
|
||||
d->mLock.unlock();
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QgsCoordinateTransformContext::calculateCoordinateOperation( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
const QString srcKey = source.authid();
|
||||
const QString destKey = destination.authid();
|
||||
|
||||
d->mLock.lockForRead();
|
||||
QString res = d->mSourceDestDatumTransforms.value( qMakePair( srcKey, destKey ), QString() );
|
||||
if ( res.isEmpty() )
|
||||
{
|
||||
// try to reverse
|
||||
res = d->mSourceDestDatumTransforms.value( qMakePair( destKey, srcKey ), QString() );
|
||||
}
|
||||
d->mLock.unlock();
|
||||
return res;
|
||||
#else
|
||||
Q_UNUSED( source )
|
||||
Q_UNUSED( destination )
|
||||
return QString();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool QgsCoordinateTransformContext::readXml( const QDomElement &element, const QgsReadWriteContext &, QStringList &missingTransforms )
|
||||
@ -140,9 +214,23 @@ bool QgsCoordinateTransformContext::readXml( const QDomElement &element, const Q
|
||||
for ( int i = 0; i < srcDestNodes.size(); ++i )
|
||||
{
|
||||
const QDomElement transformElem = srcDestNodes.at( i ).toElement();
|
||||
QString key1 = transformElem.attribute( QStringLiteral( "source" ) );
|
||||
QString key2 = transformElem.attribute( QStringLiteral( "dest" ) );
|
||||
const QString key1 = transformElem.attribute( QStringLiteral( "source" ) );
|
||||
const QString key2 = transformElem.attribute( QStringLiteral( "dest" ) );
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
const QString coordinateOp = transformElem.attribute( QStringLiteral( "coordinateOp" ) );
|
||||
|
||||
// try to instantiate operation, and check for missing grids
|
||||
if ( !QgsProjUtils::coordinateOperationIsAvailable( coordinateOp ) )
|
||||
{
|
||||
// not possible in current Proj 6 api!
|
||||
// missingTransforms.append( QgsProjUtils::nonAvailableGrids( coordinateOp ) );
|
||||
missingTransforms.append( coordinateOp ); // yuck, we don't want to expose this string to users!
|
||||
result = false;
|
||||
}
|
||||
|
||||
d->mSourceDestDatumTransforms.insert( qMakePair( key1, key2 ), coordinateOp );
|
||||
#else
|
||||
QString value1 = transformElem.attribute( QStringLiteral( "sourceTransform" ) );
|
||||
QString value2 = transformElem.attribute( QStringLiteral( "destTransform" ) );
|
||||
|
||||
@ -171,6 +259,7 @@ bool QgsCoordinateTransformContext::readXml( const QDomElement &element, const Q
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
d->mSourceDestDatumTransforms.insert( qMakePair( key1, key2 ), QgsDatumTransform::TransformPair( datumId1, datumId2 ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
d->mLock.unlock();
|
||||
@ -189,10 +278,14 @@ 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 );
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
transformElem.setAttribute( QStringLiteral( "coordinateOp" ), it.value() );
|
||||
#else
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
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 ) );
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
#endif
|
||||
contextElem.appendChild( transformElem );
|
||||
}
|
||||
|
||||
@ -212,10 +305,32 @@ void QgsCoordinateTransformContext::readSettings()
|
||||
QStringList projectionKeys = settings.allKeys();
|
||||
|
||||
//collect src and dest entries that belong together
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
QMap< QPair< QString, QString >, QString > transforms;
|
||||
#else
|
||||
QMap< QPair< QString, QString >, QPair< int, int > > transforms;
|
||||
#endif
|
||||
QStringList::const_iterator pkeyIt = projectionKeys.constBegin();
|
||||
for ( ; pkeyIt != projectionKeys.constEnd(); ++pkeyIt )
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
if ( pkeyIt->contains( QLatin1String( "coordinateOp" ) ) )
|
||||
{
|
||||
QStringList split = pkeyIt->split( '/' );
|
||||
QString srcAuthId, destAuthId;
|
||||
if ( ! split.isEmpty() )
|
||||
{
|
||||
srcAuthId = split.at( 0 );
|
||||
}
|
||||
if ( split.size() > 1 )
|
||||
{
|
||||
destAuthId = split.at( 1 ).split( '_' ).at( 0 );
|
||||
}
|
||||
|
||||
const QString proj = settings.value( *pkeyIt ).toString();
|
||||
transforms[ qMakePair( srcAuthId, destAuthId )] = proj;
|
||||
}
|
||||
#else
|
||||
if ( pkeyIt->contains( QLatin1String( "srcTransform" ) ) || pkeyIt->contains( QLatin1String( "destTransform" ) ) )
|
||||
{
|
||||
QStringList split = pkeyIt->split( '/' );
|
||||
@ -242,13 +357,18 @@ void QgsCoordinateTransformContext::readSettings()
|
||||
transforms[ qMakePair( srcAuthId, destAuthId )].second = datumId;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// add transforms to context
|
||||
QMap< QPair< QString, QString >, QPair< int, int > >::const_iterator transformIt = transforms.constBegin();
|
||||
auto transformIt = transforms.constBegin();
|
||||
for ( ; transformIt != transforms.constEnd(); ++transformIt )
|
||||
{
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
d->mSourceDestDatumTransforms.insert( transformIt.key(), transformIt.value() );
|
||||
#else
|
||||
d->mSourceDestDatumTransforms.insert( transformIt.key(), QgsDatumTransform::TransformPair( transformIt.value().first, transformIt.value().second ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
d->mLock.unlock();
|
||||
@ -263,7 +383,7 @@ void QgsCoordinateTransformContext::writeSettings()
|
||||
QStringList::const_iterator groupKeyIt = groupKeys.constBegin();
|
||||
for ( ; groupKeyIt != groupKeys.constEnd(); ++groupKeyIt )
|
||||
{
|
||||
if ( groupKeyIt->contains( QLatin1String( "srcTransform" ) ) || groupKeyIt->contains( QLatin1String( "destTransform" ) ) )
|
||||
if ( groupKeyIt->contains( QLatin1String( "srcTransform" ) ) || groupKeyIt->contains( QLatin1String( "destTransform" ) ) || groupKeyIt->contains( QLatin1String( "coordinateOp" ) ) )
|
||||
{
|
||||
settings.remove( *groupKeyIt );
|
||||
}
|
||||
@ -271,8 +391,13 @@ void QgsCoordinateTransformContext::writeSettings()
|
||||
|
||||
for ( auto transformIt = d->mSourceDestDatumTransforms.constBegin(); transformIt != d->mSourceDestDatumTransforms.constEnd(); ++transformIt )
|
||||
{
|
||||
QString srcAuthId = transformIt.key().first;
|
||||
QString destAuthId = transformIt.key().second;
|
||||
const QString srcAuthId = transformIt.key().first;
|
||||
const QString destAuthId = transformIt.key().second;
|
||||
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
const QString proj = transformIt.value();
|
||||
settings.setValue( srcAuthId + "//" + destAuthId + "_coordinateOp", proj );
|
||||
#else
|
||||
int sourceDatumTransform = transformIt.value().sourceTransformId;
|
||||
QString sourceDatumProj;
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
@ -286,6 +411,7 @@ void QgsCoordinateTransformContext::writeSettings()
|
||||
|
||||
settings.setValue( srcAuthId + "//" + destAuthId + "_srcTransform", sourceDatumProj );
|
||||
settings.setValue( srcAuthId + "//" + destAuthId + "_destTransform", destinationDatumProj );
|
||||
#endif
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
|
@ -95,10 +95,27 @@ class CORE_EXPORT QgsCoordinateTransformContext
|
||||
*
|
||||
* \see 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.
|
||||
*/
|
||||
Q_DECL_DEPRECATED QMap< QPair< QString, QString>, QgsDatumTransform::TransformPair > sourceDestinationDatumTransforms() const SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
*
|
||||
* \see 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.
|
||||
*
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
QMap< QPair< QString, QString>, QString > coordinateOperations() const;
|
||||
|
||||
/**
|
||||
* Adds a new \a sourceTransform and \a destinationTransform to use when projecting coordinates
|
||||
* from the specified \a sourceCrs to the specified \a destinationCrs.
|
||||
@ -108,16 +125,33 @@ class CORE_EXPORT QgsCoordinateTransformContext
|
||||
*
|
||||
* 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().
|
||||
*
|
||||
* \see sourceDestinationDatumTransforms()
|
||||
* \see removeSourceDestinationDatumTransform()
|
||||
*
|
||||
* \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 addCoordinateOperation() instead.
|
||||
*/
|
||||
Q_DECL_DEPRECATED bool addSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransformId, int destinationTransformId ) SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Adds a new \a coordinateOperationProjString to use when projecting coordinates
|
||||
* from the specified \a sourceCrs to the specified \a destinationCrs.
|
||||
*
|
||||
* \a coordinateOperationProjString should be set to a valid Proj coordinate operation
|
||||
* string. If \a coordinateOperationProjString is empty, then the default Proj operation
|
||||
* will be used when transforming between the coordinate reference systems.
|
||||
*
|
||||
* Returns TRUE if the new coordinate operation was added successfully.
|
||||
*
|
||||
* \see coordinateOperations()
|
||||
* \see 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.
|
||||
*
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
bool addCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString );
|
||||
|
||||
/**
|
||||
* Removes the source to destination datum transform pair for the specified \a sourceCrs and
|
||||
* \a destinationCrs.
|
||||
@ -128,15 +162,14 @@ class CORE_EXPORT QgsCoordinateTransformContext
|
||||
Q_DECL_DEPRECATED void removeSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs ) SIP_DEPRECATED ;
|
||||
|
||||
/**
|
||||
* Removes the source to destination datum coordinated operation for the specified \a sourceCrs and
|
||||
* \a destinationCrs.
|
||||
* Removes the coordinate operation for the specified \a sourceCrs and \a destinationCrs.
|
||||
*
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
void removeCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs );
|
||||
|
||||
/**
|
||||
* 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 \a source CRS to \a destination CRS.
|
||||
* \note source and destination are reversible.
|
||||
*/
|
||||
@ -151,10 +184,27 @@ class CORE_EXPORT QgsCoordinateTransformContext
|
||||
* destination.
|
||||
*
|
||||
* \note 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.
|
||||
*/
|
||||
Q_DECL_DEPRECATED QgsDatumTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const SIP_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Returns the Proj coordinate operation string to use when transforming
|
||||
* from the specified \a source CRS to \a 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.
|
||||
*
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
QString calculateCoordinateOperation( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const;
|
||||
|
||||
/**
|
||||
* Reads the context's state from a DOM \a element.
|
||||
*
|
||||
|
@ -52,25 +52,16 @@ class QgsCoordinateTransformContextPrivate : public QSharedData
|
||||
{
|
||||
other.mLock.lockForRead();
|
||||
mSourceDestDatumTransforms = other.mSourceDestDatumTransforms;
|
||||
#if 0
|
||||
mSourceDatumTransforms = other.mSourceDatumTransforms;
|
||||
mDestDatumTransforms = other.mDestDatumTransforms;
|
||||
#endif
|
||||
other.mLock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for datum transforms to use for source/destination CRS pairs.
|
||||
* Matching records from this map will take precedence over other transform maps.
|
||||
* Mapping for coordinate operation Proj string to use for source/destination CRS pairs.
|
||||
*/
|
||||
#if PROJ_VERSION_MAJOR>=6
|
||||
QMap< QPair< QString, QString >, QString > mSourceDestDatumTransforms;
|
||||
#else
|
||||
QMap< QPair< QString, QString >, QgsDatumTransform::TransformPair > mSourceDestDatumTransforms;
|
||||
|
||||
#if 0
|
||||
//! Mapping for datum transforms to use for source CRS
|
||||
QMap< QString, int > mSourceDatumTransforms;
|
||||
|
||||
//! Mapping for datum transforms to use for destination CRS
|
||||
QMap< QString, int > mDestDatumTransforms;
|
||||
#endif
|
||||
|
||||
//! Mutex for making QgsCoordinateTransformContextPrivate thread safe
|
||||
|
@ -143,6 +143,8 @@ class CORE_EXPORT QgsDatumTransform
|
||||
|
||||
/**
|
||||
* Contains information about a coordinate transformation operation.
|
||||
*
|
||||
* \note Only used in builds based on on Proj >= 6.0
|
||||
* \since QGIS 3.8
|
||||
*/
|
||||
struct TransformDetails
|
||||
|
@ -376,11 +376,11 @@ QList<QgsEllipsoidUtils::EllipsoidDefinition> QgsEllipsoidUtils::definitions()
|
||||
def.parameters.semiMinor = semiMinor;
|
||||
def.parameters.inverseFlattening = invFlattening;
|
||||
if ( !semiMinorComputed )
|
||||
def.parameters.crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=longlat +a=%1 +b=%2 +no_defs" ).arg( def.parameters.semiMajor, 0, 'g', 17 ).arg( def.parameters.semiMinor, 0, 'g', 17 ) );
|
||||
def.parameters.crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=longlat +a=%1 +b=%2 +no_defs +type=crs" ).arg( def.parameters.semiMajor, 0, 'g', 17 ).arg( def.parameters.semiMinor, 0, 'g', 17 ) );
|
||||
else if ( !qgsDoubleNear( def.parameters.inverseFlattening, 0.0 ) )
|
||||
def.parameters.crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=longlat +a=%1 +rf=%2 +no_defs" ).arg( def.parameters.semiMajor, 0, 'g', 17 ).arg( def.parameters.inverseFlattening, 0, 'g', 17 ) );
|
||||
def.parameters.crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=longlat +a=%1 +rf=%2 +no_defs +type=crs" ).arg( def.parameters.semiMajor, 0, 'g', 17 ).arg( def.parameters.inverseFlattening, 0, 'g', 17 ) );
|
||||
else
|
||||
def.parameters.crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=longlat +a=%1 +no_defs" ).arg( def.parameters.semiMajor, 0, 'g', 17 ) );
|
||||
def.parameters.crs = QgsCoordinateReferenceSystem::fromProj4( QStringLiteral( "+proj=longlat +a=%1 +no_defs +type=crs" ).arg( def.parameters.semiMajor, 0, 'g', 17 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -176,5 +176,42 @@ QgsProjUtils::proj_pj_unique_ptr QgsProjUtils::crsToSingleCrs( const PJ *crs )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool QgsProjUtils::coordinateOperationIsAvailable( const QString &projDef )
|
||||
{
|
||||
if ( projDef.isEmpty() )
|
||||
return true;
|
||||
|
||||
PJ_CONTEXT *context = QgsProjContext::get();
|
||||
QgsProjUtils::proj_pj_unique_ptr coordinateOperation( proj_create( context, projDef.toUtf8().constData() ) );
|
||||
if ( !coordinateOperation )
|
||||
return false;
|
||||
|
||||
return static_cast< bool >( proj_coordoperation_is_instantiable( context, coordinateOperation.get() ) );
|
||||
}
|
||||
|
||||
#if 0
|
||||
QStringList QgsProjUtils::nonAvailableGrids( const QString &projDef )
|
||||
{
|
||||
if ( projDef.isEmpty() )
|
||||
return QStringList();
|
||||
|
||||
PJ_CONTEXT *context = QgsProjContext::get();
|
||||
QgsProjUtils::proj_pj_unique_ptr op( proj_create( context, projDef.toUtf8().constData() ) ); < ---- - this always fails if grids are missing
|
||||
if ( !op )
|
||||
return QStringList();
|
||||
|
||||
QStringList res;
|
||||
for ( int j = 0; j < proj_coordoperation_get_grid_used_count( context, op.get() ); ++j )
|
||||
{
|
||||
const char *shortName = nullptr;
|
||||
int isAvailable = 0;
|
||||
proj_coordoperation_get_grid_used( context, op.get(), j, &shortName, nullptr, nullptr, nullptr, nullptr, nullptr, &isAvailable );
|
||||
if ( !isAvailable )
|
||||
res << QString( shortName );
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qgis_core.h"
|
||||
#include "qgsconfig.h"
|
||||
#include <memory>
|
||||
#include <QStringList>
|
||||
|
||||
#if !defined(USE_THREAD_LOCAL) || defined(Q_OS_WIN)
|
||||
#include <QThreadStorage>
|
||||
@ -74,7 +75,7 @@ class CORE_EXPORT QgsProjUtils
|
||||
using proj_pj_unique_ptr = std::unique_ptr< PJ, ProjPJDeleter >;
|
||||
|
||||
/**
|
||||
* Returns true if the given proj coordinate system uses angular units. \a projDef must be
|
||||
* Returns TRUE if the given proj coordinate system uses angular units. \a projDef must be
|
||||
* a proj string defining a CRS object.
|
||||
*/
|
||||
static bool usesAngularUnit( const QString &projDef );
|
||||
@ -82,7 +83,7 @@ class CORE_EXPORT QgsProjUtils
|
||||
//TODO - remove when proj 6.1 is minimum supported version, and replace with proj_normalize_for_visualization
|
||||
|
||||
/**
|
||||
* Returns true if the given proj coordinate system uses requires y/x coordinate
|
||||
* Returns TRUE if the given proj coordinate system uses requires y/x coordinate
|
||||
* order instead of x/y.
|
||||
*/
|
||||
static bool axisOrderIsSwapped( const PJ *crs );
|
||||
@ -93,6 +94,19 @@ class CORE_EXPORT QgsProjUtils
|
||||
*/
|
||||
static proj_pj_unique_ptr crsToSingleCrs( const PJ *crs );
|
||||
|
||||
/**
|
||||
* Returns TRUE if a coordinate operation (specified via proj string) is available.
|
||||
*/
|
||||
static bool coordinateOperationIsAvailable( const QString &projDef );
|
||||
|
||||
#if 0 // not possible in current Proj 6 API
|
||||
|
||||
/**
|
||||
* Given a coordinate operation (specified via proj string), returns a list of
|
||||
* any required grids which are not currently available for use.
|
||||
*/
|
||||
static QStringList nonAvailableGrids( const QString &projDef );
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
@ -1567,8 +1567,6 @@ QImage QgsRasterLayer::previewAsImage( QSize size, const QColor &bgColor, QImage
|
||||
myRasterViewPort->mDrawnExtent = myExtent;
|
||||
myRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
|
||||
myRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
|
||||
myRasterViewPort->mSrcDatumTransform = -1;
|
||||
myRasterViewPort->mDestDatumTransform = -1;
|
||||
|
||||
QgsMapToPixel *myMapToPixel = new QgsMapToPixel( myMapUnitsPerPixel );
|
||||
|
||||
|
@ -161,16 +161,12 @@ QgsRasterLayerRenderer::QgsRasterLayerRenderer( QgsRasterLayer *layer, QgsRender
|
||||
{
|
||||
mRasterViewPort->mSrcCRS = layer->crs();
|
||||
mRasterViewPort->mDestCRS = rendererContext.coordinateTransform().destinationCrs();
|
||||
mRasterViewPort->mSrcDatumTransform = rendererContext.coordinateTransform().sourceDatumTransformId();
|
||||
mRasterViewPort->mDestDatumTransform = rendererContext.coordinateTransform().destinationDatumTransformId();
|
||||
mRasterViewPort->mTransformContext = rendererContext.transformContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
mRasterViewPort->mSrcCRS = QgsCoordinateReferenceSystem(); // will be invalid
|
||||
mRasterViewPort->mDestCRS = QgsCoordinateReferenceSystem(); // will be invalid
|
||||
mRasterViewPort->mSrcDatumTransform = -1;
|
||||
mRasterViewPort->mDestDatumTransform = -1;
|
||||
}
|
||||
|
||||
// get dimensions of clipped raster image in device coordinate space (this is the size of the viewport)
|
||||
|
@ -67,9 +67,6 @@ struct CORE_EXPORT QgsRasterViewPort
|
||||
//! \brief Target coordinate system
|
||||
QgsCoordinateReferenceSystem mDestCRS;
|
||||
|
||||
int mSrcDatumTransform;
|
||||
int mDestDatumTransform;
|
||||
|
||||
/**
|
||||
* Coordinate transform context
|
||||
*/
|
||||
|
@ -188,6 +188,35 @@ void TestQgsCoordinateTransform::isShortCircuited()
|
||||
void TestQgsCoordinateTransform::contextShared()
|
||||
{
|
||||
//test implicit sharing of QgsCoordinateTransformContext
|
||||
#if PROJ_VERSION_MAJOR >= 6
|
||||
QgsCoordinateTransformContext original;
|
||||
original.addCoordinateOperation( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), QStringLiteral( "proj" ) );
|
||||
|
||||
QgsCoordinateTransformContext copy( original );
|
||||
QMap< QPair< QString, QString >, QString > expected;
|
||||
expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QStringLiteral( "proj" ) );
|
||||
QCOMPARE( original.coordinateOperations(), expected );
|
||||
QCOMPARE( copy.coordinateOperations(), expected );
|
||||
|
||||
// trigger detach
|
||||
copy.addCoordinateOperation( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), QStringLiteral( "proj2" ) );
|
||||
QCOMPARE( original.coordinateOperations(), expected );
|
||||
|
||||
expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QStringLiteral( "proj2" ) );
|
||||
QCOMPARE( copy.coordinateOperations(), expected );
|
||||
|
||||
// copy via assignment
|
||||
QgsCoordinateTransformContext copy2;
|
||||
copy2 = original;
|
||||
expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QStringLiteral( "proj" ) );
|
||||
QCOMPARE( original.coordinateOperations(), expected );
|
||||
QCOMPARE( copy2.coordinateOperations(), expected );
|
||||
|
||||
copy2.addCoordinateOperation( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), QStringLiteral( "proj2" ) );
|
||||
QCOMPARE( original.coordinateOperations(), expected );
|
||||
expected.insert( qMakePair( QStringLiteral( "EPSG:3111" ), QStringLiteral( "EPSG:3113" ) ), QStringLiteral( "proj2" ) );
|
||||
QCOMPARE( copy2.coordinateOperations(), expected );
|
||||
#else
|
||||
QgsCoordinateTransformContext original;
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
original.addSourceDestinationDatumTransform( QgsCoordinateReferenceSystem( 3111 ), QgsCoordinateReferenceSystem( 3113 ), 1, 2 );
|
||||
@ -218,6 +247,7 @@ void TestQgsCoordinateTransform::contextShared()
|
||||
QCOMPARE( copy2.sourceDestinationDatumTransforms(), expected );
|
||||
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
#endif
|
||||
}
|
||||
|
||||
void TestQgsCoordinateTransform::scaleFactor()
|
||||
@ -228,7 +258,15 @@ void TestQgsCoordinateTransform::scaleFactor()
|
||||
QFETCH( double, factor );
|
||||
|
||||
QgsCoordinateTransform ct( sourceCrs, destCrs, QgsProject::instance() );
|
||||
QGSCOMPARENEAR( ct.scaleFactor( rect ), factor, 0.00000001 );
|
||||
try
|
||||
{
|
||||
QGSCOMPARENEAR( ct.scaleFactor( rect ), factor, 0.000001 );
|
||||
}
|
||||
catch ( QgsCsException & )
|
||||
{
|
||||
QVERIFY( false );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TestQgsCoordinateTransform::scaleFactor_data()
|
||||
@ -244,10 +282,10 @@ void TestQgsCoordinateTransform::scaleFactor_data()
|
||||
<< QgsRectangle( 2550000, 1200000, 2550100, 1200100 )
|
||||
<< 1.1223316038381985e-5;
|
||||
QTest::newRow( "Same map units" )
|
||||
<< QgsCoordinateReferenceSystem::fromEpsgId( 2056 )
|
||||
<< QgsCoordinateReferenceSystem::fromEpsgId( 21781 )
|
||||
<< QgsRectangle( 2550000, 1200000, 2550100, 1200100 )
|
||||
<< 1.0000000000248837;
|
||||
<< QgsCoordinateReferenceSystem::fromEpsgId( 3111 )
|
||||
<< QgsCoordinateReferenceSystem::fromEpsgId( 28355 )
|
||||
<< QgsRectangle( 2560536.7, 2331787.5, 2653161.1, 2427370.4 )
|
||||
<< 0.999632;
|
||||
QTest::newRow( "Same CRS" )
|
||||
<< QgsCoordinateReferenceSystem::fromEpsgId( 2056 )
|
||||
<< QgsCoordinateReferenceSystem::fromEpsgId( 2056 )
|
||||
|
@ -17,7 +17,8 @@ from qgis.core import (QgsRectangle,
|
||||
QgsCoordinateTransform,
|
||||
QgsCoordinateTransformContext,
|
||||
QgsDatumTransform,
|
||||
QgsProject)
|
||||
QgsProject,
|
||||
QgsProjUtils)
|
||||
from qgis.testing import start_app, unittest
|
||||
|
||||
start_app()
|
||||
@ -71,68 +72,7 @@ class TestQgsCoordinateTransform(unittest.TestCase):
|
||||
self.assertAlmostEquals(myTransformedExtentReverse.yMaximum(), myExtent.yMaximum())
|
||||
self.assertAlmostEquals(myTransformedExtentReverse.yMinimum(), myExtent.yMinimum())
|
||||
|
||||
@unittest.skip('ifdefed out in c++ until required')
|
||||
def testContextSingle(self):
|
||||
"""
|
||||
Various tests to ensure that datum transforms are correctly set respecting context
|
||||
"""
|
||||
context = QgsCoordinateTransformContext()
|
||||
context.addSourceDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'), 1)
|
||||
context.addDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:4283'), 2)
|
||||
context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'),
|
||||
3, 4)
|
||||
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28354'), QgsCoordinateReferenceSystem('EPSG:28353'), context)
|
||||
# should be no datum transforms
|
||||
self.assertEqual(transform.sourceDatumTransformId(), -1)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), -1)
|
||||
# matching source
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem('EPSG:28353'), context)
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 1)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), -1)
|
||||
# matching dest
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28354'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), context)
|
||||
self.assertEqual(transform.sourceDatumTransformId(), -1)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 2)
|
||||
# matching src/dest pair
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), context)
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 3)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 4)
|
||||
|
||||
# test manual overwriting
|
||||
transform.setSourceDatumTransform(11)
|
||||
transform.setDestinationDatumTransform(13)
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 11)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 13)
|
||||
|
||||
# test that auto datum setting occurs when updating src/dest crs
|
||||
transform.setSourceCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 3)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 4)
|
||||
transform.setSourceDatumTransform(11)
|
||||
transform.setDestinationDatumTransform(13)
|
||||
|
||||
transform.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4283'))
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 3)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 4)
|
||||
transform.setSourceDatumTransform(11)
|
||||
transform.setDestinationDatumTransform(13)
|
||||
|
||||
# delayed context set
|
||||
transform = QgsCoordinateTransform()
|
||||
self.assertEqual(transform.sourceDatumTransformId(), -1)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), -1)
|
||||
transform.setSourceCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
|
||||
transform.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4283'))
|
||||
self.assertEqual(transform.sourceDatumTransformId(), -1)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), -1)
|
||||
transform.setContext(context)
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 3)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 4)
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testContext(self):
|
||||
"""
|
||||
Various tests to ensure that datum transforms are correctly set respecting context
|
||||
@ -194,6 +134,58 @@ class TestQgsCoordinateTransform(unittest.TestCase):
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 4)
|
||||
self.assertEqual(list(transform.context().sourceDestinationDatumTransforms().keys()), [('EPSG:28356', 'EPSG:4283')])
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testContextProj6(self):
|
||||
"""
|
||||
Various tests to ensure that datum transforms are correctly set respecting context
|
||||
"""
|
||||
context = QgsCoordinateTransformContext()
|
||||
context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'),
|
||||
'proj')
|
||||
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28354'), QgsCoordinateReferenceSystem('EPSG:28353'), context)
|
||||
self.assertEqual(list(transform.context().coordinateOperations().keys()), [('EPSG:28356', 'EPSG:4283')])
|
||||
|
||||
# should be no coordinate operation
|
||||
self.assertEqual(transform.coordinateOperation(), '')
|
||||
|
||||
# matching source
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem('EPSG:28353'), context)
|
||||
self.assertEqual(transform.coordinateOperation(), '')
|
||||
# matching dest
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28354'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), context)
|
||||
self.assertEqual(transform.coordinateOperation(), '')
|
||||
# matching src/dest pair
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), context)
|
||||
self.assertEqual(transform.coordinateOperation(), 'proj')
|
||||
|
||||
# test manual overwriting
|
||||
transform.setCoordinateOperation('proj2')
|
||||
self.assertEqual(transform.coordinateOperation(), 'proj2')
|
||||
|
||||
# test that auto operation setting occurs when updating src/dest crs
|
||||
transform.setSourceCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
|
||||
self.assertEqual(transform.coordinateOperation(), 'proj')
|
||||
transform.setCoordinateOperation('proj2')
|
||||
|
||||
transform.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4283'))
|
||||
self.assertEqual(transform.coordinateOperation(), 'proj')
|
||||
transform.setCoordinateOperation('proj2')
|
||||
|
||||
# delayed context set
|
||||
transform = QgsCoordinateTransform()
|
||||
self.assertEqual(transform.coordinateOperation(), '')
|
||||
transform.setSourceCrs(QgsCoordinateReferenceSystem('EPSG:28356'))
|
||||
transform.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4283'))
|
||||
self.assertEqual(transform.coordinateOperation(), '')
|
||||
transform.setContext(context)
|
||||
self.assertEqual(transform.coordinateOperation(), 'proj')
|
||||
self.assertEqual(list(transform.context().coordinateOperations().keys()), [('EPSG:28356', 'EPSG:4283')])
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testProjectContext(self):
|
||||
"""
|
||||
Test creating transform using convenience constructor which takes project reference
|
||||
@ -208,6 +200,21 @@ class TestQgsCoordinateTransform(unittest.TestCase):
|
||||
self.assertEqual(transform.sourceDatumTransformId(), 1)
|
||||
self.assertEqual(transform.destinationDatumTransformId(), 2)
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testProjectContextProj6(self):
|
||||
"""
|
||||
Test creating transform using convenience constructor which takes project reference
|
||||
"""
|
||||
p = QgsProject()
|
||||
context = p.transformContext()
|
||||
context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:3111'), 'proj')
|
||||
p.setTransformContext(context)
|
||||
|
||||
transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:28356'), QgsCoordinateReferenceSystem('EPSG:3111'), p)
|
||||
self.assertEqual(transform.coordinateOperation(), 'proj')
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testTransformInfo(self):
|
||||
# hopefully this transform is available on all platforms!
|
||||
transforms = QgsDatumTransform.datumTransformations(QgsCoordinateReferenceSystem(4613), QgsCoordinateReferenceSystem(4326))
|
||||
@ -230,6 +237,7 @@ class TestQgsCoordinateTransform(unittest.TestCase):
|
||||
self.assertIn('EPSG:4613', [QgsDatumTransform.datumTransformInfo(t.destinationTransformId).sourceCrsAuthId for t in
|
||||
transforms])
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testStringToTransformId(self):
|
||||
"""
|
||||
Test converting proj strings to corresponding datum IDs
|
||||
|
@ -17,7 +17,8 @@ from qgis.core import (QgsCoordinateReferenceSystem,
|
||||
QgsDatumTransform,
|
||||
QgsReadWriteContext,
|
||||
QgsProject,
|
||||
QgsSettings)
|
||||
QgsSettings,
|
||||
QgsProjUtils)
|
||||
from qgis.testing import start_app, unittest
|
||||
from qgis.PyQt.QtXml import QDomDocument
|
||||
from qgis.PyQt.QtTest import QSignalSpy
|
||||
@ -32,14 +33,16 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
def setUpClass(cls):
|
||||
"""Run before all tests"""
|
||||
QCoreApplication.setOrganizationName("QGIS_Test")
|
||||
QCoreApplication.setOrganizationDomain("TestPyQgsWFSProvider.com")
|
||||
QCoreApplication.setApplicationName("TestPyQgsWFSProvider")
|
||||
QCoreApplication.setOrganizationDomain("TestQgsCoordinateTransformContext.com")
|
||||
QCoreApplication.setApplicationName("TestQgsCoordinateTransformContext")
|
||||
QgsSettings().clear()
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testSourceDestinationDatumTransforms(self):
|
||||
context = QgsCoordinateTransformContext()
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {})
|
||||
self.assertFalse(context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4283')))
|
||||
self.assertFalse(
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4283')))
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), 1, 2))
|
||||
self.assertTrue(
|
||||
@ -48,92 +51,180 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4326')))
|
||||
self.assertFalse(
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3113'), QgsCoordinateReferenceSystem('EPSG:4283')))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2)})
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem(4283), 3, 4))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4)})
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem(28357), 7, 8))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(7, 8)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(7, 8)})
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:28357'), 9, 11))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)})
|
||||
|
||||
# invalid additions
|
||||
self.assertFalse(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(),
|
||||
QgsCoordinateReferenceSystem('EPSG:28357'), 9, 11))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)})
|
||||
self.assertFalse(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem(), 9, 11))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11)})
|
||||
|
||||
# indicate no transform required
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(28357),
|
||||
QgsCoordinateReferenceSystem(28356), -1, -1))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1)})
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3111),
|
||||
QgsCoordinateReferenceSystem(28356), 17, -1))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1)})
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(3113),
|
||||
QgsCoordinateReferenceSystem(28356), -1, 18))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
# remove non-existing
|
||||
context.removeCoordinateOperation(QgsCoordinateReferenceSystem(3113), QgsCoordinateReferenceSystem(3111))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2),
|
||||
('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
|
||||
# remove existing
|
||||
context.removeCoordinateOperation(QgsCoordinateReferenceSystem(3111),
|
||||
QgsCoordinateReferenceSystem(4283))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3111', 'EPSG:28356'): QgsDatumTransform.TransformPair(17, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
context.removeCoordinateOperation(QgsCoordinateReferenceSystem(3111),
|
||||
QgsCoordinateReferenceSystem(28356))
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:28356', 'EPSG:4283'): QgsDatumTransform.TransformPair(3, 4),
|
||||
('EPSG:28356', 'EPSG:28357'): QgsDatumTransform.TransformPair(9, 11),
|
||||
('EPSG:28357', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, -1),
|
||||
('EPSG:3113', 'EPSG:28356'): QgsDatumTransform.TransformPair(-1, 18)})
|
||||
|
||||
context.clear()
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testSourceDestinationDatumTransformsProj6(self):
|
||||
context = QgsCoordinateTransformContext()
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {})
|
||||
proj_string = '+proj=pipeline +step +inv +proj=lcc +lat_0=-37 +lon_0=145 +lat_1=-36 +lat_2=-38 +x_0=2500000 +y_0=2500000 +ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
self.assertFalse(
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4283')))
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), proj_string))
|
||||
self.assertTrue(
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4283')))
|
||||
self.assertFalse(
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3111'), QgsCoordinateReferenceSystem('EPSG:4326')))
|
||||
self.assertFalse(
|
||||
context.hasTransform(QgsCoordinateReferenceSystem('EPSG:3113'), QgsCoordinateReferenceSystem('EPSG:4283')))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string})
|
||||
proj_string_2 = '+proj=pipeline +step +inv +proj=utm +zone=56 +south +ellps=GRS80 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem(4283), proj_string_2))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2})
|
||||
proj_string_3 = '+proj=pipeline +step +inv +proj=utm +zone=56 +south +ellps=GRS80 +step +proj=utm +zone=57 +south +ellps=GRS80'
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem(28357), proj_string_3))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): proj_string_3})
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:28357'),
|
||||
'some other proj string'))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): 'some other proj string'})
|
||||
|
||||
# invalid additions
|
||||
self.assertFalse(context.addCoordinateOperation(QgsCoordinateReferenceSystem(),
|
||||
QgsCoordinateReferenceSystem('EPSG:28357'), 'bad proj'))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): 'some other proj string'})
|
||||
self.assertFalse(context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem(), 'bad proj'))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): 'some other proj string'})
|
||||
|
||||
# indicate no transform required
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem(28357),
|
||||
QgsCoordinateReferenceSystem(28356), ''))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): 'some other proj string',
|
||||
('EPSG:28357', 'EPSG:28356'): ''})
|
||||
|
||||
# remove non-existing
|
||||
context.removeCoordinateOperation(QgsCoordinateReferenceSystem(3113), QgsCoordinateReferenceSystem(3111))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:3111', 'EPSG:4283'): proj_string,
|
||||
('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): 'some other proj string',
|
||||
('EPSG:28357', 'EPSG:28356'): ''})
|
||||
|
||||
# remove existing
|
||||
context.removeCoordinateOperation(QgsCoordinateReferenceSystem(3111),
|
||||
QgsCoordinateReferenceSystem(4283))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28356', 'EPSG:28357'): 'some other proj string',
|
||||
('EPSG:28357', 'EPSG:28356'): ''})
|
||||
context.removeCoordinateOperation(QgsCoordinateReferenceSystem(28356),
|
||||
QgsCoordinateReferenceSystem(28357))
|
||||
self.assertEqual(context.coordinateOperations(), {('EPSG:28356', 'EPSG:4283'): proj_string_2,
|
||||
('EPSG:28357', 'EPSG:28356'): ''})
|
||||
|
||||
context.clear()
|
||||
self.assertEqual(context.coordinateOperations(), {})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testCalculateSourceDest(self):
|
||||
context = QgsCoordinateTransformContext()
|
||||
|
||||
#empty context
|
||||
# empty context
|
||||
self.assertEqual(context.calculateDatumTransforms(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283')),
|
||||
QgsDatumTransform.TransformPair(-1, -1))
|
||||
|
||||
#add specific source/dest pair - should take precedence
|
||||
# add specific source/dest pair - should take precedence
|
||||
context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'),
|
||||
3, 4)
|
||||
@ -151,6 +242,34 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
QgsCoordinateReferenceSystem('EPSG:28356')),
|
||||
QgsDatumTransform.TransformPair(4, 3))
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testCalculateSourceDestProj6(self):
|
||||
context = QgsCoordinateTransformContext()
|
||||
|
||||
# empty context
|
||||
self.assertEqual(context.calculateCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283')),
|
||||
'')
|
||||
|
||||
# add specific source/dest pair - should take precedence
|
||||
context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'),
|
||||
'proj 1')
|
||||
self.assertEqual(context.calculateCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283')),
|
||||
'proj 1')
|
||||
self.assertEqual(context.calculateCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283')),
|
||||
'')
|
||||
self.assertEqual(context.calculateCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:28356'),
|
||||
QgsCoordinateReferenceSystem('EPSG:3111')),
|
||||
'')
|
||||
# check that reverse transforms are automatically supported
|
||||
self.assertEqual(context.calculateCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:4283'),
|
||||
QgsCoordinateReferenceSystem('EPSG:28356')),
|
||||
'proj 1')
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testWriteReadXml(self):
|
||||
# setup a context
|
||||
context = QgsCoordinateTransformContext()
|
||||
@ -166,12 +285,15 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
QgsCoordinateReferenceSystem(4326))[0].destinationTransformId
|
||||
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(4204),
|
||||
QgsCoordinateReferenceSystem(4326), source_id_1, dest_id_1))
|
||||
QgsCoordinateReferenceSystem(4326), source_id_1,
|
||||
dest_id_1))
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem(4205),
|
||||
QgsCoordinateReferenceSystem(4326), source_id_2, dest_id_2))
|
||||
QgsCoordinateReferenceSystem(4326), source_id_2,
|
||||
dest_id_2))
|
||||
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1),
|
||||
('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)})
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1),
|
||||
('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)})
|
||||
|
||||
# save to xml
|
||||
doc = QDomDocument("testdoc")
|
||||
@ -183,9 +305,42 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
context2.readXml(elem, QgsReadWriteContext())
|
||||
|
||||
# check result
|
||||
self.assertEqual(context2.sourceDestinationDatumTransforms(), {('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1),
|
||||
('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)})
|
||||
self.assertEqual(context2.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1),
|
||||
('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testWriteReadXmlProj6(self):
|
||||
# setup a context
|
||||
context = QgsCoordinateTransformContext()
|
||||
|
||||
proj_1 = '+proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 +step +proj=cart +ellps=intl +step +proj=helmert +x=-18.944 +y=-379.364 +z=-24.063 +rx=-0.04 +ry=0.764 +rz=-6.431 +s=3.657 +convention=coordinate_frame +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
proj_2 = '+proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 +step +proj=cart +ellps=intl +step +proj=helmert +x=-150 +y=-250 +z=-1 +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem(4204),
|
||||
QgsCoordinateReferenceSystem(4326), proj_1))
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem(4205),
|
||||
QgsCoordinateReferenceSystem(4326), proj_2))
|
||||
|
||||
self.assertEqual(context.coordinateOperations(),
|
||||
{('EPSG:4204', 'EPSG:4326'): proj_1,
|
||||
('EPSG:4205', 'EPSG:4326'): proj_2})
|
||||
|
||||
# save to xml
|
||||
doc = QDomDocument("testdoc")
|
||||
elem = doc.createElement("test")
|
||||
context.writeXml(elem, QgsReadWriteContext())
|
||||
|
||||
# restore from xml
|
||||
context2 = QgsCoordinateTransformContext()
|
||||
context2.readXml(elem, QgsReadWriteContext())
|
||||
|
||||
# check result
|
||||
self.assertEqual(context2.coordinateOperations(),
|
||||
{('EPSG:4204', 'EPSG:4326'): proj_1,
|
||||
('EPSG:4205', 'EPSG:4326'): proj_2})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testMissingTransforms(self):
|
||||
# fudge context xml with a missing transform
|
||||
doc = QDomDocument("testdoc")
|
||||
@ -209,6 +364,34 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
# check result
|
||||
self.assertEqual(errors, ['not valid', 'not valid 2'])
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testMissingTransformsProj6(self):
|
||||
return # TODO -- this seems impossible to determine with existing PROJ6 api
|
||||
# fudge context xml with a missing transform
|
||||
doc = QDomDocument("testdoc")
|
||||
elem = doc.createElement("test")
|
||||
contextElem = doc.createElement("transformContext")
|
||||
transformElem = doc.createElement("srcDest")
|
||||
transformElem.setAttribute("source", 'EPSG:4204')
|
||||
transformElem.setAttribute("dest", 'EPSG:4326')
|
||||
|
||||
# fake a proj string with a grid which will NEVER exist
|
||||
fake_proj = '+proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +inv +proj=hgridshift +grids=this_is_not_a_real_grid.gsb +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
transformElem.setAttribute("coordinateOp", fake_proj)
|
||||
contextElem.appendChild(transformElem)
|
||||
|
||||
elem2 = doc.createElement("test2")
|
||||
elem2.appendChild(contextElem)
|
||||
|
||||
# restore from xml
|
||||
context2 = QgsCoordinateTransformContext()
|
||||
ok, errors = context2.readXml(elem2, QgsReadWriteContext())
|
||||
self.assertFalse(ok)
|
||||
|
||||
# check result
|
||||
self.assertEqual(errors, ['not valid'])
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testProject(self):
|
||||
"""
|
||||
Test project's transform context
|
||||
@ -220,8 +403,25 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), 1, 2)
|
||||
project.setTransformContext(context)
|
||||
self.assertEqual(len(context_changed_spy), 1)
|
||||
self.assertEqual(project.transformContext().sourceDestinationDatumTransforms(), {('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2)})
|
||||
self.assertEqual(project.transformContext().sourceDestinationDatumTransforms(),
|
||||
{('EPSG:3111', 'EPSG:4283'): QgsDatumTransform.TransformPair(1, 2)})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testProjectProj6(self):
|
||||
"""
|
||||
Test project's transform context
|
||||
"""
|
||||
project = QgsProject()
|
||||
context_changed_spy = QSignalSpy(project.transformContextChanged)
|
||||
context = project.transformContext()
|
||||
context.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), 'proj')
|
||||
project.setTransformContext(context)
|
||||
self.assertEqual(len(context_changed_spy), 1)
|
||||
self.assertEqual(project.transformContext().coordinateOperations(),
|
||||
{('EPSG:3111', 'EPSG:4283'): 'proj'})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testReadWriteSettings(self):
|
||||
context = QgsCoordinateTransformContext()
|
||||
context.readSettings()
|
||||
@ -240,9 +440,11 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(), {})
|
||||
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:4204'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4326'), source_id_1, dest_id_1))
|
||||
QgsCoordinateReferenceSystem('EPSG:4326'),
|
||||
source_id_1, dest_id_1))
|
||||
self.assertTrue(context.addSourceDestinationDatumTransform(QgsCoordinateReferenceSystem('EPSG:4205'),
|
||||
QgsCoordinateReferenceSystem(4326), source_id_2, dest_id_2))
|
||||
QgsCoordinateReferenceSystem(4326), source_id_2,
|
||||
dest_id_2))
|
||||
|
||||
self.assertEqual(context.sourceDestinationDatumTransforms(),
|
||||
{('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1),
|
||||
@ -261,6 +463,40 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
{('EPSG:4204', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_1, dest_id_1),
|
||||
('EPSG:4205', 'EPSG:4326'): QgsDatumTransform.TransformPair(source_id_2, dest_id_2)})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testReadWriteSettingsProj6(self):
|
||||
context = QgsCoordinateTransformContext()
|
||||
context.readSettings()
|
||||
|
||||
proj_1 = '+proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 +step +proj=cart +ellps=intl +step +proj=helmert +x=-18.944 +y=-379.364 +z=-24.063 +rx=-0.04 +ry=0.764 +rz=-6.431 +s=3.657 +convention=coordinate_frame +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
proj_2 = '+proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=push +v_3 +step +proj=cart +ellps=intl +step +proj=helmert +x=-150 +y=-250 +z=-1 +step +inv +proj=cart +ellps=WGS84 +step +proj=pop +v_3 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1'
|
||||
|
||||
# should be empty
|
||||
self.assertEqual(context.coordinateOperations(), {})
|
||||
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem(4204),
|
||||
QgsCoordinateReferenceSystem(4326), proj_1))
|
||||
self.assertTrue(context.addCoordinateOperation(QgsCoordinateReferenceSystem(4205),
|
||||
QgsCoordinateReferenceSystem(4326), proj_2))
|
||||
|
||||
self.assertEqual(context.coordinateOperations(),
|
||||
{('EPSG:4204', 'EPSG:4326'): proj_1,
|
||||
('EPSG:4205', 'EPSG:4326'): proj_2})
|
||||
|
||||
# save to settings
|
||||
context.writeSettings()
|
||||
|
||||
# restore from settings
|
||||
context2 = QgsCoordinateTransformContext()
|
||||
self.assertEqual(context2.coordinateOperations(), {})
|
||||
context2.readSettings()
|
||||
|
||||
# check result
|
||||
self.assertEqual(context2.coordinateOperations(),
|
||||
{('EPSG:4204', 'EPSG:4326'): proj_1,
|
||||
('EPSG:4205', 'EPSG:4326'): proj_2})
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() >= 6, 'Skipped on proj6 builds')
|
||||
def testEqualOperator(self):
|
||||
context1 = QgsCoordinateTransformContext()
|
||||
context2 = QgsCoordinateTransformContext()
|
||||
@ -274,6 +510,20 @@ class TestQgsCoordinateTransformContext(unittest.TestCase):
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), 1, 2)
|
||||
self.assertTrue(context1 == context2)
|
||||
|
||||
@unittest.skipIf(QgsProjUtils.projVersionMajor() < 6, 'Skipped on non proj6 builds')
|
||||
def testEqualOperatorProj6(self):
|
||||
context1 = QgsCoordinateTransformContext()
|
||||
context2 = QgsCoordinateTransformContext()
|
||||
self.assertTrue(context1 == context2)
|
||||
|
||||
context1.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), 'p1')
|
||||
self.assertFalse(context1 == context2)
|
||||
|
||||
context2.addCoordinateOperation(QgsCoordinateReferenceSystem('EPSG:3111'),
|
||||
QgsCoordinateReferenceSystem('EPSG:4283'), 'p1')
|
||||
self.assertTrue(context1 == context2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user