Skip to content

Commit 4e18d54

Browse files
committed
Tests and fixes for QgsPolygonV2
- Setting exterior ring will force all interior rings to match dimensionality of exterior ring - add equality operator - use correct WKB types for rings when creating polygon from WKB - segmentize curves when setting exterior ring with curved segments - fix export to GML2/3 (should use LinearRing, not LineString as ring element tag)
1 parent 2f72b3b commit 4e18d54

19 files changed

+565
-30
lines changed

python/core/geometry/qgscircularstringv2.sip

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ class QgsCircularStringV2: public QgsCurveV2
88
QgsCircularStringV2();
99
~QgsCircularStringV2();
1010

11+
virtual bool operator==( const QgsCurveV2& other ) const;
12+
virtual bool operator!=( const QgsCurveV2& other ) const;
13+
1114
virtual QString geometryType() const;
1215
virtual int dimension() const;
1316
virtual QgsCircularStringV2* clone() const;

python/core/geometry/qgscompoundcurvev2.sip

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ class QgsCompoundCurveV2: public QgsCurveV2
1010
//QgsCompoundCurveV2 &operator=( const QgsCompoundCurveV2 & curve );
1111
~QgsCompoundCurveV2();
1212

13+
virtual bool operator==( const QgsCurveV2& other ) const;
14+
virtual bool operator!=( const QgsCurveV2& other ) const;
15+
1316
virtual QString geometryType() const;
1417
virtual int dimension() const;
1518
virtual QgsCompoundCurveV2* clone() const;

python/core/geometry/qgscurvepolygonv2.sip

+9-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,15 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
3939
QgsCurveV2* interiorRing( int i ) const;
4040
virtual QgsPolygonV2* toPolygon() const;
4141

42-
/** Sets exterior ring (takes ownership)*/
43-
void setExteriorRing( QgsCurveV2* ring /Transfer/ );
42+
/** Sets the exterior ring of the polygon. The CurvePolygon type will be updated to match the dimensionality
43+
* of the exterior ring. For instance, setting a 2D exterior ring on a 3D CurvePolygon will drop the z dimension
44+
* from the CurvePolygon and all interior rings.
45+
* @param ring new exterior ring. Ownership is transferred to the CurvePolygon.
46+
* @see setInteriorRings()
47+
* @see exteriorRing()
48+
*/
49+
virtual void setExteriorRing( QgsCurveV2* ring /Transfer/ );
50+
4451
/** Sets interior rings (takes ownership)*/
4552
void setInteriorRings( const QList<QgsCurveV2*>& rings );
4653
virtual void addInteriorRing( QgsCurveV2* ring /Transfer/ );

python/core/geometry/qgscurvev2.sip

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ class QgsCurveV2: public QgsAbstractGeometryV2
66
public:
77
QgsCurveV2();
88
virtual ~QgsCurveV2();
9+
10+
virtual bool operator==( const QgsCurveV2& other ) const = 0;
11+
virtual bool operator!=( const QgsCurveV2& other ) const = 0;
12+
13+
virtual QgsCurveV2* clone() const = 0;
14+
915
virtual QgsPointV2 startPoint() const = 0;
1016
virtual QgsPointV2 endPoint() const = 0;
1117
virtual bool isClosed() const;
@@ -29,7 +35,7 @@ class QgsCurveV2: public QgsAbstractGeometryV2
2935
virtual QgsCurveV2* reversed() const = 0 /Factory/;
3036

3137
/** Returns a geometry without curves. Caller takes ownership*/
32-
QgsAbstractGeometryV2* segmentize() const /Factory/;
38+
virtual QgsCurveV2* segmentize() const /Factory/;
3339

3440
virtual int vertexCount(int part = 0, int ring = 0) const;
3541
virtual int ringCount(int part = 0) const;

python/core/geometry/qgslinestringv2.sip

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ class QgsLineStringV2: public QgsCurveV2
1414
QgsLineStringV2();
1515
~QgsLineStringV2();
1616

17-
bool operator==( const QgsLineStringV2& other ) const;
18-
bool operator!=( const QgsLineStringV2& other ) const;
17+
bool operator==( const QgsCurveV2& other ) const;
18+
bool operator!=( const QgsCurveV2& other ) const;
1919

