吉安感知网项目-前端
shuishen
2026-01-28 4b8b4906a8983c811954a074702b0024e7694588
feat:区域划分地图绘制相关处理
5 files modified
525 ■■■■ changed files
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue 73 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js 165 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js 91 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js 190 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js 6 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -253,6 +253,7 @@
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'
@@ -482,6 +483,56 @@
    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({
@@ -505,7 +556,8 @@
// 绘制完成回调
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
@@ -513,7 +565,11 @@
        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 }
    })
@@ -538,6 +594,16 @@
        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)
@@ -677,7 +743,8 @@
    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()
applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js
@@ -8,10 +8,18 @@
        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() {
@@ -20,6 +28,7 @@
        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 })
    }
@@ -27,47 +36,147 @@
        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),
            },
        })
    }
@@ -75,7 +184,12 @@
    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) {
@@ -107,7 +221,10 @@
        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
    }
}
applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js
@@ -1,12 +1,7 @@
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) {
@@ -14,12 +9,13 @@
        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() {
@@ -28,26 +24,37 @@
        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()
@@ -56,32 +63,20 @@
    }
    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() {
@@ -98,6 +93,13 @@
                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() {
@@ -127,9 +129,10 @@
        }
        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
    }
}
applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'
import * as Cesium from 'cesium'
import { MapTooltip } from '../Tooltip'
import { ToolBase } from '../ToolBase'
import { buildEllipsePositions, cartesianToLocal } from '../shapeUtils'
@@ -15,20 +15,40 @@
        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)
@@ -59,7 +79,9 @@
        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()
    }
@@ -71,34 +93,108 @@
        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),
            },
        })
@@ -113,31 +209,60 @@
            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())
    }
@@ -178,7 +303,12 @@
        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
    }
}
applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
@@ -85,9 +85,15 @@
        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()
    }