Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix invalid polygon rings created by map to pixel simplification
when a larger polygon contains a very small ring
  • Loading branch information
nyalldawson committed May 22, 2018
1 parent 9811783 commit c1661de
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
51 changes: 35 additions & 16 deletions src/core/qgsmaptopixelgeometrysimplifier.cpp
Expand Up @@ -71,7 +71,8 @@ bool QgsMapToPixelSimplifier::equalSnapToGrid( double x1, double y1, double x2,
static QgsGeometry generalizeWkbGeometryByBoundingBox( static QgsGeometry generalizeWkbGeometryByBoundingBox(
QgsWkbTypes::Type wkbType, QgsWkbTypes::Type wkbType,
const QgsAbstractGeometry &geometry, const QgsAbstractGeometry &geometry,
const QgsRectangle &envelope ) const QgsRectangle &envelope,
bool isRing )
{ {
unsigned int geometryType = QgsWkbTypes::singleType( QgsWkbTypes::flatType( wkbType ) ); unsigned int geometryType = QgsWkbTypes::singleType( QgsWkbTypes::flatType( wkbType ) );


Expand All @@ -89,31 +90,48 @@ static QgsGeometry generalizeWkbGeometryByBoundingBox(
const double y2 = envelope.yMaximum(); const double y2 = envelope.yMaximum();


// Write the generalized geometry // Write the generalized geometry
if ( geometryType == QgsWkbTypes::LineString ) if ( geometryType == QgsWkbTypes::LineString && !isRing )
{ {
return QgsGeometry( qgis::make_unique< QgsLineString >( QVector<double>() << x1 << x2, QVector<double>() << y1 << y2 ) ); return QgsGeometry( qgis::make_unique< QgsLineString >( QVector<double>() << x1 << x2, QVector<double>() << y1 << y2 ) );
} }
else else
{ {
return QgsGeometry::fromRect( envelope ); std::unique_ptr< QgsLineString > ext = qgis::make_unique< QgsLineString >(
QVector< double >() << x1
<< x2
<< x2
<< x1
<< x1,
QVector< double >() << y1
<< y1
<< y2
<< y2
<< y1 );
if ( geometryType == QgsWkbTypes::LineString )
return QgsGeometry( std::move( ext ) );
else
{
std::unique_ptr< QgsPolygon > polygon = qgis::make_unique< QgsPolygon >();
polygon->setExteriorRing( ext.release() );
return QgsGeometry( std::move( polygon ) );
}
} }
} }


QgsGeometry QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry QgsMapToPixelSimplifier::simplifyGeometry( int simplifyFlags,
int simplifyFlags, SimplifyAlgorithm simplifyAlgorithm,
SimplifyAlgorithm simplifyAlgorithm, const QgsAbstractGeometry &geometry, double map2pixelTol,
QgsWkbTypes::Type wkbType, bool isaLinearRing )
const QgsAbstractGeometry &geometry,
const QgsRectangle &envelope, double map2pixelTol,
bool isaLinearRing )
{ {
bool isGeneralizable = true; bool isGeneralizable = true;
QgsWkbTypes::Type wkbType = geometry.wkbType();


// Can replace the geometry by its BBOX ? // Can replace the geometry by its BBOX ?
QgsRectangle envelope = geometry.boundingBox();
if ( ( simplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && if ( ( simplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) &&
isGeneralizableByMapBoundingBox( envelope, map2pixelTol ) ) isGeneralizableByMapBoundingBox( envelope, map2pixelTol ) )
{ {
return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope ); return generalizeWkbGeometryByBoundingBox( wkbType, geometry, envelope, isaLinearRing );
} }


if ( !( simplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ) ) if ( !( simplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ) )
Expand Down Expand Up @@ -267,7 +285,7 @@ QgsGeometry QgsMapToPixelSimplifier::simplifyGeometry(
{ {
// approximate the geometry's shape by its bounding box // approximate the geometry's shape by its bounding box
// (rect for linear ring / one segment for line string) // (rect for linear ring / one segment for line string)
return generalizeWkbGeometryByBoundingBox( wkbType, geometry, r ); return generalizeWkbGeometryByBoundingBox( wkbType, geometry, r, isaLinearRing );
} }
else else
{ {
Expand All @@ -293,11 +311,12 @@ QgsGeometry QgsMapToPixelSimplifier::simplifyGeometry(
{ {
const QgsPolygon &srcPolygon = dynamic_cast<const QgsPolygon &>( geometry ); const QgsPolygon &srcPolygon = dynamic_cast<const QgsPolygon &>( geometry );
std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() ); std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() );
polygon->setExteriorRing( qgsgeometry_cast<QgsCurve *>( simplifyGeometry( simplifyFlags, simplifyAlgorithm, srcPolygon.exteriorRing()->wkbType(), *srcPolygon.exteriorRing(), envelope, map2pixelTol, true ).constGet()->clone() ) ); polygon->setExteriorRing( qgsgeometry_cast<QgsCurve *>( simplifyGeometry( simplifyFlags, simplifyAlgorithm, *srcPolygon.exteriorRing(), map2pixelTol, true ).constGet()->clone() ) );
for ( int i = 0; i < srcPolygon.numInteriorRings(); ++i ) for ( int i = 0; i < srcPolygon.numInteriorRings(); ++i )
{ {
const QgsCurve *sub = srcPolygon.interiorRing( i ); const QgsCurve *sub = srcPolygon.interiorRing( i );
polygon->addInteriorRing( qgsgeometry_cast<QgsCurve *>( simplifyGeometry( simplifyFlags, simplifyAlgorithm, sub->wkbType(), *sub, envelope, map2pixelTol, true ).constGet()->clone() ) ); std::unique_ptr< QgsCurve > ring( qgsgeometry_cast<QgsCurve *>( simplifyGeometry( simplifyFlags, simplifyAlgorithm, *sub, map2pixelTol, true ).constGet()->clone() ) );
polygon->addInteriorRing( ring.release() );
} }
return QgsGeometry( polygon.release() ); return QgsGeometry( polygon.release() );
} }
Expand All @@ -309,7 +328,7 @@ QgsGeometry QgsMapToPixelSimplifier::simplifyGeometry(
for ( int i = 0; i < numGeoms; ++i ) for ( int i = 0; i < numGeoms; ++i )
{ {
const QgsAbstractGeometry *sub = srcCollection.geometryN( i ); const QgsAbstractGeometry *sub = srcCollection.geometryN( i );
collection->addGeometry( simplifyGeometry( simplifyFlags, simplifyAlgorithm, sub->wkbType(), *sub, envelope, map2pixelTol, false ).constGet()->clone() ); collection->addGeometry( simplifyGeometry( simplifyFlags, simplifyAlgorithm, *sub, map2pixelTol, false ).constGet()->clone() );
} }
return QgsGeometry( collection.release() ); return QgsGeometry( collection.release() );
} }
Expand Down Expand Up @@ -359,5 +378,5 @@ QgsGeometry QgsMapToPixelSimplifier::simplify( const QgsGeometry &geometry ) con
return geometry; return geometry;
} }


return simplifyGeometry( mSimplifyFlags, mSimplifyAlgorithm, geometry.wkbType(), *geometry.constGet(), envelope, mTolerance, false ); return simplifyGeometry( mSimplifyFlags, mSimplifyAlgorithm, *geometry.constGet(), mTolerance, false );
} }
2 changes: 1 addition & 1 deletion src/core/qgsmaptopixelgeometrysimplifier.h
Expand Up @@ -58,7 +58,7 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier


private: private:
//! Simplify the geometry using the specified tolerance //! Simplify the geometry using the specified tolerance
static QgsGeometry simplifyGeometry( int simplifyFlags, SimplifyAlgorithm simplifyAlgorithm, QgsWkbTypes::Type wkbType, const QgsAbstractGeometry &geometry, const QgsRectangle &envelope, double map2pixelTol, bool isaLinearRing ); static QgsGeometry simplifyGeometry( int simplifyFlags, SimplifyAlgorithm simplifyAlgorithm, const QgsAbstractGeometry &geometry, double map2pixelTol, bool isaLinearRing );


protected: protected:
//! Current simplification flags //! Current simplification flags
Expand Down

0 comments on commit c1661de

Please sign in to comment.