Skip to content

Commit

Permalink
Allow use of Qgs(Referenced)Rectangle for processing extent parameter…
Browse files Browse the repository at this point in the history
… values

And add a new target CRS argument to parameterAsExtent. If set, and
the source CRS of the rectangle parameter can be determined, then
the returned value will be the rectangle automatically reprojected
to the desired target CRS.
  • Loading branch information
nyalldawson committed Sep 14, 2017
1 parent d8db3ec commit ae8bc04
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 7 deletions.
6 changes: 5 additions & 1 deletion python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -662,9 +662,13 @@ class QgsProcessingAlgorithm
:rtype: QgsCoordinateReferenceSystem
%End

QgsRectangle parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
QgsRectangle parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a rectangular extent.

If ``crs`` is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
reprojected so that it is in the specified ``crs``. In this case the extent of the reproject rectangle will be returned.
:rtype: QgsRectangle
%End

Expand Down
6 changes: 5 additions & 1 deletion python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -534,9 +534,13 @@ class QgsProcessingParameters
:rtype: QgsCoordinateReferenceSystem
%End

static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
%Docstring
Evaluates the parameter with matching ``definition`` to a rectangular extent.

If ``crs`` is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
reprojected so that it is in the specified ``crs``. In this case the extent of the reproject rectangle will be returned.
:rtype: QgsRectangle
%End

Expand Down
4 changes: 2 additions & 2 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -550,9 +550,9 @@ QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsCrs( const QVari
return QgsProcessingParameters::parameterAsCrs( parameterDefinition( name ), parameters, context );
}

QgsRectangle QgsProcessingAlgorithm::parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
QgsRectangle QgsProcessingAlgorithm::parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
{
return QgsProcessingParameters::parameterAsExtent( parameterDefinition( name ), parameters, context );
return QgsProcessingParameters::parameterAsExtent( parameterDefinition( name ), parameters, context, crs );
}

QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
Expand Down
6 changes: 5 additions & 1 deletion src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -648,8 +648,12 @@ class CORE_EXPORT QgsProcessingAlgorithm

/**
* Evaluates the parameter with matching \a name to a rectangular extent.
*
* If \a crs is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
* reprojected so that it is in the specified \a crs. In this case the extent of the reproject rectangle will be returned.
*/
QgsRectangle parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
QgsRectangle parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;

/**
* Evaluates the parameter with matching \a name to a point.
Expand Down
31 changes: 30 additions & 1 deletion src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -22,6 +22,7 @@
#include "qgsprocessingoutputs.h"
#include "qgssettings.h"
#include "qgsvectorfilewriter.h"
#include "qgsreferencedgeometry.h"
#include <functional>

bool QgsProcessingParameters::isDynamic( const QVariantMap &parameters, const QString &name )
Expand Down Expand Up @@ -484,12 +485,29 @@ QgsCoordinateReferenceSystem QgsProcessingParameters::parameterAsCrs( const QgsP
return crs;
}

QgsRectangle QgsProcessingParameters::parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
QgsRectangle QgsProcessingParameters::parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs )
{
if ( !definition )
return QgsRectangle();

QVariant val = parameters.value( definition->name() );

if ( val.canConvert< QgsRectangle >() )
{
return val.value<QgsRectangle>();
}
if ( val.canConvert< QgsReferencedRectangle >() )
{
QgsReferencedRectangle rr = val.value<QgsReferencedRectangle>();
if ( crs.isValid() && rr.crs().isValid() && crs != rr.crs() )
{
QgsCoordinateTransform ct( rr.crs(), crs );
return ct.transformBoundingBox( rr );
}
return rr;
}

QString rectText;
if ( val.canConvert<QgsProperty>() )
rectText = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
Expand Down Expand Up @@ -1133,6 +1151,17 @@ bool QgsProcessingParameterExtent::checkValueIsAcceptable( const QVariant &input
return true;
}

if ( input.canConvert< QgsRectangle >() )
{
QgsRectangle r = input.value<QgsRectangle>();
return !r.isNull();
}
if ( input.canConvert< QgsReferencedRectangle >() )
{
QgsReferencedRectangle r = input.value<QgsReferencedRectangle>();
return !r.isNull();
}

if ( input.type() != QVariant::String || input.toString().isEmpty() )
return mFlags & FlagOptional;

Expand Down
6 changes: 5 additions & 1 deletion src/core/processing/qgsprocessingparameters.h
Expand Up @@ -565,8 +565,12 @@ class CORE_EXPORT QgsProcessingParameters

/**
* Evaluates the parameter with matching \a definition to a rectangular extent.
*
* If \a crs is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
* reprojected so that it is in the specified \a crs. In this case the extent of the reproject rectangle will be returned.
*/
static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );

