mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
Add method to QgsCurvePolygon to force RHR, ensuring standard ring orientation
This commit is contained in:
parent
c22364d45e
commit
27e1ef5c1c
@ -136,6 +136,17 @@ For example, this removes unclosed rings and rings with less than 4 vertices.
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
||||
void forceRHR();
|
||||
%Docstring
|
||||
Forces the geometry to respect the Right-Hand-Rule, in which the area that is
|
||||
bounded by the polygon is to the right of the boundary. In particular, the exterior
|
||||
ring is oriented in a clockwise direction and the interior rings in a counter-clockwise
|
||||
direction.
|
||||
|
||||
.. versionadded:: 3.6
|
||||
%End
|
||||
|
||||
virtual void draw( QPainter &p ) const;
|
||||
|
||||
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) throw( QgsCsException );
|
||||
|
@ -705,6 +705,33 @@ void QgsCurvePolygon::removeInvalidRings()
|
||||
mInteriorRings = validRings;
|
||||
}
|
||||
|
||||
void QgsCurvePolygon::forceRHR()
|
||||
{
|
||||
if ( mExteriorRing && mExteriorRing->orientation() != QgsCurve::Clockwise )
|
||||
{
|
||||
// flip exterior ring orientation
|
||||
std::unique_ptr< QgsCurve > flipped( mExteriorRing->reversed() );
|
||||
mExteriorRing = std::move( flipped );
|
||||
}
|
||||
|
||||
QVector<QgsCurve *> validRings;
|
||||
for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
|
||||
{
|
||||
if ( curve && curve->orientation() != QgsCurve::CounterClockwise )
|
||||
{
|
||||
// flip interior ring orientation
|
||||
QgsCurve *flipped = curve->reversed();
|
||||
validRings << flipped;
|
||||
delete curve;
|
||||
}
|
||||
else
|
||||
{
|
||||
validRings << curve;
|
||||
}
|
||||
}
|
||||
mInteriorRings = validRings;
|
||||
}
|
||||
|
||||
void QgsCurvePolygon::draw( QPainter &p ) const
|
||||
{
|
||||
if ( !mExteriorRing )
|
||||
|
@ -133,6 +133,17 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
||||
*/
|
||||
void removeInvalidRings();
|
||||
|
||||
|
||||
/**
|
||||
* Forces the geometry to respect the Right-Hand-Rule, in which the area that is
|
||||
* bounded by the polygon is to the right of the boundary. In particular, the exterior
|
||||
* ring is oriented in a clockwise direction and the interior rings in a counter-clockwise
|
||||
* direction.
|
||||
*
|
||||
* \since QGIS 3.6
|
||||
*/
|
||||
void forceRHR();
|
||||
|
||||
void draw( QPainter &p ) const override;
|
||||
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) override SIP_THROW( QgsCsException );
|
||||
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
|
||||
|
@ -6596,6 +6596,25 @@ void TestQgsGeometry::polygon()
|
||||
invalidRingPolygon.addInteriorRing( removeInvalidPolygonRing.clone() );
|
||||
invalidRingPolygon.removeInvalidRings();
|
||||
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))" ) );
|
||||
|
||||
// force RHR
|
||||
QgsPolygon rhr;
|
||||
rhr.forceRHR(); // no crash
|
||||
rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4))" ) );
|
||||
rhr.forceRHR();
|
||||
QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4))" ) );
|
||||
rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 100 0 13 14, 100 100 23 24, 0 100 23 24, 0 0 3 4))" ) );
|
||||
rhr.forceRHR();
|
||||
QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 23 24, 100 100 23 24, 100 0 13 14, 0 0 3 4))" ) );
|
||||
rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 20 10 3 4, 20 20 4, 5, 10 20 6 8, 10 10 1 2))" ) );
|
||||
rhr.forceRHR();
|
||||
QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 20 10 3 4, 10 20 6 8, 10 10 1 2))" ) );
|
||||
rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 100 0 13 14, 100 100 13 14, 0 100 23 24, 0 0 3 4),(10 10 1 2, 20 10 3 4, 20 20 4, 5, 10 20 6 8, 10 10 1 2))" ) );
|
||||
rhr.forceRHR();
|
||||
QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 23 24, 100 100 13 14, 100 0 13 14, 0 0 3 4),(10 10 1 2, 20 10 3 4, 10 20 6 8, 10 10 1 2))" ) );
|
||||
rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 10 20 3 4, 20 10 6 8, 10 10 1 2))" ) );
|
||||
rhr.forceRHR();
|
||||
QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 20 10 6 8, 10 20 3 4, 10 10 1 2))" ) );
|
||||
}
|
||||
|
||||
void TestQgsGeometry::triangle()
|
||||
|
Loading…
x
Reference in New Issue
Block a user