2020
/** Returns the specified point from inside the line string.
2121
* @param i index of point, starting at 0 for the first point

python/core/geometry/qgspolygonv2.sip

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ class QgsPolygonV2: public QgsCurvePolygonV2
77
public:
88
QgsPolygonV2();
99

10+
bool operator==( const QgsPolygonV2& other ) const;
11+
bool operator!=( const QgsPolygonV2& other ) const;
12+
1013
virtual QString geometryType() const;
1114
virtual QgsPolygonV2* clone() const;
1215

@@ -23,4 +26,6 @@ class QgsPolygonV2: public QgsCurvePolygonV2
2326
QgsPolygonV2* surfaceToPolygon() const;
2427

2528
void addInteriorRing( QgsCurveV2* ring /Transfer/ );
29+
//overridden to handle LineString25D rings
30+
virtual void setExteriorRing( QgsCurveV2* ring /Transfer/ );
2631
};

src/core/geometry/qgscircularstringv2.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ QgsCircularStringV2::~QgsCircularStringV2()
3636

3737
}
3838

39+
bool QgsCircularStringV2::operator==( const QgsCurveV2& other ) const
40+
{
41+
const QgsCircularStringV2* otherLine = dynamic_cast< const QgsCircularStringV2* >( &other );
42+
if ( !otherLine )
43+
return false;
44+
45+
return *otherLine == *this;
46+
}
47+
48+
bool QgsCircularStringV2::operator!=( const QgsCurveV2& other ) const
49+
{
50+
return !operator==( other );
51+
}
52+
3953
QgsCircularStringV2 *QgsCircularStringV2::clone() const
4054
{
4155
return new QgsCircularStringV2( *this );

src/core/geometry/qgscircularstringv2.h

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
3333
QgsCircularStringV2();
3434
~QgsCircularStringV2();
3535

36+
virtual bool operator==( const QgsCurveV2& other ) const override;
37+
virtual bool operator!=( const QgsCurveV2& other ) const override;
38+
3639
virtual QString geometryType() const override { return "CircularString"; }
3740
virtual int dimension() const override { return 1; }
3841
virtual QgsCircularStringV2* clone() const override;

src/core/geometry/qgscompoundcurvev2.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ QgsCompoundCurveV2::~QgsCompoundCurveV2()
3535
clear();
3636
}
3737

38+
bool QgsCompoundCurveV2::operator==( const QgsCurveV2& other ) const
39+
{
40+
const QgsCompoundCurveV2* otherCurve = dynamic_cast< const QgsCompoundCurveV2* >( &other );
41+
if ( !otherCurve )
42+
return false;
43+
44+
return *otherCurve == *this;
45+
}
46+
47+
bool QgsCompoundCurveV2::operator!=( const QgsCurveV2& other ) const
48+
{
49+
return !operator==( other );
50+
}
51+
3852
QgsCompoundCurveV2::QgsCompoundCurveV2( const QgsCompoundCurveV2& curve ): QgsCurveV2( curve )
3953
{
4054
Q_FOREACH ( const QgsCurveV2* c, curve.mCurves )

src/core/geometry/qgscompoundcurvev2.h

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
3434
QgsCompoundCurveV2& operator=( const QgsCompoundCurveV2& curve );
3535
~QgsCompoundCurveV2();
3636

37+
virtual bool operator==( const QgsCurveV2& other ) const override;
38+
virtual bool operator!=( const QgsCurveV2& other ) const override;
39+
3740
virtual QString geometryType() const override { return "CompoundCurve"; }
3841
virtual int dimension() const override { return 1; }
3942
virtual QgsCompoundCurveV2* clone() const override;

src/core/geometry/qgscurvepolygonv2.cpp

+26-4
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,18 @@ QDomElement QgsCurvePolygonV2::asGML2( QDomDocument& doc, int precision, const Q
291291
QDomElement elemPolygon = doc.createElementNS( ns, "Polygon" );
292292
QDomElement elemOuterBoundaryIs = doc.createElementNS( ns, "outerBoundaryIs" );
293293
QgsLineStringV2* exteriorLineString = exteriorRing()->curveToLine();
294-
elemOuterBoundaryIs.appendChild( exteriorLineString->asGML2( doc, precision, ns ) );
294+
QDomElement outerRing = exteriorLineString->asGML2( doc, precision, ns );
295+
outerRing.toElement().setTagName( "LinearRing" );
296+
elemOuterBoundaryIs.appendChild( outerRing );
295297
delete exteriorLineString;
296298
elemPolygon.appendChild( elemOuterBoundaryIs );
297299
QDomElement elemInnerBoundaryIs = doc.createElementNS( ns, "innerBoundaryIs" );
298300
for ( int i = 0, n = numInteriorRings(); i < n; ++i )
299301
{
300302
QgsLineStringV2* interiorLineString = interiorRing( i )->curveToLine();
301-
elemInnerBoundaryIs.appendChild( interiorLineString->asGML2( doc, precision, ns ) );
303+
QDomElement innerRing = interiorLineString->asGML2( doc, precision, ns );
304+
innerRing.toElement().setTagName( "LinearRing" );
305+
elemInnerBoundaryIs.appendChild( innerRing );
302306
delete interiorLineString;
303307
}
304308
elemPolygon.appendChild( elemInnerBoundaryIs );
@@ -309,12 +313,16 @@ QDomElement QgsCurvePolygonV2::asGML3( QDomDocument& doc, int precision, const Q
309313
{
310314
QDomElement elemCurvePolygon = doc.createElementNS( ns, "Polygon" );
311315
QDomElement elemExterior = doc.createElementNS( ns, "exterior" );
312-
elemExterior.appendChild( exteriorRing()->asGML2( doc, precision, ns ) );
316+
QDomElement outerRing = exteriorRing()->asGML2( doc, precision, ns );
317+
outerRing.toElement().setTagName( "LinearRing" );
318+
elemExterior.appendChild( outerRing );
313319
elemCurvePolygon.appendChild( elemExterior );
314320
QDomElement elemInterior = doc.createElementNS( ns, "interior" );
315321
for ( int i = 0, n = numInteriorRings(); i < n; ++i )
316322
{
317-
elemInterior.appendChild( interiorRing( i )->asGML2( doc, precision, ns ) );
323+
QDomElement innerRing = interiorRing( i )->asGML2( doc, precision, ns );
324+
innerRing.toElement().setTagName( "LinearRing" );
325+
elemInterior.appendChild( innerRing );
318326
}
319327
elemCurvePolygon.appendChild( elemInterior );
320328
return elemCurvePolygon;
@@ -468,6 +476,20 @@ void QgsCurvePolygonV2::setExteriorRing( QgsCurveV2* ring )
468476
{
469477
setZMTypeFromSubGeometry( ring, QgsWKBTypes::CurvePolygon );
470478
}
479+
480+
//match dimensionality for rings
481+
Q_FOREACH ( QgsCurveV2* ring, mInteriorRings )
482+
{
483+
if ( is3D() )
484+
ring->addZValue();
485+
else
486+
ring->dropZValue();
487+
488+
if ( isMeasure() )
489+
ring->addMValue();
490+
else
491+
ring->dropMValue();
492+
}
471493
}
472494

473495
void QgsCurvePolygonV2::setInteriorRings( const QList<QgsCurveV2*>& rings )

src/core/geometry/qgscurvepolygonv2.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,15 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
6565
QgsCurveV2* interiorRing( int i ) const;
6666
virtual QgsPolygonV2* toPolygon() const;
6767

68-
/** Sets exterior ring (takes ownership)*/
69-
void setExteriorRing( QgsCurveV2* ring );
68+
/** Sets the exterior ring of the polygon. The CurvePolygon type will be updated to match the dimensionality
69+
* of the exterior ring. For instance, setting a 2D exterior ring on a 3D CurvePolygon will drop the z dimension
70+
* from the CurvePolygon and all interior rings.
71+
* @param ring new exterior ring. Ownership is transferred to the CurvePolygon.
72+
* @see setInteriorRings()
73+
* @see exteriorRing()
74+
*/
75+
virtual void setExteriorRing( QgsCurveV2* ring );
76+
7077
/** Sets all interior rings (takes ownership)*/
7178
void setInteriorRings( const QList<QgsCurveV2*>& rings );
7279
/** Adds an interior ring to the geometry (takes ownership)*/
@@ -112,6 +119,7 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
112119

