| New file |
| | |
| | | import * as Cesium from 'cesium' |
| | | import { MapTooltip } from '../Tooltip' |
| | | import { ToolBase } from '../ToolBase' |
| | | import { buildEllipsePositions } from '../shapeUtils' |
| | | |
| | | export class DrawBufferCircleTool extends ToolBase { |
| | | constructor(viewer) { |
| | | super(viewer) |
| | | this.tooltip = new MapTooltip(viewer) |
| | | this.dataSource = null |
| | | this.centerCartesian = null |
| | | this.radiusLevel1 = 0 |
| | | this.radiusLevel2 = 0 |
| | | this.radiusLevel3 = 0 |
| | | this.circleLevel1Entity = null |
| | | this.circleLevel2Entity = null |
| | | this.circleLevel3Entity = null |
| | | this.circleLevel1OutlineEntity = null |
| | | this.circleLevel2OutlineEntity = null |
| | | this.circleLevel3OutlineEntity = null |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | this.isCompleted = false |
| | | } |
| | | |
| | | start() { |
| | | this.dataSource = new Cesium.CustomDataSource('draw-buffer-circle') |
| | | this.viewer.dataSources.add(this.dataSource) |
| | | this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas) |
| | | this.handler.setInputAction(click => this.handleLeftClick(click), Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | this.handler.setInputAction(movement => this.handleMouseMove(movement), Cesium.ScreenSpaceEventType.MOUSE_MOVE) |
| | | this.drawStep = 0 |
| | | this.isCompleted = false |
| | | this.tooltip.show('单击设置中心点', { x: 0, y: 0 }) |
| | | } |
| | | |
| | | handleLeftClick(click) { |
| | | if (this.isCompleted) return |
| | | const position = this.getPositionFromScreen(click.position) |
| | | if (!position) return |
| | | |
| | | if (this.drawStep === 0) { |
| | | this.centerCartesian = position |
| | | this.radiusLevel1 = 1 |
| | | this.radiusLevel2 = 1 |
| | | this.radiusLevel3 = 1 |
| | | this.isDrawing = true |
| | | this.drawStep = 1 |
| | | this.createEntities() |
| | | this.tooltip.show('单击设置一级缓冲圆', click.position) |
| | | return |
| | | } |
| | | |
| | | if (this.drawStep === 1) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.radiusLevel1 = radius |
| | | this.radiusLevel2 = radius |
| | | this.radiusLevel3 = radius |
| | | this.drawStep = 2 |
| | | this.tooltip.show('单击设置二级缓冲圆', click.position) |
| | | return |
| | | } |
| | | |
| | | if (this.drawStep === 2) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.radiusLevel2 = Math.max(radius, this.radiusLevel1) |
| | | this.radiusLevel3 = this.radiusLevel2 |
| | | this.drawStep = 3 |
| | | this.tooltip.show('单击设置三级缓冲圆', click.position) |
| | | return |
| | | } |
| | | |
| | | if (this.drawStep === 3) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.radiusLevel3 = Math.max(radius, this.radiusLevel2) |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | this.isCompleted = true |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radiusLevel3, this.radiusLevel3) |
| | | this.notify('getPolygonPositions', { |
| | | positions, |
| | | meta: { |
| | | center: this.centerCartesian, |
| | | bufferRadii: [this.radiusLevel1, this.radiusLevel2, this.radiusLevel3], |
| | | }, |
| | | }) |
| | | this.tooltip.hide() |
| | | this.clearPreviewEntities() |
| | | } |
| | | } |
| | | |
| | | handleMouseMove(movement) { |
| | | if (this.isCompleted) return |
| | | this.tooltip.move(movement.endPosition) |
| | | if (!this.isDrawing) return |
| | | const position = this.getPositionFromScreen(movement.endPosition) |
| | | if (!position) return |
| | | if (this.drawStep === 1) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.radiusLevel1 = radius |
| | | this.radiusLevel2 = radius |
| | | this.radiusLevel3 = radius |
| | | return |
| | | } |
| | | if (this.drawStep === 2) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.radiusLevel2 = Math.max(radius, this.radiusLevel1) |
| | | this.radiusLevel3 = this.radiusLevel2 |
| | | return |
| | | } |
| | | if (this.drawStep === 3) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.radiusLevel3 = Math.max(radius, this.radiusLevel2) |
| | | } |
| | | } |
| | | |
| | | createEntities() { |
| | | if (this.circleLevel1Entity || this.circleLevel2Entity || this.circleLevel3Entity) return |
| | | this.circleLevel1Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.centerCartesian, false), |
| | | ellipse: { |
| | | semiMajorAxis: new Cesium.CallbackProperty(() => this.radiusLevel1, false), |
| | | semiMinorAxis: new Cesium.CallbackProperty(() => this.radiusLevel1, false), |
| | | material: Cesium.Color.fromBytes(247, 20, 20, 128), |
| | | outline: false, |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | }) |
| | | this.circleLevel1OutlineEntity = this.dataSource.entities.add({ |
| | | polyline: { |
| | | positions: new Cesium.CallbackProperty(() => { |
| | | if (!this.centerCartesian || this.radiusLevel1 <= 0) return [] |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radiusLevel1, this.radiusLevel1) |
| | | return positions.length ? [...positions, positions[0]] : positions |
| | | }, false), |
| | | clampToGround: true, |
| | | width: 2, |
| | | material: Cesium.Color.fromBytes(255, 0, 0, 255), |
| | | }, |
| | | }) |
| | | |
| | | this.circleLevel2Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.centerCartesian, false), |
| | | ellipse: { |
| | | semiMajorAxis: new Cesium.CallbackProperty(() => this.radiusLevel2, false), |
| | | semiMinorAxis: new Cesium.CallbackProperty(() => this.radiusLevel2, false), |
| | | material: Cesium.Color.fromBytes(255, 235, 59, 128), |
| | | outline: false, |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | }) |
| | | this.circleLevel2OutlineEntity = this.dataSource.entities.add({ |
| | | polyline: { |
| | | positions: new Cesium.CallbackProperty(() => { |
| | | if (!this.centerCartesian || this.radiusLevel2 <= 0) return [] |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radiusLevel2, this.radiusLevel2) |
| | | return positions.length ? [...positions, positions[0]] : positions |
| | | }, false), |
| | | clampToGround: true, |
| | | width: 2, |
| | | material: Cesium.Color.fromBytes(255, 235, 59, 255), |
| | | }, |
| | | }) |
| | | |
| | | this.circleLevel3Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.centerCartesian, false), |
| | | ellipse: { |
| | | semiMajorAxis: new Cesium.CallbackProperty(() => this.radiusLevel3, false), |
| | | semiMinorAxis: new Cesium.CallbackProperty(() => this.radiusLevel3, false), |
| | | material: Cesium.Color.fromBytes(25, 178, 230, 128), |
| | | outline: false, |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | }) |
| | | this.circleLevel3OutlineEntity = this.dataSource.entities.add({ |
| | | polyline: { |
| | | positions: new Cesium.CallbackProperty(() => { |
| | | if (!this.centerCartesian || this.radiusLevel3 <= 0) return [] |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radiusLevel3, this.radiusLevel3) |
| | | return positions.length ? [...positions, positions[0]] : positions |
| | | }, false), |
| | | clampToGround: true, |
| | | width: 2, |
| | | material: Cesium.Color.fromBytes(0, 251, 255, 255), |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | clearPreviewEntities() { |
| | | if (!this.dataSource) return |
| | | this.dataSource.entities.removeAll() |
| | | this.circleLevel1Entity = null |
| | | this.circleLevel2Entity = null |
| | | this.circleLevel3Entity = null |
| | | this.circleLevel1OutlineEntity = null |
| | | this.circleLevel2OutlineEntity = null |
| | | this.circleLevel3OutlineEntity = null |
| | | } |
| | | |
| | | getSurfaceDistance(startCartesian, endCartesian) { |
| | | const start = Cesium.Cartographic.fromCartesian(startCartesian) |
| | | const end = Cesium.Cartographic.fromCartesian(endCartesian) |
| | | const geodesic = new Cesium.EllipsoidGeodesic(start, end) |
| | | return geodesic.surfaceDistance |
| | | } |
| | | |
| | | getPositionFromScreen(screenPosition) { |
| | | const scene = this.viewer.scene |
| | | const cartesian = scene.pickPosition(screenPosition) |
| | | if (cartesian) return cartesian |
| | | return scene.camera.pickEllipsoid(screenPosition, scene.globe.ellipsoid) |
| | | } |
| | | |
| | | destroy() { |
| | | if (this.dataSource) { |
| | | this.dataSource.entities.removeAll() |
| | | this.viewer.dataSources.remove(this.dataSource) |
| | | this.dataSource = null |
| | | } |
| | | if (this.handler) { |
| | | this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK) |
| | | this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE) |
| | | this.handler.destroy() |
| | | this.handler = null |
| | | } |
| | | this.tooltip?.destroy() |
| | | this.tooltip = null |
| | | this.centerCartesian = null |
| | | this.radiusLevel1 = 0 |
| | | this.radiusLevel2 = 0 |
| | | this.radiusLevel3 = 0 |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | this.isCompleted = false |
| | | } |
| | | } |