Fix test failure, report distance from pole

This commit is contained in:
Nyall Dawson 2016-11-10 20:53:47 +10:00
parent d6f09c012e
commit b44093914b
9 changed files with 41 additions and 10 deletions

View File

@ -535,11 +535,12 @@ class QgsGeometry
* 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.
* Optionally, the distance to the polygon boundary from the pole can be stored.
* @see centroid()
* @see pointOnSurface()
* @note added in QGIS 3.0
*/
QgsGeometry poleOfInaccessibility( double precision ) const;
QgsGeometry poleOfInaccessibility( double precision, double* distanceToBoundary /Out/ = nullptr ) const;
/** Returns the smallest convex polygon that contains all the points in the geometry. */
QgsGeometry convexHull() const;

View File

@ -340,6 +340,8 @@ qgis:polarplot: >
qgis:poleofinaccessibility: >
This algorithm calculates the pole of inaccessibility for a polygon layer, which is the most distant internal point from the boundary of the surface. This algorithm uses the 'polylabel' algorithm (Vladimir Agafonkin, 2016), which is an iterative approach guaranteed to find the true pole of inaccessibility within a specified tolerance (in layer units). More precise tolerances require more iterations and will take longer to calculate.
The distance from the calculated pole to the polygon boundary will be stored as a new attribute in the output layer.
qgis:polygoncentroids: >
This algorithm creates a new point layer, with points representing the centroid of polygons of an input layer.

View File

@ -27,8 +27,9 @@ __revision__ = '$Format:%H$'
import os
from qgis.core import QgsGeometry, QgsWkbTypes
from qgis.core import QgsGeometry, QgsWkbTypes, QgsField, NULL
from qgis.PyQt.QtCore import QVariant
from qgis.PyQt.QtGui import QIcon
from processing.core.GeoAlgorithm import GeoAlgorithm
@ -65,9 +66,12 @@ class PoleOfInaccessibility(GeoAlgorithm):
self.getParameterValue(self.INPUT_LAYER))
tolerance = self.getParameterValue(self.TOLERANCE)
fields = layer.fields()
fields.append(QgsField('dist_pole', QVariant.Double))
writer = self.getOutputFromName(
self.OUTPUT_LAYER).getVectorWriter(
layer.fields(),
fields,
QgsWkbTypes.Point,
layer.crs())
@ -78,12 +82,19 @@ class PoleOfInaccessibility(GeoAlgorithm):
output_feature = input_feature
input_geometry = input_feature.geometry()
if input_geometry:
output_geometry = input_geometry.poleOfInaccessibility(tolerance)
output_geometry, distance = input_geometry.poleOfInaccessibility(tolerance)
if not output_geometry:
raise GeoAlgorithmExecutionException(
self.tr('Error calculating pole of inaccessibility'))
attrs = input_feature.attributes()
attrs.append(distance)
output_feature.setAttributes(attrs)
output_feature.setGeometry(output_geometry)
else:
attrs = input_feature.attributes()
attrs.append(NULL)
output_feature.setAttributes(attrs)
writer.addFeature(output_feature)
progress.setPercentage(int(current * total))

View File