113120
QgsCurveV2* mExteriorRing;
114121
QList<QgsCurveV2*> mInteriorRings;
122+
115123
};
116124

117125
#endif // QGSCURVEPOLYGONV2_H

src/core/geometry/qgscurvev2.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ bool QgsCurveV2::nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const
7777
return pointAt( id.vertex, vertex, id.type );
7878
}
7979

80-
QgsAbstractGeometryV2* QgsCurveV2::segmentize() const
80+
QgsCurveV2* QgsCurveV2::segmentize() const
8181
{
8282
return curveToLine();
8383
}

src/core/geometry/qgscurvev2.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2
3535
QgsCurveV2();
3636
virtual ~QgsCurveV2();
3737

38+
virtual bool operator==( const QgsCurveV2& other ) const = 0;
39+
virtual bool operator!=( const QgsCurveV2& other ) const = 0;
40+
41+
virtual QgsCurveV2* clone() const override = 0;
42+
3843
/** Returns the starting point of the curve.
3944
* @see endPoint
4045
*/
@@ -96,7 +101,7 @@ class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2
96101
*/
97102
virtual QgsCurveV2* reversed() const = 0;
98103

99-
QgsAbstractGeometryV2* segmentize() const override;
104+
QgsCurveV2* segmentize() const override;
100105

