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 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) || 10
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
- const positionProperty = modelEntity.positionProperty || modelEntity.entity?.position
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: currentRealPosition,
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, // Cesium实体
273
- rippleEffect: null, // 无人机图标扩散涟漪效果
274
- positionProperty, // 位置属性
275
- isFlying: false, // 飞行状态
276
- currentPosition: initialPosition, // 当前位置
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huweili-cesium",
3
- "version": "1.2.82",
3
+ "version": "1.2.83",
4
4
  "description": "基于 Cesium 的地图工具库(无人机态势、轨迹、围栏、工具栏等)",
5
5
  "type": "module",
6
6
  "main": "./index.js",