Skip to content

Commit

Permalink
Add methods for comparison of QgsPoint, QgsPolyline and QgsPolygon
Browse files Browse the repository at this point in the history
These methods allow for fuzzy comparison of coordinates with a
specified tolerance.
  • Loading branch information
nyalldawson committed Mar 19, 2015
1 parent 54a58b9 commit 7882fe2
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 2 deletions.
22 changes: 22 additions & 0 deletions python/core/qgsgeometry.sip
Expand Up @@ -475,5 +475,27 @@ class QgsGeometry
@returns the new computed QgsGeometry, or null
*/
static QgsGeometry *unaryUnion( const QList<QgsGeometry*>& geometryList ) /Factory/;

/** Compares two polylines for equality within a specified tolerance.
* @param p1 first polyline
* @param p2 second polyline
* @param epsilon maximum difference for coordinates between the polylines
* @returns true if polylines have the same number of points and all
* points are equal within the specified tolerance
* @note added in QGIS 2.9
*/
static bool compare( const QgsPolyline& p1, const QgsPolyline& p2, double epsilon = 4 * DBL_EPSILON );

/** Compares two polygons for equality within a specified tolerance.
* @param p1 first polygon
* @param p2 second polygon
* @param epsilon maximum difference for coordinates between the polygons
* @returns true if polygons have the same number of rings, and each ring has the same
* number of points and all points are equal within the specified tolerance
* @note added in QGIS 2.9
*/
static bool compare( const QgsPolygon& p1, const QgsPolygon& p2, double epsilon = 4 * DBL_EPSILON );


}; // class QgsGeometry

8 changes: 8 additions & 0 deletions python/core/qgspoint.sip
Expand Up @@ -113,6 +113,14 @@ class QgsPoint
/**Calculates azimuth between this point and other one (clockwise in degree, starting from north) */
double azimuth( const QgsPoint& other );

/** Compares this point with another point with a fuzzy tolerance
* @param other point to compare with
* @param epsilon maximum difference for coordinates between the points
* @returns true if points are equal within specified tolerance
* @note added in QGIS 2.9
*/
bool compare( const QgsPoint &other, double epsilon = 4 * DBL_EPSILON ) const;

//! equality operator
bool operator==( const QgsPoint &other );

Expand Down
26 changes: 26 additions & 0 deletions src/core/qgsgeometry.cpp
Expand Up @@ -6632,3 +6632,29 @@ QgsGeometry *QgsGeometry::unaryUnion( const QList<QgsGeometry*> &geometryList )
ret->fromGeos( geomUnion );
return ret;
}

bool QgsGeometry::compare( const QgsPolyline &p1, const QgsPolyline &p2, double epsilon )
{
if ( p1.count() != p2.count() )
return false;

for ( int i = 0; i < p1.count(); ++i )
{
if ( !p1.at( i ).compare( p2.at( i ), epsilon ) )
return false;
}
return true;
}

bool QgsGeometry::compare( const QgsPolygon &p1, const QgsPolygon &p2, double epsilon )
{
if ( p1.count() != p2.count() )
return false;

for ( int i = 0; i < p1.count(); ++i )
{
if ( !QgsGeometry::compare( p1.at( i ), p2.at( i ), epsilon ) )
return false;
}
return true;
}
24 changes: 22 additions & 2 deletions src/core/qgsgeometry.h
Expand Up @@ -521,6 +521,26 @@ class CORE_EXPORT QgsGeometry
*/
static QgsGeometry *unaryUnion( const QList<QgsGeometry*>& geometryList );

/** Compares two polylines for equality within a specified tolerance.
* @param p1 first polyline
* @param p2 second polyline
* @param epsilon maximum difference for coordinates between the polylines
* @returns true if polylines have the same number of points and all
* points are equal within the specified tolerance
* @note added in QGIS 2.9
*/
static bool compare( const QgsPolyline& p1, const QgsPolyline& p2, double epsilon = 4 * DBL_EPSILON );

/** Compares two polygons for equality within a specified tolerance.
* @param p1 first polygon
* @param p2 second polygon
* @param epsilon maximum difference for coordinates between the polygons
* @returns true if polygons have the same number of rings, and each ring has the same
* number of points and all points are equal within the specified tolerance
* @note added in QGIS 2.9
*/
static bool compare( const QgsPolygon& p1, const QgsPolygon& p2, double epsilon = 4 * DBL_EPSILON );

private:
// Private variables

Expand Down Expand Up @@ -687,7 +707,7 @@ class CORE_EXPORT QgsWkbPtr
inline const QgsWkbPtr &operator>>( char &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsWkbPtr &operator>>( QGis::WkbType &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
#ifdef QT_ARCH_ARM
inline const QgsWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v=d; return *this; }
inline const QgsWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v = d; return *this; }
#endif

