Skip to content

Commit b97ef93

Browse files
committedMar 13, 2019
[expression] Negative index support to point_n(), angle_at_vertex(), distance_to_vertex() functions
1 parent ce91247 commit b97ef93

File tree

5 files changed

+31
-5
lines changed

5 files changed

+31
-5
lines changed
 

‎resources/function_help/json/angle_at_vertex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"type": "function",
44
"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.",
55
"arguments": [ {"arg":"geometry","description":"a linestring geometry"},
6-
{"arg":"vertex","description":"vertex index, starting from 0"}],
6+
{"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"}],
77
"examples": [ { "expression":"angle_at_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)", "returns":"45.0"}]
88
}

‎resources/function_help/json/distance_to_vertex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"type": "function",
44
"description": "Returns the distance along the geometry to a specified vertex.",
55
"arguments": [ {"arg":"geometry","description":"a linestring geometry"},
6-
{"arg":"vertex","description":"vertex index, starting from 0"}],
6+
{"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"}],
77
"examples": [ { "expression":"distance_to_vertex(geometry:=geom_from_wkt('LineString(0 0, 10 0, 10 10)'),vertex:=1)", "returns":"10.0"}]
88
}

‎resources/function_help/json/point_n

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"type": "function",
44
"description": "Returns a specific node from a geometry.",
55
"arguments": [ {"arg":"geometry","description":"geometry object"},
6-
{"arg":"index","description":"index of node to return, where 1 is the first node"} ],
6+
{"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"} ],
77
"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)'"}]
88
}

‎src/core/expression/qgsexpressionfunction.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,8 +1979,19 @@ static QVariant fcnPointN( const QVariantList &values, const QgsExpressionContex
19791979
if ( geom.isNull() )
19801980
return QVariant();
19811981

1982-
//idx is 1 based
1983-
qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) - 1;
1982+
qlonglong idx = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
1983+
1984+
if ( idx < 0 )
1985+
{
1986+
//negative idx
1987+
int count = geom.constGet()->nCoordinates();
1988+
idx = count + idx;
1989+
}
1990+
else
1991+
{
1992+
//positive idx is 1 based
1993+
idx -= 1;
1994+
}
19841995

19851996
QgsVertexId vId;
19861997
if ( idx < 0 || !geom.vertexIdFromVertexNr( idx, vId ) )
@@ -3586,6 +3597,12 @@ static QVariant fcnAngleAtVertex( const QVariantList &values, const QgsExpressio
35863597
{
35873598
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
35883599
qlonglong vertex = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3600+
if ( vertex < 0 )
3601+
{
3602+
//negative idx
3603+
int count = geom.constGet()->nCoordinates();
3604+
vertex = count + vertex;
3605+
}
35893606

35903607
return geom.angleAtVertex( vertex ) * 180.0 / M_PI;
35913608
}
@@ -3594,6 +3611,12 @@ static QVariant fcnDistanceToVertex( const QVariantList &values, const QgsExpres
35943611
{
35953612
QgsGeometry geom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
35963613
qlonglong vertex = QgsExpressionUtils::getIntValue( values.at( 1 ), parent );
3614+
if ( vertex < 0 )
3615+
{
3616+
//negative idx
3617+
int count = geom.constGet()->nCoordinates();
3618+
vertex = count + vertex;
3619+
}
35973620

35983621
return geom.distanceToVertex( vertex );
35993622
}

‎tests/src/core/testqgsexpression.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ class TestQgsExpression: public QObject
816816
QTest::newRow( "point_n bad index" ) << "geom_to_wkt(point_n(geom_from_wkt('POINT(0 0)'),0))" << true << QVariant();
817817
QTest::newRow( "point_n bad index" ) << "geom_to_wkt(point_n(geom_from_wkt('POINT(0 0)'),2))" << true << QVariant();
818818
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)" );
819+
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)" );
819820
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)" );
820821
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)" );
821822
QTest::newRow( "interior_ring_n not geom" ) << "interior_ring_n('g', 1)" << true << QVariant();
@@ -1040,10 +1041,12 @@ class TestQgsExpression: public QObject
10401041
QTest::newRow( "angle_at_vertex null" ) << "angle_at_vertex(NULL, 0)" << false << QVariant();
10411042
QTest::newRow( "angle_at_vertex point" ) << "angle_at_vertex(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant( 0.0 );
10421043
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 );
1044+
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 );
10431045
QTest::newRow( "distance_to_vertex not geom" ) << "distance_to_vertex('g', 5)" << true << QVariant();
10441046
QTest::newRow( "distance_to_vertex null" ) << "distance_to_vertex(NULL, 0)" << false << QVariant();
10451047
QTest::newRow( "distance_to_vertex point" ) << "distance_to_vertex(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant( 0.0 );
10461048
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 );
1049+
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 );
10471050
QTest::newRow( "line_substring not geom" ) << "line_substring('g', 5, 6)" << true << QVariant();
10481051
QTest::newRow( "line_substring null" ) << "line_substring(NULL, 5, 6)" << false << QVariant();
10491052
QTest::newRow( "line_substring point" ) << "line_substring(geom_from_wkt('POINT(1 2)'),5,6)" << true << QVariant();

0 commit comments

Comments
 (0)
Please sign in to comment.