Cesium-通过经纬度获取高程

1,985 阅读1分钟

在三维开发中,绘制实体、添加模型等都需要经纬度、高程这三个值,但有时会遇到给的数据只有经纬度,如此,我们便可以使用以下方法通过经纬度获取到高程

turf

改方法接收一个经纬度数组,且数组第一项和最后一项需对应 image.png

    getHigh(latLogList) {
      const turfPolygon = turf.polygon([latLogList]);
      const turfExtent = turf.bbox(turfPolygon);
      
      // 在turfPolygon中按网格取样点,网格间距3米
      const turfSamplePoints = turf.pointGrid(turfExtent, 0.003, {
        units: 'kilometers',
        mask: turfPolygon,
      });
      
      // 将 turf取样点转为 Cesium取样点
      const cesiumSamplePoints = [];
      for (let i = 0; i < turfSamplePoints.features.length; i++) {
        const coord = turfSamplePoints.features[i].geometry.coordinates;
        cesiumSamplePoints.push(Cesium.Cartographic.fromDegrees(coord[0], coord[1]));
      }

      this.toolTip = new Custom.ToolTip(this.Global.viewer);
      this.toolTip.start();

      const promise = new Promise(res => {
        // 获取取样点的高程,使用 11级 地形,级别越高越精确,但越耗时
        res(Cesium.sampleTerrain(this.Global.viewer.terrainProvider, 11, cesiumSamplePoints))
      })
      promise.then(res => {
        let highest = 0 // 最大高度
        let lowest = 8888 // 最小高度
        res.forEach(point => {
          if (point.height > highest) {
            highest = point.height.toFixed(3);
          }
          if (point.height < lowest) {
            lowest = point.height.toFixed(3);
          }
        })
      })
    }

sampleTerrainMostDetailed、 sampleHeightMostDetailed

场景中同时存在模型和地形时,先调用取模型的高度,如果高度为 undefined 获取是较大的负值时,再调用取地形高度的方法,可以使点位高度尽量精准。值得注意的是,这两个方法都为 promise,是耗时操作,当点位太多时,会造成卡顿

        // 在模型上获取高度
        var c3 = new Cesium.Cartographic(
          Cesium.Math.toRadians(lon),
          Cesium.Math.toRadians(lat)
        )
        const promise = viewer.scene.sampleHeightMostDetailed([c3]);
        promise.then((data) => {
          console.log(data);
        });
        // 在地形上获取高度
        var c3 = Cesium.Cartesian3.fromDegrees(lon, lat);
        var position = []
        position.push(Cesium.Cartographic.fromCartesian(c3))
        const promise = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [position])
        promise.then((data) => {
          console.log(data);
        });

封装

 const GetPositionBylonlat = (viewer, posArr) => {
  return new Promise(function (resolve) {
    let lonlat = []
    posArr.forEach(item => {
      lonlat.push(new Cesium.Cartographic(Cesium.Math.toRadians(item.lon), Cesium.Math.toRadians(item.lat)))
    })
    let finalArr = []
    //模型上取点
    const promise = viewer.scene.sampleHeightMostDetailed(lonlat);//这里可以传多个点
    promise.then((data) => {
      data.forEach((obj, index) => {
        if (obj && obj.height) {
          finalArr[index] = Cesium.Cartesian3.fromDegrees(posArr[index].lon, posArr[index].lat, obj.height)
        } else {
          finalArr[index] = []
        }
      })
    });
    //地形上取点
    const promise1 = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, lonlat);
    promise1.then((data) => {
      data.forEach((obj, index) => {
        if (finalArr[index] && finalArr[index].height) {
          //这里就是判断是不是已经在模型上取点
        } else {
          finalArr[index] = Cesium.Cartesian3.fromDegrees(posArr[index].lon, posArr[index].lat, obj.height)
        }
      })
      resolve(finalArr)
    });
  })
}

GetPositionBylonlat(this.viewer, [{ lon: lon, lat: lat }]).then((res) => {})