分享

cesium-绘制点、线、面

 3克拉的Anran 2022-05-06 发布于北京

介绍

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

实现效果

线

完整代码

这里使用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),

        },

      }); 

    },

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多