inline QgsWkbPtr &operator<<( const double &v ) { memcpy( mP, &v, sizeof( v ) ); mP += sizeof( v ); return *this; }
Expand Down Expand Up @@ -717,7 +737,7 @@ class CORE_EXPORT QgsConstWkbPtr
inline const QgsConstWkbPtr &operator>>( char &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
inline const QgsConstWkbPtr &operator>>( QGis::WkbType &v ) const { memcpy( &v, mP, sizeof( v ) ); mP += sizeof( v ); return *this; }
#ifdef QT_ARCH_ARM
inline const QgsConstWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v=d; return *this; }
inline const QgsConstWkbPtr &operator>>( qreal &v ) const { double d; memcpy( &d, mP, sizeof( d ) ); mP += sizeof( d ); v = d; return *this; }
#endif

inline void operator+=( int n ) { mP += n; }
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgspoint.cpp
Expand Up @@ -347,6 +347,11 @@ double QgsPoint::azimuth( const QgsPoint& other )
return ( atan2( dx, dy ) * 180.0 / M_PI );
}

bool QgsPoint::compare( const QgsPoint &other, double epsilon ) const
{
return ( qgsDoubleNear( m_x, other.x(), epsilon ) && qgsDoubleNear( m_y, other.y(), epsilon ) );
}

// operators
bool QgsPoint::operator==( const QgsPoint & other )
{
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgspoint.h
Expand Up @@ -189,6 +189,14 @@ class CORE_EXPORT QgsPoint
/**Calculates azimuth between this point and other one (clockwise in degree, starting from north) */
double azimuth( const QgsPoint& other );

/** Compares this point with another point with a fuzzy tolerance
* @param other point to compare with
* @param epsilon maximum difference for coordinates between the points
* @returns true if points are equal within specified tolerance
* @note added in QGIS 2.9
*/
bool compare( const QgsPoint &other, double epsilon = 4 * DBL_EPSILON ) const;

//! equality operator
bool operator==( const QgsPoint &other );

Expand Down
45 changes: 45 additions & 0 deletions tests/src/core/testqgsgeometry.cpp
Expand Up @@ -57,6 +57,9 @@ class TestQgsGeometry : public QObject
void asQPointF();
void asQPolygonF();

void comparePolylines();
void comparePolygons();

// MK, Disabled 14.11.2014
// Too unclear what exactly should be tested and which variations are allowed for the line
#if 0
Expand Down Expand Up @@ -300,6 +303,48 @@ void TestQgsGeometry::asQPolygonF()
QVERIFY( fromBad.isEmpty() );
}

void TestQgsGeometry::comparePolylines()
{
QgsPolyline line1;
line1 << mPoint1 << mPoint2 << mPoint3;
QgsPolyline line2;
line2 << mPoint1 << mPoint2 << mPoint3;
QVERIFY( QgsGeometry::compare( line1, line2 ) );

//different number of nodes
QgsPolyline line3;
line3 << mPoint1 << mPoint2 << mPoint3 << mPoint4;
QVERIFY( !QgsGeometry::compare( line1, line3 ) );

//different nodes
QgsPolyline line4;
line3 << mPoint1 << mPointA << mPoint3 << mPoint4;
QVERIFY( !QgsGeometry::compare( line3, line4 ) );
}

void TestQgsGeometry::comparePolygons()
{
QgsPolyline ring1;
ring1 << mPoint1 << mPoint2 << mPoint3 << mPoint1;
QgsPolyline ring2;
ring2 << mPoint4 << mPointA << mPointB << mPoint4;
QgsPolygon poly1;
poly1 << ring1 << ring2;
QgsPolygon poly2;
poly2 << ring1 << ring2;
QVERIFY( QgsGeometry::compare( poly1, poly2 ) );

//different number of rings
QgsPolygon poly3;
poly3 << ring1;
QVERIFY( !QgsGeometry::compare( poly1, poly3 ) );

//different rings
QgsPolygon poly4;
poly4 << ring2;
QVERIFY( !QgsGeometry::compare( poly3, poly4 ) );
}

void TestQgsGeometry::initTestCase()
{
//
Expand Down
13 changes: 13 additions & 0 deletions tests/src/core/testqgspoint.cpp
Expand Up @@ -51,6 +51,8 @@ class TestQgsPoint: public QObject
void sqrDist();
void multiply();
void onSegment();
void compare();

private:
QgsPoint mPoint1;
QgsPoint mPoint2;
Expand Down Expand Up @@ -591,5 +593,16 @@ void TestQgsPoint::onSegment()

}

void TestQgsPoint::compare()
{
QgsPoint point1( 5.000000000001, 9.0 );
QgsPoint point2( 5.0, 8.999999999999999 );
QVERIFY( point1.compare( point2, 0.00000001 ) );
QgsPoint point3( 5.0, 6.0 );
QVERIFY( !( point3.compare( point1 ) ) );
QgsPoint point4( 10 / 3.0, 12 / 7.0 );
QVERIFY( point4.compare( QgsPoint( 10 / 3.0, 12 / 7.0 ) ) );
}

QTEST_MAIN( TestQgsPoint )
#include "testqgspoint.moc"

0 comments on commit 7882fe2

Please sign in to comment.