add CRS.Earth, move Harvesine distance there

This commit is contained in:
Vladimir Agafonkin 2014-01-02 15:42:14 +02:00
parent 6940b5bac9
commit 2ee5c90f02
6 changed files with 30 additions and 31 deletions

View File

@ -15,6 +15,7 @@ var deps = {
'geo/projection/Projection.SphericalMercator.js', 'geo/projection/Projection.SphericalMercator.js',
'geo/crs/CRS.js', 'geo/crs/CRS.js',
'geo/crs/CRS.Simple.js', 'geo/crs/CRS.Simple.js',
'geo/crs/CRS.Earth.js',
'geo/crs/CRS.EPSG3857.js', 'geo/crs/CRS.EPSG3857.js',
'geo/crs/CRS.EPSG4326.js', 'geo/crs/CRS.EPSG4326.js',
'map/Map.js', 'map/Map.js',

View File

@ -34,23 +34,8 @@ L.LatLng.prototype = {
L.Util.formatNum(this.lng, precision) + ')'; L.Util.formatNum(this.lng, precision) + ')';
}, },
// Haversine distance formula, see http://en.wikipedia.org/wiki/Haversine_formula
// TODO move to projection code, LatLng shouldn't know about Earth
distanceTo: function (other) { distanceTo: function (other) {
other = L.latLng(other); return L.CRS.Earth.distance(this, L.latLng(other));
var R = 6378137, // earth radius in meters
rad = Math.PI / 180,
dLat = (other.lat - this.lat) * rad,
dLon = (other.lng - this.lng) * rad,
lat1 = this.lat * rad,
lat2 = other.lat * rad,
sin1 = Math.sin(dLat / 2),
sin2 = Math.sin(dLon / 2);
var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2);
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
} }
}; };

View File

@ -2,9 +2,8 @@
* L.CRS.EPSG3857 (World Mercator) CRS implementation. * L.CRS.EPSG3857 (World Mercator) CRS implementation.
*/ */
L.CRS.EPSG3395 = L.extend({}, L.CRS, { L.CRS.EPSG3395 = L.extend({}, L.CRS.Earth, {
code: 'EPSG:3395', code: 'EPSG:3395',
projection: L.Projection.Mercator, projection: L.Projection.Mercator,
transformation: (function () { transformation: (function () {
@ -13,7 +12,5 @@ L.CRS.EPSG3395 = L.extend({}, L.CRS, {
scale = 0.5 / (Math.PI * r); scale = 0.5 / (Math.PI * r);
return new L.Transformation(scale, 0.5, -scale, 0.5); return new L.Transformation(scale, 0.5, -scale, 0.5);
}()), }())
wrapLng: [-180, 180]
}); });

View File

@ -2,17 +2,14 @@
* L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping and is used by Leaflet by default. * L.CRS.EPSG3857 (Spherical Mercator) is the most common CRS for web mapping and is used by Leaflet by default.
*/ */
L.CRS.EPSG3857 = L.extend({}, L.CRS, { L.CRS.EPSG3857 = L.extend({}, L.CRS.Earth, {
code: 'EPSG:3857', code: 'EPSG:3857',
projection: L.Projection.SphericalMercator, projection: L.Projection.SphericalMercator,
transformation: (function () { transformation: (function () {
var scale = 0.5 / (Math.PI * L.Projection.SphericalMercator.R); var scale = 0.5 / (Math.PI * L.Projection.SphericalMercator.R);
return new L.Transformation(scale, 0.5, -scale, 0.5); return new L.Transformation(scale, 0.5, -scale, 0.5);
}()), }())
wrapLng: [-180, 180]
}); });
L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, {

View File

@ -2,11 +2,8 @@
* L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists. * L.CRS.EPSG4326 is a CRS popular among advanced GIS specialists.
*/ */
L.CRS.EPSG4326 = L.extend({}, L.CRS, { L.CRS.EPSG4326 = L.extend({}, L.CRS.Earth, {
code: 'EPSG:4326', code: 'EPSG:4326',
projection: L.Projection.LonLat, projection: L.Projection.LonLat,
transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5), transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5)
wrapLng: [-180, 180]
}); });

22
src/geo/crs/CRS.Earth.js Normal file
View File

@ -0,0 +1,22 @@
/*
* L.CRS.Earth is the base class for all CRS representing Earth.
*/
L.CRS.Earth = L.extend({}, L.CRS, {
wrapLng: [-180, 180],
R: 6378137,
// distane between two geographic points using Harvesine formula
distance: function (latlng1, latlng2) {
var rad = Math.PI / 180,
lat1 = latlng1.lat * rad,
lat2 = latlng2.lat * rad,
sin1 = Math.sin((lat2 - lat1) / 2),
sin2 = Math.sin((latlng2.lng - latlng1.lng) * rad / 2);
var a = sin1 * sin1 + sin2 * sin2 * Math.cos(lat1) * Math.cos(lat2);
return this.R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
});