Add explicit settings for ellipsoid, distance and area units to QgsProcessingContext

to avoid having to always retrieve these via the context's project (which may
not be available in some circumstances)

Refs #37988
This commit is contained in:
Nyall Dawson 2020-07-28 11:29:25 +10:00
parent 0f7a946f51
commit 03854a41b0
4 changed files with 195 additions and 4 deletions

View File

@ -73,8 +73,8 @@ Returns the project in which the algorithm is being executed.
%Docstring
Sets the ``project`` in which the algorithm will be executed.
This also automatically sets the :py:func:`~QgsProcessingContext.transformContext` to match
the project's transform context.
This also automatically sets the :py:func:`~QgsProcessingContext.transformContext`, :py:func:`~QgsProcessingContext.ellipsoid`, :py:func:`~QgsProcessingContext.distanceUnit` and
:py:func:`~QgsProcessingContext.areaUnit` to match the project's settings.
.. seealso:: :py:func:`project`
%End
@ -105,6 +105,74 @@ Note that setting a project for the context will automatically set the coordinat
context.
.. seealso:: :py:func:`transformContext`
%End
QString ellipsoid() const;
%Docstring
Returns the ellipsoid to use for distance and area calculations.
.. seealso:: :py:func:`setEllipsoid`
.. versionadded:: 3.16
%End
void setEllipsoid( const QString &ellipsoid );
%Docstring
Sets a specified ``ellipsoid`` to use for distance and area calculations.
If not explicitly set, the ellipsoid will default to the :py:func:`~QgsProcessingContext.project`'s ellipsoid setting.
.. seealso:: :py:func:`ellipsoid`
.. versionadded:: 3.16
%End
QgsUnitTypes::DistanceUnit distanceUnit() const;
%Docstring
Returns the distance unit to use for distance calculations.
.. seealso:: :py:func:`setDistanceUnit`
.. seealso:: :py:func:`areaUnit`
.. versionadded:: 3.16
%End
void setDistanceUnit( QgsUnitTypes::DistanceUnit unit );
%Docstring
Sets the ``unit`` to use for distance calculations.
If not explicitly set, the unit will default to the :py:func:`~QgsProcessingContext.project`'s distance unit setting.
.. seealso:: :py:func:`distanceUnit`
.. seealso:: :py:func:`setAreaUnit`
.. versionadded:: 3.16
%End
QgsUnitTypes::AreaUnit areaUnit() const;
%Docstring
Returns the area unit to use for area calculations.
.. seealso:: :py:func:`setAreaUnit`
.. seealso:: :py:func:`distanceUnit`
.. versionadded:: 3.16
%End
void setAreaUnit( QgsUnitTypes::AreaUnit areaUnit );
%Docstring
Sets the ``unit`` to use for area calculations.
If not explicitly set, the unit will default to the :py:func:`~QgsProcessingContext.project`'s area unit setting.
.. seealso:: :py:func:`areaUnit`
.. seealso:: :py:func:`setDistanceUnit`
.. versionadded:: 3.16
%End
QgsMapLayerStore *temporaryLayerStore();

View File

