Skip to content

Commit

Permalink
add function $z for expression (#44776)
Browse files Browse the repository at this point in the history
[feature] [expression] add function $z for expression
  • Loading branch information
vcloarec committed Sep 1, 2021
1 parent 553bb27 commit c2e607c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 3 deletions.
8 changes: 8 additions & 0 deletions resources/function_help/json/$z
@@ -0,0 +1,8 @@
{
"name": "$z",
"type": "function",
"groups": ["GeometryGroup"],
"description": "Returns the z value of the current point feature if it is 3D. If the feature is a multipoint feature, then the z value of the first point will be returned.",
"examples": [ { "expression":"$z", "returns":"123"}
]
}
38 changes: 38 additions & 0 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -2426,6 +2426,40 @@ static QVariant fcnY( const QVariantList &, const QgsExpressionContext *context,
}
}

static QVariant fcnZ( const QVariantList &, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * )
{
FEAT_FROM_CONTEXT( context, f )
ENSURE_GEOM_TYPE( f, g, QgsWkbTypes::PointGeometry )

if ( g.isEmpty() )
return QVariant();

const QgsAbstractGeometry *abGeom = g.constGet();

if ( g.isEmpty() || !abGeom->is3D() )
return QVariant();

if ( g.type() == QgsWkbTypes::PointGeometry && !g.isMultipart() )
{
const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( g.constGet() );
if ( point )
return point->z();
}
else if ( g.type() == QgsWkbTypes::PointGeometry && g.isMultipart() )
{
if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( g.constGet() ) )
{
if ( collection->numGeometries() > 0 )
{
if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( collection->geometryN( 0 ) ) )
return point->z();
}
}
}

return QVariant();
}

static QVariant fcnGeomIsValid( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
Expand Down Expand Up @@ -6794,6 +6828,10 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
yFunc->setIsStatic( false );
functions << yFunc;

QgsStaticExpressionFunction *zFunc = new QgsStaticExpressionFunction( QStringLiteral( "$z" ), 0, fcnZ, QStringLiteral( "GeometryGroup" ), QString(), true );
zFunc->setIsStatic( false );
functions << zFunc;

QMap< QString, QgsExpressionFunction::FcnEval > geometry_overlay_definitions
{
{ QStringLiteral( "overlay_intersects" ), fcnGeomOverlayIntersects },
Expand Down
7 changes: 4 additions & 3 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -2826,12 +2826,13 @@ class TestQgsExpression: public QObject
QTest::addColumn<bool>( "evalError" );
QTest::addColumn<QVariant>( "result" );

QgsPointXY point( 123, 456 );
QgsPoint point( 123, 456, 789 );
QgsPolylineXY line;
line << QgsPointXY( 1, 1 ) << QgsPointXY( 4, 2 ) << QgsPointXY( 3, 1 );

QTest::newRow( "geom x" ) << "$x" << QgsGeometry::fromPointXY( point ) << false << QVariant( 123. );
QTest::newRow( "geom y" ) << "$y" << QgsGeometry::fromPointXY( point ) << false << QVariant( 456. );
QTest::newRow( "geom x" ) << "$x" << QgsGeometry( std::make_unique<QgsPoint>( point ) ) << false << QVariant( 123. );
QTest::newRow( "geom y" ) << "$y" << QgsGeometry( std::make_unique<QgsPoint>( point ) ) << false << QVariant( 456. );
QTest::newRow( "geom z" ) << "$z" << QgsGeometry( std::make_unique<QgsPoint>( point ) ) << false << QVariant( 789. );
QTest::newRow( "geom xat" ) << "xat(-1)" << QgsGeometry::fromPolylineXY( line ) << false << QVariant( 3. );
QTest::newRow( "geom yat" ) << "yat(1)" << QgsGeometry::fromPolylineXY( line ) << false << QVariant( 2. );
QTest::newRow( "null geometry" ) << "$geometry" << QgsGeometry() << false << QVariant();
Expand Down

0 comments on commit c2e607c

Please sign in to comment.