import * as Cesium from 'cesium'
|
import { MapTooltip } from '../Tooltip'
|
import { ToolBase } from '../ToolBase'
|
import {
|
getBoundsFromCartesians,
|
getCenterFromBounds,
|
getMetersBetween,
|
buildEllipsePositions,
|
} from '../shapeUtils'
|
|
export class DrawEllipseTool extends ToolBase {
|
constructor(viewer) {
|
super(viewer)
|
this.tooltip = new MapTooltip(viewer)
|
this.dataSource = null
|
this.ellipseEntity = null
|
this.startPosition = null
|
this.endPosition = null
|
this.centerCartesian = null
|
this.semiMajor = 0
|
this.semiMinor = 0
|
this.isDrawing = false
|
}
|
|
start() {
|
this.dataSource = new Cesium.CustomDataSource('draw-ellipse')
|
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.tooltip.show('单击设置起点', { x: 0, y: 0 })
|
}
|
|
handleLeftClick(click) {
|
const position = this.getPositionFromScreen(click.position)
|
if (!position) return
|
|
if (!this.startPosition) {
|
this.startPosition = position
|
this.endPosition = position
|
this.isDrawing = true
|
this.createEntities()
|
this.tooltip.show('单击结束绘制', click.position)
|
return
|
}
|
|
if (this.isDrawing) {
|
this.endPosition = position
|
this.updateEllipseByBounds()
|
this.isDrawing = false
|
const positions = buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor)
|
this.notify('getPolygonPositions', positions)
|
this.tooltip.hide()
|
this.clearPreviewEntities()
|
}
|
}
|
|
handleMouseMove(movement) {
|
if (!this.isDrawing) {
|
this.tooltip.move(movement.endPosition)
|
return
|
}
|
const position = this.getPositionFromScreen(movement.endPosition)
|
if (!position) return
|
this.endPosition = position
|
this.updateEllipseByBounds()
|
this.tooltip.move(movement.endPosition)
|
}
|
|
updateEllipseByBounds() {
|
const bounds = getBoundsFromCartesians([this.startPosition, this.endPosition])
|
const center = getCenterFromBounds(bounds)
|
if (!bounds || !center) return
|
this.centerCartesian = Cesium.Cartesian3.fromRadians(center.longitude, center.latitude)
|
const eastWest = getMetersBetween(
|
new Cesium.Cartographic(bounds.west, center.latitude),
|
new Cesium.Cartographic(bounds.east, center.latitude)
|
)
|
const northSouth = getMetersBetween(
|
new Cesium.Cartographic(center.longitude, bounds.south),
|
new Cesium.Cartographic(center.longitude, bounds.north)
|
)
|
this.semiMajor = Math.max(1, eastWest / 2)
|
this.semiMinor = Math.max(1, northSouth / 2)
|
}
|
|
createEntities() {
|
if (this.ellipseEntity) return
|
this.ellipseEntity = this.dataSource.entities.add({
|
position: new Cesium.CallbackProperty(() => this.centerCartesian, false),
|
ellipse: {
|
semiMajorAxis: new Cesium.CallbackProperty(() => this.semiMajor, false),
|
semiMinorAxis: new Cesium.CallbackProperty(() => this.semiMinor, false),
|
material: Cesium.Color.fromBytes(45, 140, 240, 99),
|
outline: true,
|
outlineColor: Cesium.Color.fromBytes(45, 140, 240, 255),
|
outlineWidth: 2,
|
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
},
|
})
|
}
|
|
clearPreviewEntities() {
|
if (!this.dataSource) return
|
this.dataSource.entities.removeAll()
|
this.ellipseEntity = null
|
}
|
|
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.startPosition = null
|
this.endPosition = null
|
this.centerCartesian = null
|
this.isDrawing = false
|
}
|
}
|