/**
* Evaluates the parameter with matching \a definition to a point.
Expand Down
42 changes: 42 additions & 0 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -32,6 +32,7 @@
#include "qgsvectorfilewriter.h"
#include "qgsexpressioncontext.h"
#include "qgsxmlutils.h"
#include "qgsreferencedgeometry.h"

class DummyAlgorithm : public QgsProcessingAlgorithm
{
Expand Down Expand Up @@ -1844,6 +1845,10 @@ void TestQgsProcessing::parameterExtent()
QVERIFY( def->checkValueIsAcceptable( "1,2,3,4" ) );
QVERIFY( !def->checkValueIsAcceptable( "" ) );
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( def->checkValueIsAcceptable( QgsRectangle( 1, 2, 3, 4 ) ) );
QVERIFY( !def->checkValueIsAcceptable( QgsRectangle() ) );
QVERIFY( def->checkValueIsAcceptable( QgsReferencedRectangle( QgsRectangle( 1, 2, 3, 4 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
QVERIFY( !def->checkValueIsAcceptable( QgsReferencedRectangle( QgsRectangle(), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );

// these checks require a context - otherwise we could potentially be referring to a layer source
QVERIFY( def->checkValueIsAcceptable( "1,2,3" ) );
Expand Down Expand Up @@ -1881,10 +1886,47 @@ void TestQgsProcessing::parameterExtent()
QGSCOMPARENEAR( ext.yMinimum(), 3.3, 0.001 );
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );

// with target CRS - should make no difference, because source CRS is unknown
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
QGSCOMPARENEAR( ext.xMinimum(), 1.1, 0.001 );
QGSCOMPARENEAR( ext.xMaximum(), 2.2, 0.001 );
QGSCOMPARENEAR( ext.yMinimum(), 3.3, 0.001 );
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );

// nonsense string
params.insert( "non_optional", QString( "i'm not a crs, and nothing you can do will make me one" ) );
QVERIFY( QgsProcessingParameters::parameterAsExtent( def.get(), params, context ).isNull() );

// QgsRectangle
params.insert( "non_optional", QgsRectangle( 11.1, 12.2, 13.3, 14.4 ) );
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
QGSCOMPARENEAR( ext.xMinimum(), 11.1, 0.001 );
QGSCOMPARENEAR( ext.xMaximum(), 13.3, 0.001 );
QGSCOMPARENEAR( ext.yMinimum(), 12.2, 0.001 );
QGSCOMPARENEAR( ext.yMaximum(), 14.4, 0.001 );

// with target CRS - should make no difference, because source CRS is unknown
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
QGSCOMPARENEAR( ext.xMinimum(), 11.1, 0.001 );
QGSCOMPARENEAR( ext.xMaximum(), 13.3, 0.001 );
QGSCOMPARENEAR( ext.yMinimum(), 12.2, 0.001 );
QGSCOMPARENEAR( ext.yMaximum(), 14.4, 0.001 );

// QgsReferencedRectangle
params.insert( "non_optional", QgsReferencedRectangle( QgsRectangle( 1.1, 2.2, 3.3, 4.4 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) );
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
QGSCOMPARENEAR( ext.xMinimum(), 1.1, 0.001 );
QGSCOMPARENEAR( ext.xMaximum(), 3.3, 0.001 );
QGSCOMPARENEAR( ext.yMinimum(), 2.2, 0.001 );
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );

// with target CRS
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
QGSCOMPARENEAR( ext.xMinimum(), 122451, 100 );
QGSCOMPARENEAR( ext.xMaximum(), 367354, 100 );
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );

QCOMPARE( def->valueAsPythonString( "1,2,3,4", context ), QStringLiteral( "'1,2,3,4'" ) );
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( r1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
Expand Down

0 comments on commit ae8bc04

Please sign in to comment.