From 16e15dfb516fe086ca8954d64e83ce6e27735b13 Mon Sep 17 00:00:00 2001 From: Jon Atkins Date: Fri, 2 Aug 2013 07:21:04 +0100 Subject: [PATCH] first attempt at geodesic circles - for #292 (alsao see #201 and #425) --- code/portal_detail_display.js | 2 +- external/L.Geodesic.js | 89 +++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index cbb8593a..f8398864 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -124,7 +124,7 @@ window.setPortalIndicators = function(d) { var range = getPortalRange(d); var coord = [d.locationE6.latE6/1E6, d.locationE6.lngE6/1E6]; portalRangeIndicator = (range > 0 - ? L.circle(coord, range, { fill: false, color: RANGE_INDICATOR_COLOR, weight: 3, clickable: false }) + ? L.geodesicCircle(coord, range, { fill: false, color: RANGE_INDICATOR_COLOR, weight: 3, clickable: false }) : L.circle(coord, range, { fill: false, stroke: false, clickable: false }) ).addTo(map); if(!portalAccessIndicator) diff --git a/external/L.Geodesic.js b/external/L.Geodesic.js index 55985039..8beac8e6 100644 --- a/external/L.Geodesic.js +++ b/external/L.Geodesic.js @@ -108,11 +108,85 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw } });*/ -//TODO: finish this... - L.GeodesicCircle = L.Path.extend({ - initialise: function (latlng, radius, options) { - L.Path.prototype.initialise.call(this, options); - } + + L.GeodesicCircle = L.Polygon.extend({ + initialize: function (latlng, radius, options) { + this._latlng = L.latLng(latlng); + this._mRadius = radius; + + points = this._calcPoints(); + + L.Polygon.prototype.initialize.call(this, points, options); + }, + + options: { + fill: true + }, + + setLatLng: function (latlng) { + this._latlng = L.latLng(latlng); + points = this._calcPoints(); + this.setLatLngs(points); + }, + + setRadius: function (radius) { + this._mRadius = radius; + points = this._calcPoints(); + this.setLatLngs(points); + + }, + + getLatLng: function () { + return this._latlng; + }, + + getRadius: function() { + return this._mRadius; + }, + + + _calcPoints: function() { + var R = 6378137; //earth radius in meters (approx - taken from leaflet source code) + var d2r = L.LatLng.DEG_TO_RAD; + var r2d = L.LatLng.RAD_TO_DEG; +//console.log("geodesicCircle: radius = "+this._mRadius+"m, centre "+this._latlng.lat+","+this._latlng.lng); + + // circle radius as an angle from the centre of the earth + var radRadius = this._mRadius / R * Math.PI; +//console.log(" (radius in radians "+radRadius); + + // pre-calculate various values used for every point on the circle + var centreLat = this._latlng.lat * d2r; + var centreLng = this._latlng.lng * d2r; + + var cosCentreLat = Math.cos(centreLat); + var sinCentreLat = Math.sin(centreLat); + + var cosRadRadius = Math.cos(radRadius); + var sinRadRadius = Math.sin(radRadius); + + var calcLatLngAtAngle = function(angle) { + var lat = Math.asin(sinCentreLat*cosRadRadius + cosCentreLat*sinRadRadius*Math.cos(angle)); + + var lon = centreLng + Math.asin( Math.sin(angle) * sinRadRadius / cosCentreLat ) + + return L.latLng(lat * r2d,lon * r2d); + } + + + var segments = Math.max(32,Math.floor(this._mRadius/1000)); +//console.log(" (drawing circle as "+segments+" lines)"); + var points = []; + for (var i=0; i