-
-
Save mikeatlas/0b69b354a8d713989147 to your computer and use it in GitHub Desktop.
Array.prototype.splitAtEvery = (callback) -> | |
sections = [] | |
arrayClone = this.slice(0) | |
$.each(arrayClone, (idx, item) => | |
sectionsLength = 0 | |
_.each(sections, (section) => | |
sectionsLength += section.length; | |
) | |
if callback(this, idx, item) == true | |
sections.push(arrayClone.slice(0, idx+1-sectionsLength)) | |
arrayClone = arrayClone.slice(idx+1-sectionsLength, arrayClone.length) | |
return | |
) | |
sections.push(arrayClone) | |
return sections | |
drawPolylines = (latLons, leafletMap) -> | |
normalizeIndexes = [] | |
$.each(latLons, (i, latLon) => | |
last = latLons[i-1] | |
if last? | |
if Math.abs(latLon.lng - last.lng) > 180 | |
normalizeIndexes.push(i) | |
) | |
normalizeIndexesRef = normalizeIndexes.slice(0) | |
$.each(normalizeIndexes, (i, normalizeIndex) => | |
flipDirection = if latLons[normalizeIndexesRef[i]].lng < 0 then -1 else 1 | |
latLons.splice(normalizeIndexesRef[i], 0, L.latLng(latLons[normalizeIndexesRef[i]].lat, flipDirection * -179.99999)) | |
latLons.splice(normalizeIndexesRef[i]+1, 0, L.latLng(latLons[normalizeIndexesRef[i]].lat, flipDirection * 179.99999)) | |
normalizeIndexesRef = _.map(normalizeIndexesRef, (idx) => idx+2) | |
) | |
sections = latLons.splitAtEvery((array, i, val) -> | |
return (Math.abs(val.lng) == 179.99999) && \ | |
(Math.abs(array[i+1].lng) == 179.99999) | |
) | |
$.each(sections, (i, section) -> | |
polyline = L.polyline(section, {color:'#0099cc'}).addTo(leafletMap); | |
) | |
return latLons |
Thanks for making this!
YW. @KevinCarhart, here's a quick whiteboard of the algorithm:
I have problem " normalizeIndexesRef = _.map(normalizeIndexesRef, (idx) => idx+2) "
main.js:391 Uncaught ReferenceError: _ is not defined
Does it work now ?
The whiteboard is a bit misleading as the gist does not attempt to calculate the correct latitude at the antimeridian intersection, which leads to those unusual horizontal lines and incorrect slopes in the action shot. Adding it in is pretty simple though. Just calculate the latitude in the step before the splice:
latLons.splice(normalizeIndexesRef[i], 0, L.latLng(latLons[normalizeIndexesRef[i]].lat, flipDirection * -179.99999))
I opted to use the simple linear equation of y = mx+b to determine the latitude (y) at the antimeridian (x=180) using the slope (points i and i-1), though the SE link mentioned above goes into a more accurate spherical determination.
The gist ... of the gist ... is that it detects polylines which cross the IDL by comparing serial pairs of points in the polyline, and then splits the polyline into two or more logical polylines if any of the point-pairs cross the IDL. This introduces some distortions as I basically am chopping or rounding at approximate mid-points in polylines (to .99999 decimal), while effectively adding point data into the logical polyline that didn't actually exist in the original set, which are then artifacts strictly for rendering purposes around leaflet's limitations. Kinda lame but at least it "looks" pretty-right. I also didn't experiment with multi-circumnavigation polylines. I think it might work, though. Also note that the world-copy-jump feature thing makes this even less intuitive and complicated to resolve. Not surprising there's no official support for it in Leaflet yet, but also still disappointing too.