Skip to content

Commit e110ba7

Browse files
committedAug 21, 2016
[FEATURE] Add linear referencing functions to expression engine
Adds new functions - line_interpolate_point: interpolates a point by a given distance along a linestring geometry - line_locate_point: returns the distance along a linestring to the closest position on the linestring to a given point
1 parent 409dfdf commit e110ba7

File tree

4 files changed

+50
-0
lines changed

4 files changed

+50
-0
lines changed
 
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "line_interpolate_point",
3+
"type": "function",
4+
"description": "Returns the point interpolated by a specified distance along a linestring geometry.",
5+
"arguments": [ {"arg":"geometry","description":"a linestring geometry"},
6+
{"arg":"distance","description":"distance along line to interpolate"}],
7+
"examples": [ { "expression":"geom_to_wkt(line_interpolate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5))", "returns":"'Point (5 0)'"}]
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "line_locate_point",
3+
"type": "function",
4+
"description": "Returns the distance along a linestring corresponding to the closest position the linestring comes to a specified point geometry.",
5+
"arguments": [ {"arg":"geometry","description":"a linestring geometry"},
6+
{"arg":"point","description":"point geometry to locate closest position on linestring to"}],
7+
"examples": [ { "expression":"line_locate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),point:=geom_from_wkt('Point(5 0)'))", "returns":"5.0"}]
8+
}

‎src/core/qgsexpression.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,6 +2543,27 @@ static QVariant fcnShortestLine( const QVariantList& values, const QgsExpression
25432543
return result;
25442544
}
25452545

2546+
static QVariant fcnLineInterpolatePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2547+
{
2548+
QgsGeometry lineGeom = getGeometry( values.at( 0 ), parent );
2549+
double distance = getDoubleValue( values.at( 1 ), parent );
2550+
2551+
QgsGeometry geom = lineGeom.interpolate( distance );
2552+
2553+
QVariant result = !geom.isEmpty() ? QVariant::fromValue( geom ) : QVariant();
2554+
return result;
2555+
}
2556+
2557+
static QVariant fcnLineLocatePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
2558+
{
2559+
QgsGeometry lineGeom = getGeometry( values.at( 0 ), parent );
2560+
QgsGeometry pointGeom = getGeometry( values.at( 1 ), parent );
2561+
2562+
double distance = lineGeom.lineLocatePoint( pointGeom );
2563+
2564+
return distance >= 0 ? distance : QVariant();
2565+
}
2566+
25462567
static QVariant fcnRound( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
25472568
{
25482569
if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
@@ -3121,6 +3142,7 @@ const QStringList& QgsExpression::BuiltinFunctions()
31213142
<< "bounds_width" << "bounds_height" << "is_closed" << "convex_hull" << "difference"
31223143
<< "distance" << "intersection" << "sym_difference" << "combine"
31233144
<< "extrude" << "azimuth" << "project" << "closest_point" << "shortest_line"
3145+
<< "line_locate_point" << "line_interpolate_point"
31243146
<< "union" << "geom_to_wkt" << "geomToWKT" << "geometry"
31253147
<< "transform" << "get_feature" << "getFeature"
31263148
<< "levenshtein" << "longest_common_substring" << "hamming_distance"
@@ -3345,6 +3367,10 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
33453367
<< new StaticFunction( "order_parts", 3, fcnOrderParts, "GeometryGroup", QString() )
33463368
<< new StaticFunction( "closest_point", 2, fcnClosestPoint, "GeometryGroup" )
33473369
<< new StaticFunction( "shortest_line", 2, fcnShortestLine, "GeometryGroup" )
3370+
<< new StaticFunction( "line_interpolate_point", ParameterList() << Parameter( "geometry" )
3371+
<< Parameter( "distance" ), fcnLineInterpolatePoint, "GeometryGroup" )
3372+
<< new StaticFunction( "line_locate_point", ParameterList() << Parameter( "geometry" )
3373+
<< Parameter( "point" ), fcnLineLocatePoint, "GeometryGroup" )
33483374
<< new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
33493375
<< new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
33503376
<< new StaticFunction( "uuid", 0, fcnUuid, "Record", QString(), false, QStringList(), false, QStringList() << "$uuid" )

‎tests/src/core/testqgsexpression.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,14 @@ class TestQgsExpression: public QObject
772772
QTest::newRow( "shortest_line geom" ) << "geom_to_wkt(shortest_line( geom_from_wkt('LineString( 1 1, 5 1, 5 5 )'),geom_from_wkt('Point( 6 3 )')))" << false << QVariant( "LineString (5 3, 6 3)" );
773773
QTest::newRow( "shortest_line not geom" ) << "shortest_line('g','a')" << true << QVariant();
774774
QTest::newRow( "shortest_line null" ) << "shortest_line(NULL,NULL)" << false << QVariant();
775+
QTest::newRow( "line_interpolate_point not geom" ) << "line_interpolate_point('g', 5)" << true << QVariant();
776+
QTest::newRow( "line_interpolate_point null" ) << "line_interpolate_point(NULL, 5)" << false << QVariant();
777+
QTest::newRow( "line_interpolate_point point" ) << "line_interpolate_point(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant();
778+
QTest::newRow( "line_interpolate_point line" ) << "geom_to_wkt(line_interpolate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),distance:=5))" << false << QVariant( "Point (5 0)" );
779+
QTest::newRow( "line_locate_point not geom" ) << "line_locate_point('g', geom_from_wkt('Point 5 0'))" << false << QVariant();
780+
QTest::newRow( "line_locate_point null" ) << "line_locate_point(NULL, geom_from_wkt('Point 5 0'))" << false << QVariant();
781+
QTest::newRow( "line_locate_point point" ) << "line_locate_point(geom_from_wkt('POINT(1 2)'),geom_from_wkt('Point 5 0'))" << false << QVariant();
782+
QTest::newRow( "line_locate_point line" ) << "line_locate_point(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),point:=geom_from_wkt('Point(5 0)'))" << false << QVariant( 5.0 );
775783

776784
// string functions
777785
QTest::newRow( "lower" ) << "lower('HeLLo')" << false << QVariant( "hello" );

0 commit comments

Comments
 (0)
Please sign in to comment.