mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE] Add expression functions for tapered and variable
width buffers Adds: - tapered_buffer - buffer_by_m expression functions. These expose the same functionality as the equivalent processing algorithms but for use in expressions such as geometry generators.
This commit is contained in:
parent
9ffae600f4
commit
6ca327072a
9
resources/function_help/json/buffer_by_m
Normal file
9
resources/function_help/json/buffer_by_m
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "buffer_by_m",
|
||||
"type": "function",
|
||||
"description": "Creates a buffer along a line geometry where the buffer diameter varies according to the m-values at the line vertices.",
|
||||
"arguments": [ {"arg":"geometry","description":"input geometry. Must be a (multi)line geometry with m values."},
|
||||
{"arg":"segments","optional":true,"default":"8","description":"number of segments to approximate quarter-circle curves in the buffer."}],
|
||||
"examples": [ { "expression":"buffer_by_m(geometry:=geom_from_wkt('LINESTRINGM(1 2 0.5, 4 2 0.2)'),segments:=8)", "returns":"A variable width buffer starting with a diameter of 0.5 and ending with a diameter of 0.2 along the linestring geometry."}]
|
||||
}
|
||||
|
11
resources/function_help/json/tapered_buffer
Normal file
11
resources/function_help/json/tapered_buffer
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "tapered_buffer",
|
||||
"type": "function",
|
||||
"description": "Creates a buffer along a line geometry where the buffer diameter varies evenly over the length of the line.",
|
||||
"arguments": [ {"arg":"geometry","description":"input geometry. Must be a (multi)line geometry."},
|
||||
{"arg":"start_width","description":"width of buffer at start of line,"},
|
||||
{"arg":"end_width","description":"width of buffer at end of line."},
|
||||
{"arg":"segments","optional":true,"default":"8","description":"number of segments to approximate quarter-circle curves in the buffer."}],
|
||||
"examples": [ { "expression":"tapered_buffer(geometry:=geom_from_wkt('LINESTRING(1 2, 4 2)'),start_width:=1,end_width:=2,segments:=8)", "returns":"A tapered buffer starting with a diameter of 1 and ending with a diameter of 2 along the linestring geometry."}]
|
||||
}
|
||||
|
@ -2512,6 +2512,40 @@ static QVariant fcnWedgeBuffer( const QVariantList &values, const QgsExpressionC
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnTaperedBuffer( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
if ( fGeom.type() != QgsWkbTypes::LineGeometry )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `tapered_buffer` requires a line geometry." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
double startWidth = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
|
||||
double endWidth = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
|
||||
int segments = static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 3 ), parent ) );
|
||||
|
||||
QgsGeometry geom = fGeom.taperedBuffer( startWidth, endWidth, segments );
|
||||
QVariant result = !geom.isNull() ? QVariant::fromValue( geom ) : QVariant();
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnBufferByM( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
if ( fGeom.type() != QgsWkbTypes::LineGeometry )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function `buffer_by_m` requires a line geometry." ) );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int segments = static_cast< int >( QgsExpressionUtils::getIntValue( values.at( 1 ), parent ) );
|
||||
|
||||
QgsGeometry geom = fGeom.variableWidthBufferByM( segments );
|
||||
QVariant result = !geom.isNull() ? QVariant::fromValue( geom ) : QVariant();
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnOffsetCurve( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
@ -4299,6 +4333,14 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "width" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "outer_radius" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "inner_radius" ), true, 0.0 ), fcnWedgeBuffer, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "tapered_buffer" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "start_width" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "end_width" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "segments" ), true, 8.0 )
|
||||
, fcnTaperedBuffer, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "buffer_by_m" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "segments" ), true, 8.0 )
|
||||
, fcnBufferByM, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "offset_curve" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "distance" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "segments" ), true, 8.0 )
|
||||
|
@ -818,6 +818,16 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "wedge_buffer null" ) << "wedge_buffer(NULL, 0, 45, 1)" << false << QVariant();
|
||||
QTest::newRow( "wedge_buffer point" ) << "geom_to_wkt(wedge_buffer(center:=geom_from_wkt('POINT(1 2)'),azimuth:=90,width:=180,outer_radius:=1))" << false << QVariant( QStringLiteral( "CurvePolygon (CompoundCurve (CircularString (1 3, 2 2, 1 1),(1 1, 1 2),(1 2, 1 3)))" ) );
|
||||
QTest::newRow( "wedge_buffer point inner" ) << "geom_to_wkt(wedge_buffer(center:=geom_from_wkt('POINT(1 2)'),azimuth:=90,width:=180,outer_radius:=2,inner_radius:=1))" << false << QVariant( QStringLiteral( "CurvePolygon (CompoundCurve (CircularString (1 4, 3 2, 1 0),(1 0, 1 1),CircularString (1 1, 0 2, 1 3),(1 3, 1 4)))" ) );
|
||||
QTest::newRow( "tapered_buffer not geom" ) << "tapered_buffer('g', 1, 2, 8)" << true << QVariant();
|
||||
QTest::newRow( "tapered_buffer null" ) << "tapered_buffer(NULL, 1, 2, 8)" << false << QVariant();
|
||||
QTest::newRow( "tapered_buffer point" ) << "geom_to_wkt(tapered_buffer(geometry:=geom_from_wkt('POINT(1 2)'),start_width:=1,end_width:=2,segments:=10))" << true << QVariant();
|
||||
QTest::newRow( "tapered_buffer line" ) << "geom_to_wkt(tapered_buffer(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),start_width:=1,end_width:=2,segments:=3))" << false << QVariant( QStringLiteral( "MultiPolygon (((-0 -0.5, -0.25 -0.4330127, -0.4330127 -0.25, -0.5 0, -0.4330127 0.25, -0.25 0.4330127, 0 0.5, 10 1, 10.5 0.8660254, 10.8660254 0.5, 11 -0, 10.8660254 -0.5, 10.5 -0.8660254, 10 -1, -0 -0.5)))" ) );
|
||||
QTest::newRow( "tapered_buffer line 2" ) << "geom_to_wkt(tapered_buffer(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),start_width:=2,end_width:=1,segments:=3))" << false << QVariant( QStringLiteral( "MultiPolygon (((-0 -1, -0.5 -0.8660254, -0.8660254 -0.5, -1 0, -0.8660254 0.5, -0.5 0.8660254, 0 1, 10 0.5, 10.25 0.4330127, 10.4330127 0.25, 10.5 -0, 10.4330127 -0.25, 10.25 -0.4330127, 10 -0.5, -0 -1)))" ) );
|
||||
QTest::newRow( "buffer_by_m not geom" ) << "buffer_by_m('g', 8)" << true << QVariant();
|
||||
QTest::newRow( "buffer_by_m null" ) << "buffer_by_m(NULL, 8)" << false << QVariant();
|
||||
QTest::newRow( "buffer_by_m point" ) << "geom_to_wkt(buffer_by_m(geometry:=geom_from_wkt('POINT(1 2)'),segments:=10))" << true << QVariant();
|
||||
QTest::newRow( "buffer_by_m line" ) << "geom_to_wkt(buffer_by_m(geometry:=geom_from_wkt('LineString(0 0, 10 0)'),segments:=3))" << false << QVariant( QStringLiteral( "GeometryCollection ()" ) );
|
||||
QTest::newRow( "buffer_by_m linem" ) << "geom_to_wkt(buffer_by_m(geometry:=geom_from_wkt('LineStringM(0 0 1, 10 0 2)'),segments:=3))" << false << QVariant( QStringLiteral( "MultiPolygon (((-0 -0.5, -0.25 -0.4330127, -0.4330127 -0.25, -0.5 0, -0.4330127 0.25, -0.25 0.4330127, 0 0.5, 10 1, 10.5 0.8660254, 10.8660254 0.5, 11 -0, 10.8660254 -0.5, 10.5 -0.8660254, 10 -1, -0 -0.5)))" ) );
|
||||
QTest::newRow( "single_sided_buffer not geom" ) << "single_sided_buffer('g', 5)" << true << QVariant();
|
||||
QTest::newRow( "single_sided_buffer null" ) << "single_sided_buffer(NULL, 5)" << false << QVariant();
|
||||
QTest::newRow( "single_sided_buffer point" ) << "single_sided_buffer(geom_from_wkt('POINT(1 2)'),5)" << false << QVariant();
|
||||
|
Loading…
x
Reference in New Issue
Block a user