diff --git a/external/L.Geodesic.js b/external/L.Geodesic.js index 6313db95..5c54468e 100644 --- a/external/L.Geodesic.js +++ b/external/L.Geodesic.js @@ -34,52 +34,54 @@ Modified by qnstie 2013-07-17 to maintain compatibility with Leaflet.draw } }); } - - function geodesicConvertLine(startLatlng, endLatlng, convertedPoints) { - var i, - R = 6378137, // earth radius in meters (doesn't have to be exact) - maxlength = 5000, // meters before splitting - d2r = L.LatLng.DEG_TO_RAD, - r2d = L.LatLng.RAD_TO_DEG, - lat1, lat2, lng1, lng2, dLng, d, segments, - f, A, B, x, y, z, fLat, fLng; - - dLng = (endLatlng.lng - startLatlng.lng) * d2r; - lat1 = startLatlng.lat * d2r; - lat2 = endLatlng.lat * d2r; - lng1 = startLatlng.lng * d2r; - lng2 = endLatlng.lng * d2r; - // http://en.wikipedia.org/wiki/Great-circle_distance - d = Math.atan2(Math.sqrt( Math.pow(Math.cos(lat2) * Math.sin(dLng), 2) + Math.pow(Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLng), 2) ), Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(dLng)); + // alternative geodesic line intermediate points function + // as north/south lines have very little curvature in the projection, we cam use longitude (east/west) seperation + // to calculate intermediate points. hopeefully this will avoid the rounding issues seen in the full intermediate + // points code that have been seen + function geodesicConvertLine(startLatLng, endLatLng, convertedPoints) { + var R = 6378137; // earth radius in meters (doesn't have to be exact) + var d2r = L.LatLng.DEG_TO_RAD; + var r2d = L.LatLng.RAD_TO_DEG; - segments = Math.ceil(d * R / maxlength); - // loop starts at 1 - we don't add the very first point - // loop ends before 'segments' is reached - we don't add the very last point here but outside the loop - // (this was to fix a bug - https://github.com/jonatkins/ingress-intel-total-conversion/issues/471 - // rounding errors? maths bug? not sure - but it solves the issue! and is a slight optimisation) - // UPDATE: there still seem to be rounding errors on relatively short links - but only on mobile. - // let's only add intermediate points if there's two or more - if (segments >= 3) { - for (i = 1; i < segments; i++) { - // http://williams.best.vwh.net/avform.htm#Intermediate - // modified to handle longitude above +-180 degrees - f = i / segments; - A = Math.sin((1-f)*d) / Math.sin(d); - B = Math.sin(f*d) / Math.sin(d); - x = A * Math.cos(lat1) * Math.cos(0) + B * Math.cos(lat2) * Math.cos(dLng); - y = A * Math.cos(lat1) * Math.sin(0) + B * Math.cos(lat2) * Math.sin(dLng); - z = A * Math.sin(lat1) + B * Math.sin(lat2); - fLat = r2d * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))); - fLng = r2d * (Math.atan2(y, x)+lng1); + // maths based on http://williams.best.vwh.net/avform.htm#Int - convertedPoints.push(L.latLng([fLat, fLng])); + var lat1 = startLatLng.lat * d2r; + var lat2 = endLatLng.lat * d2r; + var lng1 = startLatLng.lng * d2r; + var lng2 = endLatLng.lng * d2r; + + var dLng = lng2-lng1; + + var segments = Math.floor(Math.abs(dLng * R / 5000)); + + if (segments > 1) { + // pre-calculate some constant values for the loop + var sinLat1 = Math.sin(lat1); + var sinLat2 = Math.sin(lat2); + var cosLat1 = Math.cos(lat1); + var cosLat2 = Math.cos(lat2); + + var sinLat1CosLat2 = sinLat1*cosLat2; + 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(lng2-iLng) + sinLat2CosLat1*Math.sin(iLng-lng1)) + / cosLat1CosLat2SinDLng) + + var point = L.latLng ( [iLat*r2d, iLng*r2d] ); + convertedPoints.push(point); } } - // push the final point unmodified - convertedPoints.push(L.latLng(endLatlng)); + + convertedPoints.push(L.latLng(endLatLng)); } + + L.geodesicConvertLines = function (latlngs, fill) { if (latlngs.length == 0) { return [];