Skip to content
{{ message }}

# qgis / QGIS

Merge pull request #3451 from nyalldawson/smoooooth
`[FEATURE] New simplify + smoothing expression functions`
• Loading branch information
nyalldawson committed Sep 4, 2016
2 parents 0036274 + 679797e commit 95c4fa13409060d5780b6590bdfa3225753f4e70
 @@ -0,0 +1,9 @@ { "name": "simplify", "type": "function", "description":"Simplifies a geometry by removing nodes using a distance based threshold (ie, the Douglas Peucker algorithm). The algorithm preserves large deviations in geometries and reduces the number of vertices in nearly straight segments.", "arguments": [ {"arg":"geometry","description":"a geometry"}, {"arg":"tolerance","description":"maximum deviation from straight segments for points to be removed"} ], "examples": [ { "expression":"geom_to_wkt(simplify(geometry:=geom_from_wkt('LineString(0 0, 5 0.1, 10 0)'),tolerance:=5))", "returns":"'LineString(0 0, 10 0)'"}] }
 @@ -0,0 +1,9 @@ { "name": "simplify_vw", "type": "function", "description":"Simplifies a geometry by removing nodes using an area based threshold (ie, the Visvalingam-Whyatt algorithm). The algorithm removes vertices which create small areas in geometries, eg narrow spikes or nearly straight segments.", "arguments": [ {"arg":"geometry","description":"a geometry"}, {"arg":"tolerance","description":"a measure of the maximum area created by a node for the node to be removed"} ], "examples": [ { "expression":"geom_to_wkt(simplify_vw(geometry:=geom_from_wkt('LineString(0 0, 5 0, 5.01 10, 5.02 0, 10 0)'),tolerance:=5))", "returns":"'LineString(0 0, 10 0)'"}] }
 @@ -0,0 +1,12 @@ { "name": "smooth", "type": "function", "description":"Smooths a geometry by adding extra nodes which round off corners in the geometry.", "arguments": [ {"arg":"geometry","description":"a geometry"}, {"arg":"iterations", "optional":true,"description":"number of smoothing iterations to apply. Larger numbers result in smoother but more complex geometries."}, {"arg":"offset", "optional":true,"description":"value between 0 and 0.5 which controls how tightly the smoothed geometry follow the original geometry. Smaller values result in a tighter smoothing, larger values result in looser smoothing."}, {"arg":"min_length", "optional":true,"description":"minimum length of segments to apply smoothing to. This parameter can be used to avoid placing excessive additional nodes in shorter segments of the geometry."}, {"arg":"max_angle", "optional":true,"description":"maximum angle at node for smoothing to be applied (0-180). By lowering the maximum angle intentionally sharp corners in the geometry can be preserved. For instance, a value of 80 degrees will retain right angles in the geometry."} ], "examples": [ { "expression":"geom_to_wkt(smooth(geometry:=geom_from_wkt('LineString(0 0, 5 0, 5 5)'),iterations:=1,offset:=0.2,min_length:=-1,max_angle:=180))", "returns":"'LineString (0 0, 4 0, 5 1, 5 5)'"}] }
 @@ -51,6 +51,7 @@ #include "qgscurvepolygon.h" #include "qgsexpressionprivate.h" #include "qgsexpressionsorter.h" #include "qgsmaptopixelgeometrysimplifier.h" #if QT_VERSION < 0x050000 #include @@ -1767,6 +1768,59 @@ static QVariant fcnLineMerge( const QVariantList& values, const QgsExpressionCon return QVariant::fromValue( merged ); } static QVariant fcnSimplify( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) { QgsGeometry geom = getGeometry( values.at( 0 ), parent ); if ( geom.isEmpty() ) return QVariant(); double tolerance = getDoubleValue( values.at( 1 ), parent ); QgsGeometry simplified = geom.simplify( tolerance ); if ( simplified.isEmpty() ) return QVariant(); return simplified; } static QVariant fcnSimplifyVW( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) { QgsGeometry geom = getGeometry( values.at( 0 ), parent ); if ( geom.isEmpty() ) return QVariant(); double tolerance = getDoubleValue( values.at( 1 ), parent ); QgsMapToPixelSimplifier simplifier( QgsMapToPixelSimplifier::SimplifyGeometry, tolerance, QgsMapToPixelSimplifier::Visvalingam ); QgsGeometry simplified = simplifier.simplify( geom ); if ( simplified.isEmpty() ) return QVariant(); return simplified; } static QVariant fcnSmooth( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) { QgsGeometry geom = getGeometry( values.at( 0 ), parent ); if ( geom.isEmpty() ) return QVariant(); int iterations = qMin( getIntValue( values.at( 1 ), parent ), 10 ); double offset = qBound( 0.0, getDoubleValue( values.at( 2 ), parent ), 0.5 ); double minLength = getDoubleValue( values.at( 3 ), parent ); double maxAngle = qBound( 0.0, getDoubleValue( values.at( 4 ), parent ), 180.0 ); QgsGeometry smoothed = geom.smooth( iterations, offset, minLength, maxAngle ); if ( smoothed.isEmpty() ) return QVariant(); return smoothed; } static QVariant fcnMakePoint( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent ) { if ( values.count() < 2 || values.count() > 4 ) @@ -3166,6 +3220,7 @@ const QStringList& QgsExpression::BuiltinFunctions() << "disjoint" << "intersects" << "touches" << "crosses" << "contains" << "relate" << "overlaps" << "within" << "buffer" << "offset_curve" << "single_sided_buffer" << "simplify" << "simplify_vw" << "smooth" << "centroid" << "bounds" << "reverse" << "exterior_ring" << "boundary" << "line_merge" << "bounds_width" << "bounds_height" << "is_closed" << "convex_hull" << "difference" @@ -3377,6 +3432,12 @@ const QList& QgsExpression::Functions() << new StaticFunction( "boundary", ParameterList() << Parameter( "geometry" ), fcnBoundary, "GeometryGroup" ) << new StaticFunction( "line_merge", ParameterList() << Parameter( "geometry" ), fcnLineMerge, "GeometryGroup" ) << new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup" ) << new StaticFunction( "simplify", ParameterList() << Parameter( "geometry" ) << Parameter( "tolerance" ), fcnSimplify, "GeometryGroup" ) << new StaticFunction( "simplify_vw", ParameterList() << Parameter( "geometry" ) << Parameter( "tolerance" ), fcnSimplifyVW, "GeometryGroup" ) << new StaticFunction( "smooth", ParameterList() << Parameter( "geometry" ) << Parameter( "iterations", true, 1 ) << Parameter( "offset", true, 0.25 ) << Parameter( "min_length", true, -1 ) << Parameter( "max_angle", true, 180 ), fcnSmooth, "GeometryGroup" ) << new StaticFunction( "num_points", 1, fcnGeomNumPoints, "GeometryGroup" ) << new StaticFunction( "num_interior_rings", 1, fcnGeomNumInteriorRings, "GeometryGroup" ) << new StaticFunction( "num_rings", 1, fcnGeomNumRings, "GeometryGroup" )
 @@ -798,6 +798,18 @@ class TestQgsExpression: public QObject 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( "simplify not geom" ) << "simplify('g',5)" << true << QVariant(); QTest::newRow( "simplify null" ) << "simplify(NULL,5)" << false << QVariant(); QTest::newRow( "simplify point" ) << "geom_to_wkt(simplify(geom_from_wkt('POINT(1 2)'),10))" << false << QVariant( "Point (1 2)" ); QTest::newRow( "simplify line" ) << "geom_to_wkt(simplify(geometry:=geom_from_wkt('LineString(0 0, 5 0, 10 0)'),tolerance:=5))" << false << QVariant( "LineString (0 0, 10 0)" ); QTest::newRow( "simplify_vw not geom" ) << "simplify_vw('g',5)" << true << QVariant(); QTest::newRow( "simplify_vw null" ) << "simplify_vw(NULL,5)" << false << QVariant(); QTest::newRow( "simplify_vw point" ) << "geom_to_wkt(simplify_vw(geom_from_wkt('POINT(1 2)'),10))" << false << QVariant( "Point (1 2)" ); QTest::newRow( "simplify_vw line" ) << "geom_to_wkt(simplify_vw(geometry:=geom_from_wkt('LineString(0 0, 5 0, 5.01 10, 5.02 0, 10 0)'),tolerance:=5))" << false << QVariant( "LineString (0 0, 10 0)" ); QTest::newRow( "smooth not geom" ) << "smooth('g',5)" << true << QVariant(); QTest::newRow( "smooth null" ) << "smooth(NULL,5)" << false << QVariant(); QTest::newRow( "smooth point" ) << "geom_to_wkt(smooth(geom_from_wkt('POINT(1 2)'),10))" << false << QVariant( "Point (1 2)" ); QTest::newRow( "smooth line" ) << "geom_to_wkt(smooth(geometry:=geom_from_wkt('LineString(0 0, 5 0, 5 5)'),iterations:=1,offset:=0.2,min_length:=-1,max_angle:=180))" << false << QVariant( "LineString (0 0, 4 0, 5 1, 5 5)" ); // string functions QTest::newRow( "lower" ) << "lower('HeLLo')" << false << QVariant( "hello" );

#### 0 comments on commit `95c4fa1`

Please sign in to comment.