Skip to content

Commit 8f0cc50

Browse files
author
g_j_m
committed
Fix for ticket #71.
Problem was with the use of the haversine formula beyond it's valid range of latitude/longitude pairs git-svn-id: http://svn.osgeo.org/qgis/trunk@5296 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 191d62b commit 8f0cc50

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

src/core/qgsscalecalculator.cpp

+33-17
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,39 @@ double QgsScaleCalculator::calculateGeographicDistance(QgsRect &mapExtent)
7979
// We'll use the middle latitude for the calculation
8080
// Note this is an approximation (although very close) but calculating scale
8181
// for geographic data over large extents is quasi-meaningless
82-
double lat1 = (mapExtent.yMax() - mapExtent.yMin())/2 + mapExtent.yMin();
83-
double lat2 = lat1;
84-
double lon1 = mapExtent.xMin();
85-
double lon2 = mapExtent.xMax();
86-
double dlon = lon2 - lon1;
87-
double dlat = lat2 - lat1;
88-
double rads = (4 * atan(1.0))/180;
89-
double a = pow((sin(dlat*rads/2)),2) +
90-
cos(lat1 *rads) * cos(lat2 *rads) *pow(sin(dlon*rads/2),2);
91-
double c = 2 * atan2(sqrt(a), sqrt(1-a));
92-
// calculate radius of earth
93-
double ra = 6378;
94-
// unused! double rb = 6357;
95-
double e = .081082;
96-
double R = ra* sqrt(1-pow(e,2))/(1 - pow(e,2)*pow(sin(lat1*rads),2));
97-
double d = c *R; // kilometers;
98-
double meters = d * 1000.0;
82+
83+
// The distance between two points on a sphere can be estimated
84+
// using the Haversine formula. This gives the shortest distance
85+
// between two points on the sphere. However, what we're after is
86+
// the distance from the left of the given extent and the right of
87+
// it. This is not necessarily the shortest distance between two
88+
// points on a sphere.
89+
//
90+
// The code below uses the Haversine formula, but with some changes
91+
// to cope with the above problem, and also to deal with the extent
92+
// possibly extending beyond +/-180 degrees:
93+
//
94+
// - Use the Halversine formula to calculate the distance from -90 to
95+
// +90 degrees at the mean latitude.
96+
// - Scale this distance by the number of degrees between
97+
// mapExtent.xMin() and mapExtent.xMax();
98+
// - For a slight improvemnt, allow for the ellipsoid shape of earth.
99+
100+
101+
// For a longitude change of 180 degrees
102+
double lat = (mapExtent.yMax() + mapExtent.yMin()) * 0.5;
103+
const static double rads = (4.0 * atan(1.0))/180.0;
104+
double a = pow(cos(lat * rads), 2);
105+
double c = 2.0 * atan2(sqrt(a), sqrt(1.0-a));
106+
const static double ra = 6378000; // [m]
107+
const static double rb = 6357000; // [m]
108+
// The eccentricity. This comes from sqrt(1.0 - rb*rb/(ra*ra));
109+
const static double e = 0.0810820288;
110+
double radius = ra * (1.0 - e*e) /
111+
pow(1.0 - e*e*sin(lat*rads)*sin(lat*rads), 1.5);
112+
double meters = (mapExtent.xMax() - mapExtent.xMin()) / 180.0 * radius * c;
113+
99114
QgsDebugMsg("Distance across map extent (m): " + QString::number(meters));
115+
100116
return meters;
101117
}

0 commit comments

Comments
 (0)