Skip to content
Permalink
Browse files

[FEATURE] pole_of_inaccessibility expression function

Exposes calculation of pole of inaccessiblity to expression
engine
  • Loading branch information
nyalldawson committed Nov 14, 2016
1 parent 880647e commit 1f81a7c4fc2279f895a91dd3e694730c1bd02704
@@ -0,0 +1,8 @@
{
"name": "pole_of_inaccessibility",
"type": "function",
"description": "Calculates the approximate pole of inaccessibility for a surface, which is the most distant internal point from the boundary of the surface. This function uses the 'polylabel' algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within a specified tolerance. More precise tolerances require more iterations and will take longer to calculate.",
"arguments": [ {"arg":"geometry","description":"a geometry"},
{"arg":"tolerance","description":"maximum distance between the returned point and the true pole location"}],
"examples": [ { "expression":"geom_to_wkt(pole_of_inaccessibility( geom_from_wkt('POLYGON((0 1,0 9,3 10,3 3, 10 3, 10 1, 0 1))'), 0.1))", "returns":"Point(1.55, 1.55)"}]
}
@@ -2582,6 +2582,16 @@ static QVariant fcnPointOnSurface( const QVariantList& values, const QgsExpressi
QVariant result = !geom.isEmpty() ? QVariant::fromValue( geom ) : QVariant();
return result;
}

static QVariant fcnPoleOfInaccessibility( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
double tolerance = getDoubleValue( values.at( 1 ), parent );
QgsGeometry geom = fGeom.poleOfInaccessibility( tolerance );
QVariant result = !geom.isEmpty() ? QVariant::fromValue( geom ) : QVariant();
return result;
}

static QVariant fcnConvexHull( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
{
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
@@ -3919,6 +3929,8 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
fcnExtend, QStringLiteral( "GeometryGroup" ) )
<< new StaticFunction( QStringLiteral( "centroid" ), 1, fcnCentroid, QStringLiteral( "GeometryGroup" ) )
<< new StaticFunction( QStringLiteral( "point_on_surface" ), 1, fcnPointOnSurface, QStringLiteral( "GeometryGroup" ) )
<< new StaticFunction( QStringLiteral( "pole_of_inaccessibility" ), ParameterList() << Parameter( QStringLiteral( "geometry" ) )
<< Parameter( QStringLiteral( "tolerance" ) ), fcnPoleOfInaccessibility, QStringLiteral( "GeometryGroup" ) )
<< new StaticFunction( QStringLiteral( "reverse" ), 1, fcnReverse, QStringLiteral( "GeometryGroup" ) )
<< new StaticFunction( QStringLiteral( "exterior_ring" ), 1, fcnExteriorRing, QStringLiteral( "GeometryGroup" ) )
<< new StaticFunction( QStringLiteral( "interior_ring_n" ), 2, fcnInteriorRingN, QStringLiteral( "GeometryGroup" ) )
@@ -733,6 +733,11 @@ class TestQgsExpression: public QObject
QTest::newRow( "point on surface line" ) << "geom_to_wkt(point_on_surface( geomFromWKT('LINESTRING (-1 2, 9 12)') ))" << false << QVariant( "Point (-1 2)" );
QTest::newRow( "point on surface not geom" ) << "point_on_surface('g')" << true << QVariant();
QTest::newRow( "point on surface null" ) << "point_on_surface(NULL)" << false << QVariant();
QTest::newRow( "pole_of_inaccessibility polygon" ) << "round(x(pole_of_inaccessibility( geomFromWKT('POLYGON((0 1,0 9,3 10,3 3, 10 3, 10 1, 0 1))'), 0.1))*100)" << false << QVariant( 155 );
QTest::newRow( "pole_of_inaccessibility polygon" ) << "round(y(pole_of_inaccessibility( geomFromWKT('POLYGON((0 1,0 9,3 10,3 3, 10 3, 10 1, 0 1))'), 0.1))*100)" << false << QVariant( 255 );
QTest::newRow( "pole_of_inaccessibility not poly" ) << "geom_to_wkt(pole_of_inaccessibility( geomFromWKT('POINT (1.5 0.5)'), 0.1 ))" << false << QVariant();
QTest::newRow( "pole_of_inaccessibility not geom" ) << "pole_of_inaccessibility('g',0.1)" << true << QVariant();
QTest::newRow( "pole_of_inaccessibility null" ) << "pole_of_inaccessibility(NULL,0.1)" << false << QVariant();
QTest::newRow( "is_closed not geom" ) << "is_closed('g')" << true << QVariant();
QTest::newRow( "is_closed null" ) << "is_closed(NULL)" << false << QVariant();
QTest::newRow( "is_closed point" ) << "is_closed(geom_from_wkt('POINT(1 2)'))" << false << QVariant();

1 comment on commit 1f81a7c

@nirvn

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn commented on 1f81a7c Nov 15, 2016

@nyalldawson great feature, once again. While testing it I spotted an error: it fails on multipart polygons.

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