Cesium实现空间查询

Cesium实现空间查询,主要通过在地图上勾画区域,从而查询区域内的点。功能实现依靠viewer.screenSpaceEventHandler.setInputAction方法为屏幕空间事件绑定处理函数,主要触发的事件为Cesium.ScreenSpaceEventType.LEFT_CLICK、Cesium.ScreenSpaceEventType.MOUSE_MOVE、Cesium.ScreenSpaceEventType.RIGHT_CLICK对应鼠标左键、鼠标移动、鼠标右键。

1.Cesium.ScreenSpaceEventType.LEFT_CLICK事件

鼠标左键点击事件用来勾画地图区域。

通过点击事件来获取地球表面的具体坐标

const ray = viewer.camera.getPickRay(event.position)
const earthPosition = viewer.scene.globe.pick(ray,viewer.scene)

判断earthPosition是否点击在地球上的区域,如果不是则会返回undefined

if(Cesium.defined(earthPosition))

判断是否为第一个点如果是:

(1)创建浮动点floatingPoint,后续勾画鼠标过程中,通过更改floatingPoint的position来保证该点跟随鼠标移动

(2)将勾画的点添加到activeShapePoints数组中,用来作为动态创建多边形的顶点数组

(3)Cesium.CallbackProperty动态创建属性,动态创建多边形,用于后续鼠标移动过程中不断在activeShapePoints中添加数据,跟随鼠标移动生成多边形

if(activeShapePoints.length === 0) {
        floatingPoint = createPoint(earthPosition)
        activeShapePoints.push(earthPosition)
        //创建活动面
        const dynamicPositions = new Cesium.CallbackProperty(function () {
          return new Cesium.PolygonHierarchy(activeShapePoints)
        })
        activeShape = drawShape(dynamicPositions)
      }

后续则是将earthPosition的坐标转换为经纬度,添加到geojsonPoints数组中,通过使用turf创建polygon,判断点是否在多边形内;createPoint用来显示勾画的点

 //将Cartesian坐标转换为经纬度数据
      let cartographic = Cesium.Cartographic.fromCartesian(earthPosition)
geojsonPoints.push([Cesium.Math.toDegrees(cartographic.longitude),Cesium.Math.toDegrees(cartographic.latitude)])
      activeShapePoints.push(earthPosition)
      createPoint(earthPosition)

Cesium.ScreenSpaceEventType.LEFT_CLICK事件整体代码:

  viewer.screenSpaceEventHandler.setInputAction(function (event) {
    //通过点击事件,获取地球的坐标
    const ray = viewer.camera.getPickRay(event.position)
    const earthPosition = viewer.scene.globe.pick(ray,viewer.scene)

    //检查是否点击的地球上的位置,如果不是earthPosition则为undefined
    if(Cesium.defined(earthPosition)) {
      //点击地图区域创建点
      if(activeShapePoints.length === 0) {
        floatingPoint = createPoint(earthPosition)
        activeShapePoints.push(earthPosition)

        //动态创建多边形
        const dynamicPositions = new Cesium.CallbackProperty(function () {
          return new Cesium.PolygonHierarchy(activeShapePoints)
        })
        activeShape = drawShape(dynamicPositions)
      }
      //将Cartesian坐标转换为经纬度数据
      let cartographic = Cesium.Cartographic.fromCartesian(earthPosition)
      
      //方便后续使用turf生成polygon
geojsonPoints.push([Cesium.Math.toDegrees(cartographic.longitude),Cesium.Math.toDegrees(cartographic.latitude)])

      activeShapePoints.push(earthPosition)

      createPoint(earthPosition)
    }


  },Cesium.ScreenSpaceEventType.LEFT_CLICK)

2.Cesium.ScreenSpaceEventType.MOUSE_MOVE事件

判断是否创建了浮动点,鼠标勾画过程中需要有浮动点跟随

if(Cesium.defined(floatingPoint))

(1)与开始勾画类似 ,通过鼠标移动事件来获取地球表面的具体坐标,判断是否点击地球上的位置

(2)如果在地图上的区域,鼠标移动过程中动态更新浮动点位置;并不断替换activeShapePoints中最后一个数据,跟随鼠标移动,动态生成多边形。

