Skip to content

Commit 7882fe2

Browse files
committed
Add methods for comparison of QgsPoint, QgsPolyline and QgsPolygon
These methods allow for fuzzy comparison of coordinates with a specified tolerance.
1 parent 54a58b9 commit 7882fe2

File tree

8 files changed

+149
-2
lines changed

8 files changed

+149
-2
lines changed

python/core/qgsgeometry.sip

+22
Original file line numberDiff line numberDiff line change
@@ -475,5 +475,27 @@ class QgsGeometry
475475
@returns the new computed QgsGeometry, or null
476476
*/
477477
static QgsGeometry *unaryUnion( const QList<QgsGeometry*>& geometryList ) /Factory/;
478+
479+
/** Compares two polylines for equality within a specified tolerance.
480+
* @param p1 first polyline
481+
* @param p2 second polyline
482+
* @param epsilon maximum difference for coordinates between the polylines
483+
* @returns true if polylines have the same number of points and all
484+
* points are equal within the specified tolerance
485+
* @note added in QGIS 2.9
486+
*/
487+
static bool compare( const QgsPolyline& p1, const QgsPolyline& p2, double epsilon = 4 * DBL_EPSILON );
488+
489+
/** Compares two polygons for equality within a specified tolerance.
490+
* @param p1 first polygon
491+
* @param p2 second polygon
492+
* @param epsilon maximum difference for coordinates between the polygons
493+
* @returns true if polygons have the same number of rings, and each ring has the same
494+
* number of points and all points are equal within the specified tolerance
495+
* @note added in QGIS 2.9
496+
*/
497+
static bool compare( const QgsPolygon& p1, const QgsPolygon& p2, double epsilon = 4 * DBL_EPSILON );
498+
499+
478500
}; // class QgsGeometry
479501

python/core/qgspoint.sip

+8
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ class QgsPoint
113113
/**Calculates azimuth between this point and other one (clockwise in degree, starting from north) */
114114
double azimuth( const QgsPoint& other );
115115

116+
/** Compares this point with another point with a fuzzy tolerance
117+
* @param other point to compare with
118+
* @param epsilon maximum difference for coordinates between the points
119+
* @returns true if points are equal within specified tolerance
120+
* @note added in QGIS 2.9
121+
*/
122+
bool compare( const QgsPoint &other, double epsilon = 4 * DBL_EPSILON ) const;
123+
116124
//! equality operator
117125
bool operator==( const QgsPoint &other );
118126

src/core/qgsgeometry.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -6632,3 +6632,29 @@ QgsGeometry *QgsGeometry::unaryUnion( const QList<QgsGeometry*> &geometryList )
66326632
ret->fromGeos( geomUnion );
66336633
return ret;
66346634
}
6635+
6636+
bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
6637+
{
6638+
if ( p1.count() != p2.count() )
6639+
return false;
6640+
6641+
for ( int i = 0; i < p1.count(); ++i )
6642+
{
6643+
if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
6644+
return false;
6645+
}
6646+
return true;
6647+
}
6648+
6649+
bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
6650+
{
6651+
if ( p1.count() != p2.count() )
6652+
return false;
6653+
6654+
for ( int i = 0; i < p1.count(); ++i )
6655+
{
6656+
if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
6657+
return false;
6658+
}
6659+
return true;
6660+
}

src/core/qgsgeometry.h

+22-2
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,26 @@ class CORE_EXPORT QgsGeometry
521521
*/
522522
static QgsGeometry *unaryUnion( const QList<QgsGeometry*>& geometryList );
523523

524+
/** Compares two polylines for equality within a specified tolerance.
525+
* @param p1 first polyline
526+
* @param p2 second polyline
527+
* @param epsilon maximum difference for coordinates between the polylines
528+
* @returns true if polylines have the same number of points and all
529+
* points are equal within the specified tolerance
530+
* @note added in QGIS 2.9
531+
*/
532+
static bool compare( const QgsPolyline& p1, const QgsPolyline& p2, double epsilon = 4 * DBL_EPSILON );
533+
534+
/** Compares two polygons for equality within a specified tolerance.
535+
* @param p1 first polygon
536+
* @param p2 second polygon
537+
* @param epsilon maximum difference for coordinates between the polygons
538+
* @returns true if polygons have the same number of rings, and each ring has the same
539+
* number of points and all points are equal within the specified tolerance
540+
* @note added in QGIS 2.9
541+
*/
542+
static bool compare( const QgsPolygon& p1, const QgsPolygon& p2, double epsilon = 4 * DBL_EPSILON );
543+
524544
private:
525545
// Private variables
526546

@@ -687,7 +707,7 @@ class CORE_EXPORT QgsWkbPtr
687707
inline const QgsWkbPtr &operator>>( char &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
688708
inline const QgsWkbPtr &operator>>( QGis::WkbType &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
689709
#ifdef QT_ARCH_ARM
690-
inline const QgsWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v=d; return *this; }
710+
inline const QgsWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v = d; return *this; }
691711
#endif
692712