101106
virtual int vertexCount( int /*part*/ = 0, int /*ring*/ = 0 ) const override { return numPoints(); }
102107
virtual int ringCount( int /*part*/ = 0 ) const override { return numPoints() > 0 ? 1 : 0; }

src/core/geometry/qgslinestringv2.cpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -41,31 +41,35 @@ QgsLineStringV2::QgsLineStringV2(): QgsCurveV2()
4141
QgsLineStringV2::~QgsLineStringV2()
4242
{}
4343

44-
bool QgsLineStringV2::operator==( const QgsLineStringV2& other ) const
44+
bool QgsLineStringV2::operator==( const QgsCurveV2& other ) const
4545
{
46-
if ( mWkbType != other.mWkbType )
46+
const QgsLineStringV2* otherLine = dynamic_cast< const QgsLineStringV2* >( &other );
47+
if ( !otherLine )
4748
return false;
4849

49-
if ( mX.count() != other.mX.count() )
50+
if ( mWkbType != otherLine->mWkbType )
51+
return false;
52+
53+
if ( mX.count() != otherLine->mX.count() )
5054
return false;
5155

5256
for ( int i = 0; i < mX.count(); ++i )
5357
{
54-
if ( !qgsDoubleNear( mX.at( i ), other.mX.at( i ) )
55-
|| !qgsDoubleNear( mY.at( i ), other.mY.at( i ) ) )
58+
if ( !qgsDoubleNear( mX.at( i ), otherLine->mX.at( i ) )
59+
|| !qgsDoubleNear( mY.at( i ), otherLine->mY.at( i ) ) )
5660
return false;
5761

58-
if ( is3D() && !qgsDoubleNear( mZ.at( i ), other.mZ.at( i ) ) )
62+
if ( is3D() && !qgsDoubleNear( mZ.at( i ), otherLine->mZ.at( i ) ) )
5963
return false;
6064

61-
if ( isMeasure() && !qgsDoubleNear( mM.at( i ), other.mM.at( i ) ) )
65+
if ( isMeasure() && !qgsDoubleNear( mM.at( i ), otherLine->mM.at( i ) ) )
6266
return false;
6367
}
6468

6569
return true;
6670
}
6771

68-
bool QgsLineStringV2::operator!=( const QgsLineStringV2& other ) const
72+
bool QgsLineStringV2::operator!=( const QgsCurveV2& other ) const
6973
{
7074
return !operator==( other );
7175
}

src/core/geometry/qgslinestringv2.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
3939
QgsLineStringV2();
4040
~QgsLineStringV2();
4141

42-
bool operator==( const QgsLineStringV2& other ) const;
43-
bool operator!=( const QgsLineStringV2& other ) const;
42+
bool operator==( const QgsCurveV2& other ) const override;
43+
bool operator!=( const QgsCurveV2& other ) const override;
4444

4545
/** Returns the specified point from inside the line string.
4646
* @param i index of point, starting at 0 for the first point

0 commit comments

Comments
 (0)