From a19886d2f5d8b4acc3c4aac3cd887619cd81bf9f Mon Sep 17 00:00:00 2001 From: Martin Dobias Date: Tue, 10 Jun 2014 16:23:02 +0700 Subject: [PATCH] Fix #9951 (perimeter completely wrong with OTF on) With OTF on and computation on an ellipsoid, the coordinates were transformed twice(!) when measuring perimeter. --- python/core/qgsdistancearea.sip | 5 ++++ src/core/qgsdistancearea.cpp | 46 +++++++++++++++++++++++++++++++-- src/core/qgsdistancearea.h | 5 ++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/python/core/qgsdistancearea.sip b/python/core/qgsdistancearea.sip index e995382da05..d900748f533 100644 --- a/python/core/qgsdistancearea.sip +++ b/python/core/qgsdistancearea.sip @@ -99,6 +99,11 @@ class QgsDistanceArea double computeDistanceBearing( const QgsPoint& p1, const QgsPoint& p2, double* course1 = NULL, double* course2 = NULL ); + //! uses flat / planimetric / Euclidean distance + double computeDistanceFlat( const QgsPoint& p1, const QgsPoint& p2 ); + + //! calculate distance with given coordinates (does not do a transform anymore) + double computeDistance( const QList& points ); /** calculates area of polygon on ellipsoid diff --git a/src/core/qgsdistancearea.cpp b/src/core/qgsdistancearea.cpp index 5f7409d3063..c33ba7abcea 100644 --- a/src/core/qgsdistancearea.cpp +++ b/src/core/qgsdistancearea.cpp @@ -474,7 +474,7 @@ double QgsDistanceArea::measureLine( const QgsPoint &p1, const QgsPoint &p2 ) else { QgsDebugMsgLevel( "Cartesian calculation on canvas coordinates", 4 ); - result = sqrt(( p2.x() - p1.x() ) * ( p2.x() - p1.x() ) + ( p2.y() - p1.y() ) * ( p2.y() - p1.y() ) ); + result = computeDistanceFlat( p1, p2 ); } } catch ( QgsCsException &cse ) @@ -565,7 +565,7 @@ const unsigned char *QgsDistanceArea::measurePolygon( const unsigned char* featu if ( idx == 0 ) { // exterior ring - *perimeter += measureLine( points ); + *perimeter += computeDistance( points ); } } } @@ -712,6 +712,48 @@ double QgsDistanceArea::computeDistanceBearing( return s; } +double QgsDistanceArea::computeDistanceFlat( const QgsPoint& p1, const QgsPoint& p2 ) +{ + return sqrt( ( p2.x() - p1.x() ) * ( p2.x() - p1.x() ) + ( p2.y() - p1.y() ) * ( p2.y() - p1.y() ) ); +} + +double QgsDistanceArea::computeDistance( const QList& points ) +{ + if ( points.size() < 2 ) + return 0; + + double total = 0; + QgsPoint p1, p2; + + try + { + p1 = points[0]; + + for ( QList::const_iterator i = points.begin(); i != points.end(); ++i ) + { + p2 = *i; + if ( mEllipsoidalMode && ( mEllipsoid != GEO_NONE ) ) + { + total += computeDistanceBearing( p1, p2 ); + } + else + { + total += computeDistanceFlat( p1, p2 ); + } + + p1 = p2; + } + + return total; + } + catch ( QgsCsException &cse ) + { + Q_UNUSED( cse ); + QgsMessageLog::logMessage( QObject::tr( "Caught a coordinate system exception while trying to transform a point. Unable to calculate line length." ) ); + return 0.0; + } +} + /////////////////////////////////////////////////////////// diff --git a/src/core/qgsdistancearea.h b/src/core/qgsdistancearea.h index 4cccbde0637..5c43c2200ff 100644 --- a/src/core/qgsdistancearea.h +++ b/src/core/qgsdistancearea.h @@ -130,6 +130,11 @@ class CORE_EXPORT QgsDistanceArea double computeDistanceBearing( const QgsPoint& p1, const QgsPoint& p2, double* course1 = NULL, double* course2 = NULL ); + //! uses flat / planimetric / Euclidean distance + double computeDistanceFlat( const QgsPoint& p1, const QgsPoint& p2 ); + + //! calculate distance with given coordinates (does not do a transform anymore) + double computeDistance( const QList& points ); /** calculates area of polygon on ellipsoid