Skip to content

Instantly share code, notes, and snippets.

@mikeatlas
Last active August 30, 2017 17:53
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeatlas/0b69b354a8d713989147 to your computer and use it in GitHub Desktop.
Save mikeatlas/0b69b354a8d713989147 to your computer and use it in GitHub Desktop.
splitting polyline paths across the international dateline in leaflet (sorry that it uses a mix of jQuery and lo-dash for helpers and is in coffeescript)
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
@KevinCarhart
Copy link

Thanks for making this!

@mikeatlas
Copy link
Author

YW. @KevinCarhart, here's a quick whiteboard of the algorithm: idl split

@markpolarisdesign
Copy link

I have problem " normalizeIndexesRef = _.map(normalizeIndexesRef, (idx) => idx+2) "
main.js:391 Uncaught ReferenceError: _ is not defined

@dwy904
Copy link

dwy904 commented May 10, 2017

Does it work now ?

@tripler
Copy link

tripler commented Aug 30, 2017

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment