Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[expression] Negative index support to point_n(), angle_at_vertex(), …
…distance_to_vertex() functions
  • Loading branch information
nirvn committed Mar 13, 2019
1 parent ce91247 commit b97ef93
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 5 deletions.
2 changes: 1 addition & 1 deletion resources/function_help/json/angle_at_vertex
Expand Up @@ -3,6 +3,6 @@
"type": "function",
"description": "Returns the bisector angle (average angle) to the geometry for a specified vertex on a linestring geometry. Angles are in degrees clockwise from north.",
"arguments": [ {"arg":"geometry","description":"a linestring geometry"},
{"arg":"vertex","description":"vertex index, starting from 0"}],
{"arg":"vertex","description":"vertex index, starting from 0; if the value is negative, the selected vertex index will be its total count minus the absolute value"}],
"examples": [ { "expression":"angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)", "returns":"45.0"}]
}
2 changes: 1 addition & 1 deletion resources/function_help/json/distance_to_vertex
Expand Up @@ -3,6 +3,6 @@
"type": "function",
"description": "Returns the distance along the geometry to a specified vertex.",
"arguments": [ {"arg":"geometry","description":"a linestring geometry"},
{"arg":"vertex","description":"vertex index, starting from 0"}],
{"arg":"vertex","description":"vertex index, starting from 0; if the value is negative, the selected vertex index will be its total count minus the absolute value"}],
"examples": [ { "expression":"distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)", "returns":"10.0"}]
}
2 changes: 1 addition & 1 deletion resources/function_help/json/point_n
Expand Up @@ -3,6 +3,6 @@
"type": "function",
"description": "Returns a specific node from a geometry.",
"arguments": [ {"arg":"geometry","description":"geometry object"},
{"arg":"index","description":"index of node to return, where 1 is the first node"} ],
{"arg":"index","description":"index of node to return, where 1 is the first node; if the value is negative, the selected vertex index will be its total count minus the absolute value"} ],
"examples": [ { "expression":"geom_to_wkt(point_n(geom_from_wkt('POLYGON((0 0, 4 0, 4 2, 0 2, 0 0))'),2))", "returns":"'Point (4 0)'"}]
}
27 changes: 25 additions & 2 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -1979,8 +1979,19 @@ static QVariant fcnPointN( const QVariantList &values, const QgsExpressionContex
if ( geom.isNull() )
return QVariant();

//idx is 1 based
qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );

if ( idx < 0 )
{
//negative idx
int count = geom.constGet()->nCoordinates();
idx = count + idx;
}
else
{
//positive idx is 1 based
idx -= 1;
}

QgsVertexId vId;
if ( idx < 0 || !geom.vertexIdFromVertexNr( idx, vId ) )
Expand Down Expand Up @@ -3586,6 +3597,12 @@ static QVariant fcnAngleAtVertex( const QVariantList &values, const QgsExpressio
{
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
qlonglong vertex = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
if ( vertex < 0 )
{
//negative idx
int count = geom.constGet()->nCoordinates();
vertex = count + vertex;
}

return geom.angleAtVertex( vertex ) * 180.0 / M_PI;
}
Expand All @@ -3594,6 +3611,12 @@ static QVariant fcnDistanceToVertex( const QVariantList &values, const QgsExpres
{
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
qlonglong vertex = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
if ( vertex < 0 )
{
//negative idx
int count = geom.constGet()->nCoordinates();
vertex = count + vertex;
}

return geom.distanceToVertex( vertex );
}
Expand Down
3 changes: 3 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -816,6 +816,7 @@ class TestQgsExpression: public QObject
QTest::newRow( "point_n bad index" ) << "geom_to_wkt(point_n(geom_from_wkt('POINT(0 0)'),0))" << true << QVariant();
QTest::newRow( "point_n bad index" ) << "geom_to_wkt(point_n(geom_from_wkt('POINT(0 0)'),2))" << true << QVariant();
QTest::newRow( "point_n multipoint" ) << "geom_to_wkt(point_n(geom_from_wkt('MULTIPOINT((0 0), (1 1), (2 2))'),2))" << false << QVariant( "Point (1 1)" );
QTest::newRow( "point_n multipoint negative" ) << "geom_to_wkt(point_n(geom_from_wkt('MULTIPOINT((0 0), (1 1), (2 2))'),-1))" << false << QVariant( "Point (2 2)" );
QTest::newRow( "point_n line" ) << "geom_to_wkt(point_n(geom_from_wkt('LINESTRING(0 0, 1 1, 2 2)'),3))" << false << QVariant( "Point (2 2)" );
QTest::newRow( "point_n polygon" ) << "geom_to_wkt(point_n(geom_from_wkt('POLYGON((0 0, 4 0, 4 2, 0 2, 0 0))'),3))" << false << QVariant( "Point (4 2)" );
QTest::newRow( "interior_ring_n not geom" ) << "interior_ring_n('g', 1)" << true << QVariant();
Expand Down Expand Up @@ -1040,10 +1041,12 @@ class TestQgsExpression: public QObject
QTest::newRow( "angle_at_vertex null" ) << "angle_at_vertex(NULL, 0)" << false << QVariant();
QTest::newRow( "angle_at_vertex point" ) << "angle_at_vertex(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant( 0.0 );
QTest::newRow( "angle_at_vertex line" ) << "angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)" << false << QVariant( 45.0 );
QTest::newRow( "angle_at_vertex line negative" ) << "angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=-1)" << false << QVariant( 0.0 );
QTest::newRow( "distance_to_vertex not geom" ) << "distance_to_vertex('g', 5)" << true << QVariant();
QTest::newRow( "distance_to_vertex null" ) << "distance_to_vertex(NULL, 0)" << false << QVariant();
QTest::newRow( "distance_to_vertex point" ) << "distance_to_vertex(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant( 0.0 );
QTest::newRow( "distance_to_vertex line" ) << "distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)" << false << QVariant( 10.0 );
QTest::newRow( "distance_to_vertex line negative" ) << "distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=-1)" << false << QVariant( 20.0 );
QTest::newRow( "line_substring not geom" ) << "line_substring('g', 5, 6)" << true << QVariant();
QTest::newRow( "line_substring null" ) << "line_substring(NULL, 5, 6)" << false << QVariant();
QTest::newRow( "line_substring point" ) << "line_substring(geom_from_wkt('POINT(1 2)'),5,6)" << true << QVariant();
Expand Down

0 comments on commit b97ef93

Please sign in to comment.