Browse Source

空域修改

mh
cuitw 1 month ago
parent
commit
c01e2a91a5
  1. 30
      ruoyi-ui/src/views/cesiumMap/ContextMenu.vue
  2. 561
      ruoyi-ui/src/views/cesiumMap/index.vue

30
ruoyi-ui/src/views/cesiumMap/ContextMenu.vue

@ -172,6 +172,25 @@
</div>
</div>
<!-- 空域图形调整位置 -->
<div class="menu-section" v-if="entityData.type === 'polygon' || entityData.type === 'rectangle' || entityData.type === 'circle' || entityData.type === 'sector' || entityData.type === 'arrow'">
<div class="menu-title">位置</div>
<div class="menu-item" @click="handleAdjustPosition">
<span class="menu-icon">📍</span>
<span>调整位置</span>
</div>
</div>
<!-- 空域图形命名多边形矩形圆形扇形 -->
<div class="menu-section" v-if="entityData.type === 'polygon' || entityData.type === 'rectangle' || entityData.type === 'circle' || entityData.type === 'sector'">
<div class="menu-title">命名</div>
<div class="menu-item" @click="handleEditAirspaceName">
<span class="menu-icon">📝</span>
<span>命名</span>
<span class="menu-value">{{ entityData.name || '(未命名)' }}</span>
</div>
</div>
<!-- 多边形特有选项 -->
<div class="menu-section" v-if="entityData.type === 'polygon' || entityData.type === 'rectangle' || entityData.type === 'circle' || entityData.type === 'sector' || entityData.type === 'powerZone'">
<div class="menu-title">填充属性</div>
@ -442,6 +461,17 @@ export default {
this.$emit('delete')
},
handleAdjustPosition() {
this.$emit('adjust-airspace-position')
},
handleEditAirspaceName() {
const name = prompt('请输入图形名称:', this.entityData.name || '')
if (name !== null) {
this.$emit('update-property', 'name', name.trim())
}
},
handleDetectionZonePlatform() {
this.$emit('detection-zone')
},

561
ruoyi-ui/src/views/cesiumMap/index.vue

