forked from drone/command-center-dashboard

罗广辉
2025-04-21 2800fa4f32f3900509cb4d6eefaf2bfaf54efdd7
src/utils/cesium/frustum/CreateFrustum.js
@@ -1,275 +1,255 @@
// * 创建视锥
import * as Cesium from 'cesium';
import * as Cesium from 'cesium'
/* eslint-disable new-cap */
/* eslint-disable no-undef */
export default class CreateFrustum {
  constructor(viewer, options) {
    this.position = options.position;
    this.viewer = viewer;
    this.fov = options.fov || 0;
    this.near = options.near || 0;
    this.far = options.far || 0;
    this.heading = options.heading || 0;
    this.pitch = options.pitch || 0;
    this.roll = options.roll || 0;
    this.width = options.width;
    this.height = options.height;
    this.add();
  }
   constructor(viewer, options) {
      this.position = options.position
      this.viewer = viewer
      this.fov = options.fov || 0
      this.near = options.near || 0
      this.far = options.far || 0
      this.heading = options.heading || 0
      this.pitch = options.pitch || 0
      this.roll = options.roll || 0
      this.width = options.width
      this.height = options.height
      this.add()
   }
  UpdateWidth(value) {
    this.width = value;
    this.add();
  }
  UpdateHeight(value) {
    this.height = value;
    this.add();
  }
  UpdateFov(value) {
    this.fov = value;
    this.add();
  }
  UpdateNear(value) {
    this.near = value;
    this.add();
  }
  UpdateFar(value) {
    this.far = value;
    this.add();
  }
  UpdateHeading(value) {
    this.heading = value;
    this.add();
  }
  UpdatePitch(value) {
    this.pitch = value;
    this.add();
  }
  UpdateRoll(value) {
    this.roll = value;
    this.add();
  }
  UpdataPosition(position) {
    if (!position) return;
    this.position = position;
    this.add();
  }
   UpdateWidth(value) {
      this.width = value
      this.add()
   }
   UpdateHeight(value) {
      this.height = value
      this.add()
   }
   UpdateFov(value) {
      this.fov = value
      this.add()
   }
   UpdateNear(value) {
      this.near = value
      this.add()
   }
   UpdateFar(value) {
      this.far = value
      this.add()
   }
   UpdateHeading(value) {
      this.heading = value
      this.add()
   }
   UpdatePitch(value) {
      this.pitch = value
      this.add()
   }
   UpdateRoll(value) {
      this.roll = value
      this.add()
   }
   UpdataPosition(position) {
      if (!position) return
      this.position = position
      this.add()
   }
  // 更新视锥体的姿态
  Update(position, headingPitchRoll) {
    this.position = Cesium.Cartesian3.fromDegrees(
      position.longitude,
      position.latitude,
      position.altitude,
    );
    this.orientation = Cesium.Transforms.headingPitchRollQuaternion(
      this.position,
      new Cesium.HeadingPitchRoll.fromDegrees(
        headingPitchRoll.heading,
        headingPitchRoll.pitch,
        headingPitchRoll.roll,
      ),
    );
    this.add();
  }
   // 更新视锥体的姿态
   Update(position, headingPitchRoll) {
      this.position = Cesium.Cartesian3.fromDegrees(
         position.longitude,
         position.latitude,
         position.altitude
      )
      this.orientation = Cesium.Transforms.headingPitchRollQuaternion(
         this.position,
         new Cesium.HeadingPitchRoll.fromDegrees(
            headingPitchRoll.heading,
            headingPitchRoll.pitch,
            headingPitchRoll.roll
         )
      )
      this.add()
   }
  // 创建视锥体和轮廓线
  add() {
    this.clear();
    this.addFrustum();
    this.addOutline();
    this.addCenterline();
  }
   // 创建视锥体和轮廓线
   add() {
      this.clear()
      this.addFrustum()
      this.addOutline()
      this.addCenterline()
   }
  // 清除视锥体和轮廓线
  clear() {
    this.clearFrustum();
    this.clearOutline();
    this.clearCenterline();
  }
   // 清除视锥体和轮廓线
   clear() {
      this.clearFrustum()
      this.clearOutline()
      this.clearCenterline()
   }
  // 清除视锥体
  clearFrustum() {
    if (this.frustumPrimitive) {
      this.viewer.scene.primitives.remove(this.frustumPrimitive);
      this.frustumPrimitive = null;
    }
  }
   // 清除视锥体
   clearFrustum() {
      if (this.frustumPrimitive) {
         this.viewer.scene.primitives.remove(this.frustumPrimitive)
         this.frustumPrimitive = null
      }
   }
  // 清除轮廓线
  clearOutline() {
    if (this.outlinePrimitive) {
      this.viewer.scene.primitives.remove(this.outlinePrimitive);
      this.outlinePrimitive = null;
    }
  }
   // 清除轮廓线
   clearOutline() {
      if (this.outlinePrimitive) {
         this.viewer.scene.primitives.remove(this.outlinePrimitive)
         this.outlinePrimitive = null
      }
   }
  clearCenterline() {
    if (this.centerDataSource) {
      this.centerDataSource.entities.removeAll();
      this.viewer.dataSources.remove(this.centerDataSource);
      this.centerDataSource = null;
    }
  }
   clearCenterline() {
      if (this.centerDataSource) {
         this.centerDataSource.entities.removeAll()
         this.viewer.dataSources.remove(this.centerDataSource)
         this.centerDataSource = null
      }
   }
  // 创建视锥体
  addFrustum() {
    const frustum = new Cesium.PerspectiveFrustum({
      // 查看的视场角,绕Z轴旋转,以弧度方式输入
      fov: Cesium.Math.toRadians(this.fov),
      // 视锥体的宽度/高度
      aspectRatio: this.width / this.height,
      // 近面距视点的距离
      near: this.near,
      // 远面距视点的距离
      far: this.far,
    });
    const position = Cesium.Cartesian3.fromDegrees(
      this.position.longitude,
      this.position.latitude,
      this.position.altitude,
    );
    const geometry = new Cesium.FrustumGeometry({
      frustum: frustum,
      origin: position,
      orientation: Cesium.Transforms.headingPitchRollQuaternion(
        position,
        new Cesium.HeadingPitchRoll.fromDegrees(
          this.heading,
          this.pitch,
          this.roll,
        ),
      ),
      vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
    });
    const instance = new Cesium.GeometryInstance({
      geometry: geometry,
      attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
          Cesium.Color.fromBytes(0, 213, 144, 20),
        ),
      },
    });
    const primitive = new Cesium.Primitive({
      geometryInstances: instance,
      appearance: new Cesium.PerInstanceColorAppearance({
        closed: true,
        flat: true,
      }),
      asynchronous: false,
    });
    this.frustumPrimitive = this.viewer.scene.primitives.add(primitive);
  }
   // 创建视锥体
   addFrustum() {
      const frustum = new Cesium.PerspectiveFrustum({
         // 查看的视场角,绕Z轴旋转,以弧度方式输入
         fov: Cesium.Math.toRadians(this.fov),
         // 视锥体的宽度/高度
         aspectRatio: this.width / this.height,
         // 近面距视点的距离
         near: this.near,
         // 远面距视点的距离
         far: this.far,
      })
      const position = Cesium.Cartesian3.fromDegrees(
         this.position.longitude,
         this.position.latitude,
         this.position.altitude
      )
      const geometry = new Cesium.FrustumGeometry({
         frustum: frustum,
         origin: position,
         orientation: Cesium.Transforms.headingPitchRollQuaternion(
            position,
            new Cesium.HeadingPitchRoll.fromDegrees(this.heading, this.pitch, this.roll)
         ),
         vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
      })
      const instance = new Cesium.GeometryInstance({
         geometry: geometry,
         attributes: {
            color: Cesium.ColorGeometryInstanceAttribute.fromColor(
               Cesium.Color.fromBytes(0, 213, 144, 20)
            ),
         },
      })
      const primitive = new Cesium.Primitive({
         geometryInstances: instance,
         appearance: new Cesium.PerInstanceColorAppearance({
            closed: true,
            flat: true,
         }),
         asynchronous: false,
      })
      this.frustumPrimitive = this.viewer.scene.primitives.add(primitive)
   }
  // 创建轮廓线
  addOutline() {
    const frustum = new Cesium.PerspectiveFrustum({
      // 查看的视场角度,绕Z轴旋转,以弧度方式输入
      // The angle of the field of view (FOV), in radians.
      // This angle will be used as the horizontal FOV if the width is greater than the height, otherwise it will be the vertical FOV.
      fov: Cesium.Math.toRadians(this.fov),
      // 视锥体的宽度/高度
      aspectRatio: this.width / this.height,
      // 近面距视点的距离
      near: this.near,
      // 远面距视点的距离
      far: this.far,
    });
    const position = Cesium.Cartesian3.fromDegrees(
      this.position.longitude,
      this.position.latitude,
      this.position.altitude,
    );
    const geometry = new Cesium.FrustumOutlineGeometry({
      frustum: frustum,
      origin: position,
      orientation: Cesium.Transforms.headingPitchRollQuaternion(
        position,
        new Cesium.HeadingPitchRoll.fromDegrees(
          this.heading,
          this.pitch,
          this.roll,
        ),
      ),
      vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
    });
    const instance = new Cesium.GeometryInstance({
      geometry: geometry,
      attributes: {
        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
          Cesium.Color.fromBytes(0, 213, 144, 255),
        ),
      },
    });
    const primitive = new Cesium.Primitive({
      geometryInstances: instance,
      appearance: new Cesium.PerInstanceColorAppearance({
        closed: true,
        flat: true,
      }),
      asynchronous: false,
    });
    this.outlinePrimitive = this.viewer.scene.primitives.add(primitive);
  }
   // 创建轮廓线
   addOutline() {
      const frustum = new Cesium.PerspectiveFrustum({
         // 查看的视场角度,绕Z轴旋转,以弧度方式输入
         // The angle of the field of view (FOV), in radians.
         // This angle will be used as the horizontal FOV if the width is greater than the height, otherwise it will be the vertical FOV.
         fov: Cesium.Math.toRadians(this.fov),
         // 视锥体的宽度/高度
         aspectRatio: this.width / this.height,
         // 近面距视点的距离
         near: this.near,
         // 远面距视点的距离
         far: this.far,
      })
      const position = Cesium.Cartesian3.fromDegrees(
         this.position.longitude,
         this.position.latitude,
         this.position.altitude
      )
      const geometry = new Cesium.FrustumOutlineGeometry({
         frustum: frustum,
         origin: position,
         orientation: Cesium.Transforms.headingPitchRollQuaternion(
            position,
            new Cesium.HeadingPitchRoll.fromDegrees(this.heading, this.pitch, this.roll)
         ),
         vertexFormat: Cesium.VertexFormat.POSITION_ONLY,
      })
      const instance = new Cesium.GeometryInstance({
         geometry: geometry,
         attributes: {
            color: Cesium.ColorGeometryInstanceAttribute.fromColor(
               Cesium.Color.fromBytes(0, 213, 144, 255)
            ),
         },
      })
      const primitive = new Cesium.Primitive({
         geometryInstances: instance,
         appearance: new Cesium.PerInstanceColorAppearance({
            closed: true,
            flat: true,
         }),
         asynchronous: false,
      })
      this.outlinePrimitive = this.viewer.scene.primitives.add(primitive)
   }
  addCenterline() {
    this.centerDataSource = new Cesium.CustomDataSource();
    this.viewer.dataSources.add(this.centerDataSource);
   addCenterline() {
      this.centerDataSource = new Cesium.CustomDataSource()
      this.viewer.dataSources.add(this.centerDataSource)
    const position = Cesium.Cartesian3.fromDegrees(
      this.position.longitude,
      this.position.latitude,
      this.position.altitude,
    );
      const position = Cesium.Cartesian3.fromDegrees(
         this.position.longitude,
         this.position.latitude,
         this.position.altitude
      )
    let matrix = Cesium.Matrix3.fromQuaternion(
      Cesium.Transforms.headingPitchRollQuaternion(
        position,
        new Cesium.HeadingPitchRoll.fromDegrees(
          this.heading,
          this.pitch,
          this.roll,
        ),
      ),
      new Cesium.Matrix3(),
    );
      let matrix = Cesium.Matrix3.fromQuaternion(
         Cesium.Transforms.headingPitchRollQuaternion(
            position,
            new Cesium.HeadingPitchRoll.fromDegrees(this.heading, this.pitch, this.roll)
         ),
         new Cesium.Matrix3()
      )
    let right1 = Cesium.Matrix3.getColumn(matrix, 0, new Cesium.Cartesian3());
    let up1 = Cesium.Matrix3.getColumn(matrix, 1, new Cesium.Cartesian3());
    let direction = Cesium.Matrix3.getColumn(
      matrix,
      2,
      new Cesium.Cartesian3(),
    );
      let right1 = Cesium.Matrix3.getColumn(matrix, 0, new Cesium.Cartesian3())
      let up1 = Cesium.Matrix3.getColumn(matrix, 1, new Cesium.Cartesian3())
      let direction = Cesium.Matrix3.getColumn(matrix, 2, new Cesium.Cartesian3())
    // const direction = new Cartesian3(-0.10668226241650887, 0.8103322335050215, -0.5761775474872814)
      // const direction = new Cartesian3(-0.10668226241650887, 0.8103322335050215, -0.5761775474872814)
    let frontDirect = Cesium.Cartesian3.multiplyByScalar(
      direction,
      this.far,
      new Cesium.Cartesian3(),
    );
    let bottomCenter = Cesium.Cartesian3.add(
      position,
      frontDirect,
      new Cesium.Cartesian3(),
    );
      let frontDirect = Cesium.Cartesian3.multiplyByScalar(
         direction,
         this.far,
         new Cesium.Cartesian3()
      )
      let bottomCenter = Cesium.Cartesian3.add(position, frontDirect, new Cesium.Cartesian3())
    // 创建Entity来显示中心线
    this.centerDataSource.entities.add({
      name: 'Center Line of Frustum',
      polyline: {
        positions: [position, bottomCenter],
        width: 1,
        // material: Cesium.Color.RED.withAlpha(0.5)
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.fromBytes(0, 213, 144, 255),
          dashLength: 30.0,
          gapColor: Cesium.Color.TRANSPARENT,
          gapWidth: 1.0,
        }),
      },
    });
  }
      // 创建Entity来显示中心线
      this.centerDataSource.entities.add({
         name: 'Center Line of Frustum',
         polyline: {
            positions: [position, bottomCenter],
            width: 1,
            // material: Cesium.Color.RED.withAlpha(0.5)
            material: new Cesium.PolylineDashMaterialProperty({
               color: Cesium.Color.fromBytes(0, 213, 144, 255),
               dashLength: 30.0,
               gapColor: Cesium.Color.TRANSPARENT,
               gapWidth: 1.0,
            }),
         },
      })
   }
}