12

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?

Rob
  • 7,377
  • 7
  • 36
  • 38

2 Answers2

3

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]);
         }
       }
     }
   }
 };
jcarapia
  • 578
  • 1
  • 7
  • 20
  • 1
    I totally agree. I've seen no other way to do this. I map ship passages from Vancouver to Japan, so do it the opposite way round: making longitudes in the 140E to 180E range negative, rather than making negative longitudes positive, but either way works. – Auspex Oct 09 '18 at 14:11
  • How can I use this when loading a GeoJSON file? – Giox Jun 23 '20 at 13:30
0

Solution in ReactJS

import React from "react";
import * as GeoJson from "./data/RUS_simple.json";

function Process180Meredian() {
  function download(content, fileName, contentType) {
    var a = document.createElement("a");
    var file = new Blob([content], { type: contentType });
    a.href = URL.createObjectURL(file);
    a.download = fileName;
    a.click();
  }

  function process(obj) {
    const coordinates = obj.features[0].geometry.coordinates;

    //loop through all coordinates and add 360 to all negative values
    for (let i = 0; i < coordinates.length; i++) {
      for (let j = 0; j < coordinates[i].length; j++) {
        for (let k = 0; k < coordinates[i][j].length; k++) {
          if (coordinates[i][j][k][0] < 0) {
            coordinates[i][j][k][0] += 360;
          }
        }
      }
    }

    //download the new file
    download(JSON.stringify(obj), "RUS_simple_processed.json", "text/plain");
  }

  return (
    <div>
      <button onClick={() => process(GeoJson)}>Process</button>
    </div>
  );
}

export default Process180Meredian;

Before enter image description here

After enter image description here