[FEATURE] pole_of_inaccessibility expression function

Exposes calculation of pole of inaccessiblity to expression
engine
This commit is contained in:
Nyall Dawson 2016-11-11 07:41:03 +10:00
parent 880647e50e
commit 1f81a7c4fc
3 changed files with 25 additions and 0 deletions

View File

@ -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)"}]
}

View File

@ -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" ) )

View File

@ -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();