Skip to content

Commit 262514d

Browse files
committed
[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.
1 parent aedcf3a commit 262514d

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "exterior_ring",
3+
"type": "function",
4+
"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.",
5+
"arguments": [ {"arg":"geom","description":"a polygon geometry"}],
6+
"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)'"}]
7+
}

src/core/qgsexpression.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,21 @@ static QVariant fcnReverse( const QVariantList& values, const QgsExpressionConte
17771777
return result;
17781778
}
17791779

1780+
static QVariant fcnExteriorRing( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
1781+
{
1782+
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
1783+
if ( fGeom.isEmpty() )
1784+
return QVariant();
1785+
1786+
QgsCurvePolygonV2* curvePolygon = dynamic_cast< QgsCurvePolygonV2* >( fGeom.geometry() );
1787+
if ( !curvePolygon || !curvePolygon->exteriorRing() )
1788+
return QVariant();
1789+
1790+
QgsCurveV2* exterior = static_cast< QgsCurveV2* >( curvePolygon->exteriorRing()->clone() );
1791+
QVariant result = exterior ? QVariant::fromValue( QgsGeometry( exterior ) ) : QVariant();
1792+
return result;
1793+
}
1794+
17801795
static QVariant fcnDistance( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
17811796
{
17821797
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
@@ -2414,7 +2429,7 @@ const QStringList& QgsExpression::BuiltinFunctions()
24142429
<< "geom_from_gml" << "geomFromGML" << "intersects_bbox" << "bbox"
24152430
<< "disjoint" << "intersects" << "touches" << "crosses" << "contains"
24162431
<< "relate"
2417-
<< "overlaps" << "within" << "buffer" << "centroid" << "bounds" << "reverse"
2432+
<< "overlaps" << "within" << "buffer" << "centroid" << "bounds" << "reverse" << "exterior_ring"
24182433
<< "bounds_width" << "bounds_height" << "convex_hull" << "difference"
24192434
<< "distance" << "intersection" << "sym_difference" << "combine"
24202435
<< "union" << "geom_to_wkt" << "geomToWKT" << "geometry"
@@ -2558,6 +2573,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
25582573
<< new StaticFunction( "centroid", 1, fcnCentroid, "GeometryGroup" )
25592574
<< new StaticFunction( "point_on_surface", 1, fcnPointOnSurface, "GeometryGroup" )
25602575
<< new StaticFunction( "reverse", 1, fcnReverse, "GeometryGroup" )
2576+
<< new StaticFunction( "exterior_ring", 1, fcnExteriorRing, "GeometryGroup" )
25612577
<< new StaticFunction( "bounds", 1, fcnBounds, "GeometryGroup" )
25622578
<< new StaticFunction( "num_points", 1, fcnGeomNumPoints, "GeometryGroup" )
25632579
<< new StaticFunction( "bounds_width", 1, fcnBoundsWidth, "GeometryGroup" )

tests/src/core/testqgsexpression.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,11 @@ class TestQgsExpression: public QObject
449449
QTest::newRow( "reverse point" ) << "reverse(geom_from_wkt('POINT(1 2)'))" << false << QVariant();
450450
QTest::newRow( "reverse polygon" ) << "reverse(geom_from_wkt('POLYGON((-1 -1, 4 0, 4 2, 0 2, -1 -1))'))" << false << QVariant();
451451
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)" );
452+
QTest::newRow( "exterior_ring not geom" ) << "exterior_ring('g')" << true << QVariant();
453+
QTest::newRow( "exterior_ring null" ) << "exterior_ring(NULL)" << false << QVariant();
454+
QTest::newRow( "exterior_ring point" ) << "exterior_ring(geom_from_wkt('POINT(1 2)'))" << false << QVariant();
455+
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)" );
456+
QTest::newRow( "exterior_ring line" ) << "exterior_ring(geom_from_wkt('LINESTRING(0 0, 1 1, 2 2)'))" << false << QVariant();
452457
QTest::newRow( "centroid polygon" ) << "geom_to_wkt(centroid( geomFromWKT('POLYGON((0 0,0 9,9 0,0 0))')))" << false << QVariant( "Point (3 3)" );
453458
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)" );
454459
QTest::newRow( "centroid point" ) << "geom_to_wkt(centroid( geomFromWKT('POINT (1.5 0.5)') ))" << false << QVariant( "Point (1.5 0.5)" );

0 commit comments

Comments
 (0)