From cb43af5c2caf2184bbf1a8e417f44e9aeaa2fdd9 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Thu, 29 Jan 2026 13:38:20 +0800
Subject: [PATCH] feat:增加设备特效椭球

---
 applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js |  135 ++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 114 insertions(+), 21 deletions(-)

diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
index a957b6c..228eae3 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
@@ -9,14 +9,53 @@
 	cartesianToLocal,
 } from '../shapeUtils'
 
+const DEFAULT_STYLE = {
+	fill: Cesium.Color.fromBytes(45, 140, 240, 99),
+	outline: Cesium.Color.fromBytes(45, 140, 240, 255),
+}
+const resolveStyle = style => ({
+	fill: style?.fill || DEFAULT_STYLE.fill,
+	outline: style?.outline || DEFAULT_STYLE.outline,
+})
+
 const normalizePoints = points =>
 	(points || []).map(point => ({
 		lng: point.lng ?? point.longitude,
 		lat: point.lat ?? point.latitude,
 	}))
 
+const resolveLngLat = point => {
+	if (!point) return null
+	const lng = point.lng ?? point.longitude
+	const lat = point.lat ?? point.latitude
+	if (Number.isFinite(lng) && Number.isFinite(lat)) {
+		return { lng: Number(lng), lat: Number(lat), height: Number(point.height) || 0 }
+	}
+	return null
+}
+
+const resolveCartesian = point => {
+	if (!point) return null
+	if (Number.isFinite(point.x) && Number.isFinite(point.y) && Number.isFinite(point.z)) {
+		return new Cesium.Cartesian3(point.x, point.y, point.z)
+	}
+	const lngLat = resolveLngLat(point)
+	if (!lngLat) return null
+	return Cesium.Cartesian3.fromDegrees(lngLat.lng, lngLat.lat, lngLat.height || 0)
+}
+
+const resolveCartographic = point => {
+	if (!point) return null
+	if (Number.isFinite(point.x) && Number.isFinite(point.y) && Number.isFinite(point.z)) {
+		return Cesium.Cartographic.fromCartesian(point)
+	}
+	const lngLat = resolveLngLat(point)
+	if (!lngLat) return null
+	return Cesium.Cartographic.fromDegrees(lngLat.lng, lngLat.lat, lngLat.height || 0)
+}
+
 export class EditEllipseTool extends ToolBase {
-	constructor(viewer) {
+	constructor(viewer, options = {}) {
 		super(viewer)
 		this.tooltip = new MapTooltip(viewer)
 		this.dataSource = null
@@ -28,24 +67,46 @@
 		this.majorEntity = null
 		this.minorEntity = null
 		this.ellipseEntity = null
+		this.style = resolveStyle(options?.style)
 	}
 
-	start(points = []) {
-		const normalized = normalizePoints(points)
-		const bounds = getBoundsFromLngLats(normalized)
-		const center = getCenterFromBounds(bounds)
-		if (!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)
+	start(data = []) {
+		const inputPoints = Array.isArray(data?.points) ? data.points : data
+		const meta = data?.meta || null
+		const metaCenter = resolveCartesian(meta?.center)
+		if (metaCenter) {
+			this.centerCartesian = metaCenter
+			const centerCarto = Cesium.Cartographic.fromCartesian(metaCenter)
+			const majorFromMeta = Number.isFinite(meta?.semiMajor) ? Number(meta.semiMajor) : 0
+			const minorFromMeta = Number.isFinite(meta?.semiMinor) ? Number(meta.semiMinor) : 0
+			const majorPoint = resolveCartographic(meta?.majorPoint)
+			const minorPoint = resolveCartographic(meta?.minorPoint)
+			const majorDistance =
+				majorFromMeta || (majorPoint ? getMetersBetween(centerCarto, majorPoint) : 0)
+			const minorDistance =
+				minorFromMeta || (minorPoint ? getMetersBetween(centerCarto, minorPoint) : 0)
+			if (majorDistance > 0) this.semiMajor = Math.max(1, majorDistance)
+			if (minorDistance > 0) this.semiMinor = Math.max(1, minorDistance)
+			if (this.semiMinor > this.semiMajor) this.semiMinor = this.semiMajor
+		}
+
+		if (!this.centerCartesian || !this.semiMajor || !this.semiMinor) {
+			const normalized = normalizePoints(inputPoints)
+			const bounds = getBoundsFromLngLats(normalized)
+			const center = getCenterFromBounds(bounds)
+			if (!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)
+		}
 
 		this.dataSource = new Cesium.CustomDataSource('edit-ellipse')
 		this.viewer.dataSources.add(this.dataSource)
@@ -85,9 +146,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()
 	}
@@ -97,7 +164,16 @@
 		this.dragType = null
 		this.enableMapControl()
 		const positions = buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor)
-		this.notify('getPolygonPositions', positions)
+		this.notify('getPolygonPositions', {
+			positions,
+			meta: {
+				center: this.centerCartesian,
+				majorPoint: this.getAxisPoint(this.semiMajor, 0),
+				minorPoint: this.getAxisPoint(0, this.semiMinor),
+				semiMajor: this.semiMajor,
+				semiMinor: this.semiMinor,
+			},
+		})
 	}
 
 	createEntities() {
@@ -106,9 +182,9 @@
 			ellipse: {
 				semiMajorAxis: new Cesium.CallbackProperty(() => this.semiMajor, false),
 				semiMinorAxis: new Cesium.CallbackProperty(() => this.semiMinor, false),
-				material: Cesium.Color.fromBytes(45, 140, 240, 99),
+				material: this.style.fill,
 				outline: true,
-				outlineColor: Cesium.Color.fromBytes(45, 140, 240, 255),
+				outlineColor: this.style.outline,
 				outlineWidth: 2,
 				heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
 			},
@@ -156,7 +232,16 @@
 
 	getPositions() {
 		if (!this.centerCartesian) return []
-		return buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor)
+		return {
+			positions: buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor),
+			meta: {
+				center: this.centerCartesian,
+				majorPoint: this.getAxisPoint(this.semiMajor, 0),
+				minorPoint: this.getAxisPoint(0, this.semiMinor),
+				semiMajor: this.semiMajor,
+				semiMinor: this.semiMinor,
+			},
+		}
 	}
 
 	getAxisPoint(eastMeters, northMeters) {
@@ -172,6 +257,14 @@
 		return scene.camera.pickEllipsoid(screenPosition, scene.globe.ellipsoid)
 	}
 
+	setStyle(style) {
+		this.style = resolveStyle(style)
+		if (this.ellipseEntity?.ellipse) {
+			this.ellipseEntity.ellipse.material = this.style.fill
+			this.ellipseEntity.ellipse.outlineColor = this.style.outline
+		}
+	}
+
 	disableMapControl() {
 		const controller = this.viewer.scene.screenSpaceCameraController
 		controller.enableRotate = false

--
Gitblit v1.9.3