From 2ee5c90f0239d162b40aea5d24c26dcb44b82032 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Thu, 2 Jan 2014 15:42:14 +0200 Subject: [PATCH] add CRS.Earth, move Harvesine distance there --- build/deps.js | 1 + src/geo/LatLng.js | 17 +---------------- src/geo/crs/CRS.EPSG3395.js | 7 ++----- src/geo/crs/CRS.EPSG3857.js | 7 ++----- src/geo/crs/CRS.EPSG4326.js | 7 ++----- src/geo/crs/CRS.Earth.js | 22 ++++++++++++++++++++++ 6 files changed, 30 insertions(+), 31 deletions(-) create mode 100644 src/geo/crs/CRS.Earth.js diff --git a/build/deps.js b/build/deps.js index 502e7679..a1bb9fdb 100644 --- a/build/deps.js +++ b/build/deps.js @@ -15,6 +15,7 @@ var deps = { 'geo/projection/Projection.SphericalMercator.js', 'geo/crs/CRS.js', 'geo/crs/CRS.Simple.js', + 'geo/crs/CRS.Earth.js', 'geo/crs/CRS.EPSG3857.js', 'geo/crs/CRS.EPSG4326.js', 'map/Map.js', diff --git a/src/geo/LatLng.js b/src/geo/LatLng.js index 37791f99..9f89ed62 100644 --- a/src/geo/LatLng.js +++ b/src/geo/LatLng.js @@ -34,23 +34,8 @@ L.LatLng.prototype = { 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) { - other = 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)); + return L.CRS.Earth.distance(this, L.latLng(other)); } }; diff --git a/src/geo/crs/CRS.EPSG3395.js b/src/geo/crs/CRS.EPSG3395.js index e51755c5..4318d708 100644 --- a/src/geo/crs/CRS.EPSG3395.js +++ b/src/geo/crs/CRS.EPSG3395.js @@ -2,9 +2,8 @@ * 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', - projection: L.Projection.Mercator, transformation: (function () { @@ -13,7 +12,5 @@ L.CRS.EPSG3395 = L.extend({}, L.CRS, { scale = 0.5 / (Math.PI * r); return new L.Transformation(scale, 0.5, -scale, 0.5); - }()), - - wrapLng: [-180, 180] + }()) }); diff --git a/src/geo/crs/CRS.EPSG3857.js b/src/geo/crs/CRS.EPSG3857.js index 1d77f4a5..1601b7d7 100644 --- a/src/geo/crs/CRS.EPSG3857.js +++ b/src/geo/crs/CRS.EPSG3857.js @@ -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 = L.extend({}, L.CRS, { +L.CRS.EPSG3857 = L.extend({}, L.CRS.Earth, { code: 'EPSG:3857', - projection: L.Projection.SphericalMercator, transformation: (function () { var scale = 0.5 / (Math.PI * L.Projection.SphericalMercator.R); return new L.Transformation(scale, 0.5, -scale, 0.5); - }()), - - wrapLng: [-180, 180] + }()) }); L.CRS.EPSG900913 = L.extend({}, L.CRS.EPSG3857, { diff --git a/src/geo/crs/CRS.EPSG4326.js b/src/geo/crs/CRS.EPSG4326.js index f5eaf1a5..0420679f 100644 --- a/src/geo/crs/CRS.EPSG4326.js +++ b/src/geo/crs/CRS.EPSG4326.js @@ -2,11 +2,8 @@ * 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', - projection: L.Projection.LonLat, - transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5), - - wrapLng: [-180, 180] + transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5) }); diff --git a/src/geo/crs/CRS.Earth.js b/src/geo/crs/CRS.Earth.js new file mode 100644 index 00000000..6cf86d8d --- /dev/null +++ b/src/geo/crs/CRS.Earth.js @@ -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)); + } +});