I have a ol.geom.LineString. I want to get the center of that line using turf.js.
I thought turf.destination (yellow circle) or turf.rhumbDestination (red circle) would have computed the correct point (purple circle). They do not. turf.rhumbDestination comes the closest.
Why? What mathematically is going on? Why is OpenLayers not drawing the line geodesically or using rhumb? Is it possible to tell OpenLayers to draw the line differently so a turf calculation will give the correct coordinate? Or, is there a way to use turf to get the correct coordinate?
const coordinates = [
[-97.36992, 38.885235],
[-218.19432, -26.82873]
];
const datelineCoordinates = [
[-180, -90],
[-180, 90]
];
const datelineString = new ol.geom.LineString(datelineCoordinates);
const tLineA = turf.lineString([coordinates[0], coordinates[1]]);
const tLineB = turf.lineString(datelineCoordinates);
console.log("tLineA", tLineA);
console.log("tLineB", tLineB);
const split = turf.lineSplit(tLineA, tLineB);
turf.featureEach(split, (feature) => {
console.log("split", turf.getCoords(feature));
});
const intersect = turf.lineIntersect(tLineA, tLineB);
turf.featureEach(intersect, (feature) => {
console.log("intersect", turf.getCoords(feature));
});
const intersectCoordinate = turf.getCoord(intersect.features[0])
console.log("intersectCoordinate", intersectCoordinate);
const intersectFeature = new ol.Feature({
geometry: new ol.geom.Point(intersectCoordinate)
});
intersectFeature.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({ color: "green" })
})
})
);
const fromPoint = turf.point(coordinates[0]);
const toPoint = turf.point(coordinates[1]);
const rhumbDistance =
turf.rhumbDistance(fromPoint, toPoint, { units: "degrees" }) / 2.0;
const rhumbBearing = turf.rhumbBearing(fromPoint, toPoint);
const rhumbCenter = turf.getCoord(
turf.rhumbDestination(fromPoint, rhumbDistance, rhumbBearing, { units: "degrees" })
);
console.log("rhumbDistance", rhumbDistance);
console.log("rhumbBearing", rhumbBearing);
console.log("rhumbCenter", rhumbCenter);
const rhumbCenterFeature = new ol.Feature({
geometry: new ol.geom.Point(rhumbCenter)
});
rhumbCenterFeature.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({ color: "red" })
})
})
);
const distance =
turf.distance(fromPoint, toPoint, { units: "degrees" }) / 2.0;
const bearing = turf.bearing(fromPoint, toPoint);
const center = turf.getCoord(
turf.destination(fromPoint, distance, bearing, { units: "degrees" })
);
console.log("distance", distance);
console.log("bearing", bearing);
console.log("center", center);
const centerFeature = new ol.Feature({
geometry: new ol.geom.Point(center)
});
centerFeature.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({ color: "yellow" })
})
})
);
const lineA = new ol.geom.LineString(coordinates);
const lineFeatureA = new ol.Feature({
geometry: lineA
});
const lineACenter = lineA.getCoordinateAt(0.5);
console.log("lineACenter", lineACenter);
const lineACenterFeature = new ol.Feature({
geometry: new ol.geom.Point(lineACenter)
});
lineACenterFeature.setStyle(
new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({ color: "purple" })
})
})
);
const datelineFeature = new ol.Feature({
geometry: datelineString
});
const vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [lineFeatureA, datelineFeature, intersectFeature, rhumbCenterFeature, centerFeature, lineACenterFeature]
})
});
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: [120, 15],
zoom: 3
})
});
#map {
height: 512px;
width: 1024px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/ol.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/7.3.0/dist/ol.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<div id="map"></div>