@ -54,6 +54,7 @@
@add-waypoint-at="handleAddWaypointAt"
@toggle-waypoint-hold="handleToggleWaypointHold"
@launch-missile="openLaunchMissileDialog"
@adjust-airspace-position="startAirspacePositionEdit"
/>
<!-- 定位弹窗 -->
@ -75,6 +76,11 @@
点击地图放置复制航线右键取消
</div>
<!-- 空域位置调整提示 -->
<div v-if="airspacePositionEditContext" class="copy-route-tip">
移动鼠标调整位置左键确认右键取消
</div>
<!-- 半径输入弹窗 -->
<radius-dialog
:visible="radiusDialogVisible"
@ -495,10 +501,10 @@ export default {
defaultStyles: {
point: { color: '#FF0000', size: 8 },
line: { color: '#000000', width: 1 },
polygon: { color: '#0000FF', opacity: 0, width: 4 },
rectangle: { color: '#FFA500', opacity: 0, width: 4 },
circle: { color: '#800080', opacity: 0, width: 4 },
sector: { color: '#FF6347', opacity: 0, width: 3 },
polygon: { color: '#0000FF', opacity: 0, width: 2 },
rectangle: { color: '#FFA500', opacity: 0, width: 2 },
circle: { color: '#800080', opacity: 0, width: 2 },
sector: { color: '#FF6347', opacity: 0, width: 2 },
arrow: { color: '#FF0000', width: 6 },
text: { color: '#000000', font: '14px PingFang SC, Microsoft YaHei, Helvetica Neue, sans-serif', backgroundColor: 'rgba(255, 255, 255, 0.92)' },
image: { width: 150, height: 150 }
@ -557,7 +563,10 @@ export default {
copyPreviewMouseCartesian: null,
// /{ routeId, waypointIndex, mode: 'before'|'after', waypoints }线
addWaypointContext: null,
addWaypointPreviewEntity: null
addWaypointPreviewEntity: null,
// { entityData } CallbackProperty
airspacePositionEditContext: null,
airspacePositionEditPreviewEntity: null
}
},
components: {
@ -3510,6 +3519,15 @@ export default {
this.clearAddWaypointContext();
return;
}
//
if (this.airspacePositionEditContext) {
const placePosition = this.getClickPosition(click.position);
if (placePosition) {
this.applyAirspacePositionEdit(placePosition);
}
this.clearAirspacePositionEdit();
return;
}
const pickedObject = this.viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject) && pickedObject.id) {
@ -3675,6 +3693,13 @@ export default {
if (this.viewer.scene.requestRender) this.viewer.scene.requestRender();
}
}
if (this.airspacePositionEditContext) {
const cartesian = this.getClickPosition(movement.endPosition);
if (cartesian) {
this.airspacePositionEditContext.mouseCartesian = cartesian;
if (this.viewer.scene.requestRender) this.viewer.scene.requestRender();
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// pending
@ -3734,6 +3759,13 @@ export default {
this.$message && this.$message.info('已取消增加航点');
return;
}
//
if (this.airspacePositionEditContext) {
this.clearAirspacePositionEdit();
this.contextMenu.visible = false;
this.$message && this.$message.info('已取消调整位置');
return;
}
//
this.contextMenu.visible = false;
@ -5369,7 +5401,7 @@ export default {
return angle;
},
//
generateSectorPositions(center, radius, startAngle, endAngle) {
generateSectorPositions(center, radius, startAngle, endAngle, maxPoints) {
const positions = [];
const centerLL = Cesium.Cartographic.fromCartesian(center);
//
@ -5381,8 +5413,9 @@ export default {
}
//
angleDiff = Math.max(0.01, angleDiff);
//
const numPoints = Math.max(200, Math.ceil(angleDiff * 180 / Math.PI));
// maxPoints
let numPoints = Math.max(200, Math.ceil(angleDiff * 180 / Math.PI));
if (maxPoints != null && maxPoints > 0) numPoints = Math.max(8, Math.min(numPoints, maxPoints));
const angleStep = angleDiff / (numPoints - 1);
//
for (let i = 0; i < numPoints; i++) {
@ -5491,8 +5524,10 @@ export default {
return null;
}
},
//
// PolylineArrowMaterial
addArrowEntity(positions) {
if (!positions || positions.length < 2) return null
const arrowPositions = positions.length === 2 ? positions : [positions[0], positions[positions.length - 1]]
this.entityCounter++
const id = `arrow_${this.entityCounter}`
// 使
@ -5500,7 +5535,7 @@ export default {
id: id,
name: `箭头 ${this.entityCounter}`,
polyline: {
positions: positions,
positions: arrowPositions,
width: 12, //
material: new Cesium.PolylineArrowMaterialProperty(
Cesium.Color.fromCssColorString(this.defaultStyles.arrow.color)
@ -5513,8 +5548,8 @@ export default {
const entityData = {
id,
type: 'arrow',
points: positions.map(p => this.cartesianToLatLng(p)),
positions: positions,
points: arrowPositions.map(p => this.cartesianToLatLng(p)),
positions: arrowPositions,
entity: entity,
color: this.defaultStyles.arrow.color,
width: this.defaultStyles.arrow.width,
@ -6417,6 +6452,403 @@ export default {
}
this.addWaypointContext = null;
},
/** 为空域图形(多边形/矩形/圆形/扇形)添加或更新中心名称标签,微软雅黑、不加粗,清晰可读 */
updateAirspaceEntityLabel(entityData) {
if (!entityData || !entityData.entity || !['polygon', 'rectangle', 'circle', 'sector'].includes(entityData.type)) return
const entity = entityData.entity
const name = entityData.name
const font = '16px Microsoft YaHei'
const labelStyle = {
text: name || '',
font,
fillColor: Cesium.Color.fromCssColorString('#1a1a1a'),
style: Cesium.LabelStyle.FILL,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
backgroundColor: Cesium.Color.fromCssColorString('rgba(255, 255, 255, 0.95)'),
backgroundPadding: new Cesium.Cartesian2(10, 6),
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
if (!name) {
entity.label = undefined
return
}
const that = this
const getCenter = () => {
const c = that.getAirspaceCenter(entityData)
return c || Cesium.Cartesian3.ZERO
}
entity.label = {
...labelStyle,
position: new Cesium.CallbackProperty(getCenter, false)
}
},
/** 开始空域位置调整模式:右键菜单点击「调整位置」后进入,移动鼠标预览,左键确认、右键取消 */
startAirspacePositionEdit() {
const ed = this.contextMenu.entityData;
if (!ed || !['polygon', 'rectangle', 'circle', 'sector', 'arrow'].includes(ed.type)) {
this.contextMenu.visible = false;
return;
}
const entityData = this.allEntities.find(e => (e.entity === ed.entity || e === ed) && e.type === ed.type) || ed;
if (!entityData.entity) {
this.contextMenu.visible = false;
return;
}
this.contextMenu.visible = false;
entityData.entity.show = false;
const center = this.getAirspaceCenter(entityData);
this.airspacePositionEditContext = { entityData, mouseCartesian: center || null };
this.createAirspacePositionPreviewEntity();
this.$message && this.$message.info('移动鼠标调整位置,左键确认,右键取消');
},
/** 创建空域位置调整的预览实体(使用 CallbackProperty,每帧渲染时读取 mouseCartesian,与测距绘制一致) */
createAirspacePositionPreviewEntity() {
const ctx = this.airspacePositionEditContext;
if (!ctx || !ctx.entityData || this.airspacePositionEditPreviewEntity) return;
const entityData = ctx.entityData;
const color = entityData.color || this.defaultStyles.polygon.color;
const borderColor = entityData.borderColor || color;
const opacity = entityData.opacity != null ? entityData.opacity : 0;
const width = entityData.width != null ? entityData.width : 2;
const that = this;
switch (entityData.type) {
case 'polygon': {
if (!entityData.positions || entityData.positions.length < 3) return;
this.airspacePositionEditPreviewEntity = this.viewer.entities.add({
polygon: {
hierarchy: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const oldCenter = that.getAirspaceCenter(entityData);
if (!mc || !oldCenter) return new Cesium.PolygonHierarchy(entityData.positions);
const delta = Cesium.Cartesian3.subtract(mc, oldCenter, new Cesium.Cartesian3());
const newPositions = entityData.positions.map(p => Cesium.Cartesian3.add(p, delta, new Cesium.Cartesian3()));
return new Cesium.PolygonHierarchy(newPositions);
}, false),
material: Cesium.Color.TRANSPARENT
},
polyline: {
positions: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const oldCenter = that.getAirspaceCenter(entityData);
if (!mc || !oldCenter) return entityData.positions;
const delta = Cesium.Cartesian3.subtract(mc, oldCenter, new Cesium.Cartesian3());
const newPositions = entityData.positions.map(p => Cesium.Cartesian3.add(p, delta, new Cesium.Cartesian3()));
return [...newPositions, newPositions[0]];
}, false),
width,
material: Cesium.Color.fromCssColorString(borderColor),
arcType: Cesium.ArcType.NONE
}
});
break;
}
case 'rectangle': {
this.airspacePositionEditPreviewEntity = this.viewer.entities.add({
rectangle: {
coordinates: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const rect = entityData.entity.rectangle.coordinates.getValue(Cesium.JulianDate.now());
if (!mc || !rect) return rect || Cesium.Rectangle.fromDegrees(0, 0, 0, 0);
const oldCenter = that.getAirspaceCenter(entityData);
if (!oldCenter) return rect;
const oldCarto = Cesium.Cartographic.fromCartesian(oldCenter);
const newCarto = Cesium.Cartographic.fromCartesian(mc);
const dLon = newCarto.longitude - oldCarto.longitude;
const dLat = newCarto.latitude - oldCarto.latitude;
return new Cesium.Rectangle(
Cesium.Math.negativePiToPi(rect.west + dLon),
Math.max(-Cesium.Math.PI_OVER_TWO, Math.min(Cesium.Math.PI_OVER_TWO, rect.south + dLat)),
Cesium.Math.negativePiToPi(rect.east + dLon),
Math.max(-Cesium.Math.PI_OVER_TWO, Math.min(Cesium.Math.PI_OVER_TWO, rect.north + dLat))
);
}, false),
material: Cesium.Color.fromCssColorString(color).withAlpha(opacity)
},
polyline: {
positions: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const rect = entityData.entity.rectangle.coordinates.getValue(Cesium.JulianDate.now());
if (!rect) return [];
const oldCenter = that.getAirspaceCenter(entityData);
if (!oldCenter) {
const sw = Cesium.Cartesian3.fromRadians(rect.west, rect.south);
const se = Cesium.Cartesian3.fromRadians(rect.east, rect.south);
const ne = Cesium.Cartesian3.fromRadians(rect.east, rect.north);
const nw = Cesium.Cartesian3.fromRadians(rect.west, rect.north);
return [sw, se, ne, nw, sw];
}
const center = mc || oldCenter;
const oldCarto = Cesium.Cartographic.fromCartesian(oldCenter);
const newCarto = Cesium.Cartographic.fromCartesian(center);
const dLon = newCarto.longitude - oldCarto.longitude;
const dLat = newCarto.latitude - oldCarto.latitude;
const newWest = Cesium.Math.negativePiToPi(rect.west + dLon);
const newEast = Cesium.Math.negativePiToPi(rect.east + dLon);
const newSouth = Math.max(-Cesium.Math.PI_OVER_TWO, Math.min(Cesium.Math.PI_OVER_TWO, rect.south + dLat));
const newNorth = Math.max(-Cesium.Math.PI_OVER_TWO, Math.min(Cesium.Math.PI_OVER_TWO, rect.north + dLat));
const sw = Cesium.Cartesian3.fromRadians(newWest, newSouth);
const se = Cesium.Cartesian3.fromRadians(newEast, newSouth);
const ne = Cesium.Cartesian3.fromRadians(newEast, newNorth);
const nw = Cesium.Cartesian3.fromRadians(newWest, newNorth);
return [sw, se, ne, nw, sw];
}, false),
width,
material: Cesium.Color.fromCssColorString(borderColor),
arcType: Cesium.ArcType.NONE
}
});
break;
}
case 'circle': {
const radius = entityData.radius || 1000;
this.airspacePositionEditPreviewEntity = this.viewer.entities.add({
position: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
return mc || that.getAirspaceCenter(entityData) || Cesium.Cartesian3.ZERO;
}, false),
ellipse: {
semiMajorAxis: radius,
semiMinorAxis: radius,
material: Cesium.Color.fromCssColorString(color).withAlpha(opacity),
arcType: Cesium.ArcType.NONE
},
polyline: {
positions: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const center = mc || that.getAirspaceCenter(entityData);
if (!center) return [];
return that.generateCirclePositions(center, radius, 64);
}, false),
width,
material: Cesium.Color.fromCssColorString(borderColor),
arcType: Cesium.ArcType.NONE
}
});
break;
}
case 'sector': {
const radius = entityData.radius || 1000;
const startAngle = entityData.startAngle != null ? entityData.startAngle : 0;
const endAngle = entityData.endAngle != null ? entityData.endAngle : Math.PI * 0.5;
this.airspacePositionEditPreviewEntity = this.viewer.entities.add({
polygon: {
hierarchy: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const center = mc || that.getAirspaceCenter(entityData);
if (!center) return new Cesium.PolygonHierarchy([]);
const positions = that.generateSectorPositions(center, radius, startAngle, endAngle, 64);
return new Cesium.PolygonHierarchy(positions);
}, false),
material: Cesium.Color.fromCssColorString(color).withAlpha(opacity)
},
polyline: {
positions: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const center = mc || that.getAirspaceCenter(entityData);
if (!center) return [];
return that.generateSectorPositions(center, radius, startAngle, endAngle, 64);
}, false),
width,
material: Cesium.Color.fromCssColorString(borderColor),
arcType: Cesium.ArcType.NONE
}
});
break;
}
case 'arrow': {
const arrowColor = entityData.color || this.defaultStyles.arrow.color;
this.airspacePositionEditPreviewEntity = this.viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(() => {
const mc = that.airspacePositionEditContext?.mouseCartesian;
const oldCenter = that.getAirspaceCenter(entityData);
if (!mc || !oldCenter || !entityData.positions || entityData.positions.length < 2) return entityData.positions || [];
const delta = Cesium.Cartesian3.subtract(mc, oldCenter, new Cesium.Cartesian3());
const first = entityData.positions[0];
const last = entityData.positions[entityData.positions.length - 1];
return [
Cesium.Cartesian3.add(first, delta, new Cesium.Cartesian3()),
Cesium.Cartesian3.add(last, delta, new Cesium.Cartesian3())
];
}, false),
width: 12,
material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(arrowColor)),
arcType: Cesium.ArcType.NONE,
widthInMeters: false
}
});
break;
}
}
},
/** 获取空域图形的中心点(笛卡尔坐标) */
getAirspaceCenter(entityData) {
if (!entityData) return null;
switch (entityData.type) {
case 'polygon':
if (entityData.positions && entityData.positions.length > 0) {
const sum = entityData.positions.reduce((acc, p) => Cesium.Cartesian3.add(acc, p, new Cesium.Cartesian3()), new Cesium.Cartesian3());
return Cesium.Cartesian3.divideByScalar(sum, entityData.positions.length, new Cesium.Cartesian3());
}
break;
case 'rectangle':
if (entityData.entity && entityData.entity.rectangle && entityData.entity.rectangle.coordinates) {
const rect = entityData.entity.rectangle.coordinates.getValue(Cesium.JulianDate.now());
if (rect) {
const west = rect.west, south = rect.south, east = rect.east, north = rect.north;
return Cesium.Cartesian3.fromRadians((west + east) / 2, (south + north) / 2);
}
}
if (entityData.points && entityData.points.length >= 2) {
const lngs = entityData.points.map(p => p.lng), lats = entityData.points.map(p => p.lat);
return Cesium.Cartesian3.fromDegrees((Math.min(...lngs) + Math.max(...lngs)) / 2, (Math.min(...lats) + Math.max(...lats)) / 2);
}
break;
case 'circle':
if (entityData.entity && entityData.entity.position) {
return entityData.entity.position.getValue(Cesium.JulianDate.now());
}
if (entityData.points && entityData.points[0]) {
return Cesium.Cartesian3.fromDegrees(entityData.points[0].lng, entityData.points[0].lat);
}
break;
case 'sector':
if (entityData.center) {
return Cesium.Cartesian3.fromDegrees(entityData.center.lng, entityData.center.lat);
}
if (entityData.positions && entityData.positions.length > 0) {
const sum = entityData.positions.reduce((acc, p) => Cesium.Cartesian3.add(acc, p, new Cesium.Cartesian3()), new Cesium.Cartesian3());
return Cesium.Cartesian3.divideByScalar(sum, entityData.positions.length, new Cesium.Cartesian3());
}
break;
case 'arrow':
if (entityData.positions && entityData.positions.length >= 2) {
const sum = entityData.positions.reduce((acc, p) => Cesium.Cartesian3.add(acc, p, new Cesium.Cartesian3()), new Cesium.Cartesian3());
return Cesium.Cartesian3.divideByScalar(sum, entityData.positions.length, new Cesium.Cartesian3());
}
break;
}
return null;
},
/** 应用空域位置调整并退出模式 */
applyAirspacePositionEdit(newCenter) {
const ctx = this.airspacePositionEditContext;
if (!ctx || !ctx.entityData) return;
const entityData = ctx.entityData;
// 穿/
if (this.airspacePositionEditPreviewEntity) {
this.viewer.entities.remove(this.airspacePositionEditPreviewEntity);
this.airspacePositionEditPreviewEntity = null;
}
const oldCenter = this.getAirspaceCenter(entityData);
if (!oldCenter) return;
const delta = Cesium.Cartesian3.subtract(newCenter, oldCenter, new Cesium.Cartesian3());
const oldCarto = Cesium.Cartographic.fromCartesian(oldCenter);
const newCarto = Cesium.Cartographic.fromCartesian(newCenter);
const dLon = newCarto.longitude - oldCarto.longitude;
const dLat = newCarto.latitude - oldCarto.latitude;
switch (entityData.type) {
case 'polygon':
if (entityData.positions && entityData.positions.length > 0) {
entityData.positions = entityData.positions.map(p => Cesium.Cartesian3.add(p, delta, new Cesium.Cartesian3()));
entityData.points = entityData.positions.map(p => this.cartesianToLatLng(p));
const closed = [...entityData.positions, entityData.positions[0]];
entityData.entity.polygon.hierarchy = new Cesium.PolygonHierarchy(entityData.positions);
entityData.entity.polyline.positions = closed;
}
break;
case 'rectangle': {
const rect = entityData.entity.rectangle.coordinates.getValue(Cesium.JulianDate.now());
if (rect) {
const newWest = Cesium.Math.negativePiToPi(rect.west + dLon);
const newEast = Cesium.Math.negativePiToPi(rect.east + dLon);
const newSouth = Math.max(-Cesium.Math.PI_OVER_TWO, Math.min(Cesium.Math.PI_OVER_TWO, rect.south + dLat));
const newNorth = Math.max(-Cesium.Math.PI_OVER_TWO, Math.min(Cesium.Math.PI_OVER_TWO, rect.north + dLat));
const newRect = new Cesium.Rectangle(newWest, newSouth, newEast, newNorth);
entityData.entity.rectangle.coordinates = newRect;
const sw = Cesium.Cartesian3.fromRadians(newRect.west, newRect.south);
const se = Cesium.Cartesian3.fromRadians(newRect.east, newRect.south);
const ne = Cesium.Cartesian3.fromRadians(newRect.east, newRect.north);
const nw = Cesium.Cartesian3.fromRadians(newRect.west, newRect.north);
entityData.entity.polyline.positions = [sw, se, ne, nw, sw];
entityData.points = [this.cartesianToLatLng(sw), this.cartesianToLatLng(se), this.cartesianToLatLng(ne), this.cartesianToLatLng(nw)];
}
break;
}
case 'circle':
entityData.entity.position = newCenter;
const radius = entityData.radius || 1000;
entityData.entity.polyline.positions = this.generateCirclePositions(newCenter, radius);
entityData.points = [this.cartesianToLatLng(newCenter), entityData.points && entityData.points[1] ? entityData.points[1] : this.cartesianToLatLng(newCenter)];
break;
case 'sector': {
const newCenterLL = this.cartesianToLatLng(newCenter);
entityData.center = newCenterLL;
const r = entityData.radius || 1000;
const sa = entityData.startAngle != null ? entityData.startAngle : 0;
const ea = entityData.endAngle != null ? entityData.endAngle : Math.PI * 0.5;
const positions = this.generateSectorPositions(newCenter, r, sa, ea);
entityData.positions = positions;
entityData.entity.polygon.hierarchy = new Cesium.PolygonHierarchy(positions);
entityData.entity.polyline.positions = positions;
break;
}
case 'arrow':
if (entityData.positions && entityData.positions.length >= 2) {
const first = entityData.positions[0];
const last = entityData.positions[entityData.positions.length - 1];
const newFirst = Cesium.Cartesian3.add(first, delta, new Cesium.Cartesian3());
const newLast = Cesium.Cartesian3.add(last, delta, new Cesium.Cartesian3());
const arrowPositions = [newFirst, newLast];
const arrowColor = entityData.color || this.defaultStyles.arrow.color;
const oldEntity = entityData.entity;
this.viewer.entities.remove(oldEntity);
const newEntity = this.viewer.entities.add({
id: oldEntity.id,
name: oldEntity.name,
polyline: {
positions: arrowPositions,
width: 12,
material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(arrowColor)),
arcType: Cesium.ArcType.NONE,
widthInMeters: false
}
});
entityData.entity = newEntity;
entityData.positions = arrowPositions;
entityData.points = [this.cartesianToLatLng(newFirst), this.cartesianToLatLng(newLast)];
newEntity.clickHandler = (e) => {
this.selectEntity(entityData);
e.stopPropagation();
};
}
break;
}
entityData.entity.show = true;
this.notifyDrawingEntitiesChanged();
},
/** 清除空域位置调整模式 */
clearAirspacePositionEdit() {
if (this.airspacePositionEditPreviewEntity) {
this.viewer.entities.remove(this.airspacePositionEditPreviewEntity);
this.airspacePositionEditPreviewEntity = null;
}
if (this.airspacePositionEditContext && this.airspacePositionEditContext.entityData) {
this.airspacePositionEditContext.entityData.entity.show = true;
}
this.airspacePositionEditContext = null;
if (this.viewer.scene.requestRender) this.viewer.scene.requestRender();
},
toggleRouteLock() {
const ed = this.contextMenu.entityData;
if (!ed || ed.type !== 'route' || ed.routeId == null) {
@ -7424,6 +7856,10 @@ export default {
if (property === 'color' && (entityData.type === 'polygon' || entityData.type === 'rectangle' || entityData.type === 'circle' || entityData.type === 'sector' || entityData.type === 'powerZone')) {
entityData.opacity = 0.2
}
// ///
if (property === 'name' && ['polygon', 'rectangle', 'circle', 'sector'].includes(entityData.type)) {
this.updateAirspaceEntityLabel(entityData)
}
//
this.updateEntityStyle(entityData)
// /
@ -7723,8 +8159,9 @@ export default {
data = {
points: entity.points || [],
opacity: entity.opacity != null ? entity.opacity : 0,
width: entity.width != null ? entity.width : 4,
borderColor: entity.borderColor || entity.color
width: entity.width != null ? entity.width : 2,
borderColor: entity.borderColor || entity.color,
name: entity.name || ''
}; break
case 'rectangle':
if (entity.points && entity.points.length >= 2) {
@ -7734,16 +8171,18 @@ export default {
coordinates: { west: Math.min(...lngs), south: Math.min(...lats), east: Math.max(...lngs), north: Math.max(...lats) },
points: entity.points,
opacity: entity.opacity != null ? entity.opacity : 0,
width: entity.width != null ? entity.width : 4,
borderColor: entity.borderColor || entity.color
width: entity.width != null ? entity.width : 2,
borderColor: entity.borderColor || entity.color,
name: entity.name || ''
}
} else {
data = {
coordinates: entity.coordinates || {},
points: entity.points || [],
opacity: entity.opacity != null ? entity.opacity : 0,
width: entity.width != null ? entity.width : 4,
borderColor: entity.borderColor || entity.color
width: entity.width != null ? entity.width : 2,
borderColor: entity.borderColor || entity.color,
name: entity.name || ''
}
}
break
@ -7753,8 +8192,9 @@ export default {
center: entity.points && entity.points[0] ? entity.points[0] : (entity.positions && entity.positions[0] ? this.cartesianToLatLng(entity.positions[0]) : (entity.center && typeof entity.center.lat === 'number' ? entity.center : null)),
radius: entity.radius,
opacity: entity.opacity != null ? entity.opacity : 0,
width: entity.width != null ? entity.width : 4,
borderColor: entity.borderColor || entity.color
width: entity.width != null ? entity.width : 2,
borderColor: entity.borderColor || entity.color,
name: entity.name || ''
}; break
case 'ellipse':
case 'hold_ellipse':
@ -7771,8 +8211,9 @@ export default {
startAngle: entity.startAngle,
endAngle: entity.endAngle,
opacity: entity.opacity != null ? entity.opacity : 0,
width: entity.width != null ? entity.width : 3,
borderColor: entity.borderColor || entity.color
width: entity.width != null ? entity.width : 2,
borderColor: entity.borderColor || entity.color,
name: entity.name || ''
}; break
case 'arrow':
data = { points: entity.points || [] }; break
@ -8024,7 +8465,7 @@ export default {
case 'polygon': {
const polygonPositions = entityData.data.points.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat))
const polyOpacity = entityData.data.opacity != null ? entityData.data.opacity : 0
const polyWidth = entityData.data.width != null ? entityData.data.width : 4
const polyWidth = entityData.data.width != null ? entityData.data.width : 2
const polyBorderColor = entityData.data.borderColor || color
entity = this.viewer.entities.add({
polygon: {
@ -8038,7 +8479,23 @@ export default {
arcType: Cesium.ArcType.NONE
}
})
break
const polyEntityData = {
id: entity.id,
type: 'polygon',
points: entityData.data.points,
positions: polygonPositions,
entity,
color,
borderColor: polyBorderColor,
opacity: polyOpacity,
width: polyWidth,
label: entityData.label || '面',
name: entityData.data.name || ''
}
this.allEntities.push(polyEntityData)
if (polyEntityData.name) this.updateAirspaceEntityLabel(polyEntityData)
this.notifyDrawingEntitiesChanged()
return
}
case 'rectangle': {
let rectCoords = entityData.data.coordinates
@ -8049,7 +8506,7 @@ export default {
}
if (!rectCoords) break
const rectOpacity = entityData.data.opacity != null ? entityData.data.opacity : 0
const rectWidth = entityData.data.width != null ? entityData.data.width : 4
const rectWidth = entityData.data.width != null ? entityData.data.width : 2
const rectBorderColor = entityData.data.borderColor || color
const rectColor = Cesium.Color.fromCssColorString(color).withAlpha(rectOpacity)
const southwest = Cesium.Cartesian3.fromDegrees(rectCoords.west, rectCoords.south)
@ -8069,7 +8526,7 @@ export default {
arcType: Cesium.ArcType.NONE
}
})
this.allEntities.push({
const rectEntityData = {
id: entity.id,
type: 'rectangle',
points: entityData.data.points || [],
@ -8079,8 +8536,11 @@ export default {
borderColor: rectBorderColor,
opacity: rectOpacity,
width: rectWidth,
label: entityData.label || '矩形'
})
label: entityData.label || '矩形',
name: entityData.data.name || ''
}
this.allEntities.push(rectEntityData)
if (rectEntityData.name) this.updateAirspaceEntityLabel(rectEntityData)
return
}
case 'circle': {
@ -8092,7 +8552,7 @@ export default {
const circleCenter = Cesium.Cartesian3.fromDegrees(entityData.data.center.lng, entityData.data.center.lat)
const circlePositions = this.generateCirclePositions(circleCenter, radius)
const circleOpacity = entityData.data.opacity != null ? entityData.data.opacity : 0
const circleWidth = entityData.data.width != null ? entityData.data.width : 4
const circleWidth = entityData.data.width != null ? entityData.data.width : 2
const circleBorderColor = entityData.data.borderColor || color
entity = this.viewer.entities.add({
position: circleCenter,
@ -8109,7 +8569,24 @@ export default {
arcType: Cesium.ArcType.NONE
}
})
break
const circleEntityData = {
id: entity.id,
type: 'circle',
points: [entityData.data.center],
positions: [circleCenter],
entity,
radius,
color,
borderColor: circleBorderColor,
opacity: circleOpacity,
width: circleWidth,
label: entityData.label || '圆形',
name: entityData.data.name || ''
}
this.allEntities.push(circleEntityData)
if (circleEntityData.name) this.updateAirspaceEntityLabel(circleEntityData)
this.notifyDrawingEntitiesChanged()
return
}
case 'hold_circle': {
const hcRadius = entityData.data.radius || 1000
@ -8182,7 +8659,7 @@ export default {
const startAngle = d.startAngle != null ? d.startAngle : 0
const endAngle = d.endAngle != null ? d.endAngle : Math.PI * 0.5
const sectorOpacity = d.opacity != null ? d.opacity : 0
const sectorWidth = d.width != null ? d.width : 3
const sectorWidth = d.width != null ? d.width : 2
const sectorBorderColor = d.borderColor || color
const positions = this.generateSectorPositions(center, d.radius, startAngle, endAngle)
entity = this.viewer.entities.add({
@ -8197,7 +8674,7 @@ export default {
arcType: Cesium.ArcType.NONE
}
})
this.allEntities.push({
const sectorEntityData = {
id: entity.id,
type: 'sector',
center: d.center,
@ -8210,15 +8687,19 @@ export default {
borderColor: sectorBorderColor,
opacity: sectorOpacity,
width: sectorWidth,
label: entityData.label || '扇形'
})
label: entityData.label || '扇形',
name: entityData.data.name || ''
}
this.allEntities.push(sectorEntityData)
if (sectorEntityData.name) this.updateAirspaceEntityLabel(sectorEntityData)
this.notifyDrawingEntitiesChanged()
return
}
case 'arrow': {
const pts = entityData.data.points
if (!pts || pts.length < 2) break
const arrowPositions = pts.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat))
const allPositions = pts.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat))
const arrowPositions = allPositions.length === 2 ? allPositions : [allPositions[0], allPositions[allPositions.length - 1]]
entity = this.viewer.entities.add({
polyline: {
positions: arrowPositions,
@ -8231,7 +8712,7 @@ export default {
this.allEntities.push({
id: entity.id,
type: 'arrow',
points: pts,
points: [pts[0], pts[pts.length - 1]],
positions: arrowPositions,
entity,
color,
@ -8353,14 +8834,18 @@ export default {
}
}
if (entity) {
this.allEntities.push({
const pushed = {
id: entity.id,
type: entityData.type,
label: entityData.label,
color: color,
entity,
...entityData.data
})
}
this.allEntities.push(pushed)
if (['polygon', 'circle'].includes(entityData.type) && pushed.name) {
this.updateAirspaceEntityLabel(pushed)
}
if (this.getDrawingEntityTypes().includes(entityData.type)) this.notifyDrawingEntitiesChanged()
}
},

Loading…
Cancel
Save