Skip to content
Permalink
Browse files

[FEATURE] Add get and transform geometry in Expression

In version 2.6, new keywords has been added to Expression :
* $currentfeature - returns the current feature
* $atlasfeature - returns the atlas feature
* getFeature - gets a matching feature from a layer

But I think, Expression lacks a few keywords :
* geometry - returns the feature's geometry
* transform -  returns the transformed geometry

These new keywords can be used with getFeature for some geometry tests like
 intersects, crosses, contains, etc

Tests has been added to geometry and transform in Expression
  • Loading branch information
rldhont committed Jan 2, 2015
1 parent 2b7e49b commit a0ffad2532f8b129a29a9c8b66703b17c597ddbb
@@ -0,0 +1,12 @@
<h3>getGeometry function</h3>
Returns the feature's geometry

<h4>Syntax</h4>
<pre>geometry( f )</pre>

<h4>Arguments</h4>
f &rarr; QgsFeature

<h4>Example</h4>
<pre> geomToWKT( geometry( getFeature( layer, attributeField, value ) ) ) &rarr; POINT(6 50)</pre>
<pre> intersects( $geometry, geometry( getFeature( layer, attributeField, value ) ) ) &rarr; 1</pre>
@@ -0,0 +1,15 @@
<h3>transformGeometry function</h3>
Returns the geometry transforms from the source CRS to the dest CRS.

<h4>Syntax</h4>
<pre>transform( geom, sAuthId, dAuthId )</pre>

<h4>Arguments</h4>
geom &rarr; QgsGeometry

sCrsId &rarr; the Source Auth CRS Id

dCrsId &rarr; the Dest Auth CRS Id

