Skip to content
Permalink
Browse files

[processing] Allow QgsGeometry values for point parameter values

The centroid of the geometry is used for the point parameter value.
This makes it easier to write expressions for the value of point
parameters, since all the QGIS expression functions for working
with geometry types return QgsGeometry value themselves (e.g.
make_point, centroid, ...). In this case it's much nicer to
allow expression values like `make_point(3,4)` within a precalculated
expression based value in a Processing model.
  • Loading branch information
nyalldawson committed Mar 18, 2019
1 parent c66159b commit acdb368024ab9a5a26bfd3d4da477ff49176e8f1
@@ -1126,6 +1126,12 @@ QgsPointXY QgsProcessingParameters::parameterAsPoint( const QgsProcessingParamet
{
return val.value<QgsPointXY>();
}
if ( val.canConvert< QgsGeometry >() )
{
const QgsGeometry geom = val.value<QgsGeometry>();
if ( !geom.isNull() )
return geom.centroid().asPoint();
}
if ( val.canConvert< QgsReferencedPointXY >() )
{
QgsReferencedPointXY rp = val.value<QgsReferencedPointXY>();
@@ -2129,6 +2135,10 @@ bool QgsProcessingParameterPoint::checkValueIsAcceptable( const QVariant &input,
{
return true;
}
if ( input.canConvert< QgsGeometry >() )
{
return true;
}

if ( input.type() == QVariant::String )
{
@@ -2165,13 +2175,22 @@ QString QgsProcessingParameterPoint::valueAsPythonString( const QVariant &value,
return QStringLiteral( "'%1,%2'" ).arg( qgsDoubleToString( r.x() ),
qgsDoubleToString( r.y() ) );
}
if ( value.canConvert< QgsReferencedPointXY >() )
else if ( value.canConvert< QgsReferencedPointXY >() )
{
QgsReferencedPointXY r = value.value<QgsReferencedPointXY>();
return QStringLiteral( "'%1,%2 [%3]'" ).arg( qgsDoubleToString( r.x() ),
qgsDoubleToString( r.y() ),
r.crs().authid() );
}
else if ( value.canConvert< QgsGeometry >() )
{
const QgsGeometry g = value.value<QgsGeometry>();
if ( !g.isNull() )
{
const QString wkt = g.asWkt();
return QStringLiteral( "QgsGeometry.fromWkt('%1')" ).arg( wkt );
}
}

return QgsProcessingParameterDefinition::valueAsPythonString( value, context );
}
@@ -508,7 +508,8 @@ class CORE_EXPORT QgsProcessingParameterTypePoint : public QgsProcessingParamete
return QStringList() << QObject::tr( "str: as an 'x,y' string, e.g. '1.5,10.1'" )
<< QStringLiteral( "QgsPointXY" )
<< QStringLiteral( "QgsProperty" )
<< QStringLiteral( "QgsReferencedPointXY" );
<< QStringLiteral( "QgsReferencedPointXY" )
<< QStringLiteral( "QgsGeometry: centroid of geometry is used" );
}

QStringList acceptedStringValues() const override
@@ -2373,7 +2373,7 @@ QList<int> QgsProcessingPointWidgetWrapper::compatibleDataTypes() const

QString QgsProcessingPointWidgetWrapper::modelerExpressionFormatString() const
{
return tr( "string of the format 'x,y'" );
return tr( "string of the format 'x,y' or a geometry value (centroid is used)" );
}

QString QgsProcessingPointWidgetWrapper::parameterType() const
@@ -2774,6 +2774,8 @@ void TestQgsProcessing::parameterPoint()
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( def->checkValueIsAcceptable( QgsPointXY( 1, 2 ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsGeometry::fromPointXY( QgsPointXY( 1, 2 ) ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsGeometry::fromWkt( QStringLiteral( "LineString(10 10, 20 20)" ) ) ) );

// string representing a point
QVariantMap params;
@@ -2847,15 +2849,32 @@ void TestQgsProcessing::parameterPoint()
QCOMPARE( QgsProcessingParameters::parameterAsPointCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );

// with target CRS
params.insert( "non_optional", QgsReferencedPointXY( QgsPointXY( 1.1, 2.2 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) );
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
QGSCOMPARENEAR( point.x(), 122451, 100 );
QGSCOMPARENEAR( point.y(), 244963, 100 );

// QgsGeometry
params.insert( "non_optional", QgsGeometry::fromPointXY( QgsPointXY( 13.1, 14.2 ) ) );
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
QGSCOMPARENEAR( point.x(), 13.1, 0.001 );
QGSCOMPARENEAR( point.y(), 14.2, 0.001 );
// non point geometry should use centroid
params.insert( "non_optional", QgsGeometry::fromWkt( QStringLiteral( "LineString( 10 10, 20 10)" ) ) );
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
QGSCOMPARENEAR( point.x(), 15.0, 0.001 );
QGSCOMPARENEAR( point.y(), 10.0, 0.001 );
// with target CRS - should make no difference, because source CRS is unknown
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
QGSCOMPARENEAR( point.x(), 15.0, 0.001 );
QGSCOMPARENEAR( point.y(), 10.0, 0.001 );

QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
QCOMPARE( def->valueAsPythonString( "1,2", context ), QStringLiteral( "'1,2'" ) );
QCOMPARE( def->valueAsPythonString( "1,2 [EPSG:4326]", context ), QStringLiteral( "'1,2 [EPSG:4326]'" ) );
QCOMPARE( def->valueAsPythonString( QgsPointXY( 11, 12 ), context ), QStringLiteral( "'11,12'" ) );
QCOMPARE( def->valueAsPythonString( QgsReferencedPointXY( QgsPointXY( 11, 12 ), QgsCoordinateReferenceSystem( "epsg:4326" ) ), context ), QStringLiteral( "'11,12 [EPSG:4326]'" ) );
QCOMPARE( def->valueAsPythonString( QgsGeometry::fromWkt( QStringLiteral( "LineString( 10 10, 20 20)" ) ), context ), QStringLiteral( "QgsGeometry.fromWkt('LineString (10 10, 20 20)')" ) );

QString pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterPoint('non_optional', '', defaultValue='1,2')" ) );

0 comments on commit acdb368

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