// * 创建视锥 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() } 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() } // 创建视锥体和轮廓线 add() { this.clear() this.addFrustum() this.addOutline() this.addCenterline() } // 清除视锥体和轮廓线 clear() { this.clearFrustum() this.clearOutline() this.clearCenterline() } // 清除视锥体 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 } } 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) } // 创建轮廓线 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) 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 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) 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, }), }, }) } }