<h4>Example</h4>
<pre> geomToWKT( transform( $geometry, 'EPSG:2154', 'EPSG:4326' ) ) &rarr; POINT(0 51)</pre>
@@ -1298,8 +1298,14 @@ static QVariant fcnCombine( const QVariantList& values, const QgsFeature*, QgsEx
}
static QVariant fcnGeomToWKT( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
{
if ( values.length() < 1 || values.length() > 2 )
return QVariant();

QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
QString wkt = fGeom.exportToWkt();
int prec = 8;
if ( values.length() == 2 )
prec = getIntValue( values.at( 1 ), parent );
QString wkt = fGeom.exportToWkt( prec );
return QVariant( wkt );
}

@@ -1546,6 +1552,34 @@ static QVariant fcnSpecialColumn( const QVariantList& values, const QgsFeature*
return QgsExpression::specialColumn( varName );
}

static QVariant fcnGetGeometry( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
{
QgsFeature feat = getFeature( values.at( 0 ), parent );
QgsGeometry* geom = feat.geometry();
if ( geom )
return QVariant::fromValue( *geom );
return QVariant();
}

static QVariant fcnTransformGeometry( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
{
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
QString sAuthId = getStringValue( values.at( 1 ), parent );
QString dAuthId = getStringValue( values.at( 2 ), parent );

QgsCoordinateReferenceSystem s;
if ( ! s.createFromOgcWmsCrs( sAuthId ) )
return QVariant::fromValue( fGeom );
QgsCoordinateReferenceSystem d;
if ( ! d.createFromOgcWmsCrs( dAuthId ) )
return QVariant::fromValue( fGeom );

QgsCoordinateTransform t( s, d );
if ( fGeom.transform( t ) == 0 )
return QVariant::fromValue( fGeom );
return QVariant();
}

static QVariant fcnGetFeature( const QVariantList& values, const QgsFeature *, QgsExpression* parent )
{
//arguments: 1. layer id / name, 2. key attribute, 3. eq value
@@ -1765,7 +1799,9 @@ const QList<QgsExpression::Function*> &QgsExpression::Functions()
<< new StaticFunction( "symDifference", 2, fcnSymDifference, "Geometry" )
<< new StaticFunction( "combine", 2, fcnCombine, "Geometry" )
<< new StaticFunction( "union", 2, fcnCombine, "Geometry" )
<< new StaticFunction( "geomToWKT", 1, fcnGeomToWKT, "Geometry" )
<< new StaticFunction( "geomToWKT", -1, fcnGeomToWKT, "Geometry" )
<< new StaticFunction( "geometry", 1, fcnGetGeometry, "Geometry" )
<< new StaticFunction( "transform", 3, fcnTransformGeometry, "Geometry" )
<< new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" )
<< new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
<< new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
@@ -745,6 +745,37 @@ class TestQgsExpression: public QObject
QVariant vYMax = exp9.evaluate( &fPolygon );
QCOMPARE( vYMax.toDouble(), 6.0 );
}

void eval_geometry_wkt()
{
QgsPolyline polyline, polygon_ring;
polyline << QgsPoint( 0, 0 ) << QgsPoint( 10, 0 );
polygon_ring << QgsPoint( 2, 1 ) << QgsPoint( 10, 1 ) << QgsPoint( 10, 6 ) << QgsPoint( 2, 6 ) << QgsPoint( 2, 1 );

QgsPolygon polygon;
polygon << polygon_ring;

QgsFeature fPoint, fPolygon, fPolyline;
fPoint.setGeometry( QgsGeometry::fromPoint( QgsPoint( -1.23456789, 9.87654321 ) ) );
fPolyline.setGeometry( QgsGeometry::fromPolyline( polyline ) );
fPolygon.setGeometry( QgsGeometry::fromPolygon( polygon ) );

QgsExpression exp1( "geomToWKT($geometry)" );
QVariant vWktLine = exp1.evaluate( &fPolyline );
QCOMPARE( vWktLine.toString(), QString( "LINESTRING(0 0, 10 0)" ) );

QgsExpression exp2( "geomToWKT($geometry)" );
QVariant vWktPolygon = exp2.evaluate( &fPolygon );
QCOMPARE( vWktPolygon.toString(), QString( "POLYGON((2 1,10 1,10 6,2 6,2 1))" ) );

QgsExpression exp3( "geomToWKT($geometry)" );
QVariant vWktPoint = exp3.evaluate( &fPoint );
QCOMPARE( vWktPoint.toString(), QString( "POINT(-1.23456789 9.87654321)" ) );

QgsExpression exp4( "geomToWKT($geometry, 3)" );
QVariant vWktPointSimplify = exp4.evaluate( &fPoint );
QCOMPARE( vWktPointSimplify.toString(), QString( "POINT(-1.235 9.877)" ) );
}

void eval_geometry_constructor_data()
{
@@ -803,6 +834,64 @@ class TestQgsExpression: public QObject
QgsGeometry outGeom = out.value<QgsGeometry>();
QCOMPARE( geom->equals( &outGeom ), true );
}

void eval_geometry_access_transform_data()
{
QTest::addColumn<QString>( "string" );
QTest::addColumn<void*>( "geomptr" );
QTest::addColumn<bool>( "evalError" );

QgsPoint point( 123, 456 );
QgsPolyline line;
line << QgsPoint( 1, 1 ) << QgsPoint( 4, 2 ) << QgsPoint( 3, 1 );

QgsPolyline polyline, polygon_ring;
polyline << QgsPoint( 0, 0 ) << QgsPoint( 10, 0 );
polygon_ring << QgsPoint( 1, 1 ) << QgsPoint( 6, 1 ) << QgsPoint( 6, 6 ) << QgsPoint( 1, 6 ) << QgsPoint( 1, 1 );
QgsPolygon polygon;
polygon << polygon_ring;

QTest::newRow( "geometry Point" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPoint( point ) << false;
QTest::newRow( "geometry Line" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPolyline( line ) << false;
QTest::newRow( "geometry Polyline" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPolyline( polyline ) << false;
QTest::newRow( "geometry Polygon" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPolygon( polygon ) << false;

QgsCoordinateReferenceSystem s;
s.createFromOgcWmsCrs( "EPSG:4326" );
QgsCoordinateReferenceSystem d;
d.createFromOgcWmsCrs( "EPSG:3857" );
QgsCoordinateTransform t( s, d );

QgsGeometry* tLine = QgsGeometry::fromPolyline( line );
tLine->transform( t );
QgsGeometry* tPolygon = QgsGeometry::fromPolygon( polygon );
tPolygon->transform( t );

QTest::newRow( "transform Line" ) << "transform( geomFromWKT('" + QgsGeometry::fromPolyline( line )->exportToWkt() + "'), 'EPSG:4326', 'EPSG:3857' )" << ( void* ) tLine << false;
QTest::newRow( "transform Polygon" ) << "transform( geomFromWKT('" + QgsGeometry::fromPolygon( polygon )->exportToWkt() + "'), 'EPSG:4326', 'EPSG:3857' )" << ( void* ) tPolygon << false;
}

void eval_geometry_access_transform()
{
QFETCH( QString, string );
QFETCH( void*, geomptr );
QFETCH( bool, evalError );

QgsGeometry* geom = ( QgsGeometry* ) geomptr;

QgsFeature f;
f.setGeometry( geom );

QgsExpression exp( string );
QCOMPARE( exp.hasParserError(), false );
QCOMPARE( exp.needsGeometry(), false );
QVariant out = exp.evaluate( &f );
QCOMPARE( exp.hasEvalError(), evalError );

QCOMPARE( out.canConvert<QgsGeometry>(), true );
QgsGeometry outGeom = out.value<QgsGeometry>();
QCOMPARE( geom->equals( &outGeom ), true );
}

void eval_spatial_operator_data()
{

0 comments on commit a0ffad2

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