if(Cesium.defined(floatingPoint)) {
      const ray = viewer.camera.getPickRay(event.endPosition)
      const newPosition = viewer.scene.globe.pick(ray,viewer.scene)
      // console.log(newPosition)
      if(Cesium.defined(newPosition)) {
        //更新浮动点的位置,鼠标移动过程中,这个点跟随移动,当第二次点击是,留下一个点,因为floatingPoint又接受了一个新值
        floatingPoint.position.setValue(newPosition)
        activeShapePoints.pop()
        activeShapePoints.push(newPosition)
        // console.log(activeShapePoints)
      }
    }

Cesium.ScreenSpaceEventType.MOUSE_MOVE事件整体代码:

 viewer.screenSpaceEventHandler.setInputAction(function (event) {
    if(Cesium.defined(floatingPoint)) {
      const ray = viewer.camera.getPickRay(event.endPosition)
      const newPosition = viewer.scene.globe.pick(ray,viewer.scene)
      // console.log(newPosition)
      if(Cesium.defined(newPosition)) {
        //更新浮动点的位置,鼠标移动过程中,这个点跟随移动,当第二次点击是,留下一个点,因为floatingPoint又接受了一个新值
        floatingPoint.position.setValue(newPosition)
        activeShapePoints.pop()
        activeShapePoints.push(newPosition)
        // console.log(activeShapePoints)
      }
    }
  },Cesium.ScreenSpaceEventType.MOUSE_MOVE)

3.Cesium.ScreenSpaceEventType.RIGHT_CLICK事件

鼠标右键事件则是完成勾画,对多边形区域内的点进行查询

根据geojsonPoints中的点数据,利用turf第三方库生成多边形;turf生成多边形,需要第一个点和最后一个点相同,需要在最后一个位置再次添加第一个点

let one = geojsonPoints[0]
geojsonPoints.push(one)
let geojsonPolygon = turf.polygon([geojsonPoints])

设置要查询的点数据

let points = {
      '北京': [115.7,39.4,500],
      '成都': [104.066458,30.659461,500],
      '上海': [121.473701,31.230416,500]
    }

对数据进行遍历,通过turf.point创建点;利用turf.booleanPointInPolygon判断点是否在多边形内,如果在则添加到地图上显示

for(let key in points) {
      let point = turf.point(points[key])
      console.log(points[key])
      if(turf.booleanPointInPolygon(point, geojsonPolygon)) {
        viewer.entities.add({
          name: 'pointQuery',
          position:   Cesium.Cartesian3.fromDegrees(...points[key]),
          point: {
            color: Cesium.Color.fromCssColorString('#000000'),
            outlineColor: Cesium.Color.fromCssColorString('#ffffff'),
            outlineWidth: 2,
            pixelSize: 6,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//始终贴合地形表面
            disableDepthTestDistance: Number.POSITIVE_INFINITY, //确保一个点实体总是可见,即使它位于其他对象后面
          }
        })
      }
      
    }

最后清除相关数据,解除相关事件

terminateShape()
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)

Cesium.ScreenSpaceEventType.RIGHT_CLICK事件整体代码:

  viewer.screenSpaceEventHandler.setInputAction(function () {

    let one = geojsonPoints[0]
    geojsonPoints.push(one)
    let geojsonPolygon = turf.polygon([geojsonPoints])

    let points = {
      '北京': [115.7,39.4,500],
      '成都': [104.066458,30.659461,500],
      '上海': [121.473701,31.230416,500]
    }

    for(let key in points) {
      let point = turf.point(points[key])
      console.log(points[key])
      if(turf.booleanPointInPolygon(point, geojsonPolygon)) {
        viewer.entities.add({
          name: 'pointQuery',
          position:   Cesium.Cartesian3.fromDegrees(...points[key]),
          point: {
            color: Cesium.Color.fromCssColorString('#000000'),
            outlineColor: Cesium.Color.fromCssColorString('#ffffff'),
            outlineWidth: 2,
            pixelSize: 6,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//始终贴合地形表面
            disableDepthTestDistance: Number.POSITIVE_INFINITY, //确保一个点实体总是可见,即使它位于其他对象后面
          }
        })
      }
      
    }

    terminateShape()
    viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    // getEntity()
  },Cesium.ScreenSpaceEventType.RIGHT_CLICK)

实现效果:

