@@ -79,23 +79,39 @@ double QgsScaleCalculator::calculateGeographicDistance(QgsRect &mapExtent)
79
79
// We'll use the middle latitude for the calculation
80
80
// Note this is an approximation (although very close) but calculating scale
81
81
// 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
+
99
114
QgsDebugMsg (" Distance across map extent (m): " + QString::number (meters));
115
+
100
116
return meters;
101
117
}
0 commit comments