693713
inline QgsWkbPtr &operator<<( const double &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
@@ -717,7 +737,7 @@ class CORE_EXPORT QgsConstWkbPtr
717737
inline const QgsConstWkbPtr &operator>>( char &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
718738
inline const QgsConstWkbPtr &operator>>( QGis::WkbType &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
719739
#ifdef QT_ARCH_ARM
720-
inline const QgsConstWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v=d; return *this; }
740+
inline const QgsConstWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v = d; return *this; }
721741
#endif
722742

723743
inline void operator+=( int n ) { mP += n; }

src/core/qgspoint.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ double QgsPoint::azimuth( const QgsPoint& other )
347347
return ( atan2( dx, dy ) * 180.0 / M_PI );
348348
}
349349

350+
bool QgsPoint::compare( const QgsPoint &other, double epsilon ) const
351+
{
352+
return ( qgsDoubleNear( m_x, other.x(), epsilon ) && qgsDoubleNear( m_y, other.y(), epsilon ) );
353+
}
354+
350355
// operators
351356
bool QgsPoint::operator==( const QgsPoint & other )
352357
{

src/core/qgspoint.h

+8
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ class CORE_EXPORT QgsPoint
189189
/**Calculates azimuth between this point and other one (clockwise in degree, starting from north) */
190190
double azimuth( const QgsPoint& other );
191191

192+
/** Compares this point with another point with a fuzzy tolerance
193+
* @param other point to compare with
194+
* @param epsilon maximum difference for coordinates between the points
195+
* @returns true if points are equal within specified tolerance
196+
* @note added in QGIS 2.9
197+
*/
198+
bool compare( const QgsPoint &other, double epsilon = 4 * DBL_EPSILON ) const;
199+
192200
//! equality operator
193201
bool operator==( const QgsPoint &other );
194202

tests/src/core/testqgsgeometry.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ class TestQgsGeometry : public QObject
5757
void asQPointF();
5858
void asQPolygonF();
5959

60+
void comparePolylines();
61+
void comparePolygons();
62+
6063
// MK, Disabled 14.11.2014
6164
// Too unclear what exactly should be tested and which variations are allowed for the line
6265
#if 0
@@ -300,6 +303,48 @@ void TestQgsGeometry::asQPolygonF()
300303
QVERIFY( fromBad.isEmpty() );
301304
}
302305

306+
void TestQgsGeometry::comparePolylines()
307+
{
308+
QgsPolyline line1;
309+
line1 << mPoint1 << mPoint2 << mPoint3;
310+
QgsPolyline line2;
311+
line2 << mPoint1 << mPoint2 << mPoint3;
312+
QVERIFY( QgsGeometry::compare( line1, line2 ) );
313+
314+
//different number of nodes
315+
QgsPolyline line3;
316+
line3 << mPoint1 << mPoint2 << mPoint3 << mPoint4;
317+
QVERIFY( !QgsGeometry::compare( line1, line3 ) );
318+
319+
//different nodes
320+
QgsPolyline line4;
321+
line3 << mPoint1 << mPointA << mPoint3 << mPoint4;
322+
QVERIFY( !QgsGeometry::compare( line3, line4 ) );
323+
}
324+
325+
void TestQgsGeometry::comparePolygons()
326+
{
327+
QgsPolyline ring1;
328+
ring1 << mPoint1 << mPoint2 << mPoint3 << mPoint1;
329+
QgsPolyline ring2;
330+
ring2 << mPoint4 << mPointA << mPointB << mPoint4;
331+
QgsPolygon poly1;
332+
poly1 << ring1 << ring2;
333+
QgsPolygon poly2;
334+
poly2 << ring1 << ring2;
335+
QVERIFY( QgsGeometry::compare( poly1, poly2 ) );
336+
337+
//different number of rings
338+
QgsPolygon poly3;
339+
poly3 << ring1;
340+
QVERIFY( !QgsGeometry::compare( poly1, poly3 ) );
341+
342+
//different rings
343+
QgsPolygon poly4;
344+
poly4 << ring2;
345+
QVERIFY( !QgsGeometry::compare( poly3, poly4 ) );
346+
}
347+
303348
void TestQgsGeometry::initTestCase()
304349
{
305350
//

tests/src/core/testqgspoint.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class TestQgsPoint: public QObject
5151
void sqrDist();
5252
void multiply();
5353
void onSegment();
54+
void compare();
55+
5456
private:
5557
QgsPoint mPoint1;
5658
QgsPoint mPoint2;
@@ -591,5 +593,16 @@ void TestQgsPoint::onSegment()
591593

592594
}
593595

596+
void TestQgsPoint::compare()
597+
{
598+
QgsPoint point1( 5.000000000001, 9.0 );
599+
QgsPoint point2( 5.0, 8.999999999999999 );
600+
QVERIFY( point1.compare( point2, 0.00000001 ) );
601+
QgsPoint point3( 5.0, 6.0 );
602+
QVERIFY( !( point3.compare( point1 ) ) );
603+
QgsPoint point4( 10 / 3.0, 12 / 7.0 );
604+
QVERIFY( point4.compare( QgsPoint( 10 / 3.0, 12 / 7.0 ) ) );
605+
}
606+
594607
QTEST_MAIN( TestQgsPoint )
595608
#include "testqgspoint.moc"

0 commit comments

Comments
 (0)