[FEATURE] exterior_ring function for expressions

Returns exterior ring of a polygon as a line. Useful for geometry
generator symbology for styling only the exterior ring of
polygons.
This commit is contained in:
Nyall Dawson 2015-12-13 20:11:19 +11:00
parent aedcf3a76b
commit 262514d97d
3 changed files with 29 additions and 1 deletions

View File

@ -0,0 +1,7 @@
{
"name": "exterior_ring",
"type": "function",
"description": "Returns a line string representing the exterior ring of a polygon geometry. If the geometry is not a polygon then the result will be null.",
"arguments": [ {"arg":"geom","description":"a polygon geometry"}],
"examples": [ { "expression":"geom_to_wkt(exterior_ring(geom_from_wkt('POLYGON((-1 -1, 4 0, 4 2, 0 2, -1 -1),( 0.1 0.1, 0.1 0.2, 0.2 0.2, 0.2, 0.1, 0.1 0.1))')))", "returns":"'LineString (-1 -1, 4 0, 4 2, 0 2, -1 -1)'"}]
}

View File

@ -1777,6 +1777,21 @@ static QVariant fcnReverse( const QVariantList& values, const QgsExpressionConte
return result;
}
static QVariant fcnExteriorRing( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
if ( fGeom.isEmpty() )
return QVariant();
QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( fGeom.geometry() );
if ( !curvePolygon || !curvePolygon->exteriorRing() )
return QVariant();
QgsCurveV2* exterior = static_cast< QgsCurveV2* >( curvePolygon->exteriorRing()->clone() );
QVariant result = exterior ? QVariant::fromValue( QgsGeometry( exterior ) ) : QVariant();
return result;
}
static QVariant fcnDistance( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
@ -2414,7 +2429,7 @@ const QStringList& QgsExpression::BuiltinFunctions()
<< "geom_from_gml" << "geomFromGML" << "intersects_bbox" << "bbox"
<< "disjoint" << "intersects" << "touches" << "crosses" << "contains"
<< "relate"
<< "overlaps" << "within" << "buffer" << "centroid" << "bounds" << "reverse"
<< "overlaps" << "within" << "buffer" << "centroid" << "bounds" << "reverse" << "exterior_ring"
<< "bounds_width" << "bounds_height" << "convex_hull" << "difference"
<< "distance" << "intersection" << "sym_difference" << "combine"
<< "union" << "geom_to_wkt" << "geomToWKT" << "geometry"
@ -2558,6 +2573,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
<< new StaticFunction( "centroid", 1, fcnCentroid, "GeometryGroup" )
<< new StaticFunction( "point_on_surface", 1, fcnPointOnSurface, "GeometryGroup" )
<< new StaticFunction( "reverse", 1, fcnReverse, "GeometryGroup" )
<< new StaticFunction( "exterior_ring", 1, fcnExteriorRing, "GeometryGroup" )
<< new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup" )
<< new StaticFunction( "num_points", 1, fcnGeomNumPoints, "GeometryGroup" )
<< new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "GeometryGroup" )

View File

@ -449,6 +449,11 @@ class TestQgsExpression: public QObject
QTest::newRow( "reverse point" ) << "reverse(geom_from_wkt('POINT(1 2)'))" << false << QVariant();
QTest::newRow( "reverse polygon" ) << "reverse(geom_from_wkt('POLYGON((-1 -1, 4 0, 4 2, 0 2, -1 -1))'))" << false << QVariant();
QTest::newRow( "reverse line" ) << "geom_to_wkt(reverse(geom_from_wkt('LINESTRING(0 0, 1 1, 2 2)')))" << false << QVariant( "LineString (2 2, 1 1, 0 0)" );
QTest::newRow( "exterior_ring not geom" ) << "exterior_ring('g')" << true << QVariant();
QTest::newRow( "exterior_ring null" ) << "exterior_ring(NULL)" << false << QVariant();
QTest::newRow( "exterior_ring point" ) << "exterior_ring(geom_from_wkt('POINT(1 2)'))" << false << QVariant();
QTest::newRow( "exterior_ring polygon" ) << "geom_to_wkt(exterior_ring(geom_from_wkt('POLYGON((-1 -1, 4 0, 4 2, 0 2, -1 -1),( 0.1 0.1, 0.1 0.2, 0.2 0.2, 0.2, 0.1, 0.1 0.1))')))" << false << QVariant( "LineString (-1 -1, 4 0, 4 2, 0 2, -1 -1)" );
QTest::newRow( "exterior_ring line" ) << "exterior_ring(geom_from_wkt('LINESTRING(0 0, 1 1, 2 2)'))" << false << QVariant();
QTest::newRow( "centroid polygon" ) << "geom_to_wkt(centroid( geomFromWKT('POLYGON((0 0,0 9,9 0,0 0))')))" << false << QVariant( "Point (3 3)" );
QTest::newRow( "centroid multi polygon" ) << "geom_to_wkt(centroid( geomFromWKT('MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)),((2 0,2 1,3 1,3 0,2 0)))') ))" << false << QVariant( "Point (1.5 0.5)" );
QTest::newRow( "centroid point" ) << "geom_to_wkt(centroid( geomFromWKT('POINT (1.5 0.5)') ))" << false << QVariant( "Point (1.5 0.5)" );