@ -17,6 +17,7 @@
<ogr:name>aaaaa</ogr:name>
<ogr:intval>33</ogr:intval>
<ogr:floatval>44.123456</ogr:floatval>
<ogr:dist_pole>1.5</ogr:dist_pole>
</ogr:pole_inaccessibility_polys>
</gml:featureMember>
<gml:featureMember>
@ -25,6 +26,7 @@
<ogr:name>Aaaaa</ogr:name>
<ogr:intval>-33</ogr:intval>
<ogr:floatval>0</ogr:floatval>
<ogr:dist_pole>0.414211273193359</ogr:dist_pole>
</ogr:pole_inaccessibility_polys>
</gml:featureMember>
<gml:featureMember>
@ -32,6 +34,7 @@
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2.5,5.5</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:name>bbaaa</ogr:name>
<ogr:floatval>0.123</ogr:floatval>
<ogr:dist_pole>0.5</ogr:dist_pole>
</ogr:pole_inaccessibility_polys>
</gml:featureMember>
<gml:featureMember>
@ -39,6 +42,7 @@
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>6.585784912109375,-2.414215087890625</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:name>ASDF</ogr:name>
<ogr:intval>0</ogr:intval>
<ogr:dist_pole>0.585784912109375</ogr:dist_pole>
</ogr:pole_inaccessibility_polys>
</gml:featureMember>
<gml:featureMember>
@ -53,6 +57,7 @@
<ogr:name>elim</ogr:name>
<ogr:intval>2</ogr:intval>
<ogr:floatval>3.33</ogr:floatval>
<ogr:dist_pole>1.71028189541736</ogr:dist_pole>
</ogr:pole_inaccessibility_polys>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -1480,11 +1480,11 @@ QgsGeometry QgsGeometry::pointOnSurface() const
return QgsGeometry( pt.clone() );
}
QgsGeometry QgsGeometry::poleOfInaccessibility( double precision ) const
QgsGeometry QgsGeometry::poleOfInaccessibility( double precision, double* distanceToBoundary ) const
{
QgsInternalGeometryEngine engine( *this );
return engine.poleOfInaccessibility( precision );
return engine.poleOfInaccessibility( precision, distanceToBoundary );
}
QgsGeometry QgsGeometry::convexHull() const

View File

@ -588,11 +588,12 @@ class CORE_EXPORT QgsGeometry
* 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.
* Optionally, the distance to the polygon boundary from the pole can be stored.
* @see centroid()
* @see pointOnSurface()
* @note added in QGIS 3.0
*/
QgsGeometry poleOfInaccessibility( double precision ) const;
QgsGeometry poleOfInaccessibility( double precision, double* distanceToBoundary = nullptr ) const;
//! Returns the smallest convex polygon that contains all the points in the geometry.
QgsGeometry convexHull() const;

View File

@ -97,6 +97,7 @@ QgsGeometry QgsInternalGeometryEngine::extrude( double x, double y ) const
// ported from the original Javascript implementation developed by Vladimir Agafonkin
// originally licensed under the ISC License
/// @cond PRIVATE
class Cell
{
public:
@ -153,9 +154,13 @@ Cell* getCentroidCell( const QgsPolygonV2* polygon )
return new Cell( x / area, y / area, 0.0, polygon );
}
///@endcond
QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision ) const
QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision , double* distanceFromBoundary ) const
{
if ( distanceFromBoundary )
*distanceFromBoundary = DBL_MAX;
if ( !mGeometry || mGeometry->isEmpty() )
return QgsGeometry();
@ -232,5 +237,8 @@ QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision )
cellQueue.push( new Cell( currentCell->x + h, currentCell->y + h, h, polygon ) );
}
if ( distanceFromBoundary )
*distanceFromBoundary = bestCell->d;
return QgsGeometry( new QgsPointV2( bestCell->x, bestCell->y ) );
}

View File

@ -57,8 +57,9 @@ class QgsInternalGeometryEngine
* 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.
* Optionally, the distance to the polygon boundary from the pole can be stored.
*/
QgsGeometry poleOfInaccessibility( double precision ) const;
QgsGeometry poleOfInaccessibility( double precision, double* distanceFromBoundary = nullptr ) const;
private:
const QgsAbstractGeometry* mGeometry;

View File

@ -3960,9 +3960,11 @@ void TestQgsGeometry::poleOfInaccessibility()
QgsGeometry poly1 = QgsGeometry::fromWkt( poly1Wkt );
QgsGeometry poly2 = QgsGeometry::fromWkt( poly2Wkt );
QgsPoint point = poly1.poleOfInaccessibility( 1 ).asPoint();
double distance;
QgsPoint point = poly1.poleOfInaccessibility( 1 , &distance ).asPoint();
QGSCOMPARENEAR( point.x(), 3867.37, 0.01 );
QGSCOMPARENEAR( point.y(), 2126.45, 0.01 );
QGSCOMPARENEAR( distance, 289.51, 0.01 );
point = poly1.poleOfInaccessibility( 50 ).asPoint();
QGSCOMPARENEAR( point.x(), 3855.33, 0.01 );