// * 创建视锥 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, }), }, }); } }