cesium-添加点线面可以动可编辑

2023-11-05

使用

const drawEntities = new CesiumEntityDraw(viewer!, {});
 drawEntities.startDraw('需要绘制的类型');

CesiumEntityDraw.ts文件

import Cesium from 'cesium';
import CesiumEntityEdit from './entityMove';
class CesiumEntityDraw {
  private viewer: any;
  private config: any;
  private infoDetail: any;
  private handler: any;
  private entityEdit: any;
  constructor(
    viewer: Cesium.Viewer,
    config: { borderColor?: Cesium.Color; borderWidth?: number; material?: Cesium.Color }
  ) {
    /**cesium实例对象 */
    this.viewer = viewer;
    this.entityEdit = new CesiumEntityEdit(viewer, {});
    /**绘制要素的相关配置
       * 默认配置
       * {
          borderColor: Cesium.Color.BLUE,  边框颜色
          borderWidth: 2, 边框宽度
          material: Cesium.Color.GREEN.withAlpha(0.5),填充材质
      }
      */
    this.config = config || {
      borderColor: Cesium.Color.BLUE,
      borderWidth: 2
      // material: Cesium.Color.GREEN.withAlpha(0.5),
    };
    /**存贮绘制的数据 坐标 */
    this.infoDetail = {
      point: [],
      line: [],
      rectangle: [],
      circle: [],
      planeSelf: []
    };
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
  }
  startDraw(type: string) {
    switch (type) {
      case 'point':
        this.drawPoint();
        break;
      case 'rectangle':
        this.drawRectangle();
        break;
      case 'circle':
        this.drawCircle();
        break;
      case 'polygon':
        this.drawPolygon();
        break;
      case 'line':
        this.drawLine();
        break;
      default:
        this.drawPoint();
        break;
    }
    this.entityEdit.start();
  }
  /*******
   * @function: function
   * @return {*}
   * @description: 绘制点数据
   */
  drawPoint() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click: { position: any }) => {
      /**点击位置笛卡尔坐标 */
      const cartesian = this.viewer.camera.pickEllipsoid(
        click.position,
        this.viewer.scene.globe.ellipsoid
      );
      /**笛卡尔转弧度坐标 */
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      /**点击位置经度 */
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      /**点击位置维度 */
      const lat = Cesium.Math.toDegrees(cartographic.latitude);
      /**实体的唯一标注 */
      const id = new Date().getTime();
      this.viewer.entities.add({
        position: Cesium.Cartesian3.fromDegrees(lng, lat, 0),
        name: 'point',
        id: id,
        point: {
          color: Cesium.Color.BLUE,
          pixelSize: 13,
          outlineColor: Cesium.Color.WHITE,
          outlineWidth: 1
        }
      });
      this.infoDetail.point.push({ id: id, position: [lng, lat] });
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction((click: any) => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制矩形区域
   */
  drawRectangle() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    const positions: any = [];
    let rectangle = null;
    const canvas = this.viewer.scene.canvas;
    this.handler = new Cesium.ScreenSpaceEventHandler(canvas);
    this.handler.setInputAction((click: { position: any }) => {
      if (positions.length) return;
      const cartesian = this.getCatesian3FromPX(click.position);
      positions.push(cartesian, cartesian);
      rectangle = this.viewer.entities.add({
        name: 'rectangle',
        rectangle: {
          coordinates: new Cesium.CallbackProperty(() => {
            const obj = Cesium.Rectangle.fromCartesianArray(positions);
            return obj;
          }, false),
          height: 0.1,
          material: this.config.material,
          zIndex: 100
        }
      });
      this.handler.setInputAction((move: { endPosition: any }) => {
        const cartesian = this.getCatesian3FromPX(move.endPosition);
        if (rectangle) {
          positions[positions.length - 1] = cartesian;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.handler.setInputAction((click: any) => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制矩形区域
   */
  drawRectangleByPolygon() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**
     * 矩形四点坐标
     */
    let westSouthEastNorth: number[] = [];
    /**实体的唯一标注 */
    let id: any = null;
    /**地图点击对象 */
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click: { position: any }) => {
      this.viewer.scene.screenSpaceCameraController.enableRotate = false; //锁定相机
      /**点击位置笛卡尔坐标 */
      const cartesian = this.viewer.camera.pickEllipsoid(
        click.position,
        this.viewer.scene.globe.ellipsoid
      );
      /**笛卡尔转弧度坐标 */
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      /**点击位置经度 */
      const lng1 = Cesium.Math.toDegrees(cartographic.longitude);
      /**点击位置维度 */
      const lat1 = Cesium.Math.toDegrees(cartographic.latitude);
      /**边框坐标 */
      westSouthEastNorth = [lng1, lat1];
      id = new Date().getTime();
      if (westSouthEastNorth) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      /**面实例对象 */
      this.viewer.entities.add({
        name: 'rectangle',
        id: id,
        polygon: {
          hierarchy: new Cesium.CallbackProperty(function () {
            return {
              positions: Cesium.Cartesian3.fromDegreesArray(westSouthEastNorth)
            };
          }, false),
          height: 0,
          // 填充的颜色,withAlpha透明度
          material: this.config.material,
          // 是否被提供的材质填充
          fill: true,
          // 是否显示
          show: true
        }
        // polyline: {
        //   positions: new Cesium.CallbackProperty(function() {
        //     return Cesium.Cartesian3.fromDegreesArray(westSouthEastNorth);
        //   }),
        //   material: this.config.borderColor,
        //   width: this.config.borderWidth,
        //   zIndex: 1
        // }
      });
      this.handler.setInputAction((move: { endPosition: any }) => {
        const cartesian = this.viewer.camera.pickEllipsoid(
          move.endPosition,
          this.viewer.scene.globe.ellipsoid
        );
        const cartographic = Cesium.Cartographic.fromCartesian(
          cartesian,
          this.viewer.scene.globe.ellipsoid,
          new Cesium.Cartographic()
        );
        const lng = Cesium.Math.toDegrees(cartographic.longitude);
        const lat = Cesium.Math.toDegrees(cartographic.latitude);

        westSouthEastNorth = [lng1, lat1, lng1, lat, lng, lat, lng, lat1, lng1, lat1];
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(() => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
      this.infoDetail.rectangle.push({ id: id, position: westSouthEastNorth });
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制圆形区域
   * @return {*}
   */
  drawCircle() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**实体的唯一标注 */
    let id: any = null;

    /**圆半径 */
    let radius: number = 0;
    /**圆心 */
    let lngLat: any = [];
    /**鼠标事件 */
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click: { position: any }) => {
      id = new Date().getTime();
      const cartesian = this.viewer.camera.pickEllipsoid(
        click.position,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);
      lngLat = [lng, lat];
      const entity = this.viewer.entities.add({
        position: new Cesium.CallbackProperty(function () {
          return Cesium.Cartesian3.fromDegrees(lng, lat);
        }, false),
        name: 'circle',
        id: id,
        ellipse: {
          height: 0,
          outline: true,
          material: this.config.material,
          outlineColor: this.config.borderColor,
          outlineWidth: this.config.borderWidth
        }
      });
      entity.ellipse.semiMajorAxis = new Cesium.CallbackProperty(function () {
        return radius;
      }, false);
      entity.ellipse.semiMinorAxis = new Cesium.CallbackProperty(function () {
        return radius;
      }, false);

      if (lngLat) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      this.handler.setInputAction((move: { endPosition: any }) => {
        const cartesian2 = this.viewer.camera.pickEllipsoid(
          move.endPosition,
          this.viewer.scene.globe.ellipsoid
        );
        radius = Cesium.Cartesian3.distance(cartesian, cartesian2);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(() => {
      this.infoDetail.circle.push({ id: id, center: lngLat, radius: radius });
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 自定义区域绘制
   */
  drawPolygon() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**实体的唯一标注 */
    const id = new Date().getTime();
    /**记录拐点坐标 */
    const positions: any = [];
    /**记录返回结果 */
    const codeInfo: any = [];
    /**面的hierarchy属性 */
    const polygon = new Cesium.PolygonHierarchy();
    const _polygonEntity: any = new Cesium.Entity();
    /**面对象配置 */
    let polyObj = null;
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement: { position: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.position,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push([lng, lat]);
        positions.push(cartesian.clone());
        polygon.positions.push(cartesian.clone());
        if (!polyObj) {
          // _polygonEntity.polyline = {
          //   width: this.config.borderWidth,
          //   material: this.config.borderColor,
          //   clampToGround: false
          // };
          // _polygonEntity.polyline.positions = new Cesium.CallbackProperty(
          //   function() {
          //     return positions;
          //   },
          //   false
          // );

          _polygonEntity.polygon = {
            hierarchy: new Cesium.CallbackProperty(function () {
              return polygon;
            }, false),
            zIndex: 100,
            height: 0.1,
            material: Cesium.Color.BLUE.withAlpha(0.8),
            clampToGround: false
          };
          _polygonEntity.name = 'polygon';

          _polygonEntity._id = id;
          polyObj = this.viewer.entities.add(_polygonEntity);
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // mouse
    this.handler.setInputAction((movement: { endPosition: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.endPosition,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          polygon.positions.pop();
          polygon.positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // right
    this.handler.setInputAction((movement: any) => {
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
      this.infoDetail.planeSelf.push({ id: id, positions: codeInfo });
      positions.push(positions[0]);
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  /*******
   * @function: function
   * @return {*}
   * @description: 绘制线段
   */
  drawLine() {
    this.stopDraw();
    // 设置鼠标样式为crosshair
    document.body.style.cursor = 'crosshair';
    /**实体的唯一标注 */
    const id = new Date().getTime();
    /**记录拐点坐标 */
    const positions: any = [],
      /**记录返回结果 */
      codeInfo: any = [],
      /**面的hierarchy属性 */
      polygon = new Cesium.PolygonHierarchy(),
      _polygonEntity: any = new Cesium.Entity();
    /**面对象配置 */
    let polyObj = null;
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement: { position: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.position,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push([lng, lat]);
        positions.push(cartesian.clone());
        polygon.positions.push(cartesian.clone());
        if (!polyObj) {
          _polygonEntity.polyline = {
            width: 4,
            material: Cesium.Color.BLUE.withAlpha(0.8),
            clampToGround: true
          };
          _polygonEntity.polyline.positions = new Cesium.CallbackProperty(function () {
            return positions;
          }, false);
          _polygonEntity.name = 'line';
          _polygonEntity._id = id;

          polyObj = this.viewer.entities.add(_polygonEntity);
          // this.entityEdit = new CesiumEntityEdit(this.viewer, polyObj);
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // mouse
    this.handler.setInputAction((movement: { endPosition: any }) => {
      const cartesian = this.viewer.camera.pickEllipsoid(
        movement.endPosition,
        this.viewer.scene.globe.ellipsoid
      );
      const cartographic = Cesium.Cartographic.fromCartesian(
        cartesian,
        this.viewer.scene.globe.ellipsoid,
        new Cesium.Cartographic()
      );
      const lng = Cesium.Math.toDegrees(cartographic.longitude);
      const lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // right
    this.handler.setInputAction((movement: any) => {
      this.infoDetail.line.push({ id: id, positions: codeInfo });
      this.stopDraw();
      // 添加操作完成后恢复鼠标样式为默认箭头
      document.body.style.cursor = 'default';
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 移除实体对象
   * @return {*}
   */
  removeEntity() {
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((move: { endPosition: any }) => {
      /**实体对象信息  {id:entities,primitive:。。} */
      const pick = this.viewer.scene.pick(move.endPosition);
      this.entityEdit.removeStretchPoint();

      if (pick && pick.id && pick.id.id) {
        document.body.style.cursor = 'pointer';
        this.handler.setInputAction((click: any) => {
          let newPoint: any;
          switch (pick.id.name) {
            case 'point':
              /**删除某一条数据 */
              newPoint = this.infoDetail.point.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.point = newPoint;
              break;
            case 'line':
              /**删除某一条数据 */
              newPoint = this.infoDetail.line.filter((item: { id: any }) => item.id != pick.id._id);
              this.infoDetail.line = newPoint;
              break;
            case 'rectangle':
              /**删除某一条数据 */
              newPoint = this.infoDetail.rectangle.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.rectangle = newPoint;
              break;

            case 'planeSelf':
              /**删除某一条数据 */
              newPoint = this.infoDetail.planeSelf.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.planeSelf = newPoint;
              break;
            case 'circle':
              /**删除某一条数据 */
              newPoint = this.infoDetail.circle.filter(
                (item: { id: any }) => item.id != pick.id._id
              );
              this.infoDetail.circle = newPoint;
              break;
            default:
              break;
          }
          this.viewer.entities.remove(pick.id);
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      } else {
        document.body.style.cursor = 'default';
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }
  /**
   *
   */
  removeAllEntity() {
    this.entityEdit.removeStretchPoint();
    Object.keys(this.infoDetail).map((name) => {
      this.infoDetail[name].map((item: { id: any }) => {
        this.viewer.entities.removeById(item.id);
      });
    });
  }
  /*******
   * @function: function
   * @return {*}
   * @description: 返回绘制数据
   */
  backInfoDetail() {
    return this.infoDetail;
  }
  stopDraw() {
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
    // this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
    this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    // this.handler && this.handler.destroy();
    // this.entityEdit.stop();
  }
  stopEdit() {
    this.entityEdit.stop();
  }
  getMousePostion(position: any) {
    if (!position) return;
    /**点击位置笛卡尔坐标 */
    const cartesian = this.viewer.camera.pickEllipsoid(position, this.viewer.scene.globe.ellipsoid);
    /**笛卡尔转弧度坐标 */
    const cartographic = Cesium.Cartographic.fromCartesian(
      cartesian,
      this.viewer.scene.globe.ellipsoid,
      new Cesium.Cartographic()
    );
    /**点击位置经度 */
    const lng1 = Cesium.Math.toDegrees(cartographic.longitude);
    /**点击位置维度 */
    const lat1 = Cesium.Math.toDegrees(cartographic.latitude);
    return [lng1, lat1];
  }
  getCatesian3FromPX(px: any) {
    const ray = this.viewer.camera.getPickRay(px);
    if (!ray) return null;
    const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
    return cartesian;
  }
}
export default CesiumEntityDraw;

CesiumEntityEdit .ts文件

/**
 * cesium 实体编辑:拖拽、旋转、修改
 */
import * as turf from '@turf/turf';
import Cesium from 'cesium';
class CesiumEntityEdit {
  private viewer: any;
  private options: any;
  private selectedEntity: any; // 被选择的实体对象
  private handler: any; // 事件捕获
  private mouseStatus: any; // 当前鼠标状态 LEFT_DOWN:左键按下;LEFT_UP: 左键抬起;MOVE: 鼠标移动
  private coordinates: any; // 当前被选中的实体组成的点集合
  private entityType: any; // 当前被选中实体的类型
  private entityCenter: any; // 多边形中心点
  private strecthPointIds: any; // 拉伸点Id集合
  private strecthObj: any; // 被选中的拉伸点
  private isStrecth: any; // 当前是否点击拉伸点
  private strecthObjId_index: any;
  constructor(viewer: any, options: {} | null) {
    this.viewer = viewer;
    this.options = options || {};
    this.selectedEntity = null; // 被选择的实体对象
    this.handler = null; // 事件捕获
    this.mouseStatus = null; // 当前鼠标状态 LEFT_DOWN:左键按下;LEFT_UP: 左键抬起;MOVE: 鼠标移动
    this.coordinates = []; // 当前被选中的实体组成的点集合
    this.entityType = 'polygon'; // 当前被选中实体的类型
    this.entityCenter = []; // 多边形中心点
    this.strecthPointIds = []; // 拉伸点Id集合
    this.strecthObj = null; // 被选中的拉伸点
    this.isStrecth = false; // 当前是否点击拉伸点
  }
  start() {
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // 监听鼠标左键按下事件
    this.handler.setInputAction(
      (e: any) => this.handleLeftDown(e),
      Cesium.ScreenSpaceEventType.LEFT_DOWN
    );
    // 监听鼠标左键抬起事件
    this.handler.setInputAction(
      (e: any) => this.handleLeftUp(e),
      Cesium.ScreenSpaceEventType.LEFT_UP
    );
    // 监听鼠标移动事件
    this.handler.setInputAction(
      (e: any) => this.handleMouseMove(e),
      Cesium.ScreenSpaceEventType.MOUSE_MOVE
    );
  }
  handleLeftDown(e: { position: any }) {
    // 更新鼠标状态
    this.mouseStatus = 'LEFT_DOWN';
    // 获取当前点击位置的实体对象
    const obj = this.viewer.scene.pick(e.position);
    if (!obj) {
      this.strecthObj = null;
      this.selectedEntity = null;
      this.viewer.scene.screenSpaceCameraController.enableRotate = true;
      this.removeStretchPoint();
      return;
    }
    if (obj && obj.id.name === 'stretch_point') {
      const index = this.strecthPointIds.findIndex((p: any) => p === obj.id.id);
      this.strecthObjId_index = index;
      this.strecthObj = obj;
      this.isStrecth = true;
    } else {
      this.removeStretchPoint();
      this.strecthObj = null;
      this.selectedEntity = obj;
    }

    //锁定相机
    this.viewer.scene.screenSpaceCameraController.enableRotate = false;
    if (obj.id.polygon) {
      this.entityType = 'polygon';
      this.coordinates = this.selectedEntity.id.polygon.hierarchy.getValue().positions;
      this.entityCenter = this.getEntityCenter();
      this.addStrecthPoint(this.selectedEntity.id.polygon);
    }
    if (obj.id.rectangle) {
      this.entityType = 'rectangle';
      this.coordinates = this.selectedEntity.id.rectangle.coordinates.getValue();
      this.addStrecthPoint(this.selectedEntity.id.rectangle);
    }
    if (obj.id.point) {
      this.entityType = 'point';
    }
    if (obj.id.polyline) {
      this.entityType = 'polyline';

      this.coordinates = this.selectedEntity.id.polyline.positions.getValue();
      // this.entityCenter = this.getEntityCenter()
      this.addStrecthPoint(this.selectedEntity.id.polyline);
    }
  }
  handleLeftUp(e: any) {
    // 更新鼠标状态
    this.mouseStatus = 'LEFT_UP';
  }
  handleMouseMove(e: any) {
    if (this.mouseStatus === 'LEFT_DOWN' && this.selectedEntity) {
      // 拖拽实体
      if (this.strecthObj) {
        this.handleDrag(e, this.strecthObj);
        this.handleStretch(this.selectedEntity);
        return;
      }
      this.removeStretchPoint();
      this.handleDrag(e, this.selectedEntity);
    }
  }
  /**
   * 拖拽移动实体
   * @param {*} e
   */
  handleDrag(
    e: { startPosition: any; endPosition: any },
    selectedEntity: {
      id: {
        position: Cesium.CallbackProperty;
        polygon: { hierarchy: Cesium.CallbackProperty };
        rectangle: { coordinates: Cesium.CallbackProperty };
        polyline: { positions: Cesium.CallbackProperty };
      };
    }
  ) {
    if (!selectedEntity) return;
    const coordinates = this.coordinates;
    // 获取开始位置坐标
    const startPosition = this.viewer.scene.camera.pickEllipsoid(
      e.startPosition,
      this.viewer.scene.globe.ellipsoid
    );
    // 获取结束位置坐标
    const endPosition = this.viewer.scene.camera.pickEllipsoid(
      e.endPosition,
      this.viewer.scene.globe.ellipsoid
    );
    selectedEntity.id.position = new Cesium.CallbackProperty(function () {
      return endPosition;
    }, false);
    const changed_x = endPosition.x - startPosition.x;
    const changed_y = endPosition.y - startPosition.y;
    const changed_z = endPosition.z - startPosition.z;
    if (this.entityType === 'point') {
      const ray = this.viewer.camera.getPickRay(e.endPosition);
      const cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
      selectedEntity.id.position = new Cesium.CallbackProperty(() => {
        return cartesian;
      }, false);
    }
    if (this.entityType === 'polygon' || this.entityType === 'polyline') {
      const currentsPoint: any = [];
      for (let i = 0; i < coordinates.length; i++) {
        coordinates[i].x = coordinates[i].x + changed_x;
        coordinates[i].y = coordinates[i].y + changed_y;
        coordinates[i].z = coordinates[i].z + changed_z;
        currentsPoint.push(coordinates[i]);
      }
      if (this.entityType === 'polygon') {
        selectedEntity.id.polygon.hierarchy = new Cesium.CallbackProperty(() => {
          return { positions: currentsPoint };
        }, false); // 防止闪烁
      } else {
        selectedEntity.id.polyline.positions = new Cesium.CallbackProperty(() => {
          return currentsPoint;
        }, false); // 防止闪烁
      }
    }
    if (this.entityType === 'rectangle') {
      const position_start = startPosition;
      const cartographic_start = Cesium.Cartographic.fromCartesian(position_start);
      const longitude_start = Cesium.Math.toDegrees(cartographic_start.longitude);
      const latitude_start = Cesium.Math.toDegrees(cartographic_start.latitude);

      const position_end = endPosition;
      const cartographic_end = Cesium.Cartographic.fromCartesian(position_end);
      const longitude_end = Cesium.Math.toDegrees(cartographic_end.longitude);
      const latitude_end = Cesium.Math.toDegrees(cartographic_end.latitude);

      const changer_lng = longitude_end - longitude_start;
      const changer_lat = latitude_end - latitude_start;
      coordinates.west = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.west) + changer_lng
      );
      coordinates.east = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.east) + changer_lng
      );
      coordinates.south = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.south) + changer_lat
      );
      coordinates.north = Cesium.Math.toRadians(
        Cesium.Math.toDegrees(coordinates.north) + changer_lat
      );
      selectedEntity.id.rectangle.coordinates = new Cesium.CallbackProperty(() => {
        return coordinates;
      }, false);
    }
  }
  /**
   * 旋转实体
   * @param {*} angle
   */
  handleRotation(angle: number) {
    if (!this.selectedEntity) return;
    // 旋转时清除辅助拉伸的点
    if (this.strecthPointIds.length) {
      this.removeStretchPoint();
    }
    if (this.entityType === 'rectangle') {
      // 旋转图形
      this.selectedEntity.id.rectangle.rotation = new Cesium.CallbackProperty(function () {
        return angle;
      }, false);
      // 旋转图形材质
      this.selectedEntity.id.rectangle.stRotation = new Cesium.CallbackProperty(function () {
        return angle;
      }, false);
    }
    if (this.entityType === 'polygon') {
      // let previousCoordinates = this.selectedEntity.id.polygon.hierarchy.getValue().positions
      // let coors = this.getWGS84FromDKR(previousCoordinates)
      // console.log(coors)
      // let poly = turf.polygon([coors])
      // let centroid = turf.centroid(poly)
      // let rotatedPoly = turf.transformRotate(poly, angle, { pivot: centroid.geometry.coordinates})
      // let newCoors = rotatedPoly.geometry.coordinates[0]
      // let positions = []
      // newCoors.forEach(item => {
      //  positions.push(item[0], item[1])
      // })
      this.selectedEntity.id.polygon.stRotation = new Cesium.CallbackProperty(function () {
        return Cesium.Math.toRadians(angle);
      }, false);
      // this.selectedEntity.id.polygon.hierarchy = new Cesium.CallbackProperty(function () {
      //  return { positions: Cesium.Cartesian3.fromDegreesArray(positions) }
      // }, false)
    }
  }
  /**
   * 拉伸实体
   */
  handleStretch(selectedEntity: {
    id: {
      polygon: { hierarchy: Cesium.CallbackProperty };
      rectangle: { coordinates: Cesium.CallbackProperty };
      polyline: { positions: Cesium.CallbackProperty };
    };
  }) {
    const positions: any = [];
    // 更新polygon的位置数组
    if (selectedEntity.id.polygon) {
      for (let i = 0; i < this.strecthPointIds.length; i++) {
        const id = this.strecthPointIds[i];
        positions.push(this.viewer.entities.getById(id).position.getValue());
      }
      selectedEntity.id.polygon.hierarchy = new Cesium.CallbackProperty(() => {
        return { positions: positions };
      }, false);
    }
    // 更新polyline的位置数组
    if (selectedEntity.id.polyline) {
      for (let i = 0; i < this.strecthPointIds.length; i++) {
        const id = this.strecthPointIds[i];
        positions.push(this.viewer.entities.getById(id).position.getValue());
      }
      selectedEntity.id.polyline.positions = new Cesium.CallbackProperty(() => {
        return positions;
      }, false);
    }
    // 更新rectangle的位置数组
    if (selectedEntity.id.rectangle) {
      const index = this.strecthPointIds.findIndex((item: any) => item === this.strecthObj.id.id);
      for (let i = 0; i < this.strecthPointIds.length; i++) {
        const id = this.strecthPointIds[i];
        // 矩形由两个对角的点组成的区域,因此先判断用户点击的是哪一个点,即奇偶判断
        if (index % 2 === 0) {
          if (i % 2 === 0) {
            positions.push(this.viewer.entities.getById(id).position.getValue());
          } else {
            // 将另外一半点隐藏
            this.viewer.entities.getById(id).show = false;
          }
        } else {
          if (i % 2 != 0) {
            positions.push(this.viewer.entities.getById(id).position.getValue());
          } else {
            this.viewer.entities.getById(id).show = false;
          }
        }
      }
      selectedEntity.id.rectangle.coordinates = new Cesium.CallbackProperty(() => {
        const obj = Cesium.Rectangle.fromCartesianArray(positions);
        return obj;
      }, false);
    }
  }
  /**
   * 添加拉伸点
   * @param {*} entity
   */
  addStrecthPoint(entity: {
    hierarchy: { getValue: () => { (): any; new (): any; positions: never[] } };
    coordinates: { getValue: () => any };
    positions: { getValue: () => any };
  }) {
    let points = [];
    if (this.entityType === 'polygon') {
      points = entity.hierarchy.getValue().positions;
    } else if (this.entityType === 'rectangle') {
      const rectangle = entity.coordinates.getValue();
      Cesium.Rectangle.subsample(rectangle, Cesium.Ellipsoid.WGS84, rectangle.height, points);
    } else if (this.entityType === 'polyline') {
      points = entity.positions.getValue();
    }
    // const id = new Date().getTime();
    for (const position of points) {
      const point = this.viewer.entities.add({
        name: 'stretch_point',
        position: position,
        // id:new Date().getTime()
        point: {
          color: Cesium.Color.WHITE,
          pixelSize: 10,
          outlineColor: Cesium.Color.BLACK,
          outlineWidth: 1
        }
      });
      this.strecthPointIds.push(point.id);
    }
  }
  /**
   * 清除拉伸点
   */
  removeStretchPoint() {
    for (const id of this.strecthPointIds) {
      this.viewer.entities.removeById(id);
    }
    this.strecthPointIds = [];
    this.strecthObj = null;
    this.isStrecth = false;
  }
  /**
   * 获取多边形图形中心点
   */
  getEntityCenter() {
    const previousCoordinates = this.selectedEntity.id.polygon.hierarchy.getValue().positions;
    const coors = this.getWGS84FromDKR(previousCoordinates);
    coors.push(coors[0]);
    const poly = turf.polygon([coors]);
    const centroid = turf.centroid(poly);

    return centroid.geometry.coordinates;
  }
  /**
   * 将笛卡尔坐标转换成国际坐标
   * @param {*} coors
   * @returns
   */
  getWGS84FromDKR(coors: string | any[]) {
    const newCoors: any = [];
    for (let i = 0; i < coors.length; i++) {
      const coor = coors[i];
      const cartographic = Cesium.Cartographic.fromCartesian(coor);
      const x = Cesium.Math.toDegrees(cartographic.longitude);
      const y = Cesium.Math.toDegrees(cartographic.latitude);
      newCoors.push([x, y]);
    }

    return newCoors;
  }
  stop() {
    this.handler && this.handler.destroy();
    this.removeStretchPoint();
    this.viewer.scene.screenSpaceCameraController.enableRotate = true;
  }
}

export default CesiumEntityEdit;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cesium-添加点线面可以动可编辑 的相关文章

  • 使用 Angular 将焦点捕获在 html 容器中

    我正在构建一个可访问的网站并尝试管理焦点 我需要打开一个模式 然后将焦点放在模式中的第一个元素上 然后捕获焦点 直到模式关闭 取消 或 接受 HTML a href Open Modal a div h3 Terms of Service
  • 如何在 Nodejs - mongodb 搜索中对结果进行排序,但是,通过调用动态方法

    我正在 Nodejs 中开发一个 Web 应用程序 通过 mongo 本机连接器连接到 mongodb 在我的一个 js 文件中 我有一个通用方法来调用 find 或 findOne 操作以从 mongodb 集合中检索我需要的任何内容 如
  • Chart.js 渲染垂直堆积条形图太慢

    我正在使用 Chart js API 渲染多个堆叠的垂直条形图 但性能很慢 我什至做了一些改变 这样所有的content对象已经由服务器而不是浏览器处理 但我意识到大部分时间来自最终函数new Chart overallStatsChart
  • 如何在 的每四个循环项之后添加

    我想在循环中的每第四个数字项之后退出循环 我想创建一个二十人的名单 在每一个tr应该是4个人 So I want to break from the loop after every 4th number of loop My one tr
  • 如何使用 javascript/ASP.NET/CSS 旋转和淡入淡出背景图像

    我需要随机淡入淡出背景图像 这将是一个定时函数 例如每 5 秒一次 我需要使用 ASP NET Javascript CSS 或全部三者来完成此操作 请大家帮帮我 谢谢 Cycle 一个 jQuery 插件 是一个非常灵活的图像旋转解决方案
  • 从字符串中提取电子邮件地址

    我有一个像这样的字符串 Francesco Renga lt email protected cdn cgi l email protection gt 我只需要提取电子邮件 即 电子邮件受保护 cdn cgi l email protec
  • 用于自由形式绘图的 javascript 库

    是否有一个 JavaScript 库可以让我在网页上绘图 然后保存该绘图的状态 我想使用鼠标绘制 2D 图像 然后如何存储和加载该绘图 使用 HTML5 画布 绘制图像的简单示例如下 http jsfiddle net ghostoy wT
  • 在多个 angular.js 应用程序之间共享单个服务

    我正在构建一个电子商务网站 基于 shopify 并且使用多个小型 angularjs 应用程序来处理诸如快速购物车 愿望清单 过滤产品和其他一些较小项目之类的事情 我最初使用了一个大型应用程序 具有路由和所有内容 但当我没有完整的 RES
  • 检测 JavaScript 版本

    如何检测浏览器支持的 JavaScript 版本 如果有 我想检查 ECMAScript 3 ECMAScript 5 和 ECMAScript 6 注意 我想避免已弃用的language tag 这里有一个很好的参考给你 http www
  • Android键盘点击搜索输入时出现和消失

    我在用谷歌地图 Js API当我搜索一个地方时 我的输入搜索栏工作正常 当我通过 iPhone 设备使用它时 它也工作得很好 但是当我通过Android 设备然后键盘立即出现和消失 我已经找到了一些关于当我按下搜索栏时 android 键盘
  • 如何使用谷歌地图检测一个点是否在多边形内部?

    我想检测到google maps LatLng是在一个里面google maps Polygon 我怎样才能做到这一点 Cheers 你可以使用这个谷歌地图V3 google maps geometry poly containsLocat
  • React-Router v5 History.push 不触发组件

    很抱歉朋友们又问这个问题了 我找到了解决这个问题的几个方法 但他们让我很困惑 我只是想问一个优雅的方法来做到这一点 正如你通过标题所理解的 我有一个关于反应路由的问题 让我解释 我有一个按钮 其名称是Login 单击按钮后 我执行了一些逻辑
  • ES6 Promises/在满足多个 Promise 后调用函数(不能使用 Promises.all)[重复]

    这个问题在这里已经有答案了 我正在编写 Javascript 它需要这些事件按以下顺序发生 同时触发多个 API 调用 所有调用完成且响应返回后 执行一行代码 听起来很简单 但棘手的部分是我不能使用 Promises all 因为我仍然希望
  • 在javascript中通过window.location传递数据

    我试图通过 window location 传递数据 数据在 del id img album 中可用 我想通过 window location 发送多个值 window location save php type deldownload
  • 使用 ngx-translate 时更改 URL

    当有人使用 ngx translate 单击所选语言时 我尝试更改 URL 我想我应该通过订阅语言更改事件然后修改当前的 url 以反映所选的语言来做到这一点 因为我是新手 所以我不确定是否需要服务来做到这一点 或者可能是另一种解决方法 我
  • 如何在没有查询参数的情况下重新加载页面?

    假设我想重新加载www domain com abc num 4 但我想重新加载www domain com abcONLY 问号后没有所有内容 window location window location href split 0
  • jQuery.ajax() 记录 HTTP 请求

    我有一个发送 HTTP POST 请求的函数 我想记录它以进行调试 这是函数 function serverRequest URL DATA callback ajax url URL type POST dataType text con
  • 401 未经授权的帖子回复

    我一直在使用 Angular 模板制作 Node js 网站 但我无法在 DB Mongo 上创建数据 这是代码 节点路由 var Property mongoose model Property var jwt require expre
  • 如何找出javascript中加载了哪些javascript?

    继另一个问题的评论之后 我问自己是否有办法获取页面上加载的所有 js 代码的列表 就像 Firebug 或 chrome Inspector 所做的那样 有没有一种纯javascript的方法 一种方法是抓取脚本标签 但这样你可能会错过动态
  • 使用来自Processing-JS的JSON

    我想使用编写一个应用程序处理 JS http processingjs org 并且我希望能够使用服务器端数据加载它 我还没有编写服务器端 所以我可以使用任何东西 但似乎明显的 AJAX 事情是使用 JSON 将数据上传到页面中 如何从我的

随机推荐

  • DataTables从入门到精通

    DataTables从入门到精通
  • ListView与适配器

    ListView与适配器 ListView是什么 ListView是一个以垂直方式在项目中显示视图的列表 即在一个窗口里可以滚动查看数据 比如说查看聊天记录 是一种不能实现确定视图中的内容的适配器视图 adapter view 数据和视图的
  • $nextTick实现原理详解

    vue中有一个较为特殊的API nextTick 根据官方文档的解释 它可以在DOM更新完毕之后执行一个回调 用法如下 修改数据 vm msg Hello DOM 还没有更新 Vue nextTick function DOM 更新了 复制
  • 5 个免费开源的 3D 建模/渲染工具。

    5 个开源 3D 建模 渲染工具 3八 2011 作者 riku 本文采用 CC BY NC SA 2 5协议授权 转载请注明 本文链接 5 个免费开源的 3D 建模 渲染工具 1 Art of Illusion 跨平台 支持 Window
  • 15000cd是多少流明_光通量(lm)发光强度(cd)照度单位(lux)之间的关系

    光通量 lm 发光强度 cd 照度单位 lux 之间的关系 光通量 lm 由于人眼对不同波长的电磁波具有不同的灵敏度 我们不能直接用光源的辐 射功率或辐射通量来衡量光能量 必须采用以人眼对光的感觉量为基准的单位 光通量来衡量 光通量的用符号
  • SetUnhandledExceptionFilter处理未捕获异常

    一 首先看下百度上的对此函数的解释 设置异常捕获函数 当异常没有处理的时候 系统就会调用SetUnhandledExceptionFilter所设置异常处理函数 例如一些程序在出错的时候 会向用户报告说程序那出错就是利用这个 例如QQ 二
  • github时好时坏连接不上的问题

    1 找到自己的hosts文件 直接百度 hosts文件地址 一般都是C Windows System32 drivers etc 2 用ip在线查询工具查询github网站的ip地址 3 用记事本打开hosts文件 如图添加内容 我下载有的
  • 【Python】本地版 Whisper 自动转录器(附源码网址)

    目 录 一 实时自动语音转录器简介 二 开源Whisper实时转录器 三 pyinstaller 打包发布exe应用程序 四 修改版源代码 一 实时自动语音转录器简介 实时自动语音转录器是一种能够自动将语音信号转换为文字的应用程序 它通常具
  • 服务器被攻击怎么办?如何防止服务器被攻击?

    目前 服务器遭受攻击已经成为屡见不鲜的事情了 而且大部分企业都发生过服务器被攻击的情况 从而导致业务无法正常运行 造成严重的损失和影响 那么服务器被攻击怎么办 如何有效应对服务器被攻击呢 跟着小编来看看吧 1 换高防IP或切换高防服务器 流
  • 【华为OD机试真题 Java】创建二叉树

    前言 本专栏将持续更新华为OD机试题目 并进行详细的分析与解答 包含完整的代码实现 希望可以帮助到正在努力的你 关于OD机试流程 面经 面试指导等 如有任何疑问 欢迎联系我 wechat steven moda email nansun09
  • Binder机制详解(二)

    系列章节 Binder机制详解 一 Binder机制详解 三 文章目录 前言 一 什么是MMU 二 发展历史 三 相关概念 四 分页机制 1 页表的概念 2 页式内存管理 总结 前言 上一章通过一个例子让我们认识了Binder通信机制不同于
  • HbuilderX微信小程序uniapp分包小白教程&趟坑【伸手党福利】【干货】

    本教程为小白教程 主管操作 具体原理讲解欢迎评论区补充 微信小程序分包原因 1 多人开发 2 引入了大型js 3 单项目多模块需要分包 官方资料 https developers weixin qq com miniprogram dev
  • 扫描指定路径下有多少行代码

    import java io BufferedReader import java io File import java io FileReader import java io IOException Created by qiaoju
  • 使用蓝牙耳机听群晖ds218play中的音乐(audio station)

    缘起 有时需要欣赏nas中的音乐而又不影响家人 有什么方法呢 思路 研究了一下 发现新版的群晖dms支持蓝牙usb蓝牙适配器 可以使用audio station播放 蓝牙耳机收听 步骤 1 购买CSR USB蓝牙适配器 2 插入ds218p
  • 大数据CDC技术

    1 简介 CDC全称是Change Data Capture 是一种捕获增量数据的技术统称 目前主要应用在捕获数据库数据变更的技术 其中数据库变更包括DDL DML DCL等语句触发的变更 在数据备份容灾 数据分发 面向数仓的数据集成等场景
  • JavaScript实现WebService的http的Post请求

    javascript 这个脚本实现Webservice调用 function AjaxFunc var url http localhost MyService Service asmx var method DollarConvertTo
  • 使用Jmeter做压力测试,参数化

    1 首先在工作台下添加一个线程组 测试计划右键 添加 线程 用户 线程组 根据需求填写线程组信息 根据测试数据量填写 线程数也就是并发数 下面的调度时间代表规定的时间内完成并发 2 添加HTTP请求 在线程组下右键 添加 取样器 HTTP请
  • 微信小程序image组件的mode总结+介绍(包含heightFix)

    2 10 3版本后 微信小程序的图片即image组件新增了heightFix属性 mode 总共具有14种属性 满足各种情况的放置需要 14种属性可以分为两大类 一种是完全保留的缩放属性 一种是裁剪属性 原图 缩放属性 scaleToFil
  • 常见的List接口的实现类

    常见的List接口的实现类 ArrayList 数组实现 查询快 增删慢 轻量级 线程不安全 LinkedList 双向链表实现 增删快 查询慢 线程不安全 Vector 数组实现 重量级 线程安全 使用少 ArrayList实现类 pub
  • cesium-添加点线面可以动可编辑

    使用 const drawEntities new CesiumEntityDraw viewer drawEntities startDraw 需要绘制的类型 CesiumEntityDraw ts文件 import Cesium fro