cesium測(cè)量距離,測(cè)量地形上兩點(diǎn)的距離(工具篇)

有時(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)

輸出


控制臺(tái)輸出

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))

輸出


控制臺(tái)輸出

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))

輸出


控制臺(tái)輸出


5.測(cè)地線(橢球體上的距離,因?yàn)榈厍蚴菆A的,所以求地球上兩個(gè)點(diǎn)的距離相當(dāng)于求橢球體上的兩點(diǎn)曲線距離)


參照我的另一篇博客??cesium 求地表兩點(diǎn)的距離(基礎(chǔ)篇)

最后祝大家工作愉快,gis圈子的朋友可以幫忙關(guān)注下我博客哈!蟹蟹啦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容