Add methods for comparison of QgsPoint, QgsPolyline and QgsPolygon

These methods allow for fuzzy comparison of coordinates with a
specified tolerance.
This commit is contained in:
Nyall Dawson 2015-03-19 19:48:57 +11:00
parent 54a58b984c
commit 7882fe2f25
8 changed files with 149 additions and 2 deletions

View File

@ -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

View File

@ -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 );

View File

@ -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;
}

View File

@ -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
@ -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; }
@ -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; }

View File

@ -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 )
{

View File

@ -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 );

View File

@ -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
@ -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()
{
//

View File

@ -51,6 +51,8 @@ class TestQgsPoint: public QObject
void sqrDist();
void multiply();
void onSegment();
void compare();
private:
QgsPoint mPoint1;
QgsPoint mPoint2;
@ -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"