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-添加点线面可以动可编辑 的相关文章

  • 单击按钮重复动画

    我想每次单击按钮时都重复动画 我尝试做某事像这样 https jsfiddle net 91raod7e const dist document querySelector dist document querySelector butto
  • 如何在 Highcharts / Highstock 上显示 x 轴上的十字线选定值和 y 轴上选定的日期?

    我正在研究这个项目 其中包括在交互式图表上显示历史数据 我得出的结论是 Highcharts Highstock 是最好的选择 因为它提供了最多的定制选项 我想要实现的目标是 当我将鼠标悬停在一个点上时 分别在 x 轴和 y 轴上显示所选值
  • javascript中怪异模式的元素宽度?

    我一直在浏览所有流行的 js 库 但我找不到一个具有 DOM 元素宽度函数的库 该函数实际上可以解释 Internet Explorer 中的怪异模式 问题是 当启用怪异模式时 填充和边框不会计入宽度 据我所知 当省略 doctype 或将
  • 单击上一页的按钮路由到该页面后如何刷新页面

    我有 2 个页面 一个主页和一个页面 2 当我单击主页上的按钮时 它会路由到 page2 现在 单击主页上的按钮后 当我到达第 2 页时 它应该刷新 因为我的项目中存在一些缓存问题 我在ngoninit上添加了window location
  • Javascript:混合构造函数模式和揭示模块模式

    有什么方法可以让 Javascript 类扩展通过揭示模块模式创建的对象吗 我尝试了下面的代码 但是有没有办法实现同样的事情 sv MergeQuestionViewModel function this sv QuestionDetail
  • 用不同的颜色为 Google 热图着色

    我试图开发一个遵循 Google Map API 的热度 https developers google com maps documentation javascript examples layer heatmap https deve
  • React JS - 单击时更改颜色并将默认颜色放在所有其他颜色上

    我有 x 个渲染数文章预览依赖于 API 调用的组件 div div Object keys images map index i gt return div div
  • 使用 javascript 禁用按钮:FF 与 IE

    我有一排按钮 它们都会创建一个我想在新选项卡中打开的 pdf 文件 这样按钮页面就会保持在顶部 并且 pdf 会打开以进行打印 为了防止单击按钮两次 我禁用该按钮 如下所示 我使用 python
  • Ajax JSON 数据和灯箱冲突

    我有一个带有灯箱插件的画廊设置光廊 http sachinchoolur github io lightGallery docs 该画廊与静态 HTML 完美配合 当我动态抓取 API 数据并尝试让灯箱处理这些项目时 问题就出现了 我似乎无
  • mouseover 和 mouseout 事件在子进程上触发

    代码 div div div div 如果我将鼠标悬停在Navigation the Drop Downdiv 向下滑动 如果我将鼠标移开 它会向上滑动 问题是如果我将鼠标悬停在孩子上Drop Downdiv它也向上滑 动 有谁知道我该如何
  • 这种 JavaScript 编码风格有什么问题? (闭包与原型)

    我们一直在讨论如何最好地处理我们的 JS 应用程序中的对象 研究 Stoyan Stefanov 的书 阅读无数关于 新 这个 原型 闭包等的 SO 帖子 事实上有很多 而且它们有这么多相互竞争的理论 表明没有完全明显的答案 让我们假设我们
  • express 或express-generator:我需要两者吗?

    只是探索 Node js 并遇到了 Express 在 npm 存储库站点上https www npmjs com package express https www npmjs com package express它明确指出安装是 np
  • jQuery 在 Chrome 下发现错误元素

    我使用 jQuery 迭代 HTML 表 并动态填充每行的行号 通过在文本框中填充行号 function updateRowNums myTable find tr each function index this find input i
  • 监听浏览器宽度以进行响应式网页设计?

    我正在努力使我的网站适合移动设备 我想知道浏览器窗口的大小 以便当它比 728px 窄时我可以执行某些操作 而当它大于 728px 时我可以执行其他操作 这必须考虑到调整 PC 上的窗口大小以及在手机中从纵向模式更改为横向模式 如何才能做到
  • 为什么 document.getelementbyId 在 Firefox 中不起作用?

    我不明白为什么 document getElementById 在 Firefox 中不起作用 document getElementById main style width 100 当我检查 Firebug 时 它说 类型错误 docu
  • 使用本机 JavaScript 获取过渡中的 CSS 值

    这个问题之前被问过 但答案使用了 jQuery here https stackoverflow com q 8920934 3186555 因此 我将调整问题以专门询问native解决方案 to 最小化依赖关系 假设您有一个 div 然后
  • React + Semantic-UI:在 UI MODAL 中使用表单

    在没有 React 的普通旧 Semantic UI 中 我已经能够毫无问题地将表单放入 Modal 中 使用 Semantic UI React 版本 我能够在模态中显示表单 但它并没有按照我期望的方式工作 例如 模态框显示后 模态框内的
  • javascript:window.print() 打印 2 页,而我有 1 页

    我有一个简单的 HTML 文档 其中仅包含图像标签 我想在文档加载后打印图像 我的代码 img src form1 jpg alt form1 style margin 0 auto display block 它可以工作 但问题是它打印图
  • Nodejs 一个接一个地运行异步函数

    我是 JS nodejs 的新手 所以如果我不能提出切中要害的问题 请原谅我 所以基本上 如果我有两个异步函数 async function init async function main 如何确保在 init 完成其异步请求后调用 ma
  • 利用重力效果拖动元素

    我想完成类似于 photoshop com 和此网站的功能 http mrdoob com projects chromeexperiments google gravity http mrdoob com projects chromee

随机推荐

  • 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