cesium-绘制点、线、面

cesium-绘制点、线、面

介绍

在地图框架中,绘制点线面是最常见的功能,这里我们在cesium中实现它,让其可以在三维地形中贴地

实现效果

image-20220213144848919

线

image-20220213144923285

image-20220213144956017

完整代码

这里使用vue实现具体功能

<template>
  <div class="home">
    <el-row type="flex" :gutter="20">
      <el-col :span="24">
        <div class="grid-content bg-purple">
          <el-breadcrumb separator="/">
            <el-breadcrumb-item>cesium</el-breadcrumb-item>
            <el-breadcrumb-item>绘制功能</el-breadcrumb-item>
            <el-breadcrumb-item>点、线、面</el-breadcrumb-item>
          </el-breadcrumb>
        </div>
      </el-col>
    </el-row>
    <el-row type="flex" :gutter="20">
      <el-col :span="24">
        <div class="grid-content bg-purple">
          <cesiumComponent id="cesium" ref="refCesium"/>
        </div>
      </el-col>
    </el-row>
    <el-row type="flex" :gutter="20">
      <el-col :span="24">
        <div class="grid-content bg-purple">
          <el-button type="primary" @click="addDem()">复位</el-button>
          <el-button type="primary" @click="draw('point')">绘制点</el-button>
          <el-button type="primary" @click="draw('polyline')">绘制线</el-button>
          <el-button type="primary" @click="draw('polygon')">绘制面</el-button>
          <el-button type="primary" @click="clearDrawEntities">清空</el-button>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import cesiumComponent from '../cesium.vue'

