有時(shí)候我們的項(xiàng)目中需要開發(fā)一個(gè)測(cè)量距離工具。在三維世界中測(cè)量的距離包括1.直線距離。2.垂直距離(即兩個(gè)點(diǎn)的高程做差)。3.水平距離(即兩個(gè)點(diǎn)在同一高度上的距離)4.地形上的貼地距離。5.測(cè)地線(橢球體上的距離)。我們分別來(lái)介紹下面這幾種情況怎樣計(jì)算距離。
1.直線距離
原理:直線距離 = 計(jì)算兩個(gè)點(diǎn)向量做差求模長(zhǎng)
var startPosition=Cesium.Cartesian3.fromDegrees(113.65,23.33,500)
var endPosition=Cesium.Cartesian3.fromDegrees(113.65,23.33,10)
var distance=Cesium.Cartesian3.distance(startPosition,endPosition)
console.log(distance)
輸出

2.垂直距離
原理:垂直距離=目標(biāo)點(diǎn)高程-起始點(diǎn)高程
如果未知起始點(diǎn)和目標(biāo)點(diǎn)高程的情況下,先計(jì)算出他們的高程,然后做差
async function clampTerrainPoint(viewer,points) {
? ? let promise = Cesium.sampleTerrainMostDetailed(
? ? ? viewer.terrainProvider,
? ? ? points.map(point=>Cesium.Cartographic.fromCartesian(point))
? ? );
? ? let updatedPositions = await Cesium.when(promise);
? ? return updatedPositions
? }
var startPosition=Cesium.Cartesian3.fromDegrees(113.65,23.33)
var endPosition=Cesium.Cartesian3.fromDegrees(113.775,23.245)
clampTerrainPoint(viewer,[startPosition,endPosition]).then(p=>console.log(p[1].height-p[0].height))
輸出

3.水平距離
原理:水平距離=(目標(biāo)點(diǎn)向量 - 和目標(biāo)點(diǎn)同 一高度的起點(diǎn)向量)求模長(zhǎng)
提升或降低起點(diǎn)的高程使和目標(biāo)點(diǎn)是高程相等,然后使用1計(jì)算直線距離的方法計(jì)算就可以了
4.地形上的距離
原理:先求出兩個(gè)點(diǎn)的直線距離,然后等間距做插值,求出每一個(gè)插值點(diǎn)在地形上的世界坐標(biāo),然后對(duì)插值點(diǎn)之間求直線距離后累加得到兩點(diǎn)的地表坐標(biāo)。如果兩點(diǎn)距離過(guò)長(zhǎng)例如超過(guò)了5公里,可以適當(dāng)降低一下插值的經(jīng)度,如果直線距離超過(guò)100公里,建議采用求測(cè)地線的方法地表距離。因?yàn)榫嚯x越大插值點(diǎn)數(shù)量越多計(jì)算就越慢。
async function getSurfaceDistance(viewer,startPosition, endPosition) {
? ? let linearDistance=Cesium.Cartesian3.distance(startPosition,endPosition);
? ? //高度采樣
? ? let count = Math.floor(linearDistance);
? ? //100米之內(nèi)的精確到厘米
? ? if (linearDistance < 100) {
? ? ? count *= 100;
? ? ? //5000米之內(nèi)的精確到分米
? ? } else if (linearDistance < 5000) {
? ? ? count *= 10;
? ? }
? ? let positions = [];
? ? let startCartographic = Cesium.Cartographic.fromCartesian(startPosition);
? ? let endCartographic = Cesium.Cartographic.fromCartesian(endPosition);
? ? positions.push(startCartographic);
? ? for (let i = 1; i < count; i++) {
? ? ? let cart = Cesium.Cartesian3.lerp(
? ? ? ? startPosition,
? ? ? ? endPosition,
? ? ? ? i / count,
? ? ? ? new Cesium.Cartesian3()
? ? ? );
? ? ? positions.push(Cesium.Cartographic.fromCartesian(cart));
? ? }
? ? positions.push(endCartographic);
? ? let promise = Cesium.sampleTerrainMostDetailed(
? ? ? viewer.terrainProvider,
? ? ? positions
? ? );
? ? let updatedPositions = await Cesium.when(promise);
? ? let surfaceDistance = 0;
? ? for (let i = 0; i < updatedPositions.length; i++) {
? ? ? if (i == updatedPositions.length - 1) continue;
? ? ? surfaceDistance += Cesium.Cartesian3.distance(
? ? ? ? Cesium.Cartesian3.fromRadians(
? ? ? ? ? updatedPositions[i].longitude,
? ? ? ? ? updatedPositions[i].latitude,
? ? ? ? ? updatedPositions[i].height
? ? ? ? ),
? ? ? ? Cesium.Cartesian3.fromRadians(
? ? ? ? ? updatedPositions[i + 1].longitude,
? ? ? ? ? updatedPositions[i + 1].latitude,
? ? ? ? ? updatedPositions[i + 1].height
? ? ? ? )
? ? ? );
? ? }
? ? return surfaceDistance;
? }
var startPosition=Cesium.Cartesian3.fromDegrees(113.65,23.33,500)
var endPosition=Cesium.Cartesian3.fromDegrees(113.55,23.03,10)
getSurfaceDistance(viewer,startPosition,endPosition).then(l=>console.log(l))
輸出

5.測(cè)地線(橢球體上的距離,因?yàn)榈厍蚴菆A的,所以求地球上兩個(gè)點(diǎn)的距離相當(dāng)于求橢球體上的兩點(diǎn)曲線距離)
參照我的另一篇博客??cesium 求地表兩點(diǎn)的距離(基礎(chǔ)篇)
最后祝大家工作愉快,gis圈子的朋友可以幫忙關(guān)注下我博客哈!蟹蟹啦