mapbox-gl-js icon indicating copy to clipboard operation
mapbox-gl-js copied to clipboard

Globe does not use shortest path for line geometry between points

Open karimnaaji opened this issue 3 years ago • 7 comments

Current behavior

Line geometry between two points on globe does not use use shortest distance and there can be non-intuitive behavior around the poles where the points are always projected in the mercator space. This is especially visible in mapbox-gl-draw, where the user can drag points on the globe and create geometry on the fly:

https://user-images.githubusercontent.com/7061573/164815481-3ce73cb1-7364-4055-98c2-92ab9d3befd5.mov

Proposed behavior

Line geometry between two points on globe follows shortest distance and are either processed and subdivided in geojson-vt or on the fly. (A useful library might be https://github.com/mapbox/cheap-ruler).

This has a few challenges:

  • During the globe mercator transition, the subdivision between points would have to be interpolated between their representation in globe and their representation in mercator
  • A discontinuity in mercator is a continuity in globe

Workaround

The geometry is subdivided and adapted before feeding it to mapbox-gl.

karimnaaji avatar Apr 22 '22 23:04 karimnaaji

This also seems to affect flyTo transitions between two points, which follow the curves described above instead of a straight line. Looking at the paper that is referenced in code, this behavior does not appear to be intentional.

The easing code is defined here and uses mercator as well: https://github.com/mapbox/mapbox-gl-js/blob/6df332d17f48f878522301ea5357ef8ad8b576c3/src/ui/camera.js#L1225-L1240

Possibly related: https://github.com/mapbox/mapbox-gl-js/issues/10189

mootari avatar Aug 22 '22 06:08 mootari

I ran into this exact issue when trying to plot a flight path across the north pole. It lead to some very surprising interactions where I needed to manually inject points close to true north width longitudes 34 and 192 to prevent it from going completely haywire.

I still ended up with this abomination at the pole:

bild

This should just be two dotted lines.

runfalk avatar Aug 30 '23 13:08 runfalk

Issue still exists in v3.0.1

Example

Plotting line between San Francisco and Auckland does not render shortest path:

image

    <Map
      mapLib={import("mapbox-gl")}
      initialViewState={{
        longitude: -100,
        latitude: 40,
        zoom: 1,
      }}
      style={{ width: "100vw", height: "100vh" }}
      mapStyle="mapbox://styles/blumk/clqrgy8cf00cu01ob4nrufv5k"
      mapboxAccessToken={mapboxToken}
      onRender={(event) => event.target.resize()}
    >
      <Source
        id="polylineLayer"
        type="geojson"
        data={{
          type: "Feature",
          properties: {},
          geometry: {
            type: "LineString",
            coordinates: [
              [174.7917, -37.008],
              [-122.375, 37.6188],
            ],
          },
        }}
      >
        <Layer
          id="lineLayer"
          type="line"
          source="my-data"
          layout={{
            "line-join": "round",
            "line-cap": "round",
          }}
          paint={{
            "line-color": "rgba(3, 170, 238, 0.5)",
            "line-width": 5,
          }}
        />
      </Source>
    </Map>

blumk avatar Dec 30 '23 05:12 blumk

Having the same issue but from Auckland to New York, it doesn't go across the pacific.

Edit: It turns out any time the line is going through the 180th meridian you have to adjust the longitude. Mapbox example here:

https://docs.mapbox.com/mapbox-gl-js/example/line-across-180th-meridian/

mklnz avatar Apr 15 '24 04:04 mklnz