Skip to content
Permalink
Browse files

[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.
  • Loading branch information
nyalldawson committed Dec 13, 2015
1 parent aedcf3a commit 262514d97d0ac754e5c2989a2ae85c0eb54c7242
Showing with 29 additions and 1 deletion.
  1. +7 −0 resources/function_help/json/exterior_ring
  2. +17 −1 src/core/qgsexpression.cpp
  3. +5 −0 tests/src/core/testqgsexpression.cpp
@@ -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)'"}]
}
@@ -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" )
@@ -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)" );

0 comments on commit 262514d

Please sign in to comment.
You can’t perform that action at this time.