mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-15 00:07:25 -05:00
[expression] Add line_interpolate_point_by_m and line_locate_m expressions
This commit is contained in:
parent
e47eccc1c5
commit
5cd1e31b82
22
resources/function_help/json/line_interpolate_point_by_m
Normal file
22
resources/function_help/json/line_interpolate_point_by_m
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "line_interpolate_point_by_m",
|
||||
"type": "function",
|
||||
"groups": ["GeometryGroup"],
|
||||
"description": "Returns the point interpolated by a matching M value along a linestring geometry.",
|
||||
"arguments": [{
|
||||
"arg": "geometry",
|
||||
"description": "a linestring geometry"
|
||||
}, {
|
||||
"arg": "m",
|
||||
"description": "an M value"
|
||||
}, {
|
||||
"arg": "use_3d_distance",
|
||||
"optional": true,
|
||||
"description": "controls whether 2D or 3D distances between vertices should be used during interpolation (this option is only considered for lines with z values)"
|
||||
}],
|
||||
"examples": [{
|
||||
"expression": "geom_to_wkt(line_interpolate_point_by_m(geom_from_wkt('LineStringM(0 0 0, 10 10 10)'), m:=5))",
|
||||
"returns": "'Point (5 5)'"
|
||||
}],
|
||||
"tags": ["distance", "interpolated", "linestring", "point", "specified", "along"]
|
||||
}
|
||||
22
resources/function_help/json/line_locate_m
Normal file
22
resources/function_help/json/line_locate_m
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "line_locate_m",
|
||||
"type": "function",
|
||||
"groups": ["GeometryGroup"],
|
||||
"description": "Returns the distance along a linestring corresponding to the first matching interpolated M value.",
|
||||
"arguments": [{
|
||||
"arg": "geometry",
|
||||
"description": "a linestring geometry"
|
||||
}, {
|
||||
"arg": "m",
|
||||
"description": "an M value"
|
||||
}, {
|
||||
"arg": "use_3d_distance",
|
||||
"optional": true,
|
||||
"description": "controls whether 2D or 3D distances between vertices should be used during interpolation (this option is only considered for lines with z values)"
|
||||
}],
|
||||
"examples": [{
|
||||
"expression": "line_locate_m(geometry:=geom_from_wkt('LineStringM(0 0 0, 10 10 10)'),m:=5)",
|
||||
"returns": "7.07106"
|
||||
}],
|
||||
"tags": ["distance", "linestring", "interpolated", "corresponding", "along"]
|
||||
}
|
||||
@ -5653,6 +5653,33 @@ static QVariant fcnLineInterpolatePoint( const QVariantList &values, const QgsEx
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnLineInterpolatePointByM( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
|
||||
const bool use3DDistance = values.at( 2 ).toBool();
|
||||
|
||||
double x, y, z, distance;
|
||||
|
||||
const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( lineGeom.constGet() );
|
||||
if ( !line )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if ( line->lineLocatePointByM( m, x, y, z, distance, use3DDistance ) )
|
||||
{
|
||||
QgsPoint point( x, y );
|
||||
if ( use3DDistance && QgsWkbTypes::hasZ( lineGeom.wkbType() ) )
|
||||
{
|
||||
point.addZValue( z );
|
||||
}
|
||||
return QVariant::fromValue( QgsGeometry( point.clone() ) );
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
static QVariant fcnLineSubset( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
@ -5732,6 +5759,24 @@ static QVariant fcnLineLocatePoint( const QVariantList &values, const QgsExpress
|
||||
return distance >= 0 ? distance : QVariant();
|
||||
}
|
||||
|
||||
static QVariant fcnLineLocateM( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry lineGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
const double m = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
|
||||
const bool use3DDistance = values.at( 2 ).toBool();
|
||||
|
||||
double x, y, z, distance;
|
||||
|
||||
const QgsLineString *line = qgsgeometry_cast<const QgsLineString *>( lineGeom.constGet() );
|
||||
if ( !line )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const bool found = line->lineLocatePointByM( m, x, y, z, distance, use3DDistance );
|
||||
return found ? distance : QVariant();
|
||||
}
|
||||
|
||||
static QVariant fcnRound( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
if ( values.length() == 2 && values.at( 1 ).toInt() != 0 )
|
||||
@ -9083,10 +9128,16 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
fcnShortestLine, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "line_interpolate_point" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "distance" ) ), fcnLineInterpolatePoint, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "line_interpolate_point_by_m" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "m" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "use_3d_distance" ), true, false ),
|
||||
fcnLineInterpolatePointByM, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "line_interpolate_angle" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "distance" ) ), fcnLineInterpolateAngle, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "line_locate_point" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "point" ) ), fcnLineLocatePoint, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "line_locate_m" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "m" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "use_3d_distance" ), true, false ),
|
||||
fcnLineLocateM, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "angle_at_vertex" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "vertex" ) ), fcnAngleAtVertex, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "distance_to_vertex" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
|
||||
@ -1438,10 +1438,19 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "line_interpolate_point null" ) << "line_interpolate_point(NULL, 5)" << false << QVariant();
|
||||
QTest::newRow( "line_interpolate_point point" ) << "line_interpolate_point(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant();
|
||||
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)" );
|
||||
QTest::newRow( "line_interpolate_point_by_m not geom" ) << "line_interpolate_point_by_m('g', 5)" << true << QVariant();
|
||||
QTest::newRow( "line_interpolate_point_by_m null" ) << "line_interpolate_point_by_m(NULL, 5)" << false << QVariant();
|
||||
QTest::newRow( "line_interpolate_point_by_m point" ) << "line_interpolate_point_by_m(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant();
|
||||
QTest::newRow( "line_interpolate_point_by_m line" ) << "geom_to_wkt(line_interpolate_point_by_m(geometry:=geom_from_wkt('LineStringM(0 0 0, 10 10 10)'),m:=5))" << false << QVariant( "Point (5 5)" );
|
||||
QTest::newRow( "line_locate_point not geom" ) << "line_locate_point('g', geom_from_wkt('Point 5 0'))" << false << QVariant();
|
||||
QTest::newRow( "line_locate_point null" ) << "line_locate_point(NULL, geom_from_wkt('Point 5 0'))" << false << QVariant();
|
||||
QTest::newRow( "line_locate_point point" ) << "line_locate_point(geom_from_wkt('POINT(1 2)'),geom_from_wkt('Point 5 0'))" << false << QVariant();
|
||||
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 );
|
||||
QTest::newRow( "line_locate_m not geom" ) << "line_locate_m('g', 0)" << true << QVariant();
|
||||
QTest::newRow( "line_locate_m null" ) << "line_locate_m(NULL, 0)" << false << QVariant();
|
||||
QTest::newRow( "line_locate_m point" ) << "line_locate_m(geom_from_wkt('POINT(1 2)'),0)" << false << QVariant();
|
||||
QTest::newRow( "line_locate_m line out of range" ) << "line_locate_m(geom_from_wkt('LineStringM(0 0 0, 10 10 10)'),m:=20)" << false << QVariant();
|
||||
QTest::newRow( "line_locate_m line" ) << "line_locate_m(geom_from_wkt('LineStringM(0 0 0, 10 10 10)'),m:=0)" << false << QVariant( 0.0 );
|
||||
QTest::newRow( "line_interpolate_angle not geom" ) << "line_interpolate_angle('g', 5)" << true << QVariant();
|
||||
QTest::newRow( "line_interpolate_angle null" ) << "line_interpolate_angle(NULL, 5)" << false << QVariant();
|
||||
QTest::newRow( "line_interpolate_angle point" ) << "line_interpolate_angle(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant( 0.0 );
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user