refactor dLat/dLon <-> meters calcs and use slightly better WGS84 constants

This commit is contained in:
Bryan Housel
2014-06-23 16:23:04 -04:00
parent 71d44d561e
commit 2723c65506
3 changed files with 34 additions and 22 deletions
+30 -3
View File
@@ -21,11 +21,38 @@ iD.geo.euclideanDistance = function(a, b) {
var x = a[0] - b[0], y = a[1] - b[1];
return Math.sqrt((x * x) + (y * y));
};
// using WGS84 polar radius (6356752.314245179 m)
// const = 2 * PI * r / 360
iD.geo.latToMeters = function(dLat) {
return dLat * 110946.257617;
};
// using WGS84 equatorial radius (6378137.0 m)
// const = 2 * PI * r / 360
iD.geo.lonToMeters = function(dLon, atLat) {
return Math.abs(atLat) >= 90 ? 0 :
dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
};
// using WGS84 polar radius (6356752.314245179 m)
// const = 2 * PI * r / 360
iD.geo.metersToLat = function(m) {
return m / 110946.257617;
};
// using WGS84 equatorial radius (6378137.0 m)
// const = 2 * PI * r / 360
iD.geo.metersToLon = function(m, atLat) {
return Math.abs(atLat) >= 90 ? 0 :
m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
};
// Equirectangular approximation of spherical distances on Earth
iD.geo.sphericalDistance = function(a, b) {
var x = Math.cos(a[1]*Math.PI/180) * (a[0] - b[0]),
y = a[1] - b[1];
return 6.3710E6 * Math.sqrt((x * x) + (y * y)) * Math.PI/180;
var x = iD.geo.lonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
y = iD.geo.latToMeters(a[1] - b[1]);
return Math.sqrt((x * x) + (y * y));
};
iD.geo.edgeEqual = function(a, b) {
+2 -2
View File
@@ -58,8 +58,8 @@ _.extend(iD.geo.Extent.prototype, {
},
padByMeters: function(meters) {
var dLat = meters / 111132.954,
dLon = meters / 111132.954 / Math.abs(Math.cos(this.center()[1] * (Math.PI / 180)));
var dLat = iD.geo.metersToLat(meters),
dLon = iD.geo.metersToLon(meters, this.center()[1]);
return iD.geo.Extent(
[this[0][0] - dLon, this[0][1] - dLat],
[this[1][0] + dLon, this[1][1] + dLat]);
+2 -17
View File
@@ -4,25 +4,10 @@ iD.ui.Scale = function(context) {
maxLength = 180,
tickHeight = 8;
// http://stackoverflow.com/a/27943/7620
// Haversine distance formula
function distance(loc1, loc2) {
var R = 6371009; // Mean radius of the earth in m
var dLat = (loc2[1] - loc1[1]) * (Math.PI / 180);
var dLon = (loc2[0] - loc1[0]) * (Math.PI / 180);
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(loc1[1] * (Math.PI / 180)) *
Math.cos(loc2[1] * (Math.PI / 180)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c; // Distance in m
return d;
}
function scaleDefs(loc1, loc2) {
var lat = (loc2[1] + loc1[1]) / 2,
conversion = (imperial ? 3.28084 : 1),
dist = distance(loc1, loc2) * conversion,
dist = iD.geo.lonToMeters(loc2[0] - loc1[0], lat) * conversion,
scale = { dist: 0, px: 0, text: '' },
buckets, i, val, dLon;
@@ -41,7 +26,7 @@ iD.ui.Scale = function(context) {
}
}
dLon = scale.dist / (111132.954 * conversion) / Math.abs(Math.cos( lat * (Math.PI / 180)));
dLon = iD.geo.metersToLon(scale.dist / conversion, lat);
scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
if (imperial) {