| | |
| | | import { DrawManager } from './shapeTools/DrawManager' |
| | | import { EditManager } from './shapeTools/EditManager' |
| | | import { cartesian3Convert } from '@/utils/cesium/mapUtil' |
| | | import { buildEllipsePositions } from './shapeTools/shapeUtils' |
| | | import * as turf from '@turf/turf' |
| | | import * as Cesium from 'cesium' |
| | | import { fwPoliceStationListApi } from '@/views/areaManage/precinctInfo/precinctInfoApi' |
| | |
| | | shapeList.value.forEach(shape => { |
| | | if (!shape?.points?.length) return |
| | | if (activeToolMode.value === 'edit' && shape.id === activeShapeId.value) return |
| | | if (shape.drawType === 'buffer' && shape.meta?.bufferRadii?.length && shape.meta?.center) { |
| | | const center = shape.meta.center |
| | | const centerCartesian = Cesium.Cartesian3.fromDegrees(center.lng, center.lat, center.height || 0) |
| | | const [radius1, radius2, radius3] = shape.meta.bufferRadii |
| | | const radii = [radius1, radius2, radius3].filter(item => Number.isFinite(item) && item > 0) |
| | | if (radii.length) { |
| | | const styles = [ |
| | | { |
| | | fill: Cesium.Color.fromBytes(247, 20, 20, 128), |
| | | outline: Cesium.Color.fromBytes(255, 0, 0, 255), |
| | | }, |
| | | { |
| | | fill: Cesium.Color.fromBytes(255, 235, 59, 128), |
| | | outline: Cesium.Color.fromBytes(255, 235, 59, 255), |
| | | }, |
| | | { |
| | | fill: Cesium.Color.fromBytes(25, 178, 230, 128), |
| | | outline: Cesium.Color.fromBytes(0, 251, 255, 255), |
| | | }, |
| | | ] |
| | | radii.forEach((radius, index) => { |
| | | const style = styles[index] || styles[styles.length - 1] |
| | | dataSource.entities.add({ |
| | | name: 'shape-display', |
| | | customData: { shapeId: shape.id, drawType: shape.drawType, level: index + 1 }, |
| | | position: centerCartesian, |
| | | ellipse: { |
| | | semiMajorAxis: radius, |
| | | semiMinorAxis: radius, |
| | | material: style.fill, |
| | | outline: false, |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | }) |
| | | const positions = buildEllipsePositions(centerCartesian, radius, radius) |
| | | dataSource.entities.add({ |
| | | name: 'shape-display', |
| | | customData: { shapeId: shape.id, drawType: shape.drawType, level: index + 1, outline: true }, |
| | | polyline: { |
| | | positions: positions.length ? [...positions, positions[0]] : positions, |
| | | clampToGround: true, |
| | | width: 2, |
| | | material: style.outline, |
| | | }, |
| | | }) |
| | | }) |
| | | } |
| | | return |
| | | } |
| | | |
| | | const positions = buildShapePositions(shape.points) |
| | | if (positions.length < 3) return |
| | | dataSource.entities.add({ |
| | |
| | | |
| | | // 绘制完成回调 |
| | | const drawFinished = async data => { |
| | | if (!Array.isArray(data) || data.length < 3) { |
| | | const positions = Array.isArray(data?.positions) ? data.positions : data |
| | | if (!Array.isArray(positions) || positions.length < 3) { |
| | | pointList = [] |
| | | formData.value.areaSize = null |
| | | formData.value.longitude = null |
| | |
| | | hideTypePanel() |
| | | return |
| | | } |
| | | pointList = _.cloneDeep(data).map(item => { |
| | | const meta = data?.meta |
| | | const bufferRadii = Array.isArray(meta?.bufferRadii) ? meta.bufferRadii : null |
| | | const centerCartesian = meta?.center |
| | | const centerLngLat = centerCartesian ? cartesian3Convert(centerCartesian, viewer) : null |
| | | pointList = _.cloneDeep(positions).map(item => { |
| | | const val = cartesian3Convert(item, viewer) |
| | | return { ...val, lng: val.longitude, lat: val.latitude } |
| | | }) |
| | |
| | | areaType: formData.value.areaType, |
| | | drawType: currentShapeType.value, |
| | | points: _.cloneDeep(pointList), |
| | | meta: bufferRadii && centerLngLat |
| | | ? { |
| | | bufferRadii, |
| | | center: { |
| | | lng: centerLngLat.longitude, |
| | | lat: centerLngLat.latitude, |
| | | height: centerLngLat.height ?? 0, |
| | | }, |
| | | } |
| | | : null, |
| | | } |
| | | if (targetIndex === -1) { |
| | | shapeList.value.push(shapePayload) |
| | |
| | | currentShapeType.value = row.drawType |
| | | pointList = _.cloneDeep(row.points) |
| | | clearActiveTool() |
| | | startEdit(row.drawType, row.points) |
| | | const editPayload = row.drawType === 'buffer' ? { points: row.points, meta: row.meta } : row.points |
| | | startEdit(row.drawType, editPayload) |
| | | applyPolygonMetrics(pointList) |
| | | showTypePanelAtCurrent() |
| | | renderShapeList() |
| | |
| | | super(viewer) |
| | | this.tooltip = new MapTooltip(viewer) |
| | | this.dataSource = null |
| | | this.circleEntity = null |
| | | this.centerCartesian = null |
| | | this.radius = 0 |
| | | 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 |
| | | } |
| | | |
| | | start() { |
| | |
| | | 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.tooltip.show('单击设置中心点', { x: 0, y: 0 }) |
| | | } |
| | | |
| | |
| | | const position = this.getPositionFromScreen(click.position) |
| | | if (!position) return |
| | | |
| | | if (!this.centerCartesian) { |
| | | if (this.drawStep === 0) { |
| | | this.centerCartesian = position |
| | | this.radius = 1 |
| | | this.radiusLevel1 = 1 |
| | | this.radiusLevel2 = 1 |
| | | this.radiusLevel3 = 1 |
| | | this.isDrawing = true |
| | | this.drawStep = 1 |
| | | this.createEntities() |
| | | this.tooltip.show('单击结束绘制', click.position) |
| | | this.tooltip.show('单击设置一级缓冲圆', click.position) |
| | | return |
| | | } |
| | | |
| | | if (this.isDrawing) { |
| | | 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 |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radius, this.radius) |
| | | this.notify('getPolygonPositions', positions) |
| | | this.drawStep = 0 |
| | | 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.isDrawing) { |
| | | this.tooltip.move(movement.endPosition) |
| | | return |
| | | } |
| | | this.tooltip.move(movement.endPosition) |
| | | if (!this.isDrawing) return |
| | | const position = this.getPositionFromScreen(movement.endPosition) |
| | | if (!position) return |
| | | this.radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.tooltip.move(movement.endPosition) |
| | | 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.circleEntity) return |
| | | this.circleEntity = this.dataSource.entities.add({ |
| | | 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.radius, false), |
| | | semiMinorAxis: new Cesium.CallbackProperty(() => this.radius, false), |
| | | material: Cesium.Color.fromBytes(45, 140, 240, 99), |
| | | outline: true, |
| | | outlineColor: Cesium.Color.fromBytes(45, 140, 240, 255), |
| | | outlineWidth: 2, |
| | | 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.circleEntity = null |
| | | this.circleLevel1Entity = null |
| | | this.circleLevel2Entity = null |
| | | this.circleLevel3Entity = null |
| | | this.circleLevel1OutlineEntity = null |
| | | this.circleLevel2OutlineEntity = null |
| | | this.circleLevel3OutlineEntity = null |
| | | } |
| | | |
| | | getSurfaceDistance(startCartesian, endCartesian) { |
| | |
| | | this.tooltip?.destroy() |
| | | this.tooltip = null |
| | | this.centerCartesian = null |
| | | this.radius = 0 |
| | | this.radiusLevel1 = 0 |
| | | this.radiusLevel2 = 0 |
| | | this.radiusLevel3 = 0 |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | } |
| | | } |
| | |
| | | import * as Cesium from 'cesium' |
| | | import { MapTooltip } from '../Tooltip' |
| | | import { ToolBase } from '../ToolBase' |
| | | import { |
| | | getBoundsFromCartesians, |
| | | getCenterFromBounds, |
| | | getMetersBetween, |
| | | buildEllipsePositions, |
| | | } from '../shapeUtils' |
| | | import { buildEllipsePositions } from '../shapeUtils' |
| | | |
| | | export class DrawEllipseTool extends ToolBase { |
| | | constructor(viewer) { |
| | |
| | | this.tooltip = new MapTooltip(viewer) |
| | | this.dataSource = null |
| | | this.ellipseEntity = null |
| | | this.startPosition = null |
| | | this.endPosition = null |
| | | this.centerCartesian = null |
| | | this.majorPoint = null |
| | | this.minorPoint = null |
| | | this.semiMajor = 0 |
| | | this.semiMinor = 0 |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | } |
| | | |
| | | start() { |
| | |
| | | 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 }) |
| | | this.drawStep = 0 |
| | | 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 |
| | | if (this.drawStep === 0) { |
| | | this.centerCartesian = position |
| | | this.semiMajor = 1 |
| | | this.semiMinor = 1 |
| | | this.isDrawing = true |
| | | this.drawStep = 1 |
| | | this.createEntities() |
| | | this.tooltip.show('单击结束绘制', click.position) |
| | | this.tooltip.show('单击设置长轴', click.position) |
| | | return |
| | | } |
| | | |
| | | if (this.isDrawing) { |
| | | this.endPosition = position |
| | | this.updateEllipseByBounds() |
| | | if (this.drawStep === 1) { |
| | | this.majorPoint = position |
| | | this.semiMajor = Math.max(1, this.getSurfaceDistance(this.centerCartesian, this.majorPoint)) |
| | | this.semiMinor = this.semiMajor |
| | | this.drawStep = 2 |
| | | this.tooltip.show('单击设置短轴', click.position) |
| | | return |
| | | } |
| | | if (this.drawStep === 2) { |
| | | this.minorPoint = position |
| | | const minorRadius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, this.minorPoint)) |
| | | this.semiMinor = Math.min(minorRadius, this.semiMajor) |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor) |
| | | this.notify('getPolygonPositions', positions) |
| | | this.tooltip.hide() |
| | |
| | | } |
| | | |
| | | handleMouseMove(movement) { |
| | | if (!this.isDrawing) { |
| | | this.tooltip.move(movement.endPosition) |
| | | return |
| | | } |
| | | this.tooltip.move(movement.endPosition) |
| | | if (!this.isDrawing) 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) |
| | | if (this.drawStep === 1) { |
| | | const radius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.semiMajor = radius |
| | | this.semiMinor = radius |
| | | return |
| | | } |
| | | if (this.drawStep === 2) { |
| | | const minorRadius = Math.max(1, this.getSurfaceDistance(this.centerCartesian, position)) |
| | | this.semiMinor = Math.min(minorRadius, this.semiMajor) |
| | | } |
| | | } |
| | | |
| | | createEntities() { |
| | |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | 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 |
| | | } |
| | | |
| | | clearPreviewEntities() { |
| | |
| | | } |
| | | this.tooltip?.destroy() |
| | | this.tooltip = null |
| | | this.startPosition = null |
| | | this.endPosition = null |
| | | this.centerCartesian = null |
| | | this.majorPoint = null |
| | | this.minorPoint = null |
| | | this.isDrawing = false |
| | | this.drawStep = 0 |
| | | } |
| | | } |
| | |
| | | import * as Cesium from 'cesium' |
| | | import * as Cesium from 'cesium' |
| | | import { MapTooltip } from '../Tooltip' |
| | | import { ToolBase } from '../ToolBase' |
| | | import { buildEllipsePositions, cartesianToLocal } from '../shapeUtils' |
| | |
| | | this.tooltip = new MapTooltip(viewer) |
| | | this.dataSource = null |
| | | this.centerCartesian = null |
| | | this.radius = 0 |
| | | this.radiusLevel1 = 0 |
| | | this.radiusLevel2 = 0 |
| | | this.radiusLevel3 = 0 |
| | | this.dragType = null |
| | | this.circleEntity = null |
| | | this.circleLevel1Entity = null |
| | | this.circleLevel2Entity = null |
| | | this.circleLevel3Entity = null |
| | | this.circleLevel1OutlineEntity = null |
| | | this.circleLevel2OutlineEntity = null |
| | | this.circleLevel3OutlineEntity = null |
| | | this.centerEntity = null |
| | | this.radiusEntity = null |
| | | this.radiusLevel1Entity = null |
| | | this.radiusLevel2Entity = null |
| | | this.radiusLevel3Entity = null |
| | | } |
| | | |
| | | start(points = []) { |
| | | const normalized = normalizePoints(points) |
| | | start(data = []) { |
| | | const inputPoints = Array.isArray(data?.points) ? data.points : data |
| | | const normalized = normalizePoints(inputPoints) |
| | | if (!normalized.length) return |
| | | const centerLng = normalized.reduce((sum, p) => sum + p.lng, 0) / normalized.length |
| | | const centerLat = normalized.reduce((sum, p) => sum + p.lat, 0) / normalized.length |
| | | this.centerCartesian = Cesium.Cartesian3.fromDegrees(centerLng, centerLat) |
| | | this.radius = this.estimateRadius(normalized) |
| | | const radii = Array.isArray(data?.meta?.bufferRadii) ? data.meta.bufferRadii : null |
| | | if (radii?.length) { |
| | | const [r1, r2, r3] = radii |
| | | this.radiusLevel1 = Number.isFinite(r1) && r1 > 0 ? r1 : 1 |
| | | this.radiusLevel2 = Number.isFinite(r2) && r2 > 0 ? Math.max(r2, this.radiusLevel1) : this.radiusLevel1 |
| | | this.radiusLevel3 = Number.isFinite(r3) && r3 > 0 ? Math.max(r3, this.radiusLevel2) : this.radiusLevel2 |
| | | } else { |
| | | this.radiusLevel3 = this.estimateRadius(normalized) |
| | | this.radiusLevel2 = this.radiusLevel3 |
| | | this.radiusLevel1 = this.radiusLevel3 |
| | | } |
| | | |
| | | this.dataSource = new Cesium.CustomDataSource('edit-buffer-circle') |
| | | this.viewer.dataSources.add(this.dataSource) |
| | |
| | | const picked = this.viewer.scene.pick(evt.position)?.id |
| | | if (!picked) return |
| | | if (picked.customType === 'circle-center') this.dragType = 'center' |
| | | if (picked.customType === 'circle-radius') this.dragType = 'radius' |
| | | if (picked.customType === 'circle-radius-1') this.dragType = 'radius-1' |
| | | if (picked.customType === 'circle-radius-2') this.dragType = 'radius-2' |
| | | if (picked.customType === 'circle-radius-3') this.dragType = 'radius-3' |
| | | if (this.dragType) this.disableMapControl() |
| | | } |
| | | |
| | |
| | | |
| | | if (this.dragType === 'center') { |
| | | this.centerCartesian = position |
| | | this.updateRadiusPoint() |
| | | this.updateRadiusPoints() |
| | | return |
| | | } |
| | | |
| | | const local = cartesianToLocal(this.centerCartesian, position) |
| | | this.radius = Math.max(1, Math.sqrt(local.x * local.x + local.y * local.y)) |
| | | this.updateRadiusPoint() |
| | | const radius = Math.max(1, Math.sqrt(local.x * local.x + local.y * local.y)) |
| | | if (this.dragType === 'radius-1') { |
| | | this.radiusLevel1 = radius |
| | | if (this.radiusLevel2 < this.radiusLevel1) this.radiusLevel2 = this.radiusLevel1 |
| | | if (this.radiusLevel3 < this.radiusLevel2) this.radiusLevel3 = this.radiusLevel2 |
| | | } |
| | | if (this.dragType === 'radius-2') { |
| | | this.radiusLevel2 = Math.max(radius, this.radiusLevel1) |
| | | if (this.radiusLevel3 < this.radiusLevel2) this.radiusLevel3 = this.radiusLevel2 |
| | | } |
| | | if (this.dragType === 'radius-3') { |
| | | this.radiusLevel3 = Math.max(radius, this.radiusLevel2) |
| | | } |
| | | this.updateRadiusPoints() |
| | | } |
| | | |
| | | handleLeftUp() { |
| | | if (!this.dragType) return |
| | | this.dragType = null |
| | | this.enableMapControl() |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radius, this.radius) |
| | | this.notify('getPolygonPositions', positions) |
| | | const positions = buildEllipsePositions(this.centerCartesian, this.radiusLevel3, this.radiusLevel3) |
| | | this.notify('getPolygonPositions', { |
| | | positions, |
| | | meta: { |
| | | center: this.centerCartesian, |
| | | bufferRadii: [this.radiusLevel1, this.radiusLevel2, this.radiusLevel3], |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | createEntities() { |
| | | this.circleEntity = this.dataSource.entities.add({ |
| | | this.circleLevel1Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.centerCartesian, false), |
| | | ellipse: { |
| | | semiMajorAxis: new Cesium.CallbackProperty(() => this.radius, false), |
| | | semiMinorAxis: new Cesium.CallbackProperty(() => this.radius, false), |
| | | material: Cesium.Color.fromBytes(45, 140, 240, 99), |
| | | outline: true, |
| | | outlineColor: Cesium.Color.fromBytes(45, 140, 240, 255), |
| | | outlineWidth: 2, |
| | | 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), |
| | | }, |
| | | }) |
| | | |
| | |
| | | customType: 'circle-center', |
| | | }) |
| | | |
| | | this.radiusEntity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.getRadiusPoint(), false), |
| | | this.radiusLevel1Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.getRadiusPoint(this.radiusLevel1), false), |
| | | point: { |
| | | pixelSize: 10, |
| | | color: Cesium.Color.fromBytes(255, 255, 255, 200), |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | }, |
| | | customType: 'circle-radius', |
| | | customType: 'circle-radius-1', |
| | | }) |
| | | |
| | | this.radiusLevel2Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.getRadiusPoint(this.radiusLevel2), false), |
| | | point: { |
| | | pixelSize: 10, |
| | | color: Cesium.Color.fromBytes(255, 255, 255, 200), |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | }, |
| | | customType: 'circle-radius-2', |
| | | }) |
| | | |
| | | this.radiusLevel3Entity = this.dataSource.entities.add({ |
| | | position: new Cesium.CallbackProperty(() => this.getRadiusPoint(this.radiusLevel3), false), |
| | | point: { |
| | | pixelSize: 10, |
| | | color: Cesium.Color.fromBytes(255, 255, 255, 200), |
| | | heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, |
| | | disableDepthTestDistance: Number.POSITIVE_INFINITY, |
| | | }, |
| | | customType: 'circle-radius-3', |
| | | }) |
| | | } |
| | | |
| | | updateRadiusPoint() { |
| | | if (!this.radiusEntity) return |
| | | this.radiusEntity.position = this.getRadiusPoint() |
| | | updateRadiusPoints() { |
| | | if (this.radiusLevel1Entity) this.radiusLevel1Entity.position = this.getRadiusPoint(this.radiusLevel1) |
| | | if (this.radiusLevel2Entity) this.radiusLevel2Entity.position = this.getRadiusPoint(this.radiusLevel2) |
| | | if (this.radiusLevel3Entity) this.radiusLevel3Entity.position = this.getRadiusPoint(this.radiusLevel3) |
| | | } |
| | | |
| | | getPositions() { |
| | | if (!this.centerCartesian) return [] |
| | | return buildEllipsePositions(this.centerCartesian, this.radius, this.radius) |
| | | return { |
| | | positions: buildEllipsePositions(this.centerCartesian, this.radiusLevel3, this.radiusLevel3), |
| | | meta: { |
| | | center: this.centerCartesian, |
| | | bufferRadii: [this.radiusLevel1, this.radiusLevel2, this.radiusLevel3], |
| | | }, |
| | | } |
| | | } |
| | | |
| | | getRadiusPoint() { |
| | | getRadiusPoint(radius) { |
| | | const frame = Cesium.Transforms.eastNorthUpToFixedFrame(this.centerCartesian) |
| | | const local = new Cesium.Cartesian3(this.radius, 0, 0) |
| | | const local = new Cesium.Cartesian3(radius, 0, 0) |
| | | return Cesium.Matrix4.multiplyByPoint(frame, local, new Cesium.Cartesian3()) |
| | | } |
| | | |
| | |
| | | this.tooltip?.destroy() |
| | | this.tooltip = null |
| | | this.centerCartesian = null |
| | | this.radius = 0 |
| | | this.radiusLevel1 = 0 |
| | | this.radiusLevel2 = 0 |
| | | this.radiusLevel3 = 0 |
| | | this.circleLevel1OutlineEntity = null |
| | | this.circleLevel2OutlineEntity = null |
| | | this.circleLevel3OutlineEntity = null |
| | | this.dragType = null |
| | | } |
| | | } |
| | |
| | | const local = cartesianToLocal(this.centerCartesian, position) |
| | | if (this.dragType === 'major') { |
| | | this.semiMajor = Math.max(1, Math.abs(local.x)) |
| | | if (this.semiMajor < this.semiMinor) { |
| | | this.semiMajor = this.semiMinor |
| | | } |
| | | } |
| | | if (this.dragType === 'minor') { |
| | | this.semiMinor = Math.max(1, Math.abs(local.y)) |
| | | if (this.semiMinor > this.semiMajor) { |
| | | this.semiMinor = this.semiMajor |
| | | } |
| | | } |
| | | this.updateAxisPoints() |
| | | } |