Cesium量算-贴地形距离
查了很多贴地距离计算的,但试了下都测不准,还是自己写一个吧。
找了个地形比较夸张的地方测试了下,贴地距离比直线距离将近多两百米
主要思路:
- 起始点转成制图坐标(Cesium.Cartographic),用制图坐标的经纬度做插值,生成一组插值坐标
- 通过Cesium.sampleTerrainMostDetailed 获取每个插值在地形表面上的采样点,采样点也是Cesium.Cartographic,但此时是有高度的,正是我们需要的。
- 遍历采样点,每两个点计算出一个距离,把这些距离加起来就是总的贴地形距离。可以想象出插值量越大就会越精准,但计算时间会越长。
/**
* @description 计算贴地形距离
* @param {Cesium.Viewer} viewer
* @param {Cesium.Cartesian3} start
* @param {Cesium.Cartesian3} end
* @returns {number}
*/
function getTerrainDistance(viewer, start, end) {
return new Promise((resolve) => {
//制图坐标插值(不贴附地形)
let lerpArray = [];
//插值数量,我这里根据两点间直线距离来插,每1米插一下,插的越多越精准
let splitNum = parseInt(Cesium.Cartesian3.distance(start, end));
let startCartographic = Cesium.Cartographic.fromCartesian(start);
let startDegrees = [startCartographic.longitude, startCartographic.latitude];
let endCartographic = Cesium.Cartographic.fromCartesian(end);
let endDegrees = [endCartographic.longitude, endCartographic.latitude];
lerpArray.push(new Cesium.Cartographic(startDegrees[0], startDegrees[1]));
for (let i = 1; i <= splitNum - 1; i++) {
let x = Cesium.Math.lerp(startDegrees[0], endDegrees[0], i / splitNum);
let y = Cesium.Math.lerp(startDegrees[1], endDegrees[1], i / splitNum);
lerpArray.push(new Cesium.Cartographic(x, y));
}
//地形细节采样:传入 目标地形 和 制图坐标插值组(不贴附地形) 获取 贴地形的制图坐标插值组 再计算距离
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, lerpArray).then((cartographicArr) => {
getDetailedTerrainDistance(cartographicArr).then((distance) => {
resolve(distance);
});
});
});
}
/**
* @description 根据制图坐标计算距离
* @param {Array.<Cesium.Cartographic>} cartographicArr 制图坐标数组
* @returns {number} 距离值
*/
function getDetailedTerrainDistance(cartographicArr) {
return new Promise((resolve) => {
let terrainDistance = 0;
cartographicArr.map((currentCartographic, index) => {
if (index == cartographicArr.length - 1) {
return;
}
let nextCartographic = cartographicArr[index + 1];
let currentPosition = Cesium.Cartesian3.fromRadians(currentCartographic.longitude, currentCartographic.latitude, currentCartographic.height);
let nextPosition = Cesium.Cartesian3.fromRadians(nextCartographic.longitude, nextCartographic.latitude, nextCartographic.height);
terrainDistance += Cesium.Cartesian3.distance(currentPosition, nextPosition);
});
resolve(terrainDistance);
});
}