@ -110,7 +110,35 @@ QgsMapLayer *QgsProcessingContext::takeResultLayer( const QString &id )
return tempLayerStore.takeMapLayer( tempLayerStore.mapLayer( id ) );
}
QString QgsProcessingContext::ellipsoid() const
{
return mEllipsoid;
}
void QgsProcessingContext::setEllipsoid( const QString &ellipsoid )
{
mEllipsoid = ellipsoid;
}
QgsUnitTypes::DistanceUnit QgsProcessingContext::distanceUnit() const
{
return mDistanceUnit;
}
void QgsProcessingContext::setDistanceUnit( QgsUnitTypes::DistanceUnit unit )
{
mDistanceUnit = unit;
}
QgsUnitTypes::AreaUnit QgsProcessingContext::areaUnit() const
{
return mAreaUnit;
}
void QgsProcessingContext::setAreaUnit( QgsUnitTypes::AreaUnit areaUnit )
{
mAreaUnit = areaUnit;
}
QgsProcessingLayerPostProcessorInterface *QgsProcessingContext::LayerDetails::postProcessor() const
{

View File

@ -78,6 +78,11 @@ class CORE_EXPORT QgsProcessingContext
mTransformErrorCallback = other.mTransformErrorCallback;
mDefaultEncoding = other.mDefaultEncoding;
mFeedback = other.mFeedback;
mPreferredVectorFormat = other.mPreferredVectorFormat;
mPreferredRasterFormat = other.mPreferredRasterFormat;
mEllipsoid = other.mEllipsoid;
mDistanceUnit = other.mDistanceUnit;
mAreaUnit = other.mAreaUnit;
}
/**
@ -101,8 +106,8 @@ class CORE_EXPORT QgsProcessingContext
/**
* Sets the \a project in which the algorithm will be executed.
*
* This also automatically sets the transformContext() to match
* the project's transform context.
* This also automatically sets the transformContext(), ellipsoid(), distanceUnit() and
* areaUnit() to match the project's settings.
*
* \see project()
*/
@ -110,7 +115,15 @@ class CORE_EXPORT QgsProcessingContext
{
mProject = project;
if ( mProject )
{
mTransformContext = mProject->transformContext();
if ( mEllipsoid.isEmpty() )
mEllipsoid = mProject->ellipsoid();
if ( mDistanceUnit == QgsUnitTypes::DistanceUnknownUnit )
mDistanceUnit = mProject->distanceUnits();
if ( mAreaUnit == QgsUnitTypes::AreaUnknownUnit )
mAreaUnit = mProject->areaUnits();
}
}
/**
@ -144,6 +157,64 @@ class CORE_EXPORT QgsProcessingContext
*/
void setTransformContext( const QgsCoordinateTransformContext &context ) { mTransformContext = context; }
/**
* Returns the ellipsoid to use for distance and area calculations.
*
* \see setEllipsoid()
* \since QGIS 3.16
*/
QString ellipsoid() const;
/**
* Sets a specified \a ellipsoid to use for distance and area calculations.
*
* If not explicitly set, the ellipsoid will default to the project()'s ellipsoid setting.
*
* \see ellipsoid()
* \since QGIS 3.16
*/
void setEllipsoid( const QString &ellipsoid );
/**
* Returns the distance unit to use for distance calculations.
*
* \see setDistanceUnit()
* \see areaUnit()
* \since QGIS 3.16
*/
QgsUnitTypes::DistanceUnit distanceUnit() const;
/**
* Sets the \a unit to use for distance calculations.
*
* If not explicitly set, the unit will default to the project()'s distance unit setting.
*
* \see distanceUnit()
* \see setAreaUnit()
* \since QGIS 3.16
*/
void setDistanceUnit( QgsUnitTypes::DistanceUnit unit );
/**
* Returns the area unit to use for area calculations.
*
* \see setAreaUnit()
* \see distanceUnit()
* \since QGIS 3.16
*/
QgsUnitTypes::AreaUnit areaUnit() const;
/**
* Sets the \a unit to use for area calculations.
*
* If not explicitly set, the unit will default to the project()'s area unit setting.
*
* \see areaUnit()
* \see setDistanceUnit()
* \since QGIS 3.16
*/
void setAreaUnit( QgsUnitTypes::AreaUnit areaUnit );
/**
* Returns a reference to the layer store used for storing temporary layers during
* algorithm execution.
@ -535,6 +606,11 @@ class CORE_EXPORT QgsProcessingContext
QgsProcessingContext::Flags mFlags = QgsProcessingContext::Flags();
QPointer< QgsProject > mProject;
QgsCoordinateTransformContext mTransformContext;
QString mEllipsoid;
QgsUnitTypes::DistanceUnit mDistanceUnit = QgsUnitTypes::DistanceUnknownUnit;
QgsUnitTypes::AreaUnit mAreaUnit = QgsUnitTypes::AreaUnknownUnit;
//! Temporary project owned by the context, used for storing temporarily loaded map layers
QgsMapLayerStore tempLayerStore;
QgsExpressionContext mExpressionContext;

View File

@ -956,9 +956,28 @@ void TestQgsProcessing::context()
context.setFlags( QgsProcessingContext::Flags( nullptr ) );
QCOMPARE( context.flags(), QgsProcessingContext::Flags( nullptr ) );
QCOMPARE( context.ellipsoid(), QString() );
QCOMPARE( context.distanceUnit(), QgsUnitTypes::DistanceUnknownUnit );
QCOMPARE( context.areaUnit(), QgsUnitTypes::AreaUnknownUnit );
QgsProject p;
p.setEllipsoid( QStringLiteral( "WGS84" ) );
p.setDistanceUnits( QgsUnitTypes::DistanceFeet );
p.setAreaUnits( QgsUnitTypes::AreaHectares );
context.setProject( &p );
QCOMPARE( context.project(), &p );
QCOMPARE( context.ellipsoid(), QStringLiteral( "WGS84" ) );
QCOMPARE( context.distanceUnit(), QgsUnitTypes::DistanceFeet );
QCOMPARE( context.areaUnit(), QgsUnitTypes::AreaHectares );
// if context ellipsoid/units are already set then setting the project shouldn't overwrite them
p.setEllipsoid( QStringLiteral( "WGS84v2" ) );
p.setDistanceUnits( QgsUnitTypes::DistanceMiles );
p.setAreaUnits( QgsUnitTypes::AreaAcres );
context.setProject( &p );
QCOMPARE( context.ellipsoid(), QStringLiteral( "WGS84" ) );
QCOMPARE( context.distanceUnit(), QgsUnitTypes::DistanceFeet );
QCOMPARE( context.areaUnit(), QgsUnitTypes::AreaHectares );
context.setInvalidGeometryCheck( QgsFeatureRequest::GeometrySkipInvalid );
QCOMPARE( context.invalidGeometryCheck(), QgsFeatureRequest::GeometrySkipInvalid );