From 5a2ab50e1f8b796afffd19b0ab5c48242347b953 Mon Sep 17 00:00:00 2001 From: johndoe Date: Sat, 22 Feb 2020 12:37:48 +0200 Subject: [PATCH 1/2] refactor _processWrapped method from _geodesicConvertLines --- src/L.Geodesic.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/L.Geodesic.js b/src/L.Geodesic.js index 5276ea0..ec09eeb 100644 --- a/src/L.Geodesic.js +++ b/src/L.Geodesic.js @@ -59,7 +59,7 @@ return result; } - function geodesicConvertLines (latlngs) { + function processWrapped (latlngs, fn) { if (latlngs.length === 0) { return []; } @@ -73,14 +73,12 @@ // within +-180 degrees latlngs = latlngs.map(function (a) { return L.latLng(a.lat, a.lng-lngOffset).wrap(); }); - var geodesiclatlngs = this._processPoly(latlngs,this._geodesicConvertLine); + latlngs = fn.call(this, latlngs); // now add back the offset subtracted above. no wrapping here - the drawing code handles // things better when there's no sudden jumps in coordinates. yes, lines will extend // beyond +-180 degrees - but they won't be 'broken' - geodesiclatlngs = geodesiclatlngs.map(function (a) { return L.latLng(a.lat, a.lng+lngOffset); }); - - return geodesiclatlngs; + return latlngs.map(function (a) { return L.latLng(a.lat, a.lng+lngOffset); }); } var polyOptions = { @@ -92,10 +90,13 @@ _processPoly: processPoly, - _geodesicConvertLines: geodesicConvertLines, + _processWrapped: processWrapped, _geodesicConvert: function () { - this._latlngs = this._geodesicConvertLines(this._latlngsinit); + this._latlngs = this._processWrapped(this._latlngsinit, function (latlngs) { + return this._processPoly(latlngs, this._geodesicConvertLine); + }); + this._convertLatLngs(this._latlngs); // update bounds }, From 529abef637b4d5b7fa5c97e1c1ce07366393dd55 Mon Sep 17 00:00:00 2001 From: johndoe Date: Sat, 22 Feb 2020 16:19:41 +0200 Subject: [PATCH 2/2] Refactor for even more specialization of internal functions It's now possible to get Lat of any intermediate point with given Lng --- src/L.Geodesic.js | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/L.Geodesic.js b/src/L.Geodesic.js index ec09eeb..c9334a0 100644 --- a/src/L.Geodesic.js +++ b/src/L.Geodesic.js @@ -4,20 +4,29 @@ var r2d = 180.0/Math.PI; var earthR = 6367000.0; // earth radius in meters (doesn't have to be exact) + function segmentFn (start, end, line) { + var segments = Math.floor(Math.abs(line.dLng * earthR / this.options.segmentsCoeff)); + if (segments<2) { return false; } + line.segments = segments; + } + // alternative geodesic line intermediate points function // as north/south lines have very little curvature in the projection, we can use longitude (east/west) seperation // to calculate intermediate points. hopefully this will avoid the rounding issues seen in the full intermediate // points code that have been seen - function geodesicConvertLine (start, end, convertedPoints) { // push intermediate points into convertedPoints - + function geoLine (start, end, limitFn) { var lng1 = start.lng * d2r; var lng2 = end.lng * d2r; var dLng = lng1-lng2; + var line = { + lng1: lng1, + lng2: lng2, + dLng: dLng + } - var segments = Math.floor(Math.abs(dLng * earthR / this.options.segmentsCoeff)); - if (segments < 2) { return; } - - // maths based on https://edwilliams.org/avform.htm#Int + if (limitFn && false === this[limitFn](start, end, line)) { + return; + } // pre-calculate some constant values for the loop var lat1 = start.lat * d2r; @@ -30,16 +39,26 @@ var sinLat2CosLat1 = sinLat2*cosLat1; var cosLat1CosLat2SinDLng = cosLat1*cosLat2*Math.sin(dLng); - for (var i=1; i < segments; i++) { - var iLng = lng1-dLng*(i/segments); - var iLat = Math.atan( - (sinLat1CosLat2 * Math.sin(iLng-lng2) - sinLat2CosLat1 * Math.sin(iLng-lng1)) + // maths based on https://edwilliams.org/avform.htm#Int + line.getIntPointLat = function (lng) { + return Math.atan( + (sinLat1CosLat2 * Math.sin(lng-lng2) - sinLat2CosLat1 * Math.sin(lng-lng1)) / cosLat1CosLat2SinDLng ); - convertedPoints.push(L.latLng(iLat*r2d, iLng*r2d)); } + return line; } + function geodesicConvertLine (start, end, convertedPoints) { // push intermediate points into convertedPoints + var line = this_geoLine(start, end, '_segmentFn'); + if (!line) { return; } + + for (var i=1; i < line.segments; i++) { + var iLng = line.lng1-line.dLng*(i/line.segments); + var iLat = line.getIntPointLat(iLng); + convertedPoints.push(L.latLng(iLat*r2d, iLng*r2d)); + } + } // iterate pairs of connected vertices with fn(), adding new intermediate vertices (if returned) function processPoly (latlngs, fn) { @@ -86,6 +105,10 @@ }; var PolyMixin = { + _segmentFn: segmentFn, + + _geoLine: geoLine, + _geodesicConvertLine: geodesicConvertLine, _processPoly: processPoly,