mapbox-gl-js
mapbox-gl-js copied to clipboard
Globe does not use shortest path for line geometry between points
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.
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
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:
This should just be two dotted lines.
Issue still exists in v3.0.1
Example
Plotting line between San Francisco and Auckland does not render shortest path:
<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>
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/