I am specifying the coordinates of
[-122, 47], (in USA)
[147, -32] (in Australia)
The image it produces is:
I was under the false impression that OpenLayers would draw the shortest line between two coordinates.
What would I need to change so the line drawn is the shortest?
(In this case, the line would cross over the Pacific instead of Atlantic Ocean)
let coordinates = [
[-122, 47],
[147, -32]
];
const myFeature = new ol.Feature({
geometry: new ol.geom.LineString(coordinates),
name: "Line"
});
myFeature.setStyle(
new ol.style.Style({
stroke: new ol.style.Stroke({ color: "green", width: 8 })
})
);
const vectorSource = new ol.source.Vector({
features: [myFeature]
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [0, 0],
zoom: 1
})
});
#map {
height: 450px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/ol.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/dist/ol.min.js"></script>
<div id="map"></div>
Split the line at the antimeridian as in https://github.com/openlayers/openlayers/issues/11681#issuecomment-715583978
function splitAtDateLine(coords) {
const lineStrings = [];
let lastX = Infinity
let lineString;
for (let i = 0, ii = coords.length; i < ii; ++i) {
const coord = coords[i];
const x = coord[0];
if (Math.abs(lastX - x) > 180) { // Crossing date line will be shorter
if (lineString) {
const prevCoord = coords[i - 1];
const w1 = 180 - Math.abs(lastX);
const w2 = 180 - Math.abs(x);
const y = (w1 / (w1 + w2)) * (coord[1] - prevCoord[1]) + prevCoord[1];
if (Math.abs(lastX) !== 180) {
lineString.push([lastX > 0 ? 180 : -180, y]);
}
lineStrings.push(lineString = []);
if (Math.abs(x) !== 180) {
lineString.push([x > 0 ? 180 : -180, y]);
}
} else {
lineStrings.push(lineString = []);
}
}
lastX = x;
lineString.push(coord);
}
return lineStrings;
}
let coordinates = [
[-122, 47],
[147, -32]
];
const myFeature = new ol.Feature({
geometry: new ol.geom.MultiLineString(splitAtDateLine(coordinates)),
name: "Line"
});
myFeature.setStyle(
new ol.style.Style({
stroke: new ol.style.Stroke({ color: "green", width: 8 })
})
);
const vectorSource = new ol.source.Vector({
features: [myFeature]
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource
});
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
view: new ol.View({
projection: "EPSG:4326",
center: [0, 0],
zoom: 1
})
});
#map {
height: 450px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/ol.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.1.0/dist/ol.min.js"></script>
<div id="map"></div>
This will produce what looks like the shortest route on a flat map. In reality on a round planet the shortest route is a great circle route as in https://openlayers.org/en/latest/examples/flight-animation.html