export default {
  name: "draw",
  data() {
    return {
      _viewer: undefined,
      tempEntities: [],
    };
  },

  components: {
    cesiumComponent
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      this.$refs.refCesium.initMap();
      this._viewer = this.$refs.refCesium._viewer;
      this.addDem();
    },
    addDem() {
      let that = this;
      that._viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
        url: '../dem/ASTGTM_N29E087D'
      });
      that._viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(87.42919921875, 28.700224692776988, 67863.0),
        orientation: {
          heading: Cesium.Math.toRadians(0.0),
          pitch: Cesium.Math.toRadians(-45.0),
          roll: 0.0
        }
      });
    },
    /**
     * 根据类型绘制对象
     * @param type point、polyline、polygon
     */
    draw(type) {
      //绘制点
      let that = this;
      let viewer = this._viewer;
      let tempEntities = this.tempEntities;
      let position = [];
      let tempPoints = [];
      // 开启深度检测
      viewer.scene.globe.depthTestAgainstTerrain = true;
      let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
      switch (type) {
        case 'point':
          // 监听鼠标左键
          handler.setInputAction(function (movement) {
            // 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。
            let ray = viewer.camera.getPickRay(movement.position);
            // 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象
            position = viewer.scene.globe.pick(ray, viewer.scene);
            let point = that.drawPoint(position);
            tempEntities.push(point);
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          // 左键双击停止绘制
          handler.setInputAction(function () {
            handler.destroy();//关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
          // 右击单击停止绘制
          handler.setInputAction(function () {
            handler.destroy();//关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
        case 'polyline':
          //鼠标移动事件
          handler.setInputAction(function (movement) {
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          //左键点击操作
          handler.setInputAction(function (click) {
            //调用获取位置信息的接口
            let ray = viewer.camera.getPickRay(click.position);
            position = viewer.scene.globe.pick(ray, viewer.scene);
            tempPoints.push(position);
            let tempLength = tempPoints.length;
            //调用绘制点的接口
            let point = that.drawPoint(tempPoints[tempPoints.length - 1]);
            tempEntities.push(point);
            if (tempLength > 1) {
              let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
              tempEntities.push(pointline);
            } else {
              // tooltip.innerHTML = "请绘制下一个点,右键结束";
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //右键点击操作
          handler.setInputAction(function (click) {
            tempPoints = [];
            handler.destroy();//关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
        case 'polygon':
          //鼠标移动事件
          handler.setInputAction(function (movement) {
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          //左键点击操作
          handler.setInputAction(function (click) {
            //调用获取位置信息的接口
            let ray = viewer.camera.getPickRay(click.position);
            position = viewer.scene.globe.pick(ray, viewer.scene);
            tempPoints.push(position);
            let tempLength = tempPoints.length;
            //调用绘制点的接口
            let point = that.drawPoint(position);
            tempEntities.push(point);
            if (tempLength > 1) {
              let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
              tempEntities.push(pointline);
            } else {
              // tooltip.innerHTML = "请绘制下一个点,右键结束";
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //右键点击操作
          handler.setInputAction(function (click) {
            let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);

            if (cartesian) {
              let tempLength = tempPoints.length;
              if (tempLength < 3) {
                alert('请选择3个以上的点再执行闭合操作命令');
              } else {
                //闭合最后一条线
                let pointline = that.drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]);
                tempEntities.push(pointline);
                that.drawPolygon(tempPoints);
                tempEntities.push(tempPoints);
                handler.destroy();//关闭事件句柄
                handler = null;
              }
            }
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
      }
    },
    drawPoint(position, config) {
      let viewer = this._viewer;
      let config_ = config ? config : {};
      return viewer.entities.add({
        name: "点几何对象",
        position: position,
        point: {
          color: Cesium.Color.SKYBLUE,
          pixelSize: 10,
          outlineColor: Cesium.Color.YELLOW,
          outlineWidth: 3,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        }
      });
    },
    drawPolyline(positions, config_) {
      let viewer = this._viewer;
      if (positions.length < 1) return;
      let config = config_ ? config_ : {};
      return viewer.entities.add({
        name: "线几何对象",
        polyline: {
          positions: positions,
          width: config.width ? config.width : 5.0,
          material: new Cesium.PolylineGlowMaterialProperty({
            color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
          }),
          depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
            color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
          }),
          clampToGround: true,
        }
      });
    },
    drawPolygon(positions, config_) {
      let viewer = this._viewer;
      if (positions.length < 2) return;
      let config = config_ ? config_ : {};
      return viewer.entities.add({
        name: "面几何对象",
        polygon: {
          hierarchy: positions,
          material: config.color ? new Cesium.Color.fromCssColorString(config.color).withAlpha(.2) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.2),
        },
      });
    },
    /**
     * 清除实体
     */
    clearDrawEntities() {
      let viewer = this._viewer;
      this.tempEntities = [];
      // 清除之前的实体
      const entitys = viewer.entities._entities._array;
      let length = entitys.length
      // 倒叙遍历防止实体减少之后entitys[f]不存在
      for (let f = length - 1; f >= 0; f--) {
        if (entitys[f]._name && (entitys[f]._name === '点几何对象' || entitys[f]._name === '线几何对象' || entitys[f]._name === '面几何对象')) {
          viewer.entities.remove(entitys[f]);
        }
      }
    },
  },
  created() {

  },
}
</script>

<style scoped>
.home {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.el-breadcrumb {
  margin: 10px;
  font-size: 15px;
}
#cesium {
  max-height: 600px;
}
</style>

核心代码

这里实现思路是开启cesium的监听事件,左键开始绘制,右键完成绘制,具体监听事件代码如下:

  /**
     * 根据类型绘制对象
     * @param type point、polyline、polygon
     */
    draw(type) {
      //绘制点
      let that = this;
      let viewer = this._viewer;
      let tempEntities = this.tempEntities;
      let position = [];
      let tempPoints = [];
      // 开启深度检测
      viewer.scene.globe.depthTestAgainstTerrain = true;
      let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
      switch (type) {
        case 'point':
          // 监听鼠标左键
          handler.setInputAction(function (movement) {
            // 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。
            let ray = viewer.camera.getPickRay(movement.position);
            // 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象
            position = viewer.scene.globe.pick(ray, viewer.scene);
            let point = that.drawPoint(position);
            tempEntities.push(point);
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          // 左键双击停止绘制
          handler.setInputAction(function () {
            handler.destroy();//关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
          // 右击单击停止绘制
          handler.setInputAction(function () {
            handler.destroy();//关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
        case 'polyline':
          //鼠标移动事件
          handler.setInputAction(function (movement) {
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          //左键点击操作
          handler.setInputAction(function (click) {
            //调用获取位置信息的接口
            let ray = viewer.camera.getPickRay(click.position);
            position = viewer.scene.globe.pick(ray, viewer.scene);
            tempPoints.push(position);
            let tempLength = tempPoints.length;
            //调用绘制点的接口
            let point = that.drawPoint(tempPoints[tempPoints.length - 1]);
            tempEntities.push(point);
            if (tempLength > 1) {
              let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
              tempEntities.push(pointline);
            } else {
              // tooltip.innerHTML = "请绘制下一个点,右键结束";
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //右键点击操作
          handler.setInputAction(function (click) {
            tempPoints = [];
            handler.destroy();//关闭事件句柄
            handler = null;
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
        case 'polygon':
          //鼠标移动事件
          handler.setInputAction(function (movement) {
          }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
          //左键点击操作
          handler.setInputAction(function (click) {
            //调用获取位置信息的接口
            let ray = viewer.camera.getPickRay(click.position);
            position = viewer.scene.globe.pick(ray, viewer.scene);
            tempPoints.push(position);
            let tempLength = tempPoints.length;
            //调用绘制点的接口
            let point = that.drawPoint(position);
            tempEntities.push(point);
            if (tempLength > 1) {
              let pointline = that.drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]);
              tempEntities.push(pointline);
            } else {
              // tooltip.innerHTML = "请绘制下一个点,右键结束";
            }
          }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
          //右键点击操作
          handler.setInputAction(function (click) {
            let cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);

            if (cartesian) {
              let tempLength = tempPoints.length;
              if (tempLength < 3) {
                alert('请选择3个以上的点再执行闭合操作命令');
              } else {
                //闭合最后一条线
                let pointline = that.drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]);
                tempEntities.push(pointline);
                that.drawPolygon(tempPoints);
                tempEntities.push(tempPoints);
                handler.destroy();//关闭事件句柄
                handler = null;
              }
            }
          }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
          break;
      }
    },

绘制点、线、面的代码:

   drawPoint(position, config) {
      let viewer = this._viewer;
      let config_ = config ? config : {};
      return viewer.entities.add({
        name: "点几何对象",
        position: position,
        point: {
          color: Cesium.Color.SKYBLUE,
          pixelSize: 10,
          outlineColor: Cesium.Color.YELLOW,
          outlineWidth: 3,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        }
      });
    },
    drawPolyline(positions, config_) {
      let viewer = this._viewer;
      if (positions.length < 1) return;
      let config = config_ ? config_ : {};
      return viewer.entities.add({
        name: "线几何对象",
        polyline: {
          positions: positions,
          width: config.width ? config.width : 5.0,
          material: new Cesium.PolylineGlowMaterialProperty({
            color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
          }),
          depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
            color: config.color ? new Cesium.Color.fromCssColorString(config.color) : Cesium.Color.GOLD,
          }),
          clampToGround: true,
        }
      });
    },
    drawPolygon(positions, config_) {
      let viewer = this._viewer;
      if (positions.length < 2) return;
      let config = config_ ? config_ : {};
      return viewer.entities.add({
        name: "面几何对象",
        polygon: {
          hierarchy: positions,
          material: config.color ? new Cesium.Color.fromCssColorString(config.color).withAlpha(.2) : new Cesium.Color.fromCssColorString("#FFD700").withAlpha(.2),
        },
      });
    },
### 回答1: Cesium是一个开源的基于Web的三维地理信息系统,可以帮助您使用JavaScript在浏览器中创建交互式三维地图。如果您想在Cesium绘制线,可以使用PolylineGeometry或PolylineVolumeGeometry类。 要使用PolylineGeometry绘制线,需要提供线的端坐标数组和其他一些可选的参数,如线的颜色、宽度等。例如: ``` var polyline = new Cesium.PolylineGeometry({ positions : Cesium.Cartesian3.fromDegreesArray([ 116.3, 39.9, 117.0, 40.5 ]), width : 10.0, material : new Cesium.ColorMaterial(Cesium.Color.BLUE) }); ``` 要使用PolylineVolumeGeometry绘制线,您还需要提供线的底和顶的控制坐标数组,以及其他一些可选的参数,如线的颜色、底宽度和顶宽度等。例如: ``` var polylineVolume = new Cesium.PolylineVolumeGeometry({ vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL, positions : Cesium.Cartesian3.fromDegreesArray([ 116.3, 39.9, 117.0, 40.5 ]), shapePositions : [new Cesium.Cartesian2(-10.0, -10.0), new Cesium.Cartesian2(-10.0, 10.0), new Cesium.Cartesian2(10.0, 10.0), new Cesium.Cartesian2(10.0, -10.0)], material : new Cesium.ColorMaterial(Cesium.Color.BLUE) }); ``` 这些几何体可以通过使用Primitive类或GeometryInstance类来呈现。例如,可以使用以下代码呈现PolylineGeometry: ``` viewer.scene.primitives.add(new Cesium.Primitive({ geometryInstances : ### 回答2: Cesium是一个基于Web的开源地理信息系统 (GIS) 开发框架,可以用于在浏览器中展示地球、地图和空间数据。Cesium提供了丰富的功能,包括绘制线形图形。 要在Cesium绘制线,我们可以使用Cesium的Entity API来创建一个Entity对象,然后设置线的相关属性。以下是一个使用Cesium绘制线的示例代码: ```javascript // 创建Cesium Viewer对象 var viewer = new Cesium.Viewer('cesiumContainer'); // 设置视图位置 var position = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 100); viewer.camera.setView({ destination: position, orientation: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(-90), roll: Cesium.Math.toRadians(0) } }); // 创建一个空间直线 var line = viewer.entities.add({ name: 'Red line', polyline: { positions: Cesium.Cartesian3.fromDegreesArray([ -75, 35, -125, 35 ]), width: 5, material: Cesium.Color.RED } }); // 将视图调整到线的位置 viewer.zoomTo(line); ``` 在这个示例中,我们首先创建了一个Cesium Viewer对象,并设置了初始视图位置。然后,我们通过`viewer.entities.add`方法创建了一个Entity对象,其中设置了线形图形的相关属性。通过`positions`属性,我们指定了线的坐标,这里是起和终的经纬度数组。`width`属性用于设置线的宽度,`material`属性用于设置线的颜色。最后,通过`viewer.zoomTo`方法将视图调整到线的位置。 以上就是使用Cesium交互式绘制线的简单示例。通过调整相关属性,我们可以绘制不同样式的线形图形,并灵活控制其位置和视图展示。 ### 回答3: Cesium是一种开源的虚拟地球和空间可视化引擎,它提供了许多功能,包括绘制各种图形元素。在Cesium中,通过几个步骤可以实现交互式绘制线的功能。 首先,我们需要定义一个用于绘制线的实体对象。在Cesium中,可以使用`PolylineGraphics`来创建线对象。通过设置`positions`属性,我们可以指定线的起始和结束的位置信息。 接下来,我们可以通过添加鼠标事件监听器来实现交互式绘制线的功能。例如,我们可以监听鼠标的击事件,在击地球上的某个时创建一个新的`PolylineGraphics`对象,并将其添加到场景中。通过监听鼠标的移动事件,我们可以动态更新线的结束位置,从而实现线的交互式绘制。 在添加线对象之前,我们需要先创建一个实体对象,将线对象添加到实体的`graphics`属性中。例如,我们可以创建一个新的`Entity`对象,将线对象添加到该实体对象的`graphics`属性中。然后,将该实体对象添加到场景中即可。 最后,我们可以通过设置线对象的样式属性来自定义绘制线的外观。例如,可以设置线的颜色、宽度、材质等属性,以满足不同的需求。 总结起来,通过定义线对象、添加交互事件监听器、创建实体对象并添加到场景中、设置线样式属性,我们可以在Cesium中实现交互式绘制线的功能。这些步骤可以帮助用户在地球上自由绘制线条,并根据实际需求对线条进行样式调整。
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙霸天

你的打赏是我不断创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值