@ -47,6 +47,7 @@
@ power - zone = "openPowerZoneDialog"
@ open - waypoint - dialog = "handleContextMenuOpenWaypointDialog"
@ add - waypoint - at = "handleAddWaypointAt"
@ toggle - waypoint - hold = "handleToggleWaypointHold"
/ >
<!-- 定位弹窗 -- >
@ -91,6 +92,7 @@
: max = "32"
controls - position = "right"
style = "width: 100%;"
@ change = "handleEditPlatformFormChange"
/ >
< / e l - f o r m - i t e m >
< el -form -item label = "字体颜色" >
@ -98,6 +100,7 @@
v - model = "editPlatformForm.fontColor"
size = "small"
: predefine = "presetColors"
@ change = "handleEditPlatformFormChange"
/ >
< / e l - f o r m - i t e m >
@ -109,6 +112,7 @@
: max = "256"
controls - position = "right"
style = "width: 100%;"
@ change = "handleEditPlatformFormChange"
/ >
< / e l - f o r m - i t e m >
< el -form -item label = "平台颜色" >
@ -116,11 +120,12 @@
v - model = "editPlatformForm.iconColor"
size = "small"
: predefine = "presetColors"
@ change = "handleEditPlatformFormChange"
/ >
< / e l - f o r m - i t e m >
< / e l - f o r m >
< span slot = "footer" class = "dialog-footer" >
< el -button @ click = "editPlatformDialogVisible = false" > 取 消 < / e l - b u t t o n >
< el -button @click ="cancelEditPlatform" > 取 消 < / el -button >
< el -button type = "primary" @click ="applyEditPlatform" > 确 定 < / el -button >
< / span >
< / e l - d i a l o g >
@ -240,6 +245,7 @@ export default {
missionHoldParamsByIndex : { } ,
missionPendingHold : null ,
tempHoldEntity : null ,
tempHoldOutlineEntity : null , / / 盘 旋 圆 / 椭 圆 轮 廓
activeCursorPosition : null , / / 实 时 鼠 标 位 置
/ / 实 体 管 理
allEntities : [ ] , / / 所 有 绘 制 的 实 体
@ -274,6 +280,8 @@ export default {
iconSize : 144 ,
iconColor : '#000000'
} ,
/** 编辑平台属性时用于还原的原始样式快照(只影响预览,不直接改缓存与后端) */
editPlatformOriginalStyle : null ,
/ / 编 辑 平 台 属 性 : 字 体 颜 色 、 平 台 颜 色 预 选
presetColors : [
'#000000' , '#333333' , '#666666' , '#999999' , '#FFFFFF' ,
@ -474,6 +482,94 @@ export default {
} , 1000 )
} ,
/** 编辑平台属性表单变更时,仅做实时预览(不保存到缓存与后端) */
handleEditPlatformFormChange ( ) {
const routeId = this . editPlatformForm . routeId
if ( ! routeId || ! this . viewer || ! this . viewer . entities ) return
const fontSize = Math . max ( 10 , Math . min ( 32 , Number ( this . editPlatformForm . fontSize ) || 16 ) )
const fontColor = this . editPlatformForm . fontColor || '#333333'
const iconSize = Math . max ( 48 , Math . min ( 256 , Number ( this . editPlatformForm . iconSize ) || 144 ) )
const iconColor = this . editPlatformForm . iconColor || '#000000'
/ / 实 时 更 新 标 牌 外 观
const labelEntity = this . viewer . entities . getById ( ` route-platform-label- ${ routeId } ` )
if ( labelEntity ) {
if ( labelEntity . billboard ) {
const data = labelEntity . labelDataCache || { name : '平台' , altitude : 0 , speed : 0 , headingDeg : 0 }
const labelResult = this . createRoundedLabelCanvas ( {
name : data . name ,
altitude : data . altitude ,
speed : data . speed ,
heading : data . headingDeg ,
fontSize ,
fontColor
} )
labelEntity . billboard . image = new Cesium . ConstantProperty ( labelResult . canvas )
labelEntity . billboard . scale = labelResult . scale
} else if ( labelEntity . label ) {
labelEntity . label . font = ` ${ fontSize } px Microsoft YaHei `
labelEntity . label . fillColor = Cesium . Color . fromCssColorString ( fontColor )
labelEntity . label . backgroundColor = Cesium . Color . fromCssColorString ( 'rgba(255, 255, 255, 0.6)' )
}
}
/ / 实 时 更 新 平 台 外 观
const platformEntity = this . viewer . entities . getById ( ` route-platform- ${ routeId } ` )
if ( platformEntity && platformEntity . billboard ) {
platformEntity . billboard . width = iconSize
platformEntity . billboard . height = iconSize
platformEntity . billboard . color = Cesium . Color . fromCssColorString ( iconColor )
}
if ( this . viewer . scene && this . viewer . scene . requestRenderMode ) {
this . viewer . scene . requestRender ( )
}
} ,
/** 取消编辑平台属性:还原到打开弹窗前的样式,只关闭弹窗不保存 */
cancelEditPlatform ( ) {
const snapshot = this . editPlatformOriginalStyle
if ( snapshot && snapshot . routeId && this . viewer && this . viewer . entities ) {
const { routeId , fontSize , fontColor , iconSize , iconColor } = snapshot
const labelEntity = this . viewer . entities . getById ( ` route-platform-label- ${ routeId } ` )
if ( labelEntity ) {
if ( labelEntity . billboard ) {
const data = labelEntity . labelDataCache || { name : '平台' , altitude : 0 , speed : 0 , headingDeg : 0 }
const labelResult = this . createRoundedLabelCanvas ( {
name : data . name ,
altitude : data . altitude ,
speed : data . speed ,
heading : data . headingDeg ,
fontSize ,
fontColor
} )
labelEntity . billboard . image = new Cesium . ConstantProperty ( labelResult . canvas )
labelEntity . billboard . scale = labelResult . scale
} else if ( labelEntity . label ) {
labelEntity . label . font = ` ${ fontSize } px Microsoft YaHei `
labelEntity . label . fillColor = Cesium . Color . fromCssColorString ( fontColor )
labelEntity . label . backgroundColor = Cesium . Color . fromCssColorString ( 'rgba(255, 255, 255, 0.6)' )
}
}
const platformEntity = this . viewer . entities . getById ( ` route-platform- ${ routeId } ` )
if ( platformEntity && platformEntity . billboard ) {
platformEntity . billboard . width = iconSize
platformEntity . billboard . height = iconSize
platformEntity . billboard . color = Cesium . Color . fromCssColorString ( iconColor )
}
if ( this . viewer . scene && this . viewer . scene . requestRenderMode ) {
this . viewer . scene . requestRender ( )
}
}
this . editPlatformDialogVisible = false
this . editPlatformOriginalStyle = null
} ,
applyScaleToCamera ( metersPerPixel ) {
if ( ! this . viewer || ! this . viewer . camera ) return
@ -924,9 +1020,14 @@ export default {
setTimeout ( ( ) => window . removeEventListener ( 'contextmenu' , this . preventContextMenu , true ) , 200 ) ;
return ;
}
let pointsToEmit = this . drawingPoints ;
let pointsToEmit ;
if ( this . missionPendingHold && this . drawingPoints . length >= 2 ) {
pointsToEmit = this . getMissionRouteSolidPositions ( ) ;
} else {
pointsToEmit = [ ... this . drawingPoints ] ;
}
if ( pr . mode === 'before' ) {
if ( this . drawingPoints . length < 1 ) {
if ( pointsToEmit . length < 1 ) {
this . $message && this . $message . info ( '已取消' ) ;
this . platformRouteDrawing = null ;
this . stopDrawing ( ) ;
@ -935,7 +1036,7 @@ export default {
return ;
}
/ / 顺 序 反 转 : 先 点 的 为 倒 数 第 二 个 点 , 最 后 点 的 为 起 点 ; 平 台 为 最 后 一 个 点
pointsToEmit = [ ... this . drawingPoints ] . reverse ( ) ;
pointsToEmit = [ ... pointsToEmit ] . reverse ( ) ;
pointsToEmit . push ( platformCartesian ) ;
const lastId = ` temp_wp_ ${ pointsToEmit . length } ` ;
this . viewer . entities . add ( {
@ -970,16 +1071,22 @@ export default {
return ;
}
const latLngPoints = [ ] ;
const holdCenter = this . missionPendingHold ? this . missionPendingHold . center : null ;
pointsToEmit . forEach ( ( pos , i ) => {
const coords = this . cartesianToLatLng ( pos ) ;
const name = ( pr . mode === 'after' && i === 0 ) || ( pr . mode === 'before' && i === pointsToEmit . length - 1 ) ? pr . platformName : ` WP ${ i + 1 } ` ;
const isPlatform = ( pr . mode === 'after' && i === 0 ) || ( pr . mode === 'before' && i === pointsToEmit . length - 1 ) ;
const isHold = holdCenter && Cesium . Cartesian3 . equalsEpsilon ( pos , holdCenter , 0.1 ) ;
latLngPoints . push ( {
id : i + 1 ,
name ,
name : isPlatform ? pr . platformName : ( isHold ? 'HOLD' : ` WP ${ i + 1 } ` ) ,
lat : coords . lat ,
lng : coords . lng ,
alt : 5000 ,
speed : 800
speed : 800 ,
... ( isHold && {
pointType : this . missionPendingHold . params . radius != null ? 'hold_circle' : 'hold_ellipse' ,
holdParams : JSON . stringify ( this . missionPendingHold . params )
} )
} ) ;
} ) ;
this . $emit ( 'draw-complete' , latLngPoints , pr . platformInfo ) ;
@ -1002,16 +1109,41 @@ export default {
center : Cesium . Cartesian3 . clone ( last ) ,
params : holdParams
} ;
if ( this . tempHoldOutlineEntity ) {
try { this . viewer . entities . remove ( this . tempHoldOutlineEntity ) ; } catch ( e ) { }
this . tempHoldOutlineEntity = null ;
}
if ( this . tempHoldEntity ) {
try { this . viewer . entities . remove ( this . tempHoldEntity ) ; } catch ( e ) { }
this . tempHoldEntity = null ;
}
const center = this . missionPendingHold . center ;
const p = holdParams ;
const isCircle = p . radius != null ;
const radius = isCircle ? ( p . radius || 500 ) : 500 ;
const semiMajor = ! isCircle ? ( p . semiMajor ? ? p . semiMajorAxis ? ? 500 ) : radius ;
const semiMinor = ! isCircle ? ( p . semiMinor ? ? p . semiMinorAxis ? ? 300 ) : radius ;
const headingRad = ! isCircle ? ( ( p . headingDeg ? ? 0 ) * Math . PI ) / 180 : 0 ;
this . tempHoldOutlineEntity = this . viewer . entities . add ( {
id : 'temp_hold_outline' ,
position : center ,
ellipse : {
semiMajorAxis : semiMajor ,
semiMinorAxis : semiMinor ,
rotation : headingRad ,
material : Cesium . Color . TRANSPARENT ,
outline : true ,
outlineColor : Cesium . Color . ORANGE . withAlpha ( 0.8 ) ,
outlineWidth : 2 ,
arcType : Cesium . ArcType . NONE
}
} ) ;
this . tempHoldEntity = this . viewer . entities . add ( {
id : 'temp_hold_preview' ,
name : 'HOLD' ,
position : this . missionPendingHold . center ,
position : center ,
point : { pixelSize : 10 , color : Cesium . Color . ORANGE , outlineColor : Cesium . Color . WHITE , outlineWidth : 2 , disableDepthTestDistance : Number . POSITIVE_INFINITY } ,
label : { text : 'HOLD' , font : '14px Microsoft YaHei' , fillColor : Cesium . Color . ORANGE , outlineColor : Cesium . Color . BLACK , outlineWidth : 1 }
label : { text : '盘旋 ' , font : '14px Microsoft YaHei' , pixelOffset : new Cesium . Cartesian2 ( 0 , - 20 ) , fillColor : Cesium . Color . ORANGE , outlineColor : Cesium . Color . BLACK , outlineWidth : 1 }
} ) ;
/ / 更 新 实 线 预 览 ( 含 盘 旋 点 )
if ( this . tempEntity ) {
@ -1132,10 +1264,10 @@ export default {
const colorLabel = '#888888' ; / / 属 性 名 灰 色
const colorValue = fontColor ; / / 属 性 值 ( 默 认 黑 , 可 配 置 )
/ / 文 本 内 容
const labelAlt = '高度 : ' ;
const labelSpeed = ' 速度 : ' ;
const labelHeading = ' 航向 : ' ;
/ / 文 本 内 容 ( h : 高 度 , v : 速 度 , s : 航 向 )
const labelAlt = 'h : ' ;
const labelSpeed = ' v : ' ;
const labelHeading = ' s : ' ;
const textAlt = altitude + 'm' ;
const textSpeed = speed + 'km/h' ;
const textHeading = Math . round ( heading ) + '°' ;
@ -1619,9 +1751,8 @@ export default {
}
return ! ! nextLogical ;
} ;
/ / 遍 历 并 绘 制 航 点 标 记 : 转 弯 半 径 处 不 画 中 心 点 ; 盘 旋 处 在 圆 心 画 一 小 点 便 于 右 键 “ 向 前 / 向 后 增 加 航 点 ”
/ / 遍 历 并 绘 制 航 点 标 记 : 转 弯 半 径 处 也 画 中 心 点 + 标 签 ( 与 普 通 航 点 一 致 ) ; 盘 旋 处 在 圆 心 画 点 + 标 签
waypoints . forEach ( ( wp , index ) => {
if ( isTurnWaypointWithArc ( index ) ) return ;
const pos = originalPositions [ index ] ;
if ( this . isHoldWaypoint ( wp ) ) {
this . viewer . entities . add ( {
@ -1640,7 +1771,15 @@ export default {
outlineWidth : wpOutlineW ,
disableDepthTestDistance : Number . POSITIVE_INFINITY
} ,
label : { show : false }
label : {
text : wp . name || ` 盘旋 ${ index + 1 } ` ,
font : ` ${ wp . labelFontSize != null ? Math . min ( 28 , Math . max ( 10 , Number ( wp . labelFontSize ) ) ) : 14 } px PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif ` ,
pixelOffset : new Cesium . Cartesian2 ( 0 , - Math . max ( 14 , pixelSize + 8 ) ) ,
fillColor : Cesium . Color . fromCssColorString ( wp . labelColor || '#2c2c2c' ) ,
outlineColor : Cesium . Color . fromCssColorString ( '#e8e8e8' ) ,
outlineWidth : 0.5 ,
style : Cesium . LabelStyle . FILL_AND_OUTLINE
}
} ) ;
return ;
}
@ -1849,7 +1988,7 @@ export default {
const exit = params && params . radius != null
? this . getCircleTangentExitPoint ( currPos , nextPos || currPos , radius , clockwise )
: this . getEllipseTangentExitPoint ( currPos , nextPos || currPos , semiMajor , semiMinor , headingRad , clockwise ) ;
finalPathPositions . push ( entry ) ;
let fullCirclePoints ;
let arcPoints ;
if ( params && params . radius != null ) {
const enu = Cesium . Transforms . eastNorthUpToFixedFrame ( currPos ) ;
@ -1857,7 +1996,8 @@ export default {
const north = Cesium . Matrix4 . getColumn ( enu , 1 , new Cesium . Cartesian3 ( ) ) ;
const toEntry = Cesium . Cartesian3 . subtract ( entry , currPos , new Cesium . Cartesian3 ( ) ) ;
const entryAngle = Math . atan2 ( Cesium . Cartesian3 . dot ( toEntry , east ) , Cesium . Cartesian3 . dot ( toEntry , north ) ) ;
arcPoints = this . getCircleFullCircle ( currPos , radius , entryAngle , clockwise , 48 ) ;
fullCirclePoints = this . getCircleFullCircle ( currPos , radius , entryAngle , clockwise , 48 ) ;
arcPoints = this . getCircleArcEntryToExit ( currPos , radius , entry , exit , clockwise , 48 ) ;
} else {
const enuE = Cesium . Transforms . eastNorthUpToFixedFrame ( currPos ) ;
const eastE = Cesium . Matrix4 . getColumn ( enuE , 0 , new Cesium . Cartesian3 ( ) ) ;
@ -1865,15 +2005,17 @@ export default {
const toEntryE = Cesium . Cartesian3 . subtract ( entry , currPos , new Cesium . Cartesian3 ( ) ) ;
const thetaE = Math . atan2 ( Cesium . Cartesian3 . dot ( toEntryE , eastE ) , Cesium . Cartesian3 . dot ( toEntryE , northE ) ) ;
const entryLocalAngle = thetaE - headingRad ;
arcPoints = this . getEllipseFullCircle ( currPos , semiMajor , semiMinor , headingRad , entryLocalAngle , clockwise , 48 ) ;
fullCirclePoints = this . getEllipseFullCircle ( currPos , semiMajor , semiMinor , headingRad , entryLocalAngle , clockwise , 48 ) ;
arcPoints = this . getEllipseArcEntryToExit ( currPos , semiMajor , semiMinor , headingRad , entry , exit , clockwise , 48 ) ;
}
for ( let k = 1 ; k < arcPoints . length ; k ++ ) finalPathPositions . push ( arcPoints [ k ] ) ;
finalPathPositions . push ( exit ) ;
/ / 整 圈 + e n t r y → e x i t 弧 段 , 避 免 弦 线 : e n t r y → 整 圈 ( 回 到 e n t r y ) → 弧 段 到 e x i t
const holdPositions = [ entry , ... fullCirclePoints . slice ( 1 ) , ... arcPoints . slice ( 1 ) ] ;
for ( let k = 0 ; k < holdPositions . length ; k ++ ) finalPathPositions . push ( holdPositions [ k ] ) ;
/ / 盘 旋 不 单 独 着 色 : 仅 作 为 主 航 线 取 点 数 据 源 , s h o w : f a l s e 由 主 航 线 折 线 用 l i n e W i d t h / l i n e M a t e r i a l 统 一 绘 制
this . viewer . entities . add ( {
id : ` hold-line- ${ routeId } - ${ i } ` ,
show : false ,
polyline : { positions : [ entry , ... arcPoints . slice ( 1 ) , exit ] , width : lineWidth , material : lineMaterial , arcType : Cesium . ArcType . NONE , zIndex : 20 } ,
polyline : { positions : holdPositions , width : lineWidth , material : lineMaterial , arcType : Cesium . ArcType . NONE , zIndex : 20 } ,
properties : { routeId : routeId }
} ) ;
lastPos = exit ;
@ -2022,22 +2164,16 @@ export default {
}
} ,
/** 圆上从 entry 到 exit 的弧段(按顺时针/逆时针),采样点数 */
getCircleArcEntryToExit ( centerCartesian , radiusMeters , entryCartesian , exitCartesian , clockwise , numPoints ) {
/** 圆上整圈(360°)采样,从 startAngleRad 起按顺时针/逆时针,用于盘旋段渲染为整圆 */
getCircleFullCircle ( centerCartesian , radiusMeters , startAngleRad , clockwise , numPoints ) {
const enu = Cesium . Transforms . eastNorthUpToFixedFrame ( centerCartesian ) ;
const east = Cesium . Matrix4 . getColumn ( enu , 0 , new Cesium . Cartesian3 ( ) ) ;
const north = Cesium . Matrix4 . getColumn ( enu , 1 , new Cesium . Cartesian3 ( ) ) ;
const toEntry = Cesium . Cartesian3 . subtract ( entryCartesian , centerCartesian , new Cesium . Cartesian3 ( ) ) ;
const toExit = Cesium . Cartesian3 . subtract ( exitCartesian , centerCartesian , new Cesium . Cartesian3 ( ) ) ;
let entryAngle = Math . atan2 ( Cesium . Cartesian3 . dot ( toEntry , east ) , Cesium . Cartesian3 . dot ( toEntry , north ) ) ;
let exitAngle = Math . atan2 ( Cesium . Cartesian3 . dot ( toExit , east ) , Cesium . Cartesian3 . dot ( toExit , north ) ) ;
let diff = exitAngle - entryAngle ;
const sign = clockwise ? - 1 : 1 ;
if ( sign * diff <= 0 ) diff += sign * 2 * Math . PI ;
const points = [ ] ;
for ( let i = 0 ; i <= numPoints ; i ++ ) {
const t = i / numPoints ;
const angle = entryAngle + sign * t * Math . abs ( diff ) ;
const angle = startAngleRad + sign * t * 2 * Math . PI ;
const offset = Cesium . Cartesian3 . add (
Cesium . Cartesian3 . multiplyByScalar ( north , Math . cos ( angle ) * radiusMeters , new Cesium . Cartesian3 ( ) ) ,
Cesium . Cartesian3 . multiplyByScalar ( east , Math . sin ( angle ) * radiusMeters , new Cesium . Cartesian3 ( ) ) ,
@ -2048,16 +2184,24 @@ export default {
return points ;
} ,
/** 圆上整圈(360°)采样,从 startAngleRad 起按顺时针/逆时针,用于盘旋段渲染为整圆 */
getCircleFullCircle ( centerCartesian , radiusMeters , startAngleRad , clockwise , numPoints ) {
/** 圆上从 entry 到 exit 的弧段(按顺时针/逆时针),避免整圈后产生弦线 */
getCircleArcEntryToExit ( centerCartesian , radiusMeters , entryCartesian , exitCartesian , clockwise , numPoints ) {
const enu = Cesium . Transforms . eastNorthUpToFixedFrame ( centerCartesian ) ;
const east = Cesium . Matrix4 . getColumn ( enu , 0 , new Cesium . Cartesian3 ( ) ) ;
const north = Cesium . Matrix4 . getColumn ( enu , 1 , new Cesium . Cartesian3 ( ) ) ;
const toAngle = ( cart ) => {
const toP = Cesium . Cartesian3 . subtract ( cart , centerCartesian , new Cesium . Cartesian3 ( ) ) ;
return Math . atan2 ( Cesium . Cartesian3 . dot ( toP , east ) , Cesium . Cartesian3 . dot ( toP , north ) ) ;
} ;
let entryAngle = toAngle ( entryCartesian ) ;
let exitAngle = toAngle ( exitCartesian ) ;
let diff = exitAngle - entryAngle ;
const sign = clockwise ? - 1 : 1 ;
if ( sign * diff <= 0 ) diff += sign * 2 * Math . PI ;
const points = [ ] ;
for ( let i = 0 ; i <= numPoints ; i ++ ) {
const t = i / numPoints ;
const angle = startAngleRad + sign * t * 2 * Math . PI ;
const angle = entryAngle + sign * t * Math . abs ( diff ) ;
const offset = Cesium . Cartesian3 . add (
Cesium . Cartesian3 . multiplyByScalar ( north , Math . cos ( angle ) * radiusMeters , new Cesium . Cartesian3 ( ) ) ,
Cesium . Cartesian3 . multiplyByScalar ( east , Math . sin ( angle ) * radiusMeters , new Cesium . Cartesian3 ( ) ) ,
@ -2325,8 +2469,8 @@ export default {
const exit = params && params . radius != null
? this . getCircleTangentExitPoint ( currPos , nextPos || currPos , radius , clockwise )
: this . getEllipseTangentExitPoint ( currPos , nextPos || currPos , semiMajor , semiMinor , headingRad , clockwise ) ;
path . push ( toLngLatAlt ( entry ) ) ;
const arcStartIdx = path . length - 1 ;
const arcStartIdx = path . length ;
let fullCirclePoints ;
let arcPoints ;
if ( params && params . radius != null ) {
const enu = Cesium . Transforms . eastNorthUpToFixedFrame ( currPos ) ;
@ -2334,7 +2478,8 @@ export default {
const north = Cesium . Matrix4 . getColumn ( enu , 1 , new Cesium . Cartesian3 ( ) ) ;
const toEntry = Cesium . Cartesian3 . subtract ( entry , currPos , new Cesium . Cartesian3 ( ) ) ;
const entryAngle = Math . atan2 ( Cesium . Cartesian3 . dot ( toEntry , east ) , Cesium . Cartesian3 . dot ( toEntry , north ) ) ;
arcPoints = this . getCircleFullCircle ( currPos , radius , entryAngle , clockwise , 48 ) ;
fullCirclePoints = this . getCircleFullCircle ( currPos , radius , entryAngle , clockwise , 48 ) ;
arcPoints = this . getCircleArcEntryToExit ( currPos , radius , entry , exit , clockwise , 48 ) ;
} else {
const enuE = Cesium . Transforms . eastNorthUpToFixedFrame ( currPos ) ;
const eastE = Cesium . Matrix4 . getColumn ( enuE , 0 , new Cesium . Cartesian3 ( ) ) ;
@ -2342,10 +2487,11 @@ export default {
const toEntryE = Cesium . Cartesian3 . subtract ( entry , currPos , new Cesium . Cartesian3 ( ) ) ;
const thetaE = Math . atan2 ( Cesium . Cartesian3 . dot ( toEntryE , eastE ) , Cesium . Cartesian3 . dot ( toEntryE , northE ) ) ;
const entryLocalAngle = thetaE - headingRad ;
arcPoints = this . getEllipseFullCircle ( currPos , semiMajor , semiMinor , headingRad , entryLocalAngle , clockwise , 48 ) ;
fullCirclePoints = this . getEllipseFullCircle ( currPos , semiMajor , semiMinor , headingRad , entryLocalAngle , clockwise , 48 ) ;
arcPoints = this . getEllipseArcEntryToExit ( currPos , semiMajor , semiMinor , headingRad , entry , exit , clockwise , 48 ) ;
}
for ( let k = 1 ; k < arcPoints . length ; k ++ ) path . push ( toLngLatAlt ( arcPoints [ k ] ) ) ;
path . push ( toLngLatAlt ( exit ) ) ;
const holdPositions = [ entry , ... fullCirclePoints . slice ( 1 ) , ... arcPoints . slice ( 1 ) ] ;
for ( let k = 0 ; k < holdPositions . length ; k ++ ) path . push ( toLngLatAlt ( holdPositions [ k ] ) ) ;
holdArcRanges [ i - 1 ] = { start : arcStartIdx , end : path . length - 1 } ;
segmentEndIndices [ i - 1 ] = path . length - 1 ;
lastPos = exit ;
@ -2418,14 +2564,14 @@ export default {
return heading ;
} ,
/** 格式化飞机标牌文案:名字、高度(m)、速度(km/h)、航向 (°) */
/** 格式化飞机标牌文案:名字、h(m)、v(km/h)、s (°) */
formatPlatformLabelText ( data ) {
const name = ( data && data . name != null ) ? String ( data . name ) : '—' ;
const alt = ( data && data . altitude != null ) ? Number ( data . altitude ) : 0 ;
const speed = ( data && data . speed != null ) ? Number ( data . speed ) : 0 ;
const hdg = ( data && data . headingDeg != null ) ? Number ( data . headingDeg ) : 0 ;
const headingNorm = ( ( hdg % 360 ) + 360 ) % 360 ;
return ` ${ name } \ n高度 : ${ Math . round ( alt ) } m 速度 : ${ Math . round ( speed ) } km/h 航向 : ${ Math . round ( headingNorm ) } ° ` ;
return ` ${ name } \ nh : ${ Math . round ( alt ) } m v : ${ Math . round ( speed ) } km/h s : ${ Math . round ( headingNorm ) } ° ` ;
} ,
/** 动态推演:更新某条航线的平台图标位置与朝向(position: { lng, lat, alt } 或 Cesium.Cartesian3;directionPoint 为用于计算机头朝向的另一点;labelData 可选,用于更新标牌 { name, altitude, speed, headingDeg }) */
@ -3579,11 +3725,16 @@ export default {
if ( entity . id && (
entity . id . toString ( ) . startsWith ( 'temp_wp_' ) ||
entity . id . toString ( ) . includes ( 'temp-preview' ) ||
entity . id === 'temp_hold_preview'
entity . id === 'temp_hold_preview' ||
entity . id === 'temp_hold_outline'
) ) {
this . viewer . entities . remove ( entity ) ;
}
}
if ( this . tempHoldOutlineEntity ) {
try { this . viewer . entities . remove ( this . tempHoldOutlineEntity ) ; } catch ( e ) { }
this . tempHoldOutlineEntity = null ;
}
if ( this . tempHoldEntity ) {
try { this . viewer . entities . remove ( this . tempHoldEntity ) ; } catch ( e ) { }
this . tempHoldEntity = null ;
@ -5428,6 +5579,10 @@ export default {
this . contextMenu . visible = false ;
this . $emit ( 'add-waypoint-at' , payload ) ;
} ,
handleToggleWaypointHold ( payload ) {
this . contextMenu . visible = false ;
this . $emit ( 'toggle-waypoint-hold' , payload ) ;
} ,
/** 开始“在航点前/后增加航点”模式:显示预览折线,左键放置、右键取消。waypoints 为当前航线航点数组。 */
startAddWaypointAt ( routeId , waypointIndex , mode , waypoints ) {
if ( ! waypoints || waypoints . length === 0 ) return ;
@ -5601,6 +5756,15 @@ export default {
this . editPlatformForm . platformName = platformName
this . editPlatformForm . platformId = ed . platformId || 0
/ / 记 录 打 开 弹 窗 时 的 原 始 样 式 , 供 取 消 时 还 原 、 以 及 区 分 “ 预 览 v s 真 正 保 存 ”
this . editPlatformOriginalStyle = {
routeId ,
fontSize ,
fontColor ,
iconSize ,
iconColor
}
/ / 异 步 获 取 最 新 航 线 信 息 , 更 新 p l a t f o r m I d 和 p l a t f o r m N a m e
if ( routeId ) {
getRoutes ( routeId ) . then ( response => {