Skip to content

Commit 2a70c4b

Browse files
committed
Remove invalid ring handling from filterVertices, move to removeInvalidRings()
1 parent 53d4d0b commit 2a70c4b

6 files changed

Lines changed: 55 additions & 18 deletions

File tree

‎python/core/auto_generated/geometry/qgscurvepolygon.sip.in‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,15 @@ area will be removed.
122122

123123
.. seealso:: :py:func:`removeInteriorRing`
124124

125+
.. versionadded:: 3.0
126+
%End
127+
128+
void removeInvalidRings();
129+
%Docstring
130+
Removes any interior rings which are not valid from the polygon.
131+
132+
For example, this removes unclosed rings and rings with less than 4 vertices.
133+
125134
.. versionadded:: 3.0
126135
%End
127136

‎src/core/geometry/qgsabstractgeometry.h‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,8 +573,7 @@ class CORE_EXPORT QgsAbstractGeometry
573573
* Filters the vertices from the geometry in place, removing any which do not return true for the \a filter function
574574
* check. Has no meaning when called on a single point geometry.
575575
*
576-
* Depending on the \a filter used, this may result in an invalid geometry. However, CurvePolygon rings which are no longer
577-
* valid rings will be automatically removed after filtering.
576+
* Depending on the \a filter used, this may result in an invalid geometry.
578577
*
579578
* \note Not available in Python bindings
580579
* \since QGIS 3.2

‎src/core/geometry/qgscurvepolygon.cpp‎

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,25 @@ void QgsCurvePolygon::removeInteriorRings( double minimumAllowedArea )
703703
clearCache();
704704
}
705705

706+
void QgsCurvePolygon::removeInvalidRings()
707+
{
708+
QVector<QgsCurve *> validRings;
709+
validRings.reserve( mInteriorRings.size() );
710+
for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
711+
{
712+
if ( !curve->isRing() )
713+
{
714+
// remove invalid rings
715+
delete curve;
716+
}
717+
else
718+
{
719+
validRings << curve;
720+
}
721+
}
722+
mInteriorRings = validRings;
723+
}
724+
706725
void QgsCurvePolygon::draw( QPainter &p ) const
707726
{
708727
if ( !mExteriorRing )
@@ -1179,23 +1198,10 @@ void QgsCurvePolygon::filterVertices( const std::function<bool ( const QgsPoint
11791198
if ( mExteriorRing )
11801199
mExteriorRing->filterVertices( filter );
11811200

1182-
QVector<QgsCurve *> filteredRings;
1183-
filteredRings.reserve( mInteriorRings.size() );
11841201
for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
11851202
{
11861203
curve->filterVertices( filter );
1187-
1188-
if ( !curve->isRing() )
1189-
{
1190-
// remove invalid rings
1191-
delete curve;
1192-
}
1193-
else
1194-
{
1195-
filteredRings << curve;
1196-
}
11971204
}
1198-
mInteriorRings = filteredRings;
11991205
clearCache();
12001206
}
12011207

‎src/core/geometry/qgscurvepolygon.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
109109
*/
110110
void removeInteriorRings( double minimumAllowedArea = -1 );
111111

112+
/**
113+
* Removes any interior rings which are not valid from the polygon.
114+
*
115+
* For example, this removes unclosed rings and rings with less than 4 vertices.
116+
*
117+
* \since QGIS 3.0
118+
*/
119+
void removeInvalidRings();
120+
112121
void draw( QPainter &p ) const override;
113122
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
114123
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;

‎src/core/geometry/qgsgeometry.h‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,8 +1533,7 @@ class CORE_EXPORT QgsGeometry
15331533
* Filters the vertices from the geometry in place, removing any which do not return true for the \a filter function
15341534
* check. Has no effect when called on a single point geometry.
15351535
*
1536-
* Depending on the \a filter used, this may result in an invalid geometry. However, CurvePolygon rings which are no longer
1537-
* valid rings will be automatically removed after filtering.
1536+
* Depending on the \a filter used, this may result in an invalid geometry.
15381537
*
15391538
* \note Not available in Python bindings
15401539
* \since QGIS 3.2

‎tests/src/core/testqgsgeometry.cpp‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6317,7 +6317,22 @@ void TestQgsGeometry::polygon()
63176317
filterPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) );
63186318
filterPolygon.addInteriorRing( filterPolygonRing.clone() );
63196319
filterPolygon.filterVertices( filter );
6320-
QCOMPARE( filterPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((11 2 3 4, 11 12 13 14, 11 22 23 24, 11 2 3 4),(10 2 5 6, 11.01 2.01 15 16, 11 2.01 25 26, 11 2 5 6, 10 2 5 6))" ) );
6320+
QCOMPARE( filterPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((11 2 3 4, 11 12 13 14, 11 22 23 24, 11 2 3 4),(10 2 5 6, 11.01 2.01 15 16, 11 2.01 25 26, 11 2 5 6, 10 2 5 6),(11.01 2.01 15 16, 11 2.01 25 26))" ) );
6321+
6322+
// remove invalid rings
6323+
QgsPolygon invalidRingPolygon;
6324+
invalidRingPolygon.removeInvalidRings(); // no crash
6325+
QgsLineString removeInvalidPolygonRing;
6326+
removeInvalidPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 22, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) );
6327+
invalidRingPolygon.setExteriorRing( removeInvalidPolygonRing.clone() );
6328+
invalidRingPolygon.removeInvalidRings();
6329+
QCOMPARE( invalidRingPolygon.asWkt(), QStringLiteral( "PolygonZM ((11 2 3 4, 4 12 13 14, 11 12 13 14, 11 22 23 24, 11 2 3 4))" ) );
6330+
removeInvalidPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) );
6331+
invalidRingPolygon.addInteriorRing( removeInvalidPolygonRing.clone() );
6332+
removeInvalidPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) );
6333+
invalidRingPolygon.addInteriorRing( removeInvalidPolygonRing.clone() );
6334+
invalidRingPolygon.removeInvalidRings();
6335+
QCOMPARE( invalidRingPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((11 2 3 4, 4 12 13 14, 11 12 13 14, 11 22 23 24, 11 2 3 4),(1 2 5 6, 11.01 2.01 15 16, 11 2.01 25 26, 1 2 5 6))" ) );
63216336
}
63226337

63236338
void TestQgsGeometry::triangle()

0 commit comments

Comments
 (0)