Skip to content

Commit

Permalink
[FEATURE][expressions] If a feature is passed to a function
Browse files Browse the repository at this point in the history
expecting geometry inputs, then use that feature's geometry
instead of throwing an error

eg

buffer(@atlas_feature,100)

or

buffer(get_feature('my_layer','id=54'))
  • Loading branch information
nyalldawson committed May 29, 2016
1 parent 497d6ef commit 7cab60b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
11 changes: 10 additions & 1 deletion src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,15 @@ static QgsGeometry getGeometry( const QVariant& value, QgsExpression* parent )
{
if ( value.canConvert<QgsGeometry>() )
return value.value<QgsGeometry>();
else if ( value.canConvert<QgsFeature>() )
{
//try to grab geometry from feature
QgsFeature f = value.value<QgsFeature>();
if ( f.constGeometry() )
{
return *f.constGeometry();
}
}

parent->setEvalErrorString( "Cannot convert to QgsGeometry" );
return QgsGeometry();
Expand Down Expand Up @@ -1152,7 +1161,7 @@ static QVariant fcnWordwrap( const QVariantList& values, const QgsExpressionCont
static QVariant fcnLength( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
// two variants, one for geometry, one for string
if ( values.at( 0 ).canConvert<QgsGeometry>() )
if ( values.at( 0 ).canConvert<QgsGeometry>() || values.at( 0 ).canConvert<QgsFeature>() )
{
//geometry variant
QgsGeometry geom = getGeometry( values.at( 0 ), parent );
Expand Down
25 changes: 25 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1548,6 +1548,31 @@ class TestQgsExpression: public QObject
QCOMPARE( out.toDouble(), result );
}

void implicit_feature_to_geometry()
{
// test implicit feature to geometry cast
QgsPolyline polyline;
polyline << QgsPoint( 0, 0 ) << QgsPoint( 10, 0 );
QgsFeature feat;
feat.setGeometry( QgsGeometry::fromPolyline( polyline ) );

QgsExpressionContext context;
context.setFeature( feat );
QgsExpression exp1( "length($currentfeature)" );
QVariant result = exp1.evaluate( &context );
QCOMPARE( result.toDouble(), 10. );

QgsExpression exp2( "x(end_point($currentfeature))" );
result = exp2.evaluate( &context );
QCOMPARE( result.toDouble(), 10. );

// feature without geometry
QgsFeature feat2;
context.setFeature( feat2 );
result = exp2.evaluate( &context );
QVERIFY( !result.isValid() );
}

void eval_geometry_calc()
{
QgsPolyline polyline, polygon_ring;
Expand Down

0 comments on commit 7cab60b

Please sign in to comment.