mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.07k stars 2.21k forks source link

Globe does not use shortest path for line geometry between points #11813

Open karimnaaji opened 2 years ago

karimnaaji commented 2 years ago

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:

Workaround

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

mootari commented 2 years ago

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

runfalk commented 1 year ago

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.

blumk commented 8 months ago

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>
mklnz commented 5 months ago

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/

LukasJK commented 2 months ago

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.

Were you ever able to come up with some workaround?

runfalk commented 1 month ago

Nope, that ugly blob was with my workaround of injecting points close to the pole.