全部代码:

  viewer.screenSpaceEventHandler.setInputAction(function (event) {
    const ray = viewer.camera.getPickRay(event.position)
    const earthPosition = viewer.scene.globe.pick(ray,viewer.scene)
    console.log(earthPosition)

    //检查是否点击的地球上的位置,如果不是earthPosition则为undefined
    if(Cesium.defined(earthPosition)) {
      //点击地图区域创建点
      if(activeShapePoints.length === 0) {
        floatingPoint = createPoint(earthPosition)
        activeShapePoints.push(earthPosition)


        //创建活动面
        const dynamicPositions = new Cesium.CallbackProperty(function () {
          return new Cesium.PolygonHierarchy(activeShapePoints)
        })
        activeShape = drawShape(dynamicPositions)
      }
      //将Cartesian坐标转换为经纬度数据
      let cartographic = Cesium.Cartographic.fromCartesian(earthPosition)
      geojsonPoints.push([Cesium.Math.toDegrees(cartographic.longitude),Cesium.Math.toDegrees(cartographic.latitude)])

      activeShapePoints.push(earthPosition)

      // let hh = earthPosition
      console.log(activeShapePoints)

      createPoint(earthPosition)
    }


  },Cesium.ScreenSpaceEventType.LEFT_CLICK)

  viewer.screenSpaceEventHandler.setInputAction(function (event) {
    if(Cesium.defined(floatingPoint)) {
      const ray = viewer.camera.getPickRay(event.endPosition)
      const newPosition = viewer.scene.globe.pick(ray,viewer.scene)
      // console.log(newPosition)
      if(Cesium.defined(newPosition)) {
        //更新浮动点的位置,鼠标移动过程中,这个点跟随移动,当第二次点击是,留下一个点,因为floatingPoint又接受了一个新值
        floatingPoint.position.setValue(newPosition)
        activeShapePoints.pop()
        activeShapePoints.push(newPosition)
        // console.log(activeShapePoints)
      }
    }
  },Cesium.ScreenSpaceEventType.MOUSE_MOVE)


  viewer.screenSpaceEventHandler.setInputAction(function () {

    let one = geojsonPoints[0]
    geojsonPoints.push(one)
    let geojsonPolygon = turf.polygon([geojsonPoints])

    let points = {
      '北京': [115.7,39.4,500],
      '成都': [104.066458,30.659461,500],
      '上海': [121.473701,31.230416,500]
    }

    for(let key in points) {
      let point = turf.point(points[key])
      console.log(points[key])
      if(turf.booleanPointInPolygon(point, geojsonPolygon)) {
        viewer.entities.add({
          name: 'pointQuery',
          position:   Cesium.Cartesian3.fromDegrees(...points[key]),
          point: {
            color: Cesium.Color.fromCssColorString('#000000'),
            outlineColor: Cesium.Color.fromCssColorString('#ffffff'),
            outlineWidth: 2,
            pixelSize: 6,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//始终贴合地形表面
            disableDepthTestDistance: Number.POSITIVE_INFINITY, //确保一个点实体总是可见,即使它位于其他对象后面
          }
        })
      }
      
    }

    terminateShape()
    viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    // getEntity()
  },Cesium.ScreenSpaceEventType.RIGHT_CLICK)
})

const createPoint = (worldPosition) => {

  let point = viewer.entities.add({
    name: 'point',
    position: worldPosition,
    point: {
      color: Cesium.Color.fromCssColorString('#000000'),
      outlineColor: Cesium.Color.fromCssColorString('#03edfe'),
      outlineWidth: 2,
      pixelSize: 6,
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,//始终贴合地形表面
      disableDepthTestDistance: Number.POSITIVE_INFINITY, //确保一个点实体总是可见,即使它位于其他对象后面
    }
  })

  return point

}

const drawShape = (dynamicPositions) => {
  return viewer.entities.add({
    name: 'sketchPolygon',
    polygon: {
      hierarchy:dynamicPositions,
      material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.2))
    }
  })
}

const terminateShape = () => {
  // drawShape(activeShapePoints)
  viewer.entities.remove(floatingPoint)
  viewer.entities.remove(activeShape)
  activeShapePoints = []
  floatingPoint = undefined
  activeShape = undefined
  clearPoint()
}

const clearPoint = () => {
  //清除点entity
  let entities = viewer.entities.values
  let entitiesToRemove = entities.filter((entity) => {
    return entity.name == 'point'
  })
  console.log(entitiesToRemove)
  entitiesToRemove.forEach((entity) => {
    viewer.entities.remove(entity)
  })
}

参考链接:

(九)Cesium实现坐标、距离和面积测量_cesium.math.todegrees-CSDN博客

### 回答1: Cesium提供了多种空间分析工具,可以帮助用户在三维场景中进行空间分析。以下是其中的一些工具: 1. 空间测量工具:该工具可以帮助用户测量两点之间的距离、两线之间的距离、多边形面积等。 2. 可视域分析工具:该工具可以帮助用户确定一个位置是否可以看到其他位置,从而帮助用户进行可视域分析。 3. 地形剖面工具:该工具可以帮助用户生成地形剖面图,以便用户更好地了解地形的变化情况。 4. 空间查询工具:该工具可以帮助用户查询三维场景中的对象信息,例如查找离某个位置最近的建筑物、查找所有高于某个高度的建筑物等。 5. 模拟分析工具:该工具可以帮助用户进行模拟分析,例如飞行模拟、车辆行驶模拟等。 这些工具可以通过Cesium的API进行调用并进行定制化配置,满足用户的不同分析需求。 ### 回答2: Cesium是一个基于Web的三维地球、地理空间数据可视化的开源库。虽然Cesium本身并不直接提供空间分析功能,但可以通过它的一些插件、扩展以及与其他库的结合来实现空间分析。 首先,Cesium提供了一些基本的几何对象,例如点、线、面等,可以用来表示和操作地理空间数据。通过这些基本对象,可以进行一些简单的空间分析,如计算两个点之间的距离、两条线的交点等。 其次,Cesium可以与其他地理空间数据处理库结合使用,如Turf.js、JSTS等。这些库提供了丰富的空间分析功能,例如缓冲区分析、叠加分析、网络分析等。通过将这些库与Cesium结合使用,可以在Cesium实现更复杂的空间分析。 此外,Cesium还支持加载和展示各种地理空间数据格式,包括矢量数据(如GeoJSON、KML)、栅格数据(如影像、地形)以及点云数据等。通过加载和展示这些数据,可以对其进行空间分析,例如提取特定区域的数据、计算数据的统计特征等。 最后,Cesium还提供了一些插件和扩展,例如cesium-ion、cesium-sensor-volumes等。这些插件和扩展可以用来进行更复杂的空间分析,如视域分析、阴影分析等。 综上所述,尽管Cesium本身并不直接提供空间分析功能,但通过结合其他库的使用、加载地理空间数据以及使用相关插件和扩展,我们可以在Cesium实现各种空间分析操作。 ### 回答3: Cesium是一个用于构建虚拟地球和空间可视化的JavaScript库。通过Cesium,我们可以实现多种空间分析功能。 首先,Cesium提供了高度精确的地理坐标定位系统,支持包括经纬度、高度、海拔等在内的多种空间坐标系统。我们可以通过Cesium的坐标转换函数,在不同坐标系统之间进行转换,实现空间数据的兼容性。 其次,Cesium提供了强大的地理信息处理功能。我们可以使用该库加载和显示各种地理数据,如矢量数据、栅格数据、地形数据等。同时,Cesium还支持空间数据的可视化和渲染,可以将数据以三维模型、标注、热力图等形式呈现在虚拟地球上。 在空间分析方面,Cesium提供了一系列的工具和功能。例如,我们可以使用Cesium的渲染器,对空间数据进行空间关系分析,如相交、包含、相离等。此外,Cesium还支持路径规划和导航功能,可以进行经纬度之间的路线规划和导航。 另外,Cesium还提供了高级的空间分析功能,如可视域分析、阴影分析、地形剖面等。我们可以使用Cesium的可视化工具,在虚拟地球上模拟光照条件,并计算特定位置的可视域范围。同时,Cesium还支持地形剖面功能,可以跟踪沿着指定路径的地形特征,如高程、坡度等。 总而言之,Cesium通过提供强大的地理信息处理和可视化功能,为空间数据分析提供了丰富的工具和技术支持。无论是在地理信息系统、城市规划还是环境监测领域,Cesium都可以帮助我们更好地分析、展示和理解空间数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值