huweili-cesium 1.2.82 → 1.2.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/js/movePoint.js +38 -121
- package/js/setPoint.js +11 -10
- package/package.json +1 -1
package/js/movePoint.js
CHANGED
|
@@ -19,8 +19,6 @@ import { pointGetPool } from './cardPool'
|
|
|
19
19
|
import { scheduleRefreshFlyHandQRCode } from './qrCodeGenerator'
|
|
20
20
|
import { groundLinkConfig } from './groundLink'
|
|
21
21
|
|
|
22
|
-
const MIN_DRONE_MOVE_DISTANCE = 0.1
|
|
23
|
-
const MIN_DRONE_MOVE_DISTANCE_SQUARED = MIN_DRONE_MOVE_DISTANCE * MIN_DRONE_MOVE_DISTANCE
|
|
24
22
|
const DEFAULT_FAR_FUTURE_SECONDS = 3600
|
|
25
23
|
|
|
26
24
|
export function movePointConfig(baseUrl) {
|
|
@@ -176,26 +174,54 @@ export function movePointConfig(baseUrl) {
|
|
|
176
174
|
}
|
|
177
175
|
|
|
178
176
|
/**
|
|
179
|
-
*
|
|
177
|
+
* 移动无人机点位到新的坐标位置(即时定位:收到新坐标立刻到位,无新数据则保持悬停)
|
|
180
178
|
* @param options 配置选项
|
|
181
179
|
* @param options.pointId 点位唯一标识
|
|
182
180
|
* @param options.uavName 无人机名称
|
|
183
181
|
* @param options.lng 新的经度
|
|
184
182
|
* @param options.lat 新的纬度
|
|
185
183
|
* @param options.height 高度
|
|
186
|
-
* @param options.speed
|
|
184
|
+
* @param options.speed 速度(仅写入 info 展示,不参与位移)
|
|
187
185
|
* @param options.flyingHandName 飞手姓名
|
|
188
186
|
* @param options.flyingHandPhone 飞手电话
|
|
189
187
|
* @param options.flyingHandPosition 飞手位置
|
|
190
188
|
* @param options.frequencyBand 频段
|
|
191
189
|
* @param options.distance 距离
|
|
192
|
-
* @param options.speed 速度
|
|
193
|
-
* @param options.height 高度
|
|
194
190
|
* @param options.GROUND_LINK_LNG 地面固定点经度
|
|
195
191
|
* @param options.GROUND_LINK_LAT 地面固定点纬度
|
|
196
192
|
* @param options.status 无人机状态标识(0-绿色/默认, 1-红色, 2-灰色)
|
|
197
193
|
* @param options.receiveTime 接收时间毫秒级时间戳)
|
|
198
|
-
|
|
194
|
+
*/
|
|
195
|
+
const snapDronePosition = (modelEntity, map, position, currentTime) => {
|
|
196
|
+
if (modelEntity.flightEndListener) {
|
|
197
|
+
map.clock.onTick.removeEventListener(modelEntity.flightEndListener)
|
|
198
|
+
modelEntity.flightEndListener = null
|
|
199
|
+
}
|
|
200
|
+
modelEntity.isFlying = false
|
|
201
|
+
|
|
202
|
+
modelEntity.currentPosition = Cesium.Cartesian3.clone(
|
|
203
|
+
position,
|
|
204
|
+
modelEntity.currentPosition || new Cesium.Cartesian3()
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
const positionProperty = new Cesium.SampledPositionProperty()
|
|
208
|
+
positionProperty.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD
|
|
209
|
+
positionProperty.backwardExtrapolationType = Cesium.ExtrapolationType.HOLD
|
|
210
|
+
positionProperty.forwardExtrapolationDuration = Number.POSITIVE_INFINITY
|
|
211
|
+
positionProperty.backwardExtrapolationDuration = Number.POSITIVE_INFINITY
|
|
212
|
+
positionProperty.addSample(currentTime, modelEntity.currentPosition)
|
|
213
|
+
|
|
214
|
+
const holdTime = Cesium.JulianDate.addSeconds(
|
|
215
|
+
currentTime,
|
|
216
|
+
DEFAULT_FAR_FUTURE_SECONDS,
|
|
217
|
+
new Cesium.JulianDate()
|
|
218
|
+
)
|
|
219
|
+
positionProperty.addSample(holdTime, modelEntity.currentPosition)
|
|
220
|
+
|
|
221
|
+
modelEntity.positionProperty = positionProperty
|
|
222
|
+
modelEntity.entity.position = positionProperty
|
|
223
|
+
}
|
|
224
|
+
|
|
199
225
|
const moveDronePoint = (options) => {
|
|
200
226
|
const { pointId, mapId, uavName } = options
|
|
201
227
|
const map = mapStore.getMap(mapId)
|
|
@@ -204,7 +230,6 @@ export function movePointConfig(baseUrl) {
|
|
|
204
230
|
return null
|
|
205
231
|
}
|
|
206
232
|
|
|
207
|
-
// 先统一转换并校验经纬度,避免 Cesium 坐标计算出现 NaN。
|
|
208
233
|
const lng = Number(options.lng)
|
|
209
234
|
const lat = Number(options.lat)
|
|
210
235
|
if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
|
|
@@ -212,14 +237,13 @@ export function movePointConfig(baseUrl) {
|
|
|
212
237
|
return false
|
|
213
238
|
}
|
|
214
239
|
|
|
215
|
-
const speed = Number(options.speed)
|
|
240
|
+
const speed = Number(options.speed)
|
|
216
241
|
const height = Number(options.height) || 0
|
|
217
242
|
const status = options.status || DroneStatus.WHITELIST
|
|
218
243
|
const currentTime = map.clock.currentTime
|
|
219
244
|
|
|
220
245
|
let modelEntity = mapStore.getGraphicMap(pointId, mapId)
|
|
221
246
|
if (!modelEntity) {
|
|
222
|
-
// 首次收到该无人机点位时创建实体,后续更新才走插值飞行逻辑。
|
|
223
247
|
modelEntity = setDronePointByGlb({
|
|
224
248
|
id: pointId,
|
|
225
249
|
uavName,
|
|
@@ -233,20 +257,11 @@ export function movePointConfig(baseUrl) {
|
|
|
233
257
|
mapId
|
|
234
258
|
})
|
|
235
259
|
if (modelEntity) {
|
|
236
|
-
// 新建实体后立即绑定点击事件
|
|
237
260
|
clickHandler.bindDroneClickHandler({ id: pointId, modelEntity, map, mapId })
|
|
238
261
|
}
|
|
239
|
-
// 新创建的实体直接返回(首次创建无飞行状态)
|
|
240
262
|
return modelEntity
|
|
241
263
|
}
|
|
242
264
|
|
|
243
|
-
// 初始化复用对象,避免上百个无人机高频移动时反复创建临时对象
|
|
244
|
-
modelEntity.scratchPosition ||= new Cesium.Cartesian3()
|
|
245
|
-
modelEntity.scratchTargetPosition ||= new Cesium.Cartesian3()
|
|
246
|
-
modelEntity.scratchFlightEndTime ||= new Cesium.JulianDate()
|
|
247
|
-
modelEntity.scratchFarFutureTime ||= new Cesium.JulianDate()
|
|
248
|
-
|
|
249
|
-
// 如果存在实体,确保实体属性实时同步
|
|
250
265
|
const groundLinkLng = Number(options.GROUND_LINK_LNG)
|
|
251
266
|
const groundLinkLat = Number(options.GROUND_LINK_LAT)
|
|
252
267
|
|
|
@@ -255,7 +270,7 @@ export function movePointConfig(baseUrl) {
|
|
|
255
270
|
info.lng = lng
|
|
256
271
|
info.lat = lat
|
|
257
272
|
info.height = height
|
|
258
|
-
info.speed = speed
|
|
273
|
+
info.speed = Number.isFinite(speed) ? speed : ''
|
|
259
274
|
info.flyingHandName = options.flyingHandName || ''
|
|
260
275
|
info.flyingHandPhone = options.flyingHandPhone || ''
|
|
261
276
|
info.groundLinkLng = Number.isFinite(groundLinkLng) ? groundLinkLng.toFixed(4) : '--'
|
|
@@ -268,113 +283,15 @@ export function movePointConfig(baseUrl) {
|
|
|
268
283
|
info.distance = options.distance || ''
|
|
269
284
|
info.receiveTime = options.receiveTime || ''
|
|
270
285
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
let currentRealPosition = positionProperty?.getValue?.(currentTime, modelEntity.scratchPosition)
|
|
274
|
-
|
|
275
|
-
if (!currentRealPosition && modelEntity.currentPosition) {
|
|
276
|
-
// 插值属性取不到值时,回退到上一次缓存的真实位置。
|
|
277
|
-
currentRealPosition = Cesium.Cartesian3.clone(modelEntity.currentPosition, modelEntity.scratchPosition)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (!currentRealPosition) {
|
|
281
|
-
// 仍没有当前位置时,使用本次传入坐标作为起点。
|
|
282
|
-
currentRealPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height, modelEntity.scratchPosition)
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// getValue 复用 scratchPosition,后续 targetPosition 也会复用其它 scratch,先把当前位置固定到独立对象,避免被后续计算覆盖。
|
|
286
|
-
currentRealPosition = Cesium.Cartesian3.clone(currentRealPosition, modelEntity.currentPosition || new Cesium.Cartesian3())
|
|
287
|
-
modelEntity.currentPosition = currentRealPosition
|
|
288
|
-
// ========== 实时位置获取结束 ==========
|
|
286
|
+
const targetPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height)
|
|
287
|
+
snapDronePosition(modelEntity, map, targetPosition, currentTime)
|
|
289
288
|
|
|
290
|
-
// ========== 保留轨迹 ==========
|
|
291
|
-
// 在飞行开始前,先记录当前点,保证轨迹不会从新目标点突兀开始。
|
|
292
289
|
moveDroneTrail({
|
|
293
290
|
pointId,
|
|
294
|
-
newPosition:
|
|
291
|
+
newPosition: modelEntity.currentPosition,
|
|
295
292
|
mapId
|
|
296
293
|
})
|
|
297
294
|
|
|
298
|
-
// ========== 终止当前所有飞行状态 ==========
|
|
299
|
-
// 终止旧飞行监听;飞行插值和轨迹更新都在同一个 onTick 中处理。
|
|
300
|
-
if (modelEntity.flightEndListener) {
|
|
301
|
-
map.clock.onTick.removeEventListener(modelEntity.flightEndListener)
|
|
302
|
-
modelEntity.flightEndListener = null
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
modelEntity.isFlying = false
|
|
306
|
-
// 每次移动都重建采样属性,只保留“当前位置 -> 新目标点”的最新飞行段。
|
|
307
|
-
modelEntity.positionProperty = new Cesium.SampledPositionProperty()
|
|
308
|
-
modelEntity.positionProperty.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD
|
|
309
|
-
modelEntity.positionProperty.backwardExtrapolationType = Cesium.ExtrapolationType.HOLD
|
|
310
|
-
modelEntity.positionProperty.forwardExtrapolationDuration = Number.POSITIVE_INFINITY
|
|
311
|
-
modelEntity.positionProperty.backwardExtrapolationDuration = Number.POSITIVE_INFINITY
|
|
312
|
-
modelEntity.positionProperty.addSample(currentTime, currentRealPosition)
|
|
313
|
-
modelEntity.entity.position = modelEntity.positionProperty
|
|
314
|
-
|
|
315
|
-
// ========== 计算新的飞行路径 ==========
|
|
316
|
-
const targetPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height)
|
|
317
|
-
const distanceSquared = Cesium.Cartesian3.distanceSquared(currentRealPosition, targetPosition)
|
|
318
|
-
|
|
319
|
-
// 距离过近则直接定位
|
|
320
|
-
if (distanceSquared < MIN_DRONE_MOVE_DISTANCE_SQUARED) {
|
|
321
|
-
modelEntity.currentPosition = Cesium.Cartesian3.clone(targetPosition, modelEntity.currentPosition)
|
|
322
|
-
modelEntity.positionProperty.addSample(currentTime, modelEntity.currentPosition)
|
|
323
|
-
|
|
324
|
-
moveDroneTrail({
|
|
325
|
-
pointId,
|
|
326
|
-
newPosition: modelEntity.currentPosition,
|
|
327
|
-
mapId
|
|
328
|
-
})
|
|
329
|
-
return modelEntity
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// 按距离和速度计算本段飞行时长,由 SampledPositionProperty 自动插值位置。
|
|
333
|
-
const flightDuration = Math.sqrt(distanceSquared) / speed
|
|
334
|
-
const flightEndTime = Cesium.JulianDate.addSeconds(currentTime, flightDuration, new Cesium.JulianDate())
|
|
335
|
-
|
|
336
|
-
if (!map.clock.shouldAnimate) {
|
|
337
|
-
map.clock.shouldAnimate = true
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// 不再为每个无人机改全局 clock.startTime/stopTime,避免多无人机互相抢时钟范围。
|
|
341
|
-
modelEntity.positionProperty.addSample(flightEndTime, targetPosition)
|
|
342
|
-
modelEntity.isFlying = true
|
|
343
|
-
|
|
344
|
-
const flightTickListener = (clock) => {
|
|
345
|
-
if (!modelEntity.isFlying) return
|
|
346
|
-
|
|
347
|
-
const isFinished = Cesium.JulianDate.compare(clock.currentTime, flightEndTime) >= 0
|
|
348
|
-
const tickPosition = isFinished
|
|
349
|
-
? targetPosition
|
|
350
|
-
: modelEntity.positionProperty.getValue(clock.currentTime, modelEntity.scratchPosition)
|
|
351
|
-
|
|
352
|
-
if (tickPosition) {
|
|
353
|
-
// 每帧缓存插值后的真实位置,并同步追加轨迹点。
|
|
354
|
-
modelEntity.currentPosition = Cesium.Cartesian3.clone(tickPosition, modelEntity.currentPosition)
|
|
355
|
-
moveDroneTrail({
|
|
356
|
-
pointId,
|
|
357
|
-
newPosition: modelEntity.currentPosition,
|
|
358
|
-
mapId
|
|
359
|
-
})
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
if (!isFinished) return
|
|
363
|
-
|
|
364
|
-
modelEntity.currentPosition = Cesium.Cartesian3.clone(targetPosition, modelEntity.currentPosition)
|
|
365
|
-
modelEntity.isFlying = false
|
|
366
|
-
|
|
367
|
-
// 到达目标后追加远期采样点,让实体在终点保持不动。
|
|
368
|
-
const farFutureTime = Cesium.JulianDate.addSeconds(flightEndTime, DEFAULT_FAR_FUTURE_SECONDS, new Cesium.JulianDate())
|
|
369
|
-
modelEntity.positionProperty.addSample(farFutureTime, modelEntity.currentPosition)
|
|
370
|
-
|
|
371
|
-
clock.onTick.removeEventListener(flightTickListener)
|
|
372
|
-
modelEntity.flightEndListener = null
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
modelEntity.flightEndListener = flightTickListener
|
|
376
|
-
map.clock.onTick.addEventListener(flightTickListener)
|
|
377
|
-
|
|
378
295
|
return modelEntity
|
|
379
296
|
};
|
|
380
297
|
|
package/js/setPoint.js
CHANGED
|
@@ -261,20 +261,21 @@ export function setPoint(baseUrl) {
|
|
|
261
261
|
positionProperty.forwardExtrapolationDuration = Number.POSITIVE_INFINITY
|
|
262
262
|
positionProperty.backwardExtrapolationDuration = Number.POSITIVE_INFINITY
|
|
263
263
|
positionProperty.addSample(currentTime, initialPosition)
|
|
264
|
+
const holdTime = Cesium.JulianDate.addSeconds(currentTime, 3600, new Cesium.JulianDate())
|
|
265
|
+
positionProperty.addSample(holdTime, initialPosition)
|
|
264
266
|
|
|
265
267
|
// 模型实例(用于后续销毁/修改)
|
|
266
268
|
const modelEntity = {
|
|
267
269
|
receiveTime: receiveTime,
|
|
268
|
-
targetLng: lng,
|
|
269
|
-
targetLat: lat,
|
|
270
|
-
targetHeight: height,
|
|
271
|
-
speed: 50,
|
|
272
|
-
entity: null,
|
|
273
|
-
rippleEffect: null,
|
|
274
|
-
positionProperty,
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
trailEntityId: `${id}_trail`, // 轨迹实体ID,用于管理独立的轨迹
|
|
270
|
+
targetLng: lng,
|
|
271
|
+
targetLat: lat,
|
|
272
|
+
targetHeight: height,
|
|
273
|
+
speed: 50,
|
|
274
|
+
entity: null,
|
|
275
|
+
rippleEffect: null,
|
|
276
|
+
positionProperty,
|
|
277
|
+
currentPosition: initialPosition,
|
|
278
|
+
trailEntityId: `${id}_trail`,
|
|
278
279
|
info: {}
|
|
279
280
|
}
|
|
280
281
|
|