Skip to content

Commit a0ffad2

Browse files
committedJan 2, 2015
[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
1 parent 2b7e49b commit a0ffad2

File tree

4 files changed

+154
-2
lines changed

4 files changed

+154
-2
lines changed
 

‎resources/function_help/geometry

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<h3>getGeometry function</h3>
2+
Returns the feature's geometry
3+
4+
<h4>Syntax</h4>
5+
<pre>geometry( f )</pre>
6+
7+
<h4>Arguments</h4>
8+
f &rarr; QgsFeature
9+
10+
<h4>Example</h4>
11+
<pre> geomToWKT( geometry( getFeature( layer, attributeField, value ) ) ) &rarr; POINT(6 50)</pre>
12+
<pre> intersects( $geometry, geometry( getFeature( layer, attributeField, value ) ) ) &rarr; 1</pre>

‎resources/function_help/transform

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<h3>transformGeometry function</h3>
2+
Returns the geometry transforms from the source CRS to the dest CRS.
3+
4+
<h4>Syntax</h4>
5+
<pre>transform( geom, sAuthId, dAuthId )</pre>
6+
7+
<h4>Arguments</h4>
8+
geom &rarr; QgsGeometry
9+
10+
sCrsId &rarr; the Source Auth CRS Id
11+
12+
dCrsId &rarr; the Dest Auth CRS Id
13+
14+
<h4>Example</h4>
15+
<pre> geomToWKT( transform( $geometry, 'EPSG:2154', 'EPSG:4326' ) ) &rarr; POINT(0 51)</pre>

‎src/core/qgsexpression.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,8 +1298,14 @@ static QVariant fcnCombine( const QVariantList& values, const QgsFeature*, QgsEx
12981298
}
12991299
static QVariant fcnGeomToWKT( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
13001300
{
1301+
if ( values.length() < 1 || values.length() > 2 )
1302+
return QVariant();
1303+
13011304
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1302-
QString wkt = fGeom.exportToWkt();
1305+
int prec = 8;
1306+
if ( values.length() == 2 )
1307+
prec = getIntValue( values.at( 1 ), parent );
1308+
QString wkt = fGeom.exportToWkt( prec );
13031309
return QVariant( wkt );
13041310
}
13051311

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

1555+
static QVariant fcnGetGeometry( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1556+
{
1557+
QgsFeature feat = getFeature( values.at( 0 ), parent );
1558+
QgsGeometry* geom = feat.geometry();
1559+
if ( geom )
1560+
return QVariant::fromValue( *geom );
1561+
return QVariant();
1562+
}
1563+
1564+
static QVariant fcnTransformGeometry( const QVariantList& values, const QgsFeature*, QgsExpression* parent )
1565+
{
1566+
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1567+
QString sAuthId = getStringValue( values.at( 1 ), parent );
1568+
QString dAuthId = getStringValue( values.at( 2 ), parent );
1569+
1570+
QgsCoordinateReferenceSystem s;
1571+
if ( ! s.createFromOgcWmsCrs( sAuthId ) )
1572+
return QVariant::fromValue( fGeom );
1573+
QgsCoordinateReferenceSystem d;
1574+
if ( ! d.createFromOgcWmsCrs( dAuthId ) )
1575+
return QVariant::fromValue( fGeom );
1576+
1577+
QgsCoordinateTransform t( s, d );
1578+
if ( fGeom.transform( t ) == 0 )
1579+
return QVariant::fromValue( fGeom );
1580+
return QVariant();
1581+
}
1582+
15491583
static QVariant fcnGetFeature( const QVariantList& values, const QgsFeature *, QgsExpression* parent )
15501584
{
15511585
//arguments: 1. layer id / name, 2. key attribute, 3. eq value
@@ -1765,7 +1799,9 @@ const QList<QgsExpression::Function*> &QgsExpression::Functions()
17651799
<< new StaticFunction( "symDifference", 2, fcnSymDifference, "Geometry" )
17661800
<< new StaticFunction( "combine", 2, fcnCombine, "Geometry" )
17671801
<< new StaticFunction( "union", 2, fcnCombine, "Geometry" )
1768-
<< new StaticFunction( "geomToWKT", 1, fcnGeomToWKT, "Geometry" )
1802+
<< new StaticFunction( "geomToWKT", -1, fcnGeomToWKT, "Geometry" )
1803+
<< new StaticFunction( "geometry", 1, fcnGetGeometry, "Geometry" )
1804+
<< new StaticFunction( "transform", 3, fcnTransformGeometry, "Geometry" )
17691805
<< new StaticFunction( "$rownum", 0, fcnRowNumber, "Record" )
17701806
<< new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
17711807
<< new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )

‎tests/src/core/testqgsexpression.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,37 @@ class TestQgsExpression: public QObject
745745
QVariant vYMax = exp9.evaluate( &fPolygon );
746746
QCOMPARE( vYMax.toDouble(), 6.0 );
747747
}
748+
749+
void eval_geometry_wkt()
750+
{
751+
QgsPolyline polyline, polygon_ring;
752+
polyline << QgsPoint( 0, 0 ) << QgsPoint( 10, 0 );
753+
polygon_ring << QgsPoint( 2, 1 ) << QgsPoint( 10, 1 ) << QgsPoint( 10, 6 ) << QgsPoint( 2, 6 ) << QgsPoint( 2, 1 );
754+
755+
QgsPolygon polygon;
756+
polygon << polygon_ring;
757+
758+
QgsFeature fPoint, fPolygon, fPolyline;
759+
fPoint.setGeometry( QgsGeometry::fromPoint( QgsPoint( -1.23456789, 9.87654321 ) ) );
760+
fPolyline.setGeometry( QgsGeometry::fromPolyline( polyline ) );
761+
fPolygon.setGeometry( QgsGeometry::fromPolygon( polygon ) );
762+
763+
QgsExpression exp1( "geomToWKT($geometry)" );
764+
QVariant vWktLine = exp1.evaluate( &fPolyline );
765+
QCOMPARE( vWktLine.toString(), QString( "LINESTRING(0 0, 10 0)" ) );
766+
767+
QgsExpression exp2( "geomToWKT($geometry)" );
768+
QVariant vWktPolygon = exp2.evaluate( &fPolygon );
769+
QCOMPARE( vWktPolygon.toString(), QString( "POLYGON((2 1,10 1,10 6,2 6,2 1))" ) );
770+
771+
QgsExpression exp3( "geomToWKT($geometry)" );
772+
QVariant vWktPoint = exp3.evaluate( &fPoint );
773+
QCOMPARE( vWktPoint.toString(), QString( "POINT(-1.23456789 9.87654321)" ) );
774+
775+
QgsExpression exp4( "geomToWKT($geometry, 3)" );
776+
QVariant vWktPointSimplify = exp4.evaluate( &fPoint );
777+
QCOMPARE( vWktPointSimplify.toString(), QString( "POINT(-1.235 9.877)" ) );
778+
}
748779

749780
void eval_geometry_constructor_data()
750781
{
@@ -803,6 +834,64 @@ class TestQgsExpression: public QObject
803834
QgsGeometry outGeom = out.value<QgsGeometry>();
804835
QCOMPARE( geom->equals( &outGeom ), true );
805836
}
837+
838+
void eval_geometry_access_transform_data()
839+
{
840+
QTest::addColumn<QString>( "string" );
841+
QTest::addColumn<void*>( "geomptr" );
842+
QTest::addColumn<bool>( "evalError" );
843+
844+
QgsPoint point( 123, 456 );
845+
QgsPolyline line;
846+
line << QgsPoint( 1, 1 ) << QgsPoint( 4, 2 ) << QgsPoint( 3, 1 );
847+
848+
QgsPolyline polyline, polygon_ring;
849+
polyline << QgsPoint( 0, 0 ) << QgsPoint( 10, 0 );
850+
polygon_ring << QgsPoint( 1, 1 ) << QgsPoint( 6, 1 ) << QgsPoint( 6, 6 ) << QgsPoint( 1, 6 ) << QgsPoint( 1, 1 );
851+
QgsPolygon polygon;
852+
polygon << polygon_ring;
853+
854+
QTest::newRow( "geometry Point" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPoint( point ) << false;
855+
QTest::newRow( "geometry Line" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPolyline( line ) << false;
856+
QTest::newRow( "geometry Polyline" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPolyline( polyline ) << false;
857+
QTest::newRow( "geometry Polygon" ) << "geometry( $currentfeature )" << ( void* ) QgsGeometry::fromPolygon( polygon ) << false;
858+
859+
QgsCoordinateReferenceSystem s;
860+
s.createFromOgcWmsCrs( "EPSG:4326" );
861+
QgsCoordinateReferenceSystem d;
862+
d.createFromOgcWmsCrs( "EPSG:3857" );
863+
QgsCoordinateTransform t( s, d );
864+
865+
QgsGeometry* tLine = QgsGeometry::fromPolyline( line );
866+
tLine->transform( t );
867+
QgsGeometry* tPolygon = QgsGeometry::fromPolygon( polygon );
868+
tPolygon->transform( t );
869+
870+
QTest::newRow( "transform Line" ) << "transform( geomFromWKT('" + QgsGeometry::fromPolyline( line )->exportToWkt() + "'), 'EPSG:4326', 'EPSG:3857' )" << ( void* ) tLine << false;
871+
QTest::newRow( "transform Polygon" ) << "transform( geomFromWKT('" + QgsGeometry::fromPolygon( polygon )->exportToWkt() + "'), 'EPSG:4326', 'EPSG:3857' )" << ( void* ) tPolygon << false;
872+
}
873+
874+
void eval_geometry_access_transform()
875+
{
876+
QFETCH( QString, string );
877+
QFETCH( void*, geomptr );
878+
QFETCH( bool, evalError );
879+
880+
QgsGeometry* geom = ( QgsGeometry* ) geomptr;
881+
882+
QgsFeature f;
883+
f.setGeometry( geom );
884+
885+
QgsExpression exp( string );
886+
QCOMPARE( exp.hasParserError(), false );
887+
QCOMPARE( exp.needsGeometry(), false );
888+
QVariant out = exp.evaluate( &f );
889+
QCOMPARE( exp.hasEvalError(), evalError );
890+
891+
QCOMPARE( out.canConvert<QgsGeometry>(), true );
892+
QgsGeometry outGeom = out.value<QgsGeometry>();
893+
QCOMPARE( geom->equals( &outGeom ), true );
894+
}
806895

807896
void eval_spatial_operator_data()
808897
{

0 commit comments

Comments
 (0)
Please sign in to comment.