Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display GeoJSON with leaflet that spans the 180th meridian

I am trying to display a geoJSON object (outline of Russia, in this case) that spans the 180th meridian. Currently this displays with part of the country on the left side of the map and part on the right:

russia and the 180th meridian

Looking at leaflet, it seems there is a fix for this but that doesn't seem to work: https://github.com/Leaflet/Leaflet/issues/82. I have also tried adding a coordsToLatLng function but can't seem to get that to work either. Tile layers have a continuousWorld option which I do not think works with a geoJSON object.

This data is here: https://dl.dropboxusercontent.com/u/12085570/RUS.json. The data was generated from a shapefile to geojson and finally to topojson. Converting the topojson I used the --no-stitch-poles option which lets this display "nicely" on the map meaning it doesn't connect the points on the right to the left side of the map.

Is there a way to get this to display as a continuous object without splitting around the meridian?

like image 748
Rob Avatar asked Mar 27 '14 19:03

Rob


1 Answers

I ran into this same issue and my solution involved taking advantage of a couple of things: 1) Leaflet allows you to place elements beyond the 180/-180 longitudes. 2) Geographic bodies that cross the antimeridian contain mostly all negative or positive longitude coordinates.

My solution was to use a recursive function to traverse the coordinates array within the geoJSON object and, in the case of Russia, convert the negative coordinate values to equivalent positive values. For example, a value of -175 would be converted to 185.

Below is the function I used to process the coordinates array. I used it for locations in the Eastern hemisphere - you'd have to modify the conversion in order to work with locations in the Western hemisphere.

  antimeridian(elem: any) {
   if (Array.isArray(elem)) {
     for (var i = 0; i < elem.length; i++) {
       if (Array.isArray(elem[i][0])) {
         this.antimeridian(elem[i]);
       } else {
         if (elem[i][0] < 0) {
           elem[i][0] = 180 + (180 + elem[i][0]);
         }
       }
     }
   }
 };
like image 143
jcarapia Avatar answered Sep 28 '22 11:09

jcarapia