cesium-multi-target-framework 0.1.0

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.
Files changed (41) hide show
  1. package/README.md +474 -0
  2. package/dist/assets/renderWorker-118e8f3b.js +1 -0
  3. package/dist/cesium-multi-target-framework.js +4605 -0
  4. package/dist/cesium-multi-target-framework.umd.cjs +101 -0
  5. package/dist/cluster/QuadCluster.d.ts +66 -0
  6. package/dist/cluster/clusterClient.d.ts +44 -0
  7. package/dist/cluster/clusterWorker.d.ts +1 -0
  8. package/dist/config/types.d.ts +266 -0
  9. package/dist/core/EventEmitter.d.ts +9 -0
  10. package/dist/core/MultiTargetFramework.d.ts +184 -0
  11. package/dist/core/MultiTargetScene.d.ts +224 -0
  12. package/dist/data/types.d.ts +67 -0
  13. package/dist/events/bus.d.ts +336 -0
  14. package/dist/index.d.ts +22 -0
  15. package/dist/render/AirGroundReferenceRenderer.d.ts +20 -0
  16. package/dist/render/InstancedGltfBatch.d.ts +37 -0
  17. package/dist/render/InstancedSymbolRenderer.d.ts +65 -0
  18. package/dist/render/LowModelInstancedRenderer.d.ts +39 -0
  19. package/dist/render/ModelPoolRenderer.d.ts +43 -0
  20. package/dist/render/PointCloudRenderer.d.ts +135 -0
  21. package/dist/render/SelectionOverlayRenderer.d.ts +37 -0
  22. package/dist/render/targetVisualMetrics.d.ts +9 -0
  23. package/dist/site/SiteLayer.d.ts +43 -0
  24. package/dist/site/SiteLowModelRenderer.d.ts +12 -0
  25. package/dist/site/SiteSpatialIndex.d.ts +10 -0
  26. package/dist/site/types.d.ts +72 -0
  27. package/dist/track/TrackHoverPicker.d.ts +26 -0
  28. package/dist/track/TrackManager.d.ts +42 -0
  29. package/dist/track/TrackRenderer.d.ts +29 -0
  30. package/dist/track/types.d.ts +27 -0
  31. package/dist/worker/protocol.d.ts +182 -0
  32. package/dist/worker/renderWorker.d.ts +1 -0
  33. package/doc//345/244/232/347/233/256/346/240/207/344/274/230/345/214/226/344/270/216/351/242/204/346/265/213/346/270/262/346/237/223/350/257/264/346/230/216.md +186 -0
  34. package/doc//345/244/232/347/273/204/344/273/266/344/272/213/344/273/266/346/226/271/346/241/210.md +410 -0
  35. package/doc//345/257/271/345/244/226/346/216/245/345/217/243/350/257/264/346/230/216.md +519 -0
  36. package/doc//345/267/245/344/275/234/350/256/241/345/210/222.md +59 -0
  37. package/doc//346/270/262/346/237/223/344/270/232/345/212/241/351/200/273/350/276/221.md +202 -0
  38. package/doc//347/253/231/347/202/271/346/270/262/346/237/223/344/270/216/345/217/263/351/224/256/350/217/234/345/215/225/345/256/236/347/216/260/350/257/264/346/230/216.md +49 -0
  39. package/doc//350/247/206/345/217/243/351/251/261/345/212/250/346/225/260/346/215/256/346/265/201/347/250/213/344/277/256/346/224/271/350/256/241/345/210/222.md +69 -0
  40. package/doc//351/241/271/347/233/256/350/257/264/346/230/216/344/271/246.md +729 -0
  41. package/package.json +51 -0
@@ -0,0 +1,4605 @@
1
+ var fi = Object.defineProperty;
2
+ var mi = (i, e, t) => e in i ? fi(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t;
3
+ var a = (i, e, t) => (mi(i, typeof e != "symbol" ? e + "" : e, t), t);
4
+ import * as Re from "cesium";
5
+ import { Color as D, PolylineCollection as Ve, PointPrimitiveCollection as pi, Cartesian3 as f, Material as ae, Cartographic as et, Matrix4 as R, BoundingSphere as Ze, HeadingPitchRoll as Vt, Math as A, Transforms as Ye, Model as gi, ModelAnimationLoop as Le, BillboardCollection as fe, Cartesian2 as J, HorizontalOrigin as vi, VerticalOrigin as yi, SceneTransforms as Ae, ScreenSpaceEventHandler as Wt, ScreenSpaceEventType as N, HeadingPitchRange as wi } from "cesium";
6
+ export * from "cesium";
7
+ const Pe = {
8
+ SURFACE: "surface",
9
+ AIR: "air",
10
+ UNDERWATER: "underwater"
11
+ }, Mi = {
12
+ pointAbove: 15e4,
13
+ animatedBelow: 1e4
14
+ }, Ii = { size: 3e4 }, Si = { size: 64 }, ye = {
15
+ updateFps: 30,
16
+ predictSeconds: 10,
17
+ predictFitSeconds: 2,
18
+ masterHideHeight: 15e4
19
+ };
20
+ function xi(i) {
21
+ var o, r, l, h, c, m, u, v, d, p, g, y, w, M, I, C, k, S, T, z, L, E, B, Z, Q, q, ee, $, X, le, me, pe, ge, x, H, O;
22
+ const e = /* @__PURE__ */ new Map();
23
+ for (const j of i.nodeTypes ?? [])
24
+ e.set(j.type, j);
25
+ const t = Array.from(e.values()).map(Ti), s = ((o = i.pool) == null ? void 0 : o.size) ?? Ii.size, n = ((r = i.frame) == null ? void 0 : r.heatmapAboveHeight) ?? 2e6;
26
+ return {
27
+ nodeTypes: e,
28
+ renderTypes: t,
29
+ lod: i.lod ?? Mi,
30
+ poolSize: s,
31
+ animatedCapacity: ((l = i.animatedPool) == null ? void 0 : l.size) ?? Si.size,
32
+ updateFps: i.updateFps ?? ye.updateFps,
33
+ predictSeconds: i.predictSeconds ?? ye.predictSeconds,
34
+ predictFitSeconds: i.predictFitSeconds ?? ye.predictFitSeconds,
35
+ fadeMs: i.fadeMs ?? 350,
36
+ masterHideHeight: i.masterHideHeight ?? ye.masterHideHeight,
37
+ groundSymbols: i.groundSymbols ?? !1,
38
+ groundSymbolPixelSize: i.groundSymbolPixelSize ?? 30,
39
+ merge: Ai(i.merge, s),
40
+ pick: {
41
+ enabled: ((h = i.pick) == null ? void 0 : h.enabled) ?? !0,
42
+ pixelThreshold: ((c = i.pick) == null ? void 0 : c.pixelThreshold) ?? 20,
43
+ hover: ((m = i.pick) == null ? void 0 : m.hover) ?? !0
44
+ },
45
+ cull: {
46
+ enabled: ((u = i.cull) == null ? void 0 : u.enabled) ?? !0,
47
+ padding: ((v = i.cull) == null ? void 0 : v.padding) ?? 3e4,
48
+ viewportCull: ((d = i.cull) == null ? void 0 : d.viewportCull) ?? !0,
49
+ viewportBufferRatio: ((p = i.cull) == null ? void 0 : p.viewportBufferRatio) ?? 0.15,
50
+ viewportBufferMinMeters: Math.max(0, ((g = i.cull) == null ? void 0 : g.viewportBufferMinMeters) ?? 500)
51
+ },
52
+ horizonCull: {
53
+ enabled: ((y = i.horizonCull) == null ? void 0 : y.enabled) ?? !0,
54
+ pitchThreshold: ((w = i.horizonCull) == null ? void 0 : w.pitchThreshold) ?? -25,
55
+ minDistance: Math.max(0, ((M = i.horizonCull) == null ? void 0 : M.minDistance) ?? 8e3),
56
+ maxDistance: Math.max(0, ((I = i.horizonCull) == null ? void 0 : I.maxDistance) ?? 4e4),
57
+ cameraHeightMultiplier: Math.max(0, ((C = i.horizonCull) == null ? void 0 : C.cameraHeightMultiplier) ?? 6),
58
+ maxCameraHeight: Math.max(0, ((k = i.horizonCull) == null ? void 0 : k.maxCameraHeight) ?? 8e4)
59
+ },
60
+ label: Ke(i.label),
61
+ frame: {
62
+ maxScanPerFrame: ((S = i.frame) == null ? void 0 : S.maxScanPerFrame) ?? 3e4,
63
+ maxScanMs: ((T = i.frame) == null ? void 0 : T.maxScanMs) ?? 4,
64
+ maxIngestPerFrame: ((z = i.frame) == null ? void 0 : z.maxIngestPerFrame) ?? 2e4,
65
+ maxLowModelRenderItems: ((L = i.frame) == null ? void 0 : L.maxLowModelRenderItems) ?? ((E = i.frame) == null ? void 0 : E.maxModelRenderItems) ?? 3e3,
66
+ maxModelRenderItems: ((B = i.frame) == null ? void 0 : B.maxModelRenderItems) ?? 2e3,
67
+ suspendRenderUpdateWhileMoving: ((Z = i.frame) == null ? void 0 : Z.suspendRenderUpdateWhileMoving) ?? !0,
68
+ heatmapAboveHeight: n,
69
+ heatmapBelowHeight: ((Q = i.frame) == null ? void 0 : Q.heatmapBelowHeight) ?? Math.max(0, n * 0.9),
70
+ heatmapSwitchSettleMs: ((q = i.frame) == null ? void 0 : q.heatmapSwitchSettleMs) ?? 300,
71
+ heatmapUpdateIntervalMs: ((ee = i.frame) == null ? void 0 : ee.heatmapUpdateIntervalMs) ?? 6e5
72
+ },
73
+ data: {
74
+ commitIntervalMs: (($ = i.data) == null ? void 0 : $.commitIntervalMs) ?? 2e3,
75
+ leading: ((X = i.data) == null ? void 0 : X.leading) ?? !0,
76
+ worker: ((le = i.data) == null ? void 0 : le.worker) ?? !0
77
+ },
78
+ adaptive: {
79
+ enabled: ((me = i.adaptive) == null ? void 0 : me.enabled) ?? !0,
80
+ dynamic: ((pe = i.adaptive) == null ? void 0 : pe.dynamic) ?? !0,
81
+ minFps: ((ge = i.adaptive) == null ? void 0 : ge.minFps) ?? 25,
82
+ upFps: ((x = i.adaptive) == null ? void 0 : x.upFps) ?? 50,
83
+ windowMs: ((H = i.adaptive) == null ? void 0 : H.windowMs) ?? 2e3,
84
+ baseTier: ((O = i.adaptive) == null ? void 0 : O.baseTier) ?? "high"
85
+ }
86
+ };
87
+ }
88
+ function Ti(i) {
89
+ const e = i.targetDomain ?? Ci(i.type);
90
+ return {
91
+ ...i,
92
+ targetDomain: e,
93
+ forceHighModelInLowLod: i.forceHighModelInLowLod ?? e === Pe.AIR,
94
+ iconPath: i.iconPath ?? i.pointIcon ?? bi(i.type),
95
+ defaultColor: i.defaultColor ?? Pi(i.type),
96
+ pointHeadingOffset: i.pointHeadingOffset ?? 0,
97
+ smoothMove: i.smoothMove ?? !1,
98
+ smoothMoveMinCameraHeight: i.smoothMoveMinCameraHeight ?? 25e3,
99
+ smoothMoveDurationMs: i.smoothMoveDurationMs ?? i.moveAnimationDurationMs ?? 400,
100
+ predictMove: i.predictMove ?? !1,
101
+ predictMinCameraHeight: i.predictMinCameraHeight ?? 25e3,
102
+ predictSeconds: i.predictSeconds,
103
+ predictFitSeconds: i.predictFitSeconds
104
+ };
105
+ }
106
+ function Ci(i) {
107
+ return i.startsWith("air") || i.startsWith("uav") || i.includes("bird") || i.includes("aircraft") || i.includes("fpv") ? Pe.AIR : i.startsWith("underwater") || i.startsWith("subsea") ? Pe.UNDERWATER : Pe.SURFACE;
108
+ }
109
+ function bi(i) {
110
+ return i.startsWith("air") || i.startsWith("uav") ? "/icons/target-uav-mask.png" : i.startsWith("person") ? "/icons/target-person-mask.png" : i.startsWith("car") ? "/icons/target-car-mask.png" : "/icons/target-ship-mask.png";
111
+ }
112
+ function Pi(i) {
113
+ return i.startsWith("air") || i.startsWith("uav") ? "#22d2f2" : i.startsWith("person") ? "#ffdc40" : i.startsWith("car") ? "#ff9a2a" : "#25e65c";
114
+ }
115
+ function Xt(i) {
116
+ return {
117
+ key: i.key,
118
+ label: i.label,
119
+ source: i.source ?? "standard",
120
+ fallback: i.fallback,
121
+ minCameraHeight: i.minCameraHeight,
122
+ maxCameraHeight: i.maxCameraHeight
123
+ };
124
+ }
125
+ function tt(i) {
126
+ let e = 0;
127
+ for (const t of i ?? [])
128
+ t.maxCameraHeight != null && t.maxCameraHeight > e && (e = t.maxCameraHeight);
129
+ return e;
130
+ }
131
+ function Ri(i) {
132
+ var e;
133
+ return {
134
+ ...i,
135
+ fields: (e = i.fields) == null ? void 0 : e.map(Xt),
136
+ maxCameraHeight: i.maxCameraHeight != null ? Math.max(0, i.maxCameraHeight) : void 0,
137
+ maxCount: i.maxCount != null ? Math.max(0, i.maxCount) : void 0
138
+ };
139
+ }
140
+ function Ke(i) {
141
+ var o;
142
+ const e = Math.max(0, (i == null ? void 0 : i.maxCameraHeight) ?? 5e3), t = (o = i == null ? void 0 : i.fields) != null && o.length ? i.fields.map(Xt) : [{ key: "id" }];
143
+ let s = Math.max(e, tt(t));
144
+ const n = i != null && i.byType ? Object.fromEntries(Object.entries(i.byType).map(([r, l]) => [r, Ri(l)])) : void 0;
145
+ if (n)
146
+ for (const r of Object.values(n))
147
+ s = Math.max(s, r.maxCameraHeight ?? 0, tt(r.fields));
148
+ return {
149
+ enabled: (i == null ? void 0 : i.enabled) ?? !0,
150
+ maxCount: Math.max(0, (i == null ? void 0 : i.maxCount) ?? 200),
151
+ maxCameraHeight: s,
152
+ maxDistance: i == null ? void 0 : i.maxDistance,
153
+ fields: t,
154
+ byType: n,
155
+ resolve: i == null ? void 0 : i.resolve,
156
+ backgroundColor: (i == null ? void 0 : i.backgroundColor) ?? "#0000008c",
157
+ textColor: (i == null ? void 0 : i.textColor) ?? "#ffffff",
158
+ fontSize: Math.max(1, (i == null ? void 0 : i.fontSize) ?? 12),
159
+ fontFamily: (i == null ? void 0 : i.fontFamily) ?? "sans-serif",
160
+ backgroundRadius: Math.max(0, (i == null ? void 0 : i.backgroundRadius) ?? 6),
161
+ overlapThreshold: ki((i == null ? void 0 : i.overlapThreshold) ?? 0.35, 0, 1),
162
+ occlusionGraceMs: Math.max(0, (i == null ? void 0 : i.occlusionGraceMs) ?? 300),
163
+ offsetX: Math.max(0, (i == null ? void 0 : i.offsetX) ?? 18),
164
+ offsetY: Math.max(0, (i == null ? void 0 : i.offsetY) ?? 24),
165
+ connectorColor: (i == null ? void 0 : i.connectorColor) ?? (i == null ? void 0 : i.backgroundColor) ?? "#0000008c",
166
+ connectorWidth: Math.max(0, (i == null ? void 0 : i.connectorWidth) ?? 1.5),
167
+ connectorStemLength: Math.max(0, (i == null ? void 0 : i.connectorStemLength) ?? 50),
168
+ showFieldLabels: (i == null ? void 0 : i.showFieldLabels) ?? !0
169
+ };
170
+ }
171
+ function ki(i, e, t) {
172
+ return Math.max(e, Math.min(t, i));
173
+ }
174
+ function Ai(i, e) {
175
+ if (!i)
176
+ return;
177
+ const t = (i.radii ?? [100, 200, 500, 1e3, 2e3, 5e3, 1e4]).slice().sort((s, n) => s - n);
178
+ return {
179
+ enabled: i.enabled,
180
+ mode: i.mode ?? "global",
181
+ maxVisible: i.maxVisible ?? e,
182
+ globalRootLimit: Math.max(1, i.globalRootLimit ?? 500),
183
+ globalMaxLevels: Math.max(1, i.globalMaxLevels ?? 64),
184
+ globalRebuildIntervalMs: Math.max(0, i.globalRebuildIntervalMs ?? 3e5),
185
+ globalViewportHeight: Math.max(0, i.globalViewportHeight ?? 45e4),
186
+ cameraMergeBaseHeight: Math.max(0, i.cameraMergeBaseHeight ?? 1e5),
187
+ cameraMergeStepHeight: Math.max(1, i.cameraMergeStepHeight ?? 1e4),
188
+ cameraMergeStepRadius: Math.max(1, i.cameraMergeStepRadius ?? 100),
189
+ innerRatio: Math.max(0, Math.min(1, i.innerRatio ?? 0.6)),
190
+ radii: t,
191
+ byType: i.byType ?? !0,
192
+ minSecrecy: i.minSecrecy,
193
+ bucketCellDeg: i.bucketCellDeg ?? 0.02
194
+ };
195
+ }
196
+ class qe {
197
+ constructor() {
198
+ a(this, "handlers", /* @__PURE__ */ new Map());
199
+ }
200
+ on(e, t) {
201
+ let s = this.handlers.get(e);
202
+ return s || (s = /* @__PURE__ */ new Set(), this.handlers.set(e, s)), s.add(t), () => this.off(e, t);
203
+ }
204
+ off(e, t) {
205
+ var s;
206
+ (s = this.handlers.get(e)) == null || s.delete(t);
207
+ }
208
+ emit(e, t) {
209
+ const s = this.handlers.get(e);
210
+ if (s)
211
+ for (const n of s)
212
+ n(t);
213
+ }
214
+ clear() {
215
+ this.handlers.clear();
216
+ }
217
+ }
218
+ const it = new D(0.22, 0.82, 1, 0.68), Li = new D(0.22, 0.82, 1, 0), He = new D(0.12, 0.72, 1, 0.72), De = new D(1, 1, 1, 0.9);
219
+ class Hi {
220
+ constructor(e) {
221
+ a(this, "lineCollection");
222
+ a(this, "pointCollection");
223
+ a(this, "pool", []);
224
+ this.scene = e, this.lineCollection = this.scene.primitives.add(new Ve({ show: !0 })), this.pointCollection = this.scene.primitives.add(new pi({ show: !0 }));
225
+ }
226
+ setTargets(e) {
227
+ this.ensurePool(e.length);
228
+ for (let t = 0; t < e.length; t++)
229
+ this.updateSlot(this.pool[t], e[t]);
230
+ for (let t = e.length; t < this.pool.length; t++)
231
+ this.pool[t].line.show = !1, this.pool[t].point.show = !1;
232
+ }
233
+ clear() {
234
+ for (const e of this.pool)
235
+ e.line.show = !1, e.point.show = !1;
236
+ }
237
+ destroy() {
238
+ this.clear(), this.scene.primitives.remove(this.lineCollection), this.scene.primitives.remove(this.pointCollection);
239
+ }
240
+ ensurePool(e) {
241
+ for (; this.pool.length < e; )
242
+ this.pool.push(this.createSlot());
243
+ }
244
+ createSlot() {
245
+ const e = f.clone(f.ZERO), t = f.clone(f.ZERO), s = [e, t], n = ae.fromType(ae.PolylineDashType, {
246
+ color: D.clone(it),
247
+ gapColor: D.clone(Li),
248
+ dashLength: 14,
249
+ dashPattern: 255
250
+ }), o = this.lineCollection.add({
251
+ show: !1,
252
+ positions: s,
253
+ width: 1.5,
254
+ material: n
255
+ }), r = this.pointCollection.add({
256
+ show: !1,
257
+ position: t,
258
+ pixelSize: 7,
259
+ color: D.clone(He),
260
+ outlineColor: D.clone(De),
261
+ outlineWidth: 1.5,
262
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
263
+ });
264
+ return {
265
+ line: o,
266
+ point: r,
267
+ top: e,
268
+ ground: t,
269
+ positions: s,
270
+ cartographic: new et(),
271
+ lineMaterial: n
272
+ };
273
+ }
274
+ updateSlot(e, t) {
275
+ f.clone(t.position, e.top);
276
+ const s = et.fromCartesian(t.position, void 0, e.cartographic);
277
+ if (!s) {
278
+ e.line.show = !1, e.point.show = !1;
279
+ return;
280
+ }
281
+ f.fromRadians(s.longitude, s.latitude, 0, void 0, e.ground), e.line.positions = e.positions, e.point.position = e.ground, e.line.id = t.id, e.point.id = t.id;
282
+ const n = Math.max(0, Math.min(1, t.visualScale));
283
+ Di(e.lineMaterial, n * it.alpha), e.point.color = st(He, n * He.alpha, e.point.color), e.point.outlineColor = st(
284
+ De,
285
+ n * De.alpha,
286
+ e.point.outlineColor
287
+ ), e.line.show = n > 1e-3, e.point.show = n > 1e-3;
288
+ }
289
+ }
290
+ function Di(i, e) {
291
+ const t = i.uniforms;
292
+ !t || !t.color || (t.color.alpha = e);
293
+ }
294
+ function st(i, e, t) {
295
+ const s = t ?? new D();
296
+ return s.red = i.red, s.green = i.green, s.blue = i.blue, s.alpha = e, s;
297
+ }
298
+ const F = Re, ce = F.Buffer, he = F.BufferUsage, Ei = F.VertexArray, nt = F.IndexDatatype, _i = F.ShaderProgram, Oi = F.DrawCommand, Bi = F.RenderState, Ni = F.Pass, Fi = F.PrimitiveType, se = F.ComponentDatatype, zi = F.Texture, Vi = F.Sampler, Wi = {
299
+ 5120: Int8Array,
300
+ 5121: Uint8Array,
301
+ 5122: Int16Array,
302
+ 5123: Uint16Array,
303
+ 5125: Uint32Array,
304
+ 5126: Float32Array
305
+ }, Xi = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT4: 16 };
306
+ class Ui {
307
+ constructor(e, t, s = 8e3) {
308
+ a(this, "url");
309
+ a(this, "scene");
310
+ a(this, "capacity");
311
+ a(this, "center", new f());
312
+ a(this, "instMatrices", new Float32Array(0));
313
+ // count*16, RTC 相对
314
+ a(this, "count", 0);
315
+ a(this, "dirty", !1);
316
+ a(this, "ready", !1);
317
+ a(this, "show", !0);
318
+ a(this, "groups", []);
319
+ a(this, "segments", []);
320
+ // {cmd, instBufs[4], va, sp, texture}
321
+ a(this, "built", !1);
322
+ a(this, "_mm");
323
+ a(this, "_cols", []);
324
+ this.scene = e, this.url = t, this.capacity = s, this.instMatrices = new Float32Array(s * 16), this.load(t);
325
+ }
326
+ /** matrices: Float32Array(count*16) 列主序,平移已相对 center。 */
327
+ setInstances(e, t, s) {
328
+ this.count = Math.min(t, this.capacity), this.instMatrices.set(e.subarray(0, this.count * 16)), f.clone(s, this.center), this.dirty = !0;
329
+ }
330
+ setVisible(e) {
331
+ this.show = e;
332
+ }
333
+ async load(e) {
334
+ try {
335
+ const s = await (await fetch(e)).json(), n = (s.buffers ?? []).map((o) => Yi(o.uri));
336
+ this.groups = Ji(s, n), this.ready = this.groups.length > 0;
337
+ } catch (t) {
338
+ console.warn("[multi-target] InstancedGltfBatch load failed", e, t);
339
+ }
340
+ }
341
+ update(e) {
342
+ if (!this.show || !this.ready || this.count === 0)
343
+ return;
344
+ const t = e.context;
345
+ this.built || this.build(t), R.fromTranslation(this.center, this._mm ?? (this._mm = new R()));
346
+ for (const s of this.segments) {
347
+ if (this.dirty)
348
+ for (let n = 0; n < 4; n++)
349
+ s.instBufs[n].copyFromArrayView(this.columnView(n), 0);
350
+ R.clone(this._mm, s.cmd.modelMatrix), s.cmd.instanceCount = this.count, e.commandList.push(s.cmd);
351
+ }
352
+ this.dirty = !1;
353
+ }
354
+ // 把 count*16 拆成第 k 列(count*4)
355
+ columnView(e) {
356
+ this._cols[e] || (this._cols[e] = new Float32Array(this.capacity * 4));
357
+ const t = this._cols[e];
358
+ for (let s = 0; s < this.count; s++)
359
+ t[s * 4 + 0] = this.instMatrices[s * 16 + e * 4 + 0], t[s * 4 + 1] = this.instMatrices[s * 16 + e * 4 + 1], t[s * 4 + 2] = this.instMatrices[s * 16 + e * 4 + 2], t[s * 4 + 3] = this.instMatrices[s * 16 + e * 4 + 3];
360
+ return t;
361
+ }
362
+ build(e) {
363
+ this.built = !0;
364
+ for (const t of this.groups) {
365
+ const s = ce.createVertexBuffer({ context: e, typedArray: new Float32Array(t.positions), usage: he.STATIC_DRAW }), n = ce.createVertexBuffer({ context: e, typedArray: new Float32Array(t.normals), usage: he.STATIC_DRAW }), o = ce.createVertexBuffer({ context: e, typedArray: new Float32Array(t.uvs), usage: he.STATIC_DRAW }), r = t.vcount > 65535 ? new Uint32Array(t.indices) : new Uint16Array(t.indices), l = ce.createIndexBuffer({
366
+ context: e,
367
+ typedArray: r,
368
+ usage: he.STATIC_DRAW,
369
+ indexDatatype: t.vcount > 65535 ? nt.UNSIGNED_INT : nt.UNSIGNED_SHORT
370
+ }), h = [0, 1, 2, 3].map(
371
+ () => ce.createVertexBuffer({ context: e, typedArray: new Float32Array(this.capacity * 4), usage: he.DYNAMIC_DRAW })
372
+ ), c = new Ei({
373
+ context: e,
374
+ attributes: [
375
+ { index: 0, vertexBuffer: s, componentsPerAttribute: 3, componentDatatype: se.FLOAT },
376
+ { index: 1, vertexBuffer: n, componentsPerAttribute: 3, componentDatatype: se.FLOAT },
377
+ { index: 2, vertexBuffer: o, componentsPerAttribute: 2, componentDatatype: se.FLOAT },
378
+ { index: 3, vertexBuffer: h[0], componentsPerAttribute: 4, componentDatatype: se.FLOAT, instanceDivisor: 1 },
379
+ { index: 4, vertexBuffer: h[1], componentsPerAttribute: 4, componentDatatype: se.FLOAT, instanceDivisor: 1 },
380
+ { index: 5, vertexBuffer: h[2], componentsPerAttribute: 4, componentDatatype: se.FLOAT, instanceDivisor: 1 },
381
+ { index: 6, vertexBuffer: h[3], componentsPerAttribute: 4, componentDatatype: se.FLOAT, instanceDivisor: 1 }
382
+ ],
383
+ indexBuffer: l
384
+ }), m = _i.fromCache({
385
+ context: e,
386
+ vertexShaderSource: Gi,
387
+ fragmentShaderSource: Zi,
388
+ attributeLocations: { a_pos: 0, a_nrm: 1, a_uv: 2, a_m0: 3, a_m1: 4, a_m2: 5, a_m3: 6 }
389
+ }), u = this.makeTexture(e, t.imageUri), v = {
390
+ u_tex: () => u.value ?? e.defaultTexture,
391
+ u_hasTex: () => u.value ? 1 : 0
392
+ }, d = new Oi({
393
+ primitiveType: Fi.TRIANGLES,
394
+ vertexArray: c,
395
+ shaderProgram: m,
396
+ renderState: Bi.fromCache({ depthTest: { enabled: !0 }, depthMask: !0, cull: { enabled: !1 } }),
397
+ pass: Ni.OPAQUE,
398
+ modelMatrix: R.clone(R.IDENTITY, new R()),
399
+ uniformMap: v,
400
+ count: t.indices.length,
401
+ instanceCount: this.count,
402
+ cull: !1,
403
+ boundingVolume: new Ze(f.ZERO, 1e8),
404
+ owner: this
405
+ });
406
+ this.segments.push({ cmd: d, instBufs: h, va: c, sp: m, texture: u });
407
+ }
408
+ }
409
+ makeTexture(e, t) {
410
+ const s = { value: void 0 };
411
+ if (!t)
412
+ return s;
413
+ const n = new Image();
414
+ return n.onload = () => {
415
+ var o, r;
416
+ s.value = new zi({ context: e, source: n, flipY: !1, sampler: new Vi({}) }), (r = (o = this.scene).requestRender) == null || r.call(o);
417
+ }, n.src = t, s;
418
+ }
419
+ isDestroyed() {
420
+ return !1;
421
+ }
422
+ destroy() {
423
+ for (const e of this.segments)
424
+ e.sp && e.sp.destroy(), e.va && e.va.destroy(), e.texture && e.texture.value && e.texture.value.destroy();
425
+ return this.segments = [], !0;
426
+ }
427
+ }
428
+ const Gi = `
429
+ in vec3 a_pos;
430
+ in vec3 a_nrm;
431
+ in vec2 a_uv;
432
+ in vec4 a_m0;
433
+ in vec4 a_m1;
434
+ in vec4 a_m2;
435
+ in vec4 a_m3;
436
+ out vec2 v_uv;
437
+ out vec3 v_nrm;
438
+ void main() {
439
+ mat4 inst = mat4(a_m0, a_m1, a_m2, a_m3);
440
+ vec4 worldRTC = inst * vec4(a_pos, 1.0);
441
+ v_uv = a_uv;
442
+ v_nrm = normalize(mat3(a_m0.xyz, a_m1.xyz, a_m2.xyz) * a_nrm);
443
+ gl_Position = czm_modelViewProjection * worldRTC;
444
+ czm_vertexLogDepth();
445
+ }
446
+ `, Zi = `
447
+ in vec2 v_uv;
448
+ in vec3 v_nrm;
449
+ uniform sampler2D u_tex;
450
+ uniform float u_hasTex;
451
+ void main() {
452
+ vec3 base = u_hasTex > 0.5 ? texture(u_tex, v_uv).rgb : vec3(0.7);
453
+ float lambert = 0.45 + 0.55 * max(0.0, dot(v_nrm, czm_sunDirectionWC));
454
+ out_FragColor = vec4(base * lambert, 1.0);
455
+ }
456
+ `;
457
+ function Yi(i) {
458
+ const e = i.split(",")[1] ?? "", t = atob(e), s = new Uint8Array(t.length);
459
+ for (let n = 0; n < t.length; n++)
460
+ s[n] = t.charCodeAt(n);
461
+ return s.buffer;
462
+ }
463
+ function we(i, e, t) {
464
+ const s = i.accessors[t], n = i.bufferViews[s.bufferView], o = e[n.buffer], r = Xi[s.type], l = Wi[s.componentType], h = l.BYTES_PER_ELEMENT, c = (n.byteOffset ?? 0) + (s.byteOffset ?? 0), m = n.byteStride, u = new Float32Array(s.count * r);
465
+ if (!m || m === r * h) {
466
+ const v = new l(o, c, s.count * r);
467
+ for (let d = 0; d < u.length; d++)
468
+ u[d] = v[d];
469
+ } else {
470
+ const v = new DataView(o);
471
+ for (let d = 0; d < s.count; d++)
472
+ for (let p = 0; p < r; p++) {
473
+ const g = c + d * m + p * h;
474
+ u[d * r + p] = Ki(v, g, s.componentType);
475
+ }
476
+ }
477
+ return u;
478
+ }
479
+ function Ki(i, e, t) {
480
+ switch (t) {
481
+ case 5126:
482
+ return i.getFloat32(e, !0);
483
+ case 5125:
484
+ return i.getUint32(e, !0);
485
+ case 5123:
486
+ return i.getUint16(e, !0);
487
+ case 5122:
488
+ return i.getInt16(e, !0);
489
+ case 5121:
490
+ return i.getUint8(e);
491
+ default:
492
+ return i.getInt8(e);
493
+ }
494
+ }
495
+ function qi(i) {
496
+ if (i.matrix)
497
+ return R.fromColumnMajorArray(i.matrix, new R());
498
+ const e = i.translation ? new f(i.translation[0], i.translation[1], i.translation[2]) : f.ZERO, t = i.rotation ? new Re.Quaternion(i.rotation[0], i.rotation[1], i.rotation[2], i.rotation[3]) : Re.Quaternion.IDENTITY, s = i.scale ? new f(i.scale[0], i.scale[1], i.scale[2]) : new f(1, 1, 1);
499
+ return R.fromTranslationQuaternionRotationScale(e, t, s, new R());
500
+ }
501
+ function $i(i, e) {
502
+ var o, r, l, h, c, m, u;
503
+ if (e == null)
504
+ return;
505
+ const t = (o = i.materials) == null ? void 0 : o[e], s = (l = (r = t == null ? void 0 : t.pbrMetallicRoughness) == null ? void 0 : r.baseColorTexture) == null ? void 0 : l.index;
506
+ if (s == null)
507
+ return;
508
+ const n = (c = (h = i.textures) == null ? void 0 : h[s]) == null ? void 0 : c.source;
509
+ if (n != null)
510
+ return (u = (m = i.images) == null ? void 0 : m[n]) == null ? void 0 : u.uri;
511
+ }
512
+ function ji() {
513
+ const i = F.Axis, e = R.clone(i.Y_UP_TO_Z_UP, new R());
514
+ return R.multiplyTransformation(e, i.Z_UP_TO_X_UP, e);
515
+ }
516
+ function Ji(i, e) {
517
+ var l, h;
518
+ const t = /* @__PURE__ */ new Map(), s = ((h = (l = i.scenes) == null ? void 0 : l[i.scene ?? 0]) == null ? void 0 : h.nodes) ?? [], n = ji(), o = new f(), r = (c, m) => {
519
+ const u = i.nodes[c], v = R.multiply(m, qi(u), new R());
520
+ if (u.mesh != null)
521
+ for (const d of i.meshes[u.mesh].primitives) {
522
+ const p = we(i, e, d.attributes.POSITION), g = d.attributes.NORMAL != null ? we(i, e, d.attributes.NORMAL) : null, y = d.attributes.TEXCOORD_0 != null ? we(i, e, d.attributes.TEXCOORD_0) : null, w = d.indices != null ? we(i, e, d.indices) : null, M = $i(i, d.material) ?? "__none__";
523
+ let I = t.get(M);
524
+ I || (I = { positions: [], normals: [], uvs: [], indices: [], vcount: 0, imageUri: M === "__none__" ? void 0 : M }, t.set(M, I));
525
+ const C = I.vcount, k = p.length / 3;
526
+ for (let S = 0; S < k; S++)
527
+ o.x = p[S * 3], o.y = p[S * 3 + 1], o.z = p[S * 3 + 2], R.multiplyByPoint(v, o, o), I.positions.push(o.x, o.y, o.z), g ? (o.x = g[S * 3], o.y = g[S * 3 + 1], o.z = g[S * 3 + 2], R.multiplyByPointAsVector(v, o, o), f.normalize(o, o), I.normals.push(o.x, o.y, o.z)) : I.normals.push(0, 0, 1), y ? I.uvs.push(y[S * 2], y[S * 2 + 1]) : I.uvs.push(0, 0);
528
+ if (w)
529
+ for (let S = 0; S < w.length; S++)
530
+ I.indices.push(C + w[S]);
531
+ else
532
+ for (let S = 0; S < k; S++)
533
+ I.indices.push(C + S);
534
+ I.vcount += k;
535
+ }
536
+ for (const d of u.children ?? [])
537
+ r(d, v);
538
+ };
539
+ for (const c of s)
540
+ r(c, n);
541
+ return Array.from(t.values());
542
+ }
543
+ const Qi = 400, Ee = 8e3;
544
+ class Ut {
545
+ constructor(e, t) {
546
+ a(this, "renderIds", /* @__PURE__ */ new Set());
547
+ a(this, "states", /* @__PURE__ */ new Map());
548
+ a(this, "batches", /* @__PURE__ */ new Map());
549
+ // url -> batch
550
+ a(this, "scratch", /* @__PURE__ */ new Map());
551
+ // url -> mats 缓冲
552
+ a(this, "center", new f());
553
+ this.scene = e, this.fadeMs = t;
554
+ }
555
+ activeTargetIds() {
556
+ return Array.from(this.renderIds);
557
+ }
558
+ setCandidates(e) {
559
+ const t = new Set(e.map((s) => s.id));
560
+ this.renderIds.clear();
561
+ for (const s of e)
562
+ this.renderIds.add(s.id);
563
+ for (const s of e) {
564
+ let n = this.states.get(s.id);
565
+ n || (n = ts(s), this.states.set(s.id, n)), this.applyCandidate(n, s);
566
+ }
567
+ for (const [, s] of this.states)
568
+ t.has(s.id) || (s.active = !1);
569
+ return this.activeTargetIds();
570
+ }
571
+ getTargetFrame(e, t = new f()) {
572
+ const s = this.states.get(e);
573
+ if (!(!s || s.visualScale <= 1e-3))
574
+ return { position: f.clone(s.currentPosition, t), heading: s.currentHeading };
575
+ }
576
+ update(e) {
577
+ const t = ss(e, this.fadeMs);
578
+ for (const [n, o] of Array.from(this.states))
579
+ is(o, e), o.visualScale = ns(o.visualScale, o.active ? 1 : 0, t), o.modelMatrix = Gt(o, o.modelStyle, o.modelMatrix), o.scaledMatrix = R.multiplyByUniformScale(o.modelMatrix, Math.max(1e-3, o.visualScale), o.scaledMatrix), !o.active && o.visualScale <= 1e-3 && (this.states.delete(n), this.renderIds.delete(n));
580
+ f.clone(this.scene.camera.positionWC, this.center);
581
+ const s = /* @__PURE__ */ new Map();
582
+ for (const n of this.states.values()) {
583
+ if (n.visualScale <= 1e-3)
584
+ continue;
585
+ const o = n.url;
586
+ let r = this.batches.get(o);
587
+ r || (r = new Ui(this.scene, o, Ee), this.batches.set(o, r), this.scene.primitives.add(r));
588
+ let l = this.scratch.get(o);
589
+ l || (l = new Float32Array(Ee * 16), this.scratch.set(o, l));
590
+ const h = s.get(o) ?? 0;
591
+ if (h >= Ee)
592
+ continue;
593
+ const c = n.scaledMatrix, m = h * 16;
594
+ for (let u = 0; u < 16; u++)
595
+ l[m + u] = c[u];
596
+ l[m + 12] = c[12] - this.center.x, l[m + 13] = c[13] - this.center.y, l[m + 14] = c[14] - this.center.z, s.set(o, h + 1);
597
+ }
598
+ for (const [n, o] of this.batches) {
599
+ const r = this.scratch.get(n);
600
+ o.setInstances(r ?? es, s.get(n) ?? 0, this.center);
601
+ }
602
+ }
603
+ clear() {
604
+ this.renderIds.clear();
605
+ for (const e of this.states.values())
606
+ e.active = !1;
607
+ }
608
+ suspend() {
609
+ this.renderIds.clear(), this.states.clear();
610
+ for (const e of this.batches.values())
611
+ this.scene.primitives.remove(e);
612
+ this.batches.clear(), this.scratch.clear();
613
+ }
614
+ destroy() {
615
+ this.suspend();
616
+ }
617
+ applyCandidate(e, t) {
618
+ e.active = !0, e.url = t.url, e.modelKey = t.modelKey, e.modelStyle = t.modelStyle, e.position = t.position, e.heading = t.heading, e.smoothMove = t.smoothMove, e.moveDurationMs = t.moveDurationMs, t.smoothMove ? (f.clone(e.currentPosition, e.startPosition), f.clone(t.position, e.targetPosition), e.startHeading = e.currentHeading, e.targetHeading = t.heading, e.moveElapsedSec = 0, e.moveDurationSec = Math.max(16, t.moveDurationMs || Qi) / 1e3) : (f.clone(t.position, e.currentPosition), f.clone(t.position, e.startPosition), f.clone(t.position, e.targetPosition), e.currentHeading = t.heading, e.startHeading = t.heading, e.targetHeading = t.heading, e.moveElapsedSec = 0, e.moveDurationSec = 0);
619
+ }
620
+ }
621
+ const es = new Float32Array(0);
622
+ function ts(i) {
623
+ const e = Gt(
624
+ { ...i, currentPosition: i.position, currentHeading: i.heading },
625
+ i.modelStyle,
626
+ R.clone(R.IDENTITY)
627
+ );
628
+ return {
629
+ ...i,
630
+ active: !0,
631
+ currentPosition: f.clone(i.position),
632
+ startPosition: f.clone(i.position),
633
+ targetPosition: f.clone(i.position),
634
+ currentHeading: i.heading,
635
+ startHeading: i.heading,
636
+ targetHeading: i.heading,
637
+ moveElapsedSec: 0,
638
+ moveDurationSec: 0,
639
+ visualScale: 0,
640
+ modelMatrix: e,
641
+ scaledMatrix: R.clone(e)
642
+ };
643
+ }
644
+ function is(i, e) {
645
+ if (i.moveDurationSec <= 0)
646
+ return;
647
+ i.moveElapsedSec += e;
648
+ const t = os(Math.min(1, i.moveElapsedSec / Math.max(1e-3, i.moveDurationSec)));
649
+ f.lerp(i.startPosition, i.targetPosition, t, i.currentPosition), i.currentHeading = rs(i.startHeading, i.targetHeading, t), t >= 1 && (f.clone(i.targetPosition, i.currentPosition), i.currentHeading = i.targetHeading, i.moveElapsedSec = 0, i.moveDurationSec = 0);
650
+ }
651
+ function Gt(i, e, t) {
652
+ const s = new Vt(
653
+ A.toRadians(i.currentHeading + (e.headingOffset ?? 0)),
654
+ A.toRadians(e.pitchOffset ?? 0),
655
+ A.toRadians(e.rollOffset ?? 0)
656
+ );
657
+ return Ye.headingPitchRollToFixedFrame(i.currentPosition, s, void 0, void 0, t), R.multiplyByUniformScale(t, e.scale ?? 1, t);
658
+ }
659
+ function ss(i, e) {
660
+ return e <= 0 ? 1 : Math.max(0, i * 1e3 / e);
661
+ }
662
+ function ns(i, e, t) {
663
+ return i < e ? Math.min(e, i + t) : i > e ? Math.max(e, i - t) : i;
664
+ }
665
+ function os(i) {
666
+ return i < 0.5 ? 4 * i * i * i : 1 - Math.pow(-2 * i + 2, 3) / 2;
667
+ }
668
+ function rs(i, e, t) {
669
+ const s = ((e - i) % 360 + 540) % 360 - 180;
670
+ return i + s * t;
671
+ }
672
+ const as = 1, ls = 2, cs = 16, hs = 32, ds = 64, Zt = 400, us = 0.75;
673
+ class fs {
674
+ constructor(e, t, s, n, o, r) {
675
+ a(this, "lowModels");
676
+ a(this, "airReferences");
677
+ a(this, "renderIds", /* @__PURE__ */ new Set());
678
+ a(this, "states", /* @__PURE__ */ new Map());
679
+ a(this, "retiring", []);
680
+ a(this, "scene");
681
+ a(this, "animationKeepAliveElapsedSec", 0);
682
+ a(this, "lastLowRenderCount", 0);
683
+ a(this, "lastHighRenderCount", 0);
684
+ this.viewer = e, this.styles = t, this.lowCapacity = s, this.highCapacity = n, this.fadeMs = r, this.scene = e.scene, this.lowModels = new Ut(this.scene, r), this.airReferences = new Hi(this.scene);
685
+ }
686
+ activeTargetIds() {
687
+ return [...this.lowModels.activeTargetIds(), ...Array.from(this.renderIds)];
688
+ }
689
+ renderStats() {
690
+ return { low: this.lastLowRenderCount, high: this.lastHighRenderCount };
691
+ }
692
+ getTargetFrame(e, t = new f()) {
693
+ const s = this.states.get(e);
694
+ return s != null && s.active && s.visualScale > 1e-3 ? {
695
+ position: f.clone(s.currentPosition, t),
696
+ heading: s.currentHeading
697
+ } : this.lowModels.getTargetFrame(e, t);
698
+ }
699
+ setPacket(e) {
700
+ const t = ms(e, this.styles, this.viewer.scene.camera.positionCartographic.height), s = t.filter((h) => h.lodKind === 1).slice(0, this.lowCapacity), n = t.filter((h) => h.lodKind === 2).slice(0, this.highCapacity);
701
+ this.lastLowRenderCount = s.length, this.lastHighRenderCount = n.length, this.lowModels.setCandidates(s);
702
+ const o = n, r = new Set(o.map((h) => h.id));
703
+ for (const h of Array.from(this.renderIds))
704
+ r.has(h) || this.renderIds.delete(h);
705
+ for (const h of o)
706
+ this.renderIds.add(h.id);
707
+ const l = new Map(o.map((h) => [h.id, h]));
708
+ for (const h of this.renderIds) {
709
+ const c = l.get(h);
710
+ if (!c)
711
+ continue;
712
+ let m = this.states.get(h);
713
+ m || (m = ps(c), this.states.set(h, m)), this.applyCandidate(m, c);
714
+ }
715
+ for (const [h, c] of Array.from(this.states))
716
+ this.renderIds.has(h) || (c.active = !1);
717
+ return this.activeTargetIds();
718
+ }
719
+ update(e) {
720
+ this.lowModels.update(e), this.animationKeepAliveElapsedSec += e;
721
+ const t = this.animationKeepAliveElapsedSec >= us;
722
+ let s = !1;
723
+ const n = vs(e, this.fadeMs);
724
+ for (const [o, r] of Array.from(this.states))
725
+ gs(r, e), r.visualScale = ot(r.visualScale, r.active ? 1 : 0, n), r.modelMatrix = We(
726
+ r.currentPosition,
727
+ r.currentHeading,
728
+ r.modelStyle,
729
+ r.modelMatrix
730
+ ), r.model && (r.model.modelMatrix = de(r.modelMatrix, r.visualScale, r.transitionMatrix), r.model.show = r.visualScale > 1e-3, r.modelStyle.runAnimations && r.active && (s = !0, t && this.ensureModelAnimations(r.model, r.modelStyle))), !r.active && r.visualScale <= 1e-3 && this.removeState(o, r);
731
+ this.updateAirReferences();
732
+ for (let o = this.retiring.length - 1; o >= 0; o--) {
733
+ const r = this.retiring[o];
734
+ r.visualScale = ot(r.visualScale, 0, n), r.model.modelMatrix = de(r.modelMatrix, r.visualScale, r.transitionMatrix), r.model.show = r.visualScale > 1e-3, r.visualScale <= 1e-3 && (this.scene.primitives.remove(r.model), this.retiring.splice(o, 1));
735
+ }
736
+ s && this.ensureAnimationClock(), t && (this.animationKeepAliveElapsedSec = 0);
737
+ }
738
+ clear() {
739
+ this.lowModels.clear(), this.airReferences.clear(), this.lastLowRenderCount = 0, this.lastHighRenderCount = 0, this.renderIds.clear();
740
+ for (const e of this.states.values())
741
+ e.active = !1;
742
+ }
743
+ suspend() {
744
+ if (this.lowModels.suspend(), this.airReferences.clear(), this.lastLowRenderCount = 0, this.lastHighRenderCount = 0, !(this.renderIds.size === 0 && this.states.size === 0 && this.retiring.length === 0)) {
745
+ this.renderIds.clear();
746
+ for (const e of this.states.values())
747
+ e.model && this.scene.primitives.remove(e.model), e.model = null, e.loading = !1, e.loadToken++;
748
+ this.states.clear();
749
+ for (const e of this.retiring)
750
+ this.scene.primitives.remove(e.model);
751
+ this.retiring.length = 0;
752
+ }
753
+ }
754
+ destroy() {
755
+ this.lowModels.destroy(), this.airReferences.destroy();
756
+ for (const e of this.states.values())
757
+ e.model && this.scene.primitives.remove(e.model), e.model = null, e.loading = !1, e.loadToken++;
758
+ this.states.clear(), this.renderIds.clear();
759
+ for (const e of this.retiring)
760
+ this.scene.primitives.remove(e.model);
761
+ this.retiring.length = 0;
762
+ }
763
+ applyCandidate(e, t) {
764
+ const s = Ms(e, t), n = e.url !== t.url || e.lodKind !== t.lodKind;
765
+ if (n && (this.retireStateModel(e), e.url = t.url, e.modelKey = t.modelKey, e.lodKind = t.lodKind, e.targetDomain = t.targetDomain, e.modelStyle = t.modelStyle, e.visualScale = 0), e.active = !0, e.url = t.url, e.modelKey = t.modelKey, e.modelStyle = t.modelStyle, e.targetDomain = t.targetDomain, e.category = t.category, e.position = t.position, e.heading = t.heading, e.smoothMove = t.smoothMove, e.moveDurationMs = t.moveDurationMs, e.predictMove = t.predictMove, (t.smoothMove || t.predictMove) && e.model && !n && s ? (f.clone(e.currentPosition, e.startPosition), f.clone(t.position, e.targetPosition), e.startHeading = e.currentHeading, e.targetHeading = t.heading, e.moveElapsedSec = 0, e.moveDurationSec = Math.max(16, t.moveDurationMs || Zt) / 1e3) : (f.clone(t.position, e.currentPosition), f.clone(t.position, e.startPosition), f.clone(t.position, e.targetPosition), e.currentHeading = t.heading, e.startHeading = t.heading, e.targetHeading = t.heading, e.moveElapsedSec = 0, e.moveDurationSec = 0), e.modelMatrix = We(
766
+ e.currentPosition,
767
+ e.currentHeading,
768
+ e.modelStyle,
769
+ e.modelMatrix
770
+ ), e.model) {
771
+ e.model.id = e.id, e.model.modelMatrix = de(e.modelMatrix, e.visualScale, e.transitionMatrix), e.model.show = !0;
772
+ return;
773
+ }
774
+ e.loading || this.loadModel(e);
775
+ }
776
+ loadModel(e) {
777
+ const t = ++e.loadToken, s = e.url, n = e.id, o = e.lodKind;
778
+ e.loading = !0, gi.fromGltfAsync({
779
+ url: s,
780
+ scene: this.scene,
781
+ modelMatrix: de(e.modelMatrix, e.visualScale, e.transitionMatrix),
782
+ scale: e.modelStyle.scale ?? 1,
783
+ allowPicking: !0,
784
+ id: n
785
+ }).then((r) => {
786
+ if (e.loadToken !== t || e.url !== s || e.id !== n || e.lodKind !== o || !e.active) {
787
+ this.scene.primitives.remove(r);
788
+ return;
789
+ }
790
+ e.model = this.scene.primitives.add(r), e.model.id = e.id, e.model.show = !0, e.model.modelMatrix = de(e.modelMatrix, e.visualScale, e.transitionMatrix), this.ensureModelAnimations(e.model, e.modelStyle), this.scene.requestRender();
791
+ }).catch((r) => {
792
+ console.warn("[multi-target] model load failed", s, r);
793
+ }).finally(() => {
794
+ e.loadToken === t && (e.loading = !1);
795
+ });
796
+ }
797
+ removeState(e, t) {
798
+ this.retireStateModel(t), t.loadToken++, t.loading = !1, this.states.delete(e);
799
+ }
800
+ retireStateModel(e) {
801
+ e.model && (this.retiring.push({
802
+ model: e.model,
803
+ modelMatrix: R.clone(e.modelMatrix),
804
+ transitionMatrix: R.clone(e.transitionMatrix),
805
+ visualScale: e.visualScale
806
+ }), e.model = null);
807
+ }
808
+ ensureAnimationClock() {
809
+ this.viewer.clock && (this.viewer.clock.shouldAnimate = !0);
810
+ }
811
+ ensureModelAnimations(e, t) {
812
+ if (!t.runAnimations)
813
+ return;
814
+ const s = e;
815
+ if (!s.__multiTargetAnimationUnavailable && (this.ensureAnimationClock(), !Kt(e) && !_e(e, t))) {
816
+ if (s.ready === !0) {
817
+ s.__multiTargetAnimationStarted || (s.__multiTargetAnimationUnavailable = !0);
818
+ return;
819
+ }
820
+ if (!s.__multiTargetAnimationReadyHooked) {
821
+ if (s.readyEvent && typeof s.readyEvent.addEventListener == "function") {
822
+ s.__multiTargetAnimationReadyHooked = !0;
823
+ const n = s.readyEvent.addEventListener(() => {
824
+ s.__multiTargetAnimationReadyHooked = !1, _e(e, t), typeof n == "function" && n();
825
+ });
826
+ return;
827
+ }
828
+ s.readyPromise && typeof s.readyPromise.then == "function" && (s.__multiTargetAnimationReadyHooked = !0, s.readyPromise.then(() => {
829
+ s.__multiTargetAnimationReadyHooked = !1, _e(e, t);
830
+ }).catch(() => {
831
+ s.__multiTargetAnimationReadyHooked = !1;
832
+ }));
833
+ }
834
+ }
835
+ }
836
+ updateAirReferences() {
837
+ const e = [];
838
+ for (const t of this.states.values())
839
+ !t.active || t.targetDomain !== "air" || t.visualScale <= 1e-3 || e.push({
840
+ id: t.id,
841
+ position: t.currentPosition,
842
+ visualScale: t.visualScale
843
+ });
844
+ this.airReferences.setTargets(e);
845
+ }
846
+ }
847
+ function ms(i, e, t) {
848
+ const s = [];
849
+ for (let n = 0; n < i.lon.length; n++) {
850
+ const o = i.flags[n], r = o >> ls & 3;
851
+ if (r === 0 || o & as || !(o & ds))
852
+ continue;
853
+ const l = i.ids[n] ?? "";
854
+ if (!l)
855
+ continue;
856
+ const h = i.category[n], c = e[h], m = Ss(c, r);
857
+ if (!m)
858
+ continue;
859
+ const u = m.url, v = (o & hs) !== 0;
860
+ s.push({
861
+ id: l,
862
+ url: u,
863
+ category: h,
864
+ modelKey: Is(u),
865
+ lodKind: r,
866
+ targetDomain: c == null ? void 0 : c.targetDomain,
867
+ modelStyle: m,
868
+ position: f.fromDegrees(i.lon[n], i.lat[n], i.height[n]),
869
+ heading: i.heading[n] || 0,
870
+ smoothMove: (o & cs) !== 0,
871
+ moveDurationMs: i.moveDurationMs[n] || Zt,
872
+ predictMove: v
873
+ });
874
+ }
875
+ return s;
876
+ }
877
+ function ps(i) {
878
+ const e = We(i.position, i.heading, void 0, R.clone(R.IDENTITY));
879
+ return {
880
+ ...i,
881
+ model: null,
882
+ loading: !1,
883
+ loadToken: 0,
884
+ active: !0,
885
+ visualScale: 0,
886
+ currentPosition: f.clone(i.position),
887
+ startPosition: f.clone(i.position),
888
+ targetPosition: f.clone(i.position),
889
+ currentHeading: i.heading,
890
+ startHeading: i.heading,
891
+ targetHeading: i.heading,
892
+ moveElapsedSec: 0,
893
+ moveDurationSec: 0,
894
+ modelMatrix: e,
895
+ transitionMatrix: R.clone(R.IDENTITY)
896
+ };
897
+ }
898
+ function gs(i, e) {
899
+ if (i.moveDurationSec <= 0)
900
+ return;
901
+ i.moveElapsedSec += e;
902
+ const t = Math.min(1, i.moveElapsedSec / Math.max(1e-3, i.moveDurationSec)), s = i.predictMove ? t : ys(t);
903
+ f.lerp(i.startPosition, i.targetPosition, s, i.currentPosition), i.currentHeading = ws(i.startHeading, i.targetHeading, s), s >= 1 && (f.clone(i.targetPosition, i.currentPosition), i.currentHeading = i.targetHeading, i.moveElapsedSec = 0, i.moveDurationSec = 0);
904
+ }
905
+ function vs(i, e) {
906
+ return e <= 0 ? 1 : Math.max(0, i * 1e3 / e);
907
+ }
908
+ function ot(i, e, t) {
909
+ return i < e ? Math.min(e, i + t) : i > e ? Math.max(e, i - t) : i;
910
+ }
911
+ function We(i, e, t, s) {
912
+ const n = new Vt(
913
+ A.toRadians(e + ((t == null ? void 0 : t.headingOffset) ?? 0)),
914
+ A.toRadians((t == null ? void 0 : t.pitchOffset) ?? 0),
915
+ A.toRadians((t == null ? void 0 : t.rollOffset) ?? 0)
916
+ );
917
+ return Ye.headingPitchRollToFixedFrame(i, n, void 0, void 0, s);
918
+ }
919
+ function de(i, e, t) {
920
+ return R.multiplyByUniformScale(i, Math.max(1e-3, e), t);
921
+ }
922
+ function ys(i) {
923
+ return i < 0.5 ? 4 * i * i * i : 1 - Math.pow(-2 * i + 2, 3) / 2;
924
+ }
925
+ function ws(i, e, t) {
926
+ const s = Yt(i, e);
927
+ return i + s * t;
928
+ }
929
+ function Yt(i, e) {
930
+ return ((e - i) % 360 + 540) % 360 - 180;
931
+ }
932
+ function Ms(i, e) {
933
+ return f.distanceSquared(i.position, e.position) > 1e-4 || Math.abs(Yt(i.heading, e.heading)) > 1e-3;
934
+ }
935
+ function Is(i) {
936
+ const e = i.split(/[?#]/, 1)[0] ?? i;
937
+ return e.slice(Math.max(e.lastIndexOf("/"), e.lastIndexOf("\\")) + 1).toLowerCase();
938
+ }
939
+ function Ss(i, e) {
940
+ if (!i)
941
+ return;
942
+ const t = e === 1 ? i.lowModel : i.highModel;
943
+ if (t)
944
+ return rt(t, e);
945
+ const s = e === 1 ? i.lowModelUrl : i.highModelUrl;
946
+ if (s)
947
+ return rt({
948
+ url: s,
949
+ scale: i.scale,
950
+ headingOffset: i.modelHeadingOffset,
951
+ pitchOffset: i.modelPitchOffset,
952
+ rollOffset: i.modelRollOffset
953
+ }, e);
954
+ }
955
+ function rt(i, e) {
956
+ return {
957
+ ...i,
958
+ runAnimations: i.runAnimations ?? e === 2,
959
+ animationLoop: i.animationLoop ?? "repeat",
960
+ animationMultiplier: i.animationMultiplier ?? 1
961
+ };
962
+ }
963
+ function _e(i, e) {
964
+ if (!e.runAnimations)
965
+ return !1;
966
+ const t = i, s = t.activeAnimations;
967
+ if (!s || typeof s.addAll != "function")
968
+ return !1;
969
+ try {
970
+ const n = s.addAll({
971
+ loop: xs(e.animationLoop),
972
+ multiplier: e.animationMultiplier ?? 1
973
+ });
974
+ return (Array.isArray(n) ? n.length > 0 : !!n) || Kt(i) ? (t.__multiTargetAnimationStarted = !0, !0) : !1;
975
+ } catch {
976
+ return !1;
977
+ }
978
+ }
979
+ function Kt(i) {
980
+ const e = i.activeAnimations;
981
+ return !!e && typeof e.length == "number" && e.length > 0;
982
+ }
983
+ function xs(i) {
984
+ return i === "none" ? Le.NONE : i === "mirroredRepeat" ? Le.MIRRORED_REPEAT : Le.REPEAT;
985
+ }
986
+ const Ts = 1.75, te = 36;
987
+ function qt(i, e, t = !1) {
988
+ const s = Math.max(8, e + (t ? 4 : 2)) * 2, n = Math.min(s, 64);
989
+ let o = n * 1.35, r = n * 0.9;
990
+ return i.startsWith("ship") ? (o = n * 1.15, r = n * 1.45) : i.startsWith("uav") ? (o = n * 1.35, r = n * 1.35) : i.startsWith("person") && (o = n * 0.9, r = n * 1.2), {
991
+ width: o,
992
+ height: r,
993
+ maxDimension: Math.max(o, r)
994
+ };
995
+ }
996
+ function $t(i, e, t = !1) {
997
+ const s = qt(i, e, t);
998
+ return Math.max(te, s.maxDimension * Ts);
999
+ }
1000
+ const Cs = [
1001
+ { type: "ship", iconPath: "/icons/target-ship-mask.png", defaultColor: "#25e65c" },
1002
+ { type: "uav", iconPath: "/icons/target-uav-mask.png", defaultColor: "#22d2f2" },
1003
+ { type: "person", iconPath: "/icons/target-person-mask.png", defaultColor: "#ffdc40" },
1004
+ { type: "car", iconPath: "/icons/target-car-mask.png", defaultColor: "#ff9a2a" }
1005
+ ], Oe = 400, bs = 180, at = 100, lt = 1e3, Ps = "target-glow-circle", ct = 3.6, Rs = 0.34, ks = 0.22, As = 64, Y = {
1006
+ enabled: !0,
1007
+ maxCount: 200,
1008
+ maxCameraHeight: 5e3,
1009
+ maxDistance: void 0,
1010
+ fields: [{ key: "id", source: "standard" }],
1011
+ byType: void 0,
1012
+ resolve: void 0,
1013
+ backgroundColor: "#0000008c",
1014
+ textColor: "#ffffff",
1015
+ fontSize: 12,
1016
+ fontFamily: "sans-serif",
1017
+ backgroundRadius: 6,
1018
+ overlapThreshold: 0.35,
1019
+ occlusionGraceMs: 300,
1020
+ offsetX: 18,
1021
+ offsetY: 24,
1022
+ connectorColor: "#eafcffcc",
1023
+ connectorWidth: 1.5,
1024
+ connectorStemLength: 50,
1025
+ showFieldLabels: !0
1026
+ };
1027
+ let Ls = 0;
1028
+ class Hs {
1029
+ constructor(e, t, s = {}) {
1030
+ a(this, "glowCollection");
1031
+ a(this, "collection");
1032
+ a(this, "labelCollection");
1033
+ a(this, "pool", []);
1034
+ a(this, "glowPool", []);
1035
+ a(this, "labelPool", []);
1036
+ a(this, "typeStyles");
1037
+ a(this, "labelConfig");
1038
+ a(this, "labelTextResolver");
1039
+ a(this, "imageIds");
1040
+ a(this, "imageUrls");
1041
+ a(this, "processedImages");
1042
+ a(this, "glowImage");
1043
+ a(this, "labelImageCache", /* @__PURE__ */ new Map());
1044
+ a(this, "glowSourceIndexes", []);
1045
+ a(this, "labelSourceIndexes", []);
1046
+ a(this, "labelIds", []);
1047
+ a(this, "labelSmoothStarts", []);
1048
+ a(this, "labelSmoothTargets", []);
1049
+ a(this, "labelSmoothElapsedSec", []);
1050
+ a(this, "labelSmoothDurationSec", []);
1051
+ a(this, "labelScales", []);
1052
+ a(this, "labelTargetScales", []);
1053
+ a(this, "labelPositionsById", /* @__PURE__ */ new Map());
1054
+ a(this, "labelScalesById", /* @__PURE__ */ new Map());
1055
+ a(this, "labelLastClearVisibleAt", /* @__PURE__ */ new Map());
1056
+ a(this, "labelVisibleIds", /* @__PURE__ */ new Set());
1057
+ a(this, "poolCategories", []);
1058
+ a(this, "poolIds", []);
1059
+ a(this, "poolHeadings", []);
1060
+ a(this, "poolMerged", []);
1061
+ a(this, "colorCache", /* @__PURE__ */ new Map());
1062
+ a(this, "glowColorCache", /* @__PURE__ */ new Map());
1063
+ a(this, "smoothStarts", []);
1064
+ a(this, "smoothTargets", []);
1065
+ a(this, "smoothElapsedSec", []);
1066
+ a(this, "smoothDurationSec", []);
1067
+ a(this, "baseWidths", []);
1068
+ a(this, "baseHeights", []);
1069
+ a(this, "pointScales", /* @__PURE__ */ new Map());
1070
+ a(this, "modelTargetIds", /* @__PURE__ */ new Set());
1071
+ a(this, "modelHandoffEnabled", !1);
1072
+ // 姓名版锚点解析器。相机跟随某目标时用的是 model / 贴地符号(groundSymbols) 的渲染
1073
+ // 位置,而 point billboard 可能被隐藏或走另一条平滑曲线。姓名版必须锚到与相机完全
1074
+ // 相同的位置源,否则相机锁住目标、姓名版却跟着 point 漂移,贴近时剧烈抖动(越近越明显,
1075
+ // 因屏幕像素差∝1/相机距离)。该解析器由 scene 注入,内部即相机用的 getRenderedTargetFrame
1076
+ // 同源链。返回 undefined 时(目标无 model/symbol)回退到本地 point 平滑位置。
1077
+ a(this, "anchorPositionResolver", null);
1078
+ a(this, "anchorPositionScratch", new f());
1079
+ a(this, "directionalExternal", !1);
1080
+ a(this, "targetVisible", !0);
1081
+ a(this, "visibleCount", 0);
1082
+ a(this, "glowActiveCount", 0);
1083
+ a(this, "labelActiveCount", 0);
1084
+ a(this, "glowPhase", 0);
1085
+ // 姓名版 RTC(相对相机中心):贴近时绝对 ECEF 坐标(~6.3e6 米)经 GPU Float32 投影会量化抖动
1086
+ // (~0.3-0.7m,贴近放大成数像素)。把 labelCollection.modelMatrix 设为“相机位置(网格丸)平移”,
1087
+ // billboard.position 只存“锚点 - 参考点”的米级小偏移,GPU 投影不再碰大坐标 → 消除抖动。
1088
+ // 参考点用 100m 网格丸,避免相机微动导致参考点每帧跳、引入新抖源。
1089
+ a(this, "labelRtcRef", new f());
1090
+ a(this, "labelRtcScratch", new f());
1091
+ var n;
1092
+ this.scene = e, this.typeStyles = (n = s.targetTypes) != null && n.length ? s.targetTypes : Cs, this.labelConfig = dt(s.label), this.labelTextResolver = s.labelTextResolver ?? ((o) => Us(o, this.labelConfig)), this.imageIds = this.typeStyles.map((o, r) => `target-${r}-${o.type}`), this.imageUrls = this.typeStyles.map((o) => o.iconPath), this.processedImages = [...this.imageUrls], this.glowImage = Ks(), this.glowCollection = this.scene.primitives.add(new fe({ scene: e })), this.collection = this.scene.primitives.add(new fe({ scene: e })), this.labelCollection = this.scene.primitives.add(new fe({ scene: e })), this.glowCollection.show = !0, this.collection.show = !0, this.labelCollection.show = !0, this.preprocessImages(), this.ensureLabelPool(Math.min(this.labelConfig.maxCount, at));
1093
+ }
1094
+ setPacket(e) {
1095
+ var h;
1096
+ const t = e.lon.length;
1097
+ this.ensurePool(t), this.ensureGlowPool(), this.syncLabelRtcReference();
1098
+ let s = 0, n = 0;
1099
+ const o = /* @__PURE__ */ new Set(), r = this.labelVisibleIds, l = this.selectLabelInfos(e);
1100
+ this.ensureLabelPool(l.size);
1101
+ for (let c = 0; c < t; c++) {
1102
+ const m = this.pool[c], u = (e.flags[c] & 1) === 1;
1103
+ this.poolMerged[c] = u;
1104
+ const v = ht(e.category[c] ?? 0, this.imageIds.length), d = Ds(e.color[c], u, this.colorCache), p = qt(((h = this.typeStyles[v]) == null ? void 0 : h.type) ?? "", e.size[c], u), g = this.poolIds[c] === e.ids[c];
1105
+ this.poolCategories[c] !== v && (m.setImage(this.imageIds[v], this.processedImages[v]), this.poolCategories[c] = v), this.poolIds[c] = e.ids[c];
1106
+ const y = f.fromDegrees(e.lon[c], e.lat[c], e.height[c]), w = (e.flags[c] & 16) !== 0 && g && (m.show || this.directionalExternal);
1107
+ w ? (this.smoothStarts[c] = f.clone(m.position, this.smoothStarts[c] ?? new f()), this.smoothTargets[c] = y, this.smoothElapsedSec[c] = 0, this.smoothDurationSec[c] = Math.max(16, e.moveDurationMs[c] || Oe) / 1e3) : (m.position = y, this.smoothStarts[c] = null, this.smoothTargets[c] = null, this.smoothElapsedSec[c] = 0, this.smoothDurationSec[c] = 0), this.baseWidths[c] = p.width, this.baseHeights[c] = p.height;
1108
+ const M = this.modelHandoffEnabled ? this.pointScales.get(e.ids[c]) ?? (this.modelTargetIds.has(e.ids[c]) ? 0 : 1) : 1;
1109
+ if (m.width = p.width * Math.max(1e-3, M), m.height = p.height * Math.max(1e-3, M), m.rotation = -A.toRadians(e.heading[c] || 0), this.poolHeadings[c] = e.heading[c] || 0, m.color = d, m.id = e.ids[c], m.show = this.slotVisible(c), e.animation[c] === 1 && this.targetVisible && s < lt) {
1110
+ const C = this.glowPool[s];
1111
+ C.position = m.position, C.width = p.width * ct, C.height = p.height * ct, C.color = Es(e.animationColor[c] || e.color[c], this.glowColorCache, this.glowPhase), C.show = !0, this.glowSourceIndexes[s] = c, s++;
1112
+ }
1113
+ const I = l.get(c);
1114
+ if (I) {
1115
+ const C = e.ids[c] ?? "", k = this.labelPool[n], S = this.labelIds[n] !== C;
1116
+ S && (k.show = !1, k.scale = 0), this.setLabelPosition(n, k, C, m.position, w, e.moveDurationMs[c]), k.width = I.width, k.height = I.height, k.pixelOffset = new J(-I.anchorX, I.marginY), k.setImage(I.id, I.image), S && (this.labelScales[n] = C && r.has(C) ? this.labelScalesById.get(C) ?? 1 : 0), this.labelTargetScales[n] = 1, k.scale = this.labelScales[n] || 0, this.labelSourceIndexes[n] = c, this.labelIds[n] = C, this.updateLabelPosition(n), k.show = !0, C && (o.add(C), this.labelScalesById.set(C, this.labelScales[n] ?? 0)), n++;
1117
+ }
1118
+ }
1119
+ this.hideUnusedGlows(s), this.hideUnusedLabels(n, o), this.labelVisibleIds = o, this.glowActiveCount = s, this.labelActiveCount = Math.max(this.labelActiveCount, n), this.hideUnused(t);
1120
+ }
1121
+ clear() {
1122
+ this.hideUnused(0);
1123
+ }
1124
+ getTargetFrame(e, t = new f()) {
1125
+ for (let s = 0; s < this.visibleCount; s++)
1126
+ if (!(this.poolIds[s] !== e || !this.pool[s].show))
1127
+ return {
1128
+ position: f.clone(this.pool[s].position, t),
1129
+ heading: this.poolHeadings[s] || 0
1130
+ };
1131
+ }
1132
+ update(e) {
1133
+ this.glowPhase = (this.glowPhase + e * 2.8) % (Math.PI * 2), this.collection.show = this.targetVisible, this.glowCollection.show = this.targetVisible, this.labelCollection.show = !0, this.syncLabelRtcReference();
1134
+ for (let s = 0; s < this.visibleCount; s++) {
1135
+ const n = this.smoothStarts[s], o = this.smoothTargets[s];
1136
+ if (!n || !o)
1137
+ continue;
1138
+ this.smoothElapsedSec[s] += e;
1139
+ const r = Math.max(1e-3, this.smoothDurationSec[s] || Oe / 1e3), l = Gs(Math.min(1, this.smoothElapsedSec[s] / r)), h = f.lerp(n, o, l, new f());
1140
+ this.pool[s].position = h, l >= 1 && (this.pool[s].position = o, this.smoothStarts[s] = null, this.smoothTargets[s] = null);
1141
+ }
1142
+ const t = Zs(e, Oe);
1143
+ for (let s = 0; s < this.visibleCount; s++) {
1144
+ const n = this.poolIds[s];
1145
+ if (!n)
1146
+ continue;
1147
+ if (!this.modelHandoffEnabled) {
1148
+ this.pool[s].width = this.baseWidths[s] || 9, this.pool[s].height = this.baseHeights[s] || 9, this.pool[s].show = this.slotVisible(s);
1149
+ continue;
1150
+ }
1151
+ const o = this.modelHandoffEnabled && this.modelTargetIds.has(n) ? 0 : 1, r = this.pointScales.get(n) ?? 1, l = ut(r, o, t);
1152
+ this.pointScales.set(n, l), this.pool[s].width = (this.baseWidths[s] || 9) * Math.max(1e-3, l), this.pool[s].height = (this.baseHeights[s] || 9) * Math.max(1e-3, l), this.pool[s].show = this.slotVisible(s) && l > 1e-3;
1153
+ }
1154
+ if (this.glowActiveCount > 0) {
1155
+ const s = Jt(this.glowPhase);
1156
+ for (let n = 0; n < this.glowActiveCount; n++) {
1157
+ const o = this.glowPool[n], r = this.glowSourceIndexes[n];
1158
+ o.position = this.pool[r].position, o.color = o.color.withAlpha(s);
1159
+ }
1160
+ }
1161
+ for (let s = 0; s < this.labelActiveCount; s++)
1162
+ this.updateLabelScale(s, e), this.labelPool[s].show && this.updateLabelPosition(s);
1163
+ this.trimInactiveLabels();
1164
+ }
1165
+ setPointLayerVisible(e) {
1166
+ this.targetVisible = e, this.collection.show = e, this.glowCollection.show = e;
1167
+ }
1168
+ /** 单目标有向图标是否交由外部(实例化符号层)渲染。开启后本渲染器对 count===1 的条目不显示 billboard,
1169
+ * 仍保留 merged 簇 billboard、glow、姓名版。 */
1170
+ setDirectionalHandledExternally(e) {
1171
+ this.directionalExternal = e;
1172
+ }
1173
+ slotVisible(e) {
1174
+ return !(!this.targetVisible || this.directionalExternal && !this.poolMerged[e]);
1175
+ }
1176
+ setModelTargetIds(e, t = !0) {
1177
+ this.modelHandoffEnabled = t && e.length > 0, this.modelTargetIds = this.modelHandoffEnabled ? new Set(e) : /* @__PURE__ */ new Set(), this.modelHandoffEnabled || this.pointScales.clear();
1178
+ }
1179
+ // 注入姓名版锚点解析器:让姓名版锚到与相机完全相同的渲染位置源(model/symbol),消除
1180
+ // 贴近时姓名版相对相机/目标的抖动。返回 undefined 时回退到 point 位置。
1181
+ setAnchorPositionResolver(e) {
1182
+ this.anchorPositionResolver = e;
1183
+ }
1184
+ syncLabelRtcReference() {
1185
+ const e = this.scene.camera.positionWC;
1186
+ this.labelRtcRef.x = Math.floor(e.x / 100) * 100, this.labelRtcRef.y = Math.floor(e.y / 100) * 100, this.labelRtcRef.z = Math.floor(e.z / 100) * 100, R.fromTranslation(this.labelRtcRef, this.labelCollection.modelMatrix);
1187
+ }
1188
+ updateLabelPosition(e) {
1189
+ const t = this.labelSourceIndexes[e];
1190
+ if (t < 0)
1191
+ return;
1192
+ const s = this.labelIds[e];
1193
+ let n = this.pool[t].position;
1194
+ if (s && this.anchorPositionResolver) {
1195
+ const o = this.anchorPositionResolver(s, this.anchorPositionScratch);
1196
+ o && (n = o);
1197
+ }
1198
+ this.labelPool[e].position = f.subtract(n, this.labelRtcRef, this.labelRtcScratch), s && this.labelPositionsById.set(s, f.clone(n, this.labelPositionsById.get(s) ?? new f()));
1199
+ }
1200
+ setLabelOptions(e, t) {
1201
+ this.labelConfig = dt(e), t && (this.labelTextResolver = t), this.applyLabelStyle(), this.ensureLabelPool(Math.min(this.labelConfig.maxCount, at)), this.scene.requestRender();
1202
+ }
1203
+ get pointLayerVisible() {
1204
+ return this.targetVisible;
1205
+ }
1206
+ get heatmapActive() {
1207
+ return !1;
1208
+ }
1209
+ destroy() {
1210
+ this.scene.primitives.remove(this.glowCollection), this.scene.primitives.remove(this.collection), this.scene.primitives.remove(this.labelCollection);
1211
+ }
1212
+ ensurePool(e) {
1213
+ for (; this.pool.length < e; ) {
1214
+ const t = this.collection.add({
1215
+ position: f.ZERO,
1216
+ show: !1,
1217
+ width: 9,
1218
+ height: 9,
1219
+ color: D.WHITE.withAlpha(0.92),
1220
+ rotation: 0
1221
+ });
1222
+ t.setImage(this.imageIds[0], this.processedImages[0]), this.pool.push(t), this.poolCategories.push(0), this.poolIds.push(""), this.smoothStarts.push(null), this.smoothTargets.push(null), this.smoothElapsedSec.push(0), this.smoothDurationSec.push(0), this.baseWidths.push(9), this.baseHeights.push(9);
1223
+ }
1224
+ }
1225
+ ensureGlowPool() {
1226
+ for (; this.glowPool.length < lt; ) {
1227
+ const e = this.glowCollection.add({
1228
+ position: f.ZERO,
1229
+ show: !1,
1230
+ width: 20,
1231
+ height: 20,
1232
+ color: D.WHITE.withAlpha(0.22),
1233
+ rotation: 0
1234
+ });
1235
+ e.setImage(Ps, this.glowImage), this.glowPool.push(e), this.glowSourceIndexes.push(-1);
1236
+ }
1237
+ }
1238
+ ensureLabelPool(e) {
1239
+ const t = Math.max(0, Math.min(this.labelConfig.maxCount, Math.ceil(e)));
1240
+ for (; this.labelPool.length < t; ) {
1241
+ const s = this.labelCollection.add({
1242
+ position: f.ZERO,
1243
+ show: !1,
1244
+ width: 1,
1245
+ height: 1,
1246
+ color: D.WHITE,
1247
+ horizontalOrigin: vi.LEFT,
1248
+ verticalOrigin: yi.BOTTOM,
1249
+ pixelOffset: J.ZERO,
1250
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
1251
+ });
1252
+ this.labelPool.push(s), this.labelSourceIndexes.push(-1), this.labelIds.push(""), this.labelSmoothStarts.push(null), this.labelSmoothTargets.push(null), this.labelSmoothElapsedSec.push(0), this.labelSmoothDurationSec.push(0), this.labelScales.push(0), this.labelTargetScales.push(0), s.scale = 0;
1253
+ }
1254
+ }
1255
+ applyLabelStyle() {
1256
+ this.labelImageCache.clear();
1257
+ for (const e of this.labelPool)
1258
+ e.show = !1, e.width = 1, e.height = 1, e.scale = 0;
1259
+ for (let e = 0; e < this.labelPool.length; e++)
1260
+ this.labelScales[e] = 0, this.labelTargetScales[e] = 0;
1261
+ this.labelScalesById.clear(), this.labelLastClearVisibleAt.clear(), this.labelActiveCount = 0;
1262
+ }
1263
+ setLabelPosition(e, t, s, n, o, r) {
1264
+ const l = s ? this.labelPositionsById.get(s) : void 0;
1265
+ this.labelSmoothStarts[e] = null, this.labelSmoothTargets[e] = null, this.labelSmoothElapsedSec[e] = 0, this.labelSmoothDurationSec[e] = 0, s && this.labelPositionsById.set(s, f.clone(n, l ?? new f()));
1266
+ }
1267
+ updateLabelScale(e, t) {
1268
+ const s = this.labelPool[e], n = this.labelTargetScales[e] ?? 0, o = this.labelScales[e] ?? 0, r = t * 1e3 / bs, l = ut(o, n, r);
1269
+ this.labelScales[e] = l;
1270
+ const h = this.labelIds[e];
1271
+ if (h && this.labelScalesById.set(h, l), s.scale = l, l <= 1e-3 && n <= 0) {
1272
+ s.show = !1, this.labelSourceIndexes[e] = -1, h && this.labelScalesById.set(h, 0), this.labelIds[e] = "", this.labelScales[e] = 0, h && this.labelLastClearVisibleAt.delete(h);
1273
+ return;
1274
+ }
1275
+ s.show = !0;
1276
+ }
1277
+ trimInactiveLabels() {
1278
+ for (; this.labelActiveCount > 0 && !this.labelPool[this.labelActiveCount - 1].show; )
1279
+ this.labelActiveCount--;
1280
+ }
1281
+ selectLabelInfos(e) {
1282
+ var v, d, p;
1283
+ const t = this.scene.camera.positionCartographic;
1284
+ if (!this.labelConfig.enabled || this.labelConfig.maxCount <= 0 || t.height > this.labelConfig.maxCameraHeight)
1285
+ return /* @__PURE__ */ new Map();
1286
+ const s = this.labelConfig.maxDistance != null && Number.isFinite(this.labelConfig.maxDistance) ? this.labelConfig.maxDistance * this.labelConfig.maxDistance : Number.POSITIVE_INFINITY, n = A.toDegrees(t.longitude), o = A.toDegrees(t.latitude), r = Ys(), l = [], h = this.scene.canvas;
1287
+ for (let g = 0; g < e.lon.length; g++) {
1288
+ if (!(e.flags[g] & As))
1289
+ continue;
1290
+ const y = _s(n, o, t.height, e.lon[g], e.lat[g], e.height[g]);
1291
+ if (y > s)
1292
+ continue;
1293
+ const w = ht(e.category[g] ?? 0, this.typeStyles.length), M = ((v = this.typeStyles[w]) == null ? void 0 : v.type) ?? "", I = this.labelTextResolver({
1294
+ id: e.ids[g] ?? "",
1295
+ type: M,
1296
+ data: void 0,
1297
+ cameraHeight: t.height,
1298
+ distance: Math.sqrt(y),
1299
+ count: e.count[g]
1300
+ });
1301
+ if (!I)
1302
+ continue;
1303
+ const C = typeof I == "string" || Array.isArray(I) ? I : I.text, k = Array.isArray(C) ? C.join(`
1304
+ `) : C;
1305
+ if (!k)
1306
+ continue;
1307
+ const S = typeof I == "object" && !Array.isArray(I) && I.style ? I.style : void 0, T = S ? { ...this.labelConfig, ...S } : this.labelConfig, z = this.labelImageOf(k, T), L = Ae.wgs84ToWindowCoordinates(
1308
+ this.scene,
1309
+ f.fromDegrees(e.lon[g], e.lat[g], e.height[g])
1310
+ );
1311
+ if (!L)
1312
+ continue;
1313
+ const E = Os(L.x, L.y, z.plateWidth, z.plateHeight, T);
1314
+ E.right < 0 || E.bottom < 0 || E.left > h.clientWidth || E.top > h.clientHeight || l.push({ index: g, id: e.ids[g] ?? "", distance2: y, info: z, rect: E, type: M });
1315
+ }
1316
+ l.sort((g, y) => g.distance2 - y.distance2);
1317
+ const c = /* @__PURE__ */ new Map(), m = [], u = /* @__PURE__ */ new Map();
1318
+ for (const g of l) {
1319
+ if (c.size >= this.labelConfig.maxCount)
1320
+ break;
1321
+ const y = (p = (d = this.labelConfig.byType) == null ? void 0 : d[g.type]) == null ? void 0 : p.maxCount;
1322
+ if (y != null && (u.get(g.type) ?? 0) >= y)
1323
+ continue;
1324
+ const w = Bs(g.rect, m, this.labelConfig.overlapThreshold), M = w && this.isLabelWithinOcclusionGrace(g.id, r);
1325
+ w && !M || (!w && g.id && this.labelLastClearVisibleAt.set(g.id, r), c.set(g.index, { index: g.index, ...g.info }), m.push(g.rect), u.set(g.type, (u.get(g.type) ?? 0) + 1));
1326
+ }
1327
+ return c;
1328
+ }
1329
+ labelImageOf(e, t) {
1330
+ const s = t ?? this.labelConfig, n = Fs(e, s), o = this.labelImageCache.get(n);
1331
+ if (o)
1332
+ return o;
1333
+ const r = zs(e, s), l = {
1334
+ id: `nameplate-${Ls++}`,
1335
+ image: r.canvas,
1336
+ width: r.width,
1337
+ height: r.height,
1338
+ plateWidth: r.plateWidth,
1339
+ plateHeight: r.plateHeight,
1340
+ anchorX: r.anchorX,
1341
+ marginY: r.marginY
1342
+ };
1343
+ return this.labelImageCache.set(n, l), l;
1344
+ }
1345
+ isLabelWithinOcclusionGrace(e, t) {
1346
+ if (!e || this.labelConfig.occlusionGraceMs <= 0)
1347
+ return !1;
1348
+ const s = this.labelLastClearVisibleAt.get(e);
1349
+ return s != null && t - s <= this.labelConfig.occlusionGraceMs;
1350
+ }
1351
+ hideUnused(e) {
1352
+ for (let t = e; t < this.visibleCount; t++)
1353
+ this.pool[t].show = !1, this.smoothStarts[t] = null, this.smoothTargets[t] = null, this.smoothElapsedSec[t] = 0, this.smoothDurationSec[t] = 0, this.poolIds[t] = "", this.baseWidths[t] = 0, this.baseHeights[t] = 0;
1354
+ this.visibleCount = e;
1355
+ }
1356
+ hideUnusedGlows(e) {
1357
+ for (let t = e; t < this.glowActiveCount; t++)
1358
+ this.glowPool[t].show = !1, this.glowSourceIndexes[t] = -1;
1359
+ }
1360
+ hideUnusedLabels(e, t) {
1361
+ for (let s = e; s < this.labelActiveCount; s++) {
1362
+ const n = this.labelIds[s];
1363
+ if (n && t.has(n)) {
1364
+ this.labelPool[s].show = !1, this.labelSourceIndexes[s] = -1, this.labelIds[s] = "", this.labelScales[s] = 0, this.labelTargetScales[s] = 0, this.labelSmoothStarts[s] = null, this.labelSmoothTargets[s] = null, this.labelSmoothElapsedSec[s] = 0, this.labelSmoothDurationSec[s] = 0;
1365
+ continue;
1366
+ }
1367
+ this.labelTargetScales[s] = 0, this.labelSourceIndexes[s] = -1, this.labelSmoothStarts[s] = null, this.labelSmoothTargets[s] = null, this.labelSmoothElapsedSec[s] = 0, this.labelSmoothDurationSec[s] = 0;
1368
+ }
1369
+ }
1370
+ preprocessImages() {
1371
+ for (let e = 0; e < this.imageUrls.length; e++) {
1372
+ const t = new Image();
1373
+ t.decoding = "async", t.onload = () => {
1374
+ const s = qs(t, "#ffffff");
1375
+ this.processedImages[e] = s;
1376
+ for (let n = 0; n < this.pool.length; n++)
1377
+ this.poolCategories[n] === e && this.pool[n].setImage(this.imageIds[e], s);
1378
+ this.scene.requestRender();
1379
+ }, t.src = this.imageUrls[e];
1380
+ }
1381
+ }
1382
+ }
1383
+ function ht(i, e) {
1384
+ return i >= 0 && i < e ? i : 0;
1385
+ }
1386
+ function Ds(i, e, t) {
1387
+ const s = (i & 16777215) << 1 | (e ? 1 : 0), n = t.get(s);
1388
+ if (n)
1389
+ return n;
1390
+ const o = jt(i, e ? 1 : 0.92);
1391
+ return t.set(s, o), o;
1392
+ }
1393
+ function Es(i, e, t) {
1394
+ const s = Jt(t), n = (i & 16777215) << 8 | Math.round(s * 255), o = e.get(n);
1395
+ if (o)
1396
+ return o;
1397
+ const r = jt(i, s);
1398
+ return e.set(n, r), r;
1399
+ }
1400
+ function jt(i, e) {
1401
+ return D.fromBytes(i >> 16 & 255, i >> 8 & 255, i & 255, Math.round(e * 255));
1402
+ }
1403
+ function Jt(i) {
1404
+ return Rs + (Math.sin(i) + 1) * ks;
1405
+ }
1406
+ function _s(i, e, t, s, n, o) {
1407
+ const r = A.toRadians((e + n) * 0.5), l = (s - i) * 111320 * Math.cos(r), h = (n - e) * 110540, c = o - t;
1408
+ return l * l + h * h + c * c;
1409
+ }
1410
+ function Os(i, e, t, s, n) {
1411
+ const o = i + (n.offsetX ?? 0), r = e - (n.offsetY ?? 0) - (n.connectorStemLength ?? 0), l = r - s;
1412
+ return {
1413
+ left: o,
1414
+ top: l,
1415
+ right: o + t,
1416
+ bottom: r,
1417
+ area: t * s
1418
+ };
1419
+ }
1420
+ function Bs(i, e, t) {
1421
+ for (const s of e) {
1422
+ const n = Math.max(i.left, s.left), o = Math.min(i.right, s.right);
1423
+ if (o <= n)
1424
+ continue;
1425
+ const r = Math.max(i.top, s.top), l = Math.min(i.bottom, s.bottom);
1426
+ if (l <= r)
1427
+ continue;
1428
+ if ((o - n) * (l - r) / Math.max(1, Math.min(i.area, s.area)) >= t)
1429
+ return !0;
1430
+ }
1431
+ return !1;
1432
+ }
1433
+ function dt(i) {
1434
+ var e;
1435
+ return Ke({
1436
+ ...Y,
1437
+ ...i ?? {},
1438
+ fontSize: Math.max(1, (i == null ? void 0 : i.fontSize) ?? Y.fontSize),
1439
+ backgroundRadius: Math.max(0, (i == null ? void 0 : i.backgroundRadius) ?? Y.backgroundRadius),
1440
+ overlapThreshold: Math.max(0, Math.min(1, (i == null ? void 0 : i.overlapThreshold) ?? Y.overlapThreshold)),
1441
+ offsetX: Math.max(0, (i == null ? void 0 : i.offsetX) ?? Y.offsetX),
1442
+ offsetY: Math.max(0, (i == null ? void 0 : i.offsetY) ?? Y.offsetY),
1443
+ connectorColor: (i == null ? void 0 : i.connectorColor) ?? (i == null ? void 0 : i.backgroundColor) ?? Y.connectorColor,
1444
+ connectorWidth: Math.max(0, (i == null ? void 0 : i.connectorWidth) ?? Y.connectorWidth),
1445
+ connectorStemLength: Math.max(0, (i == null ? void 0 : i.connectorStemLength) ?? Y.connectorStemLength),
1446
+ fields: (e = i == null ? void 0 : i.fields) != null && e.length ? i.fields.map((t) => ({
1447
+ key: t.key,
1448
+ label: t.label,
1449
+ source: t.source ?? "standard",
1450
+ fallback: t.fallback,
1451
+ minCameraHeight: t.minCameraHeight,
1452
+ maxCameraHeight: t.maxCameraHeight
1453
+ })) : Y.fields
1454
+ });
1455
+ }
1456
+ function Ns(i) {
1457
+ return `${Math.max(1, i.fontSize ?? 12)}px ${i.fontFamily || "sans-serif"}`;
1458
+ }
1459
+ function Fs(i, e) {
1460
+ return [
1461
+ i,
1462
+ e.backgroundColor ?? "",
1463
+ e.textColor ?? "",
1464
+ e.fontSize ?? 12,
1465
+ e.fontFamily ?? "sans-serif",
1466
+ e.backgroundRadius ?? 0,
1467
+ e.offsetX ?? 0,
1468
+ e.offsetY ?? 0,
1469
+ e.connectorColor ?? "",
1470
+ e.connectorWidth ?? 0,
1471
+ e.connectorStemLength ?? 0
1472
+ ].join("");
1473
+ }
1474
+ function zs(i, e) {
1475
+ const s = i.split(/\r?\n/).filter((L) => L.length > 0), n = Math.max(1, e.fontSize), o = Ns(e), r = Math.ceil(n * 1.35), l = Math.ceil(n * 0.7), h = Math.ceil(n * 0.45), m = document.createElement("canvas").getContext("2d");
1476
+ let u = 1;
1477
+ if (m) {
1478
+ m.font = o;
1479
+ for (const L of s)
1480
+ u = Math.max(u, m.measureText(L).width);
1481
+ } else
1482
+ for (const L of s)
1483
+ u = Math.max(u, L.length * n * 0.6);
1484
+ const v = Math.ceil(u + l * 2), d = Math.ceil(s.length * r + h * 2), p = Math.ceil(e.connectorWidth * 0.5) + 1, g = p + e.offsetX, y = Math.ceil(g + v), w = Math.ceil(e.connectorStemLength + e.offsetY + d), M = y + 2 * 2, I = w + 2 * 2, C = p + 2, k = Math.min(2, Math.max(1, window.devicePixelRatio || 1)), S = document.createElement("canvas");
1485
+ S.width = Math.ceil(M * k), S.height = Math.ceil(I * k), S.style.width = `${M}px`, S.style.height = `${I}px`;
1486
+ const T = S.getContext("2d");
1487
+ if (!T)
1488
+ return { canvas: S, width: M, height: I, plateWidth: v, plateHeight: d, anchorX: C, marginY: 2 };
1489
+ T.scale(k, k), T.clearRect(0, 0, M, I), T.translate(2, 2);
1490
+ const z = Math.min(e.backgroundRadius, d * 0.5, v * 0.5);
1491
+ if (e.connectorWidth > 0) {
1492
+ const L = w - e.connectorStemLength, E = Ws(g, d, z), B = Math.min(10, Math.max(3, e.connectorStemLength * 0.35)), Z = E.x - p, Q = E.y - L, q = Math.max(1e-3, Math.sqrt(Z * Z + Q * Q)), ee = p + Z / q * B, $ = L + Q / q * B;
1493
+ T.lineWidth = e.connectorWidth, T.lineCap = "round", T.lineJoin = "round";
1494
+ const X = T.createLinearGradient(p, L + B, p, w);
1495
+ X.addColorStop(0, e.connectorColor), X.addColorStop(1, Xs(e.connectorColor)), T.beginPath(), T.strokeStyle = X, T.moveTo(p, w), T.lineTo(p, L + B), T.stroke(), T.beginPath(), T.strokeStyle = e.connectorColor, T.moveTo(p, L + B), T.quadraticCurveTo(p, L, ee, $), T.lineTo(E.x, E.y), T.stroke();
1496
+ }
1497
+ T.fillStyle = e.backgroundColor, Vs(T, g, 0, v, d, z), T.fill(), T.font = o, T.fillStyle = e.textColor, T.textAlign = "left", T.textBaseline = "middle";
1498
+ for (let L = 0; L < s.length; L++)
1499
+ T.fillText(s[L], g + l, h + r * L + r * 0.5);
1500
+ return { canvas: S, width: M, height: I, plateWidth: v, plateHeight: d, anchorX: C, marginY: 2 };
1501
+ }
1502
+ function Vs(i, e, t, s, n, o) {
1503
+ i.beginPath(), i.moveTo(e + o, t), i.lineTo(e + s - o, t), i.quadraticCurveTo(e + s, t, e + s, t + o), i.lineTo(e + s, t + n - o), i.quadraticCurveTo(e + s, t + n, e + s - o, t + n), i.lineTo(e + o, t + n), i.quadraticCurveTo(e, t + n, e, t + n - o), i.lineTo(e, t + o), i.quadraticCurveTo(e, t, e + o, t), i.closePath();
1504
+ }
1505
+ function Ws(i, e, t) {
1506
+ return { x: i + t, y: e };
1507
+ }
1508
+ function Xs(i) {
1509
+ const e = i.trim(), t = e.startsWith("#") ? e.slice(1) : "";
1510
+ if (t.length === 3 || t.length === 4) {
1511
+ const n = Number.parseInt(t[0] + t[0], 16), o = Number.parseInt(t[1] + t[1], 16), r = Number.parseInt(t[2] + t[2], 16);
1512
+ if (Number.isFinite(n) && Number.isFinite(o) && Number.isFinite(r))
1513
+ return `rgba(${n}, ${o}, ${r}, 0)`;
1514
+ }
1515
+ if (t.length === 6 || t.length === 8) {
1516
+ const n = Number.parseInt(t.slice(0, 2), 16), o = Number.parseInt(t.slice(2, 4), 16), r = Number.parseInt(t.slice(4, 6), 16);
1517
+ if (Number.isFinite(n) && Number.isFinite(o) && Number.isFinite(r))
1518
+ return `rgba(${n}, ${o}, ${r}, 0)`;
1519
+ }
1520
+ const s = e.match(/^rgba?\(([^)]+)\)$/i);
1521
+ if (s) {
1522
+ const n = s[1].split(",").map((o) => o.trim());
1523
+ if (n.length >= 3)
1524
+ return `rgba(${n[0]}, ${n[1]}, ${n[2]}, 0)`;
1525
+ }
1526
+ return "rgba(255, 255, 255, 0)";
1527
+ }
1528
+ function Us(i, e) {
1529
+ const t = i.count > 1 ? `merged x${i.count}` : i.id;
1530
+ return e.showFieldLabels === !1 ? t : `target: ${t}`;
1531
+ }
1532
+ function Gs(i) {
1533
+ return i < 0.5 ? 4 * i * i * i : 1 - Math.pow(-2 * i + 2, 3) / 2;
1534
+ }
1535
+ function Zs(i, e) {
1536
+ return e <= 0 ? 1 : Math.max(0, i * 1e3 / e);
1537
+ }
1538
+ function ut(i, e, t) {
1539
+ return i < e ? Math.min(e, i + t) : i > e ? Math.max(e, i - t) : i;
1540
+ }
1541
+ function Ys() {
1542
+ return typeof performance < "u" ? performance.now() : Date.now();
1543
+ }
1544
+ function Ks() {
1545
+ const t = document.createElement("canvas");
1546
+ t.width = 160, t.height = 160;
1547
+ const s = t.getContext("2d");
1548
+ if (!s)
1549
+ return t;
1550
+ const n = s.createRadialGradient(80, 80, 0, 80, 80, 80);
1551
+ return n.addColorStop(0, "rgba(255,255,255,1)"), n.addColorStop(0.2, "rgba(255,255,255,1)"), n.addColorStop(0.52, "rgba(255,255,255,0.72)"), n.addColorStop(0.82, "rgba(255,255,255,0.3)"), n.addColorStop(1, "rgba(255,255,255,0)"), s.fillStyle = n, s.fillRect(0, 0, 160, 160), t;
1552
+ }
1553
+ function qs(i, e) {
1554
+ const n = document.createElement("canvas");
1555
+ n.width = 128, n.height = 128;
1556
+ const o = n.getContext("2d");
1557
+ if (!o)
1558
+ return n;
1559
+ o.imageSmoothingEnabled = !0, o.imageSmoothingQuality = "high", o.clearRect(0, 0, 128, 128);
1560
+ const r = document.createElement("canvas");
1561
+ r.width = 128, r.height = 128;
1562
+ const l = r.getContext("2d");
1563
+ return l && (l.imageSmoothingEnabled = !0, l.imageSmoothingQuality = "high", l.drawImage(i, 8, 8, 128 - 8 * 2, 128 - 8 * 2), $s(o, r, e)), n;
1564
+ }
1565
+ function $s(i, e, t) {
1566
+ const s = e.getContext("2d");
1567
+ if (!s)
1568
+ return;
1569
+ const { width: n, height: o } = e, r = s.getImageData(0, 0, n, o), l = i.createImageData(n, o), h = js(t), c = new Float32Array(n * o), m = new Float32Array(n * o);
1570
+ for (let d = 0; d < r.data.length; d += 4) {
1571
+ const p = d / 4, g = r.data[d], y = r.data[d + 1], w = r.data[d + 2], M = r.data[d + 3] / 255, I = (g * 0.2126 + y * 0.7152 + w * 0.0722) / 255;
1572
+ c[p] = I * M, m[p] = (1 - I) * M;
1573
+ }
1574
+ const u = ft(c, n, o, 3), v = ft(m, n, o, 4);
1575
+ for (let d = 0; d < r.data.length; d += 4) {
1576
+ const p = d / 4, g = Math.min(1, Math.max(c[p], u[p] * 0.72)), y = Math.min(0.34, m[p] * 0.24 + v[p] * 0.7), w = y + g * (1 - y);
1577
+ if (w <= 0)
1578
+ continue;
1579
+ const M = g * (1 - y) / w;
1580
+ l.data[d] = Math.round(h.r * M), l.data[d + 1] = Math.round(h.g * M), l.data[d + 2] = Math.round(h.b * M), l.data[d + 3] = Math.round(w * 255);
1581
+ }
1582
+ i.putImageData(l, 0, 0);
1583
+ }
1584
+ function ft(i, e, t, s) {
1585
+ const n = [443e-5, 0.05401, 0.24204, 0.39905, 0.24204, 0.05401, 443e-5], o = 3, r = new Float32Array(i.length);
1586
+ let l = i, h = new Float32Array(i.length);
1587
+ for (let c = 0; c < s; c++) {
1588
+ for (let m = 0; m < t; m++)
1589
+ for (let u = 0; u < e; u++) {
1590
+ let v = 0;
1591
+ for (let d = -o; d <= o; d++) {
1592
+ const p = mt(u + d, 0, e - 1);
1593
+ v += l[m * e + p] * n[d + o];
1594
+ }
1595
+ r[m * e + u] = v;
1596
+ }
1597
+ h = new Float32Array(i.length);
1598
+ for (let m = 0; m < t; m++)
1599
+ for (let u = 0; u < e; u++) {
1600
+ let v = 0;
1601
+ for (let d = -o; d <= o; d++) {
1602
+ const p = mt(m + d, 0, t - 1);
1603
+ v += r[p * e + u] * n[d + o];
1604
+ }
1605
+ h[m * e + u] = v;
1606
+ }
1607
+ l = h;
1608
+ }
1609
+ return h;
1610
+ }
1611
+ function mt(i, e, t) {
1612
+ return Math.max(e, Math.min(t, i));
1613
+ }
1614
+ function js(i) {
1615
+ const e = i.startsWith("#") ? i.slice(1) : i;
1616
+ return {
1617
+ r: Number.parseInt(e.slice(0, 2), 16),
1618
+ g: Number.parseInt(e.slice(2, 4), 16),
1619
+ b: Number.parseInt(e.slice(4, 6), 16)
1620
+ };
1621
+ }
1622
+ const W = Re, Me = W.Buffer, Ie = W.BufferUsage, Js = W.VertexArray, Qs = W.ShaderProgram, en = W.DrawCommand, tn = W.RenderState, sn = W.BlendingState, nn = W.Pass, on = W.PrimitiveType, Se = W.ComponentDatatype, rn = W.Texture, an = W.Sampler, ln = 1, cn = 2, hn = 64;
1623
+ class Qt {
1624
+ constructor(e, t) {
1625
+ a(this, "scene");
1626
+ a(this, "capacity");
1627
+ a(this, "pixelSize");
1628
+ a(this, "iconCount");
1629
+ a(this, "headingOffsets");
1630
+ a(this, "center", new f());
1631
+ a(this, "pos");
1632
+ // dx,dy,dz,heading
1633
+ a(this, "col");
1634
+ // r,g,b,a
1635
+ a(this, "ico");
1636
+ // iconIndex
1637
+ a(this, "ids");
1638
+ a(this, "count", 0);
1639
+ a(this, "dirty", !1);
1640
+ a(this, "idIndex", /* @__PURE__ */ new Map());
1641
+ a(this, "headingById", /* @__PURE__ */ new Map());
1642
+ a(this, "cmd");
1643
+ a(this, "posBuf");
1644
+ a(this, "colBuf");
1645
+ a(this, "icoBuf");
1646
+ a(this, "texture");
1647
+ a(this, "iconImages");
1648
+ a(this, "iconReady", 0);
1649
+ a(this, "show", !0);
1650
+ this.scene = e, this.capacity = t.capacity ?? 3e4, this.pixelSize = t.pixelSize ?? 30;
1651
+ const s = t.typeStyles;
1652
+ this.iconCount = Math.max(1, s.length), this.headingOffsets = s.map((n) => n.pointHeadingOffset ?? 0), this.pos = new Float32Array(this.capacity * 4), this.col = new Float32Array(this.capacity * 4), this.ico = new Float32Array(this.capacity), this.ids = new Array(this.capacity).fill(""), this.iconImages = new Array(this.iconCount).fill(null), s.forEach((n, o) => {
1653
+ const r = new Image();
1654
+ r.crossOrigin = "anonymous", r.onload = () => {
1655
+ this.iconImages[o] = r, this.iconReady++;
1656
+ }, r.onerror = () => {
1657
+ this.iconReady++;
1658
+ }, r.src = n.iconPath;
1659
+ });
1660
+ }
1661
+ setVisible(e) {
1662
+ this.show = e;
1663
+ }
1664
+ /** 通用实例入口(站点等静态对象用)。color 为 [r,g,b,a] 0~1,可选。 */
1665
+ setInstances(e) {
1666
+ f.clone(this.scene.camera.positionWC, this.center), this.idIndex.clear(), this.headingById.clear();
1667
+ const t = new f();
1668
+ let s = 0;
1669
+ for (let n = 0; n < e.length && s < this.capacity; n++) {
1670
+ const o = e[n];
1671
+ f.fromDegrees(o.lon, o.lat, o.height ?? 0, void 0, t), this.pos[s * 4 + 0] = t.x - this.center.x, this.pos[s * 4 + 1] = t.y - this.center.y, this.pos[s * 4 + 2] = t.z - this.center.z;
1672
+ const r = o.iconIndex ?? 0, l = r < 0 ? 0 : r >= this.iconCount ? this.iconCount - 1 : r, h = this.renderHeadingOf(o.heading ?? 0, l);
1673
+ this.pos[s * 4 + 3] = h;
1674
+ const c = o.color ?? [1, 1, 1, 1];
1675
+ this.col[s * 4 + 0] = c[0], this.col[s * 4 + 1] = c[1], this.col[s * 4 + 2] = c[2], this.col[s * 4 + 3] = c[3], this.ico[s] = l, this.ids[s] = o.id, this.idIndex.set(o.id, s), this.headingById.set(o.id, o.heading ?? 0), s++;
1676
+ }
1677
+ this.clearSlotsFrom(s), this.count = s, this.dirty = !0;
1678
+ }
1679
+ /** 每包重建实例(worker 已做裁剪/合并,packet 即当前应渲染集)。 */
1680
+ setPacket(e) {
1681
+ const t = this.scene.camera.positionWC;
1682
+ f.clone(t, this.center), this.idIndex.clear(), this.headingById.clear();
1683
+ let s = 0;
1684
+ const n = e.lon.length, o = new f();
1685
+ for (let r = 0; r < n && s < this.capacity; r++) {
1686
+ const l = e.flags[r];
1687
+ if (l >> cn & 3 || !(l & hn) || l & ln || e.count[r] !== 1)
1688
+ continue;
1689
+ f.fromDegrees(e.lon[r], e.lat[r], e.height[r], void 0, o), this.pos[s * 4 + 0] = o.x - this.center.x, this.pos[s * 4 + 1] = o.y - this.center.y, this.pos[s * 4 + 2] = o.z - this.center.z;
1690
+ const h = e.heading[r] || 0, c = e.color[r] >>> 0;
1691
+ this.col[s * 4 + 0] = (c >> 16 & 255) / 255, this.col[s * 4 + 1] = (c >> 8 & 255) / 255, this.col[s * 4 + 2] = (c & 255) / 255, this.col[s * 4 + 3] = 1;
1692
+ const m = e.category[r] ?? 0, u = m < 0 ? 0 : m >= this.iconCount ? this.iconCount - 1 : m;
1693
+ this.ico[s] = u;
1694
+ const v = e.ids[r], d = this.renderHeadingOf(h, u);
1695
+ this.ids[s] = v, this.pos[s * 4 + 3] = d, this.idIndex.set(v, s), this.headingById.set(v, h), s++;
1696
+ }
1697
+ this.clearSlotsFrom(s), this.count = s, this.dirty = !0;
1698
+ }
1699
+ getTargetFrame(e, t = new f()) {
1700
+ const s = this.idIndex.get(e);
1701
+ if (s !== void 0)
1702
+ return t.x = this.pos[s * 4 + 0] + this.center.x, t.y = this.pos[s * 4 + 1] + this.center.y, t.z = this.pos[s * 4 + 2] + this.center.z, { position: t, heading: this.headingById.get(e) ?? 0 };
1703
+ }
1704
+ /** Cesium 渲染管线每帧回调(通过 scene.primitives.add 自动调用)。 */
1705
+ update(e) {
1706
+ if (!this.show || this.count === 0)
1707
+ return;
1708
+ const t = e.context;
1709
+ this.cmd || this.build(t), !this.texture && this.iconReady >= this.iconCount && this.buildAtlas(t), this.dirty && (this.posBuf.copyFromArrayView(this.pos, 0), this.colBuf.copyFromArrayView(this.col, 0), this.icoBuf.copyFromArrayView(this.ico, 0), this.dirty = !1), R.fromTranslation(this.center, this.cmd.modelMatrix), this.cmd.instanceCount = this.count, e.commandList.push(this.cmd);
1710
+ }
1711
+ buildAtlas(e) {
1712
+ const s = document.createElement("canvas");
1713
+ s.width = 128 * this.iconCount, s.height = 128;
1714
+ const n = s.getContext("2d");
1715
+ if (n) {
1716
+ for (let o = 0; o < this.iconCount; o++) {
1717
+ const r = this.iconImages[o];
1718
+ r && n.drawImage(r, o * 128, 0, 128, 128);
1719
+ }
1720
+ this.texture = new rn({
1721
+ context: e,
1722
+ source: s,
1723
+ sampler: new an({})
1724
+ });
1725
+ }
1726
+ }
1727
+ build(e) {
1728
+ const t = new Float32Array([
1729
+ -0.5,
1730
+ -0.5,
1731
+ 0,
1732
+ 1,
1733
+ 0.5,
1734
+ -0.5,
1735
+ 1,
1736
+ 1,
1737
+ 0.5,
1738
+ 0.5,
1739
+ 1,
1740
+ 0,
1741
+ -0.5,
1742
+ -0.5,
1743
+ 0,
1744
+ 1,
1745
+ 0.5,
1746
+ 0.5,
1747
+ 1,
1748
+ 0,
1749
+ -0.5,
1750
+ 0.5,
1751
+ 0,
1752
+ 0
1753
+ ]), s = Me.createVertexBuffer({ context: e, typedArray: t, usage: Ie.STATIC_DRAW });
1754
+ this.posBuf = Me.createVertexBuffer({ context: e, typedArray: this.pos, usage: Ie.DYNAMIC_DRAW }), this.colBuf = Me.createVertexBuffer({ context: e, typedArray: this.col, usage: Ie.DYNAMIC_DRAW }), this.icoBuf = Me.createVertexBuffer({ context: e, typedArray: this.ico, usage: Ie.DYNAMIC_DRAW });
1755
+ const n = new Js({
1756
+ context: e,
1757
+ attributes: [
1758
+ { index: 0, vertexBuffer: s, componentsPerAttribute: 4, componentDatatype: Se.FLOAT },
1759
+ { index: 1, vertexBuffer: this.posBuf, componentsPerAttribute: 4, componentDatatype: Se.FLOAT, instanceDivisor: 1 },
1760
+ { index: 2, vertexBuffer: this.colBuf, componentsPerAttribute: 4, componentDatatype: Se.FLOAT, instanceDivisor: 1 },
1761
+ { index: 3, vertexBuffer: this.icoBuf, componentsPerAttribute: 1, componentDatatype: Se.FLOAT, instanceDivisor: 1 }
1762
+ ]
1763
+ }), o = `
1764
+ in vec4 a_quad; // xy=corner, zw=uv
1765
+ in vec4 a_inst; // xyz=ECEF相对中心, w=heading(度)
1766
+ in vec4 a_color; // rgba
1767
+ in float a_icon; // 图标索引
1768
+ uniform vec3 u_center;
1769
+ uniform float u_pixelSize;
1770
+ uniform float u_iconCount;
1771
+ out vec2 v_uv;
1772
+ out vec4 v_color;
1773
+ void main() {
1774
+ vec3 pRel = a_inst.xyz;
1775
+ float heading = radians(a_inst.w);
1776
+ vec3 ecefAbs = u_center + pRel;
1777
+ vec3 up = normalize(ecefAbs);
1778
+ vec3 east = normalize(cross(vec3(0.0, 0.0, 1.0), up));
1779
+ vec3 north = cross(up, east);
1780
+ float ch = cos(heading), sh = sin(heading);
1781
+ vec2 r = vec2(ch * a_quad.x - sh * a_quad.y, sh * a_quad.x + ch * a_quad.y);
1782
+ vec4 eye = czm_modelView * vec4(pRel, 1.0);
1783
+ float worldPerPixel = 2.0 * length(eye.xyz) / (czm_viewport.w * czm_projection[1][1]);
1784
+ vec3 offset = (r.x * east + r.y * north) * (u_pixelSize * worldPerPixel);
1785
+ v_uv = vec2((a_icon + a_quad.z) / u_iconCount, a_quad.w);
1786
+ v_color = a_color;
1787
+ gl_Position = czm_modelViewProjection * vec4(pRel + offset, 1.0);
1788
+ czm_vertexLogDepth();
1789
+ }
1790
+ `, r = `
1791
+ in vec2 v_uv;
1792
+ in vec4 v_color;
1793
+ uniform sampler2D u_icon;
1794
+ uniform float u_hasIcon;
1795
+ void main() {
1796
+ vec4 tex = u_hasIcon > 0.5 ? texture(u_icon, v_uv) : vec4(1.0);
1797
+ if (tex.a < 0.05) discard;
1798
+ // 图标 rgb 携带"白色填充 + 深色描边",乘以实例颜色着色(保留描边)。
1799
+ out_FragColor = vec4(v_color.rgb * tex.rgb, v_color.a * tex.a);
1800
+ }
1801
+ `, l = Qs.fromCache({
1802
+ context: e,
1803
+ vertexShaderSource: o,
1804
+ fragmentShaderSource: r,
1805
+ attributeLocations: { a_quad: 0, a_inst: 1, a_color: 2, a_icon: 3 }
1806
+ }), h = {
1807
+ u_center: () => this.center,
1808
+ u_pixelSize: () => this.pixelSize,
1809
+ u_iconCount: () => this.iconCount,
1810
+ u_icon: () => this.texture,
1811
+ u_hasIcon: () => this.texture ? 1 : 0
1812
+ };
1813
+ this.cmd = new en({
1814
+ primitiveType: on.TRIANGLES,
1815
+ vertexArray: n,
1816
+ shaderProgram: l,
1817
+ renderState: tn.fromCache({
1818
+ depthTest: { enabled: !0 },
1819
+ depthMask: !0,
1820
+ blending: sn.ALPHA_BLEND
1821
+ }),
1822
+ pass: nn.TRANSLUCENT,
1823
+ modelMatrix: R.fromTranslation(this.center, new R()),
1824
+ uniformMap: h,
1825
+ count: 6,
1826
+ instanceCount: this.count,
1827
+ cull: !1,
1828
+ boundingVolume: new Ze(f.ZERO, 1e8),
1829
+ owner: this
1830
+ });
1831
+ }
1832
+ isDestroyed() {
1833
+ return !1;
1834
+ }
1835
+ destroy() {
1836
+ return this.cmd && (this.cmd.shaderProgram && this.cmd.shaderProgram.destroy(), this.cmd.vertexArray && this.cmd.vertexArray.destroy(), this.cmd = void 0), this.texture && (this.texture.destroy(), this.texture = void 0), !0;
1837
+ }
1838
+ renderHeadingOf(e, t) {
1839
+ return dn((this.headingOffsets[t] ?? 0) - e);
1840
+ }
1841
+ clearSlotsFrom(e) {
1842
+ for (let t = e; t < this.count; t++)
1843
+ this.ids[t] = "";
1844
+ }
1845
+ }
1846
+ function dn(i) {
1847
+ return (i % 360 + 360) % 360;
1848
+ }
1849
+ const un = "target-selection-overlay", fn = "target-hover-overlay", pt = 500, ei = 0.85, mn = 0.42, ti = 1;
1850
+ class pn {
1851
+ constructor(e, t) {
1852
+ a(this, "collection");
1853
+ a(this, "pool", []);
1854
+ a(this, "baseSizes", []);
1855
+ a(this, "selectedIds", /* @__PURE__ */ new Set());
1856
+ a(this, "pulseElapsedById", /* @__PURE__ */ new Map());
1857
+ a(this, "hoveredId", null);
1858
+ a(this, "lastPacket", null);
1859
+ a(this, "activeCount", 0);
1860
+ a(this, "selectionImage");
1861
+ a(this, "hoverImage");
1862
+ a(this, "hoverBillboard");
1863
+ this.scene = e, this.renderTypes = t, this.selectionImage = vt(
1864
+ "rgba(255, 42, 42, 0.98)",
1865
+ "rgba(255, 24, 24, 0.72)",
1866
+ "rgba(255, 190, 190, 0.9)"
1867
+ ), this.hoverImage = vt(
1868
+ "rgba(154, 255, 184, 0.98)",
1869
+ "rgba(120, 255, 160, 0.58)",
1870
+ "rgba(222, 255, 231, 0.95)"
1871
+ ), this.collection = this.scene.primitives.add(new fe({ scene: e })), this.collection.show = !0, this.hoverBillboard = this.collection.add({
1872
+ position: f.ZERO,
1873
+ show: !1,
1874
+ width: te,
1875
+ height: te,
1876
+ color: D.WHITE,
1877
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
1878
+ }), this.hoverBillboard.setImage(fn, this.hoverImage);
1879
+ }
1880
+ setSelectedIds(e) {
1881
+ const t = new Set(this.selectedIds), s = new Set(e);
1882
+ for (const n of t)
1883
+ s.has(n) || this.pulseElapsedById.delete(n);
1884
+ this.selectedIds.clear();
1885
+ for (const n of e)
1886
+ !t.has(n) && !this.pulseElapsedById.has(n) && this.pulseElapsedById.set(n, 0), this.selectedIds.add(n);
1887
+ this.refresh();
1888
+ }
1889
+ setPacket(e) {
1890
+ this.lastPacket = e, this.refresh();
1891
+ }
1892
+ setHoveredId(e) {
1893
+ this.hoveredId !== e && (this.hoveredId = e, this.refresh());
1894
+ }
1895
+ update(e) {
1896
+ if (this.activeCount === 0 || this.pulseElapsedById.size === 0)
1897
+ return;
1898
+ let t = !1;
1899
+ for (const [s, n] of this.pulseElapsedById) {
1900
+ const o = n + e;
1901
+ if (o >= ei) {
1902
+ this.pulseElapsedById.delete(s), t = !0;
1903
+ continue;
1904
+ }
1905
+ this.pulseElapsedById.set(s, o), t = !0;
1906
+ }
1907
+ for (let s = 0; s < this.activeCount; s++) {
1908
+ const n = this.baseSizes[s] || te, o = gn(this.pool[s]), r = o ? gt(this.pulseElapsedById.get(o)) : ti;
1909
+ this.pool[s].width = n * r, this.pool[s].height = n * r;
1910
+ }
1911
+ t && this.scene.requestRender();
1912
+ }
1913
+ getRenderedTarget(e) {
1914
+ const t = this.lastPacket;
1915
+ if (!(!t || !this.selectedIds.has(e))) {
1916
+ for (let s = 0; s < t.ids.length; s++)
1917
+ if (!(t.ids[s] !== e || t.count[s] !== 1))
1918
+ return {
1919
+ id: e,
1920
+ position: f.fromDegrees(t.lon[s], t.lat[s], t.height[s]),
1921
+ size: this.overlaySizeOf(t, s)
1922
+ };
1923
+ }
1924
+ }
1925
+ clear() {
1926
+ this.lastPacket = null, this.hoveredId = null, this.pulseElapsedById.clear(), this.hideUnused(0), this.hoverBillboard.show = !1;
1927
+ }
1928
+ destroy() {
1929
+ this.clear(), this.scene.primitives.remove(this.collection);
1930
+ }
1931
+ refresh() {
1932
+ const e = this.lastPacket;
1933
+ if (!e) {
1934
+ this.hideUnused(0), this.hoverBillboard.show = !1;
1935
+ return;
1936
+ }
1937
+ if (this.selectedIds.size === 0) {
1938
+ this.hideUnused(0), this.refreshHover(e), this.scene.requestRender();
1939
+ return;
1940
+ }
1941
+ let t = 0;
1942
+ this.ensurePool(Math.min(this.selectedIds.size, pt));
1943
+ for (let s = 0; s < e.ids.length && !(t >= pt); s++) {
1944
+ const n = e.ids[s];
1945
+ if (!n || e.count[s] !== 1 || !this.selectedIds.has(n))
1946
+ continue;
1947
+ const o = this.pool[t], r = this.overlaySizeOf(e, s);
1948
+ o.position = f.fromDegrees(e.lon[s], e.lat[s], e.height[s]), this.baseSizes[t] = r;
1949
+ const l = gt(this.pulseElapsedById.get(n));
1950
+ o.width = r * l, o.height = r * l, o.rotation = 0, o.id = { targetId: n, selectionOverlay: !0 }, o.show = !0, t++;
1951
+ }
1952
+ this.hideUnused(t), this.refreshHover(e), this.scene.requestRender();
1953
+ }
1954
+ ensurePool(e) {
1955
+ for (; this.pool.length < e; ) {
1956
+ const t = this.collection.add({
1957
+ position: f.ZERO,
1958
+ show: !1,
1959
+ width: te,
1960
+ height: te,
1961
+ color: D.WHITE,
1962
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
1963
+ });
1964
+ t.setImage(un, this.selectionImage), this.pool.push(t), this.baseSizes.push(te);
1965
+ }
1966
+ }
1967
+ hideUnused(e) {
1968
+ for (let t = e; t < this.activeCount; t++)
1969
+ this.pool[t].show = !1, this.baseSizes[t] = te;
1970
+ this.activeCount = e;
1971
+ }
1972
+ refreshHover(e) {
1973
+ const t = this.hoveredId;
1974
+ if (!t) {
1975
+ this.hoverBillboard.show = !1;
1976
+ return;
1977
+ }
1978
+ for (let s = 0; s < e.ids.length; s++) {
1979
+ if (e.ids[s] !== t || e.count[s] !== 1)
1980
+ continue;
1981
+ const n = this.overlaySizeOf(e, s);
1982
+ this.hoverBillboard.position = f.fromDegrees(e.lon[s], e.lat[s], e.height[s]), this.hoverBillboard.width = n, this.hoverBillboard.height = n, this.hoverBillboard.rotation = 0, this.hoverBillboard.id = { targetId: t, hoverOverlay: !0 }, this.hoverBillboard.show = !0;
1983
+ return;
1984
+ }
1985
+ this.hoverBillboard.show = !1;
1986
+ }
1987
+ overlaySizeOf(e, t) {
1988
+ var o;
1989
+ const s = e.category[t] ?? 0, n = ((o = this.renderTypes[s]) == null ? void 0 : o.type) ?? "";
1990
+ return $t(n, e.size[t], e.count[t] > 1);
1991
+ }
1992
+ }
1993
+ function gt(i) {
1994
+ if (i == null)
1995
+ return ti;
1996
+ const e = i / ei;
1997
+ return 1 + (1 - e) * (1 - e) * mn;
1998
+ }
1999
+ function gn(i) {
2000
+ const e = i.id;
2001
+ return e == null ? void 0 : e.targetId;
2002
+ }
2003
+ function vt(i, e, t) {
2004
+ const n = document.createElement("canvas");
2005
+ n.width = 64, n.height = 64;
2006
+ const o = n.getContext("2d");
2007
+ if (!o)
2008
+ return n;
2009
+ o.clearRect(0, 0, 64, 64), o.strokeStyle = i, o.lineWidth = 4.5, o.shadowColor = e, o.shadowBlur = 10;
2010
+ const r = 9, l = 17;
2011
+ return xe(o, r, r, l, 1, 1), xe(o, 64 - r, r, l, -1, 1), xe(o, r, 64 - r, l, 1, -1), xe(o, 64 - r, 64 - r, l, -1, -1), o.shadowBlur = 0, o.strokeStyle = t, o.lineWidth = 1.6, o.beginPath(), o.arc(64 * 0.5, 64 * 0.5, 6, 0, A.TWO_PI), o.stroke(), n;
2012
+ }
2013
+ function xe(i, e, t, s, n, o) {
2014
+ i.beginPath(), i.moveTo(e, t + o * s), i.lineTo(e, t), i.lineTo(e + n * s, t), i.stroke();
2015
+ }
2016
+ const vn = 80, yt = typeof performance < "u" && typeof performance.now == "function" ? () => performance.now() : () => Date.now();
2017
+ class yn {
2018
+ constructor(e, t) {
2019
+ a(this, "points", []);
2020
+ a(this, "index", null);
2021
+ // 索引建立时的相机位姿。屏幕坐标是世界点投影出来的,相机平移/缩放/旋转后
2022
+ // 同一世界点会落到不同屏幕位置,但 canvas 尺寸不变。必须按位姿失效,否则平移
2023
+ // 海图后 hover 命中的是旧屏幕坐标(表现为要在偏移位置才 hover 得到)。
2024
+ a(this, "builtCameraPosition", null);
2025
+ a(this, "builtCameraDirection", null);
2026
+ // 相机连续运动时,每帧 pick 都重投影全部轨迹点是 O(n) 开销。位姿变化后的重建做
2027
+ // 节流:最多每 HOVER_REBUILD_THROTTLE_MS 重建一次,期间复用旧索引(最多 80ms 陈旧,
2028
+ // hover 体感无差)。canvas 尺寸变化与数据变更(setPoints/invalidate)不受节流,立即重建。
2029
+ a(this, "lastBuiltAt", 0);
2030
+ this.scene = e, this.pixelThreshold = t;
2031
+ }
2032
+ setPoints(e) {
2033
+ this.points = e.slice(), this.index = null;
2034
+ }
2035
+ invalidate() {
2036
+ this.index = null;
2037
+ }
2038
+ rebuild() {
2039
+ this.index = null, this.ensureIndex();
2040
+ }
2041
+ pick(e) {
2042
+ const t = this.ensureIndex();
2043
+ if (!t)
2044
+ return null;
2045
+ const s = Math.max(1, this.pixelThreshold), n = s * s, o = Math.floor(e.x / t.cellSize), r = Math.floor(e.y / t.cellSize);
2046
+ let l = null, h = 0, c = 0, m = n;
2047
+ for (let u = r - 1; u <= r + 1; u++)
2048
+ for (let v = o - 1; v <= o + 1; v++) {
2049
+ const d = t.bins.get(wt(v, u));
2050
+ if (d)
2051
+ for (const p of d) {
2052
+ const g = t.screenX[p] - e.x, y = t.screenY[p] - e.y, w = g * g + y * y;
2053
+ w > m || (m = w, l = this.points[p], h = t.screenX[p], c = t.screenY[p]);
2054
+ }
2055
+ }
2056
+ return l ? {
2057
+ targetId: l.targetId,
2058
+ pointIndex: l.pointIndex,
2059
+ point: l.point,
2060
+ screenX: h,
2061
+ screenY: c
2062
+ } : null;
2063
+ }
2064
+ ensureIndex() {
2065
+ const e = this.scene.canvas, t = this.scene.camera, s = !!this.index && this.index.canvasWidth === e.clientWidth && this.index.canvasHeight === e.clientHeight, n = s && !!this.builtCameraPosition && !!this.builtCameraDirection && f.equalsEpsilon(t.positionWC, this.builtCameraPosition, A.EPSILON7) && f.equalsEpsilon(t.directionWC, this.builtCameraDirection, A.EPSILON9);
2066
+ if (this.index && s && n)
2067
+ return this.index;
2068
+ if (this.index && s && !n && yt() - this.lastBuiltAt < vn)
2069
+ return this.index;
2070
+ if (this.index = null, this.builtCameraPosition = f.clone(t.positionWC, this.builtCameraPosition ?? new f()), this.builtCameraDirection = f.clone(t.directionWC, this.builtCameraDirection ?? new f()), this.lastBuiltAt = yt(), this.points.length === 0)
2071
+ return null;
2072
+ const o = Math.max(48, this.pixelThreshold * 2), r = /* @__PURE__ */ new Map(), l = new Float32Array(this.points.length), h = new Float32Array(this.points.length);
2073
+ l.fill(Number.NaN), h.fill(Number.NaN);
2074
+ for (let c = 0; c < this.points.length; c++) {
2075
+ const m = Ae.wgs84ToWindowCoordinates(this.scene, this.points[c].position);
2076
+ if (!m)
2077
+ continue;
2078
+ const u = m.x, v = m.y;
2079
+ if (!Number.isFinite(u) || !Number.isFinite(v) || u < 0 || v < 0 || u > e.clientWidth || v > e.clientHeight)
2080
+ continue;
2081
+ l[c] = u, h[c] = v;
2082
+ const d = wt(Math.floor(u / o), Math.floor(v / o)), p = r.get(d);
2083
+ p ? p.push(c) : r.set(d, [c]);
2084
+ }
2085
+ return this.index = {
2086
+ bins: r,
2087
+ screenX: l,
2088
+ screenY: h,
2089
+ canvasWidth: e.clientWidth,
2090
+ canvasHeight: e.clientHeight,
2091
+ cellSize: o
2092
+ }, this.index;
2093
+ }
2094
+ }
2095
+ function wt(i, e) {
2096
+ return `${i}:${e}`;
2097
+ }
2098
+ const Mt = new D(0.22, 0.82, 1, 0.84), wn = "track-point-overlay", It = 12, Mn = new f(0, 0, -24);
2099
+ class In {
2100
+ constructor(e) {
2101
+ a(this, "historyCollection");
2102
+ a(this, "connectorCollection");
2103
+ a(this, "pointCollection");
2104
+ a(this, "linePool", []);
2105
+ a(this, "pointPool", []);
2106
+ a(this, "lineCount", 0);
2107
+ a(this, "pointImage");
2108
+ this.scene = e, this.historyCollection = this.scene.primitives.add(new Ve({ show: !0 })), this.connectorCollection = this.scene.primitives.add(new Ve({ show: !0 })), this.pointCollection = this.scene.primitives.add(new fe({ show: !0, scene: e })), this.pointImage = Sn();
2109
+ }
2110
+ setTracks(e) {
2111
+ this.ensureLinePool(e.length);
2112
+ let t = 0;
2113
+ for (let s = 0; s < e.length; s++) {
2114
+ const n = e[s], o = this.linePool[s];
2115
+ o.history.positions = n.cartesianPoints, o.history.show = n.cartesianPoints.length >= 2, o.history.id = { targetId: n.targetId, trackHistory: !0 }, St(o, n.cartesianPoints, n.currentPosition);
2116
+ for (let r = 0; r < n.cartesianPoints.length; r++) {
2117
+ const l = this.ensurePoint(t++);
2118
+ l.position = n.cartesianPoints[r], l.id = { targetId: n.targetId, trackPointIndex: r, trackPoint: !0 }, l.show = !0;
2119
+ }
2120
+ }
2121
+ this.lineCount = e.length, this.hideUnusedLines(e.length), this.hideUnusedPoints(t);
2122
+ }
2123
+ updateConnectors(e) {
2124
+ const t = Math.min(e.length, this.lineCount);
2125
+ for (let s = 0; s < t; s++)
2126
+ St(this.linePool[s], e[s].cartesianPoints, e[s].currentPosition);
2127
+ }
2128
+ clear() {
2129
+ this.hideUnusedLines(0), this.hideUnusedPoints(0), this.lineCount = 0;
2130
+ }
2131
+ destroy() {
2132
+ this.clear(), this.scene.primitives.remove(this.historyCollection), this.scene.primitives.remove(this.connectorCollection), this.scene.primitives.remove(this.pointCollection);
2133
+ }
2134
+ ensureLinePool(e) {
2135
+ for (; this.linePool.length < e; )
2136
+ this.linePool.push(this.createLineSlot());
2137
+ }
2138
+ ensurePoint(e) {
2139
+ for (; this.pointPool.length <= e; ) {
2140
+ const t = this.pointCollection.add({
2141
+ show: !1,
2142
+ position: f.ZERO,
2143
+ width: It,
2144
+ height: It,
2145
+ color: D.WHITE,
2146
+ eyeOffset: f.clone(Mn),
2147
+ disableDepthTestDistance: Number.POSITIVE_INFINITY
2148
+ });
2149
+ t.setImage(wn, this.pointImage), this.pointPool.push(t);
2150
+ }
2151
+ return this.pointPool[e];
2152
+ }
2153
+ createLineSlot() {
2154
+ const e = f.clone(f.ZERO), t = f.clone(f.ZERO), s = [e, t], n = ae.fromType(ae.ColorType, { color: D.clone(Mt) }), o = ae.fromType(ae.ColorType, { color: D.clone(Mt) }), r = this.historyCollection.add({
2155
+ show: !1,
2156
+ positions: [],
2157
+ width: 2.2,
2158
+ material: n
2159
+ }), l = this.connectorCollection.add({
2160
+ show: !1,
2161
+ positions: s,
2162
+ width: 1.5,
2163
+ material: o
2164
+ });
2165
+ return {
2166
+ history: r,
2167
+ connector: l,
2168
+ connectorStart: e,
2169
+ connectorEnd: t,
2170
+ connectorPositions: s,
2171
+ historyMaterial: n,
2172
+ connectorMaterial: o
2173
+ };
2174
+ }
2175
+ hideUnusedLines(e) {
2176
+ for (let t = e; t < this.linePool.length; t++)
2177
+ this.linePool[t].history.show = !1, this.linePool[t].connector.show = !1;
2178
+ }
2179
+ hideUnusedPoints(e) {
2180
+ for (let t = e; t < this.pointPool.length; t++)
2181
+ this.pointPool[t].show = !1;
2182
+ }
2183
+ }
2184
+ function Sn() {
2185
+ const e = document.createElement("canvas");
2186
+ e.width = 48, e.height = 48;
2187
+ const t = e.getContext("2d");
2188
+ if (!t)
2189
+ return e;
2190
+ const s = 48 * 0.5;
2191
+ return t.clearRect(0, 0, 48, 48), t.fillStyle = "rgba(234,252,255,0.98)", t.strokeStyle = "rgba(18,138,184,0.95)", t.lineWidth = 5, t.beginPath(), t.arc(s, s, 11, 0, Math.PI * 2), t.fill(), t.stroke(), t.strokeStyle = "rgba(255,255,255,0.95)", t.lineWidth = 2, t.beginPath(), t.arc(s, s, 15, 0, Math.PI * 2), t.stroke(), e;
2192
+ }
2193
+ function St(i, e, t) {
2194
+ if (e.length === 0 || !t) {
2195
+ i.connector.show = !1;
2196
+ return;
2197
+ }
2198
+ const s = e[e.length - 1];
2199
+ if (f.distance(s, t) < 1) {
2200
+ i.connector.show = !1;
2201
+ return;
2202
+ }
2203
+ f.clone(s, i.connectorStart), f.clone(t, i.connectorEnd), i.connector.positions = i.connectorPositions, i.connector.show = !0;
2204
+ }
2205
+ class xn extends qe {
2206
+ constructor(t, s) {
2207
+ super();
2208
+ a(this, "records", /* @__PURE__ */ new Map());
2209
+ a(this, "renderer");
2210
+ a(this, "hoverPicker");
2211
+ a(this, "lastPacket", null);
2212
+ a(this, "hoverPosition", null);
2213
+ a(this, "lastPointerPosition", null);
2214
+ a(this, "hoverRafId", 0);
2215
+ a(this, "rebuildHoverIndexTimer", 0);
2216
+ a(this, "currentHoverKey", "");
2217
+ a(this, "removeCameraListener");
2218
+ a(this, "onPointerMoveBound");
2219
+ a(this, "onPointerLeaveBound");
2220
+ a(this, "onPointerDownBound");
2221
+ a(this, "onWheelBound");
2222
+ this.viewer = t, this.renderer = new In(this.viewer.scene), this.hoverPicker = new yn(this.viewer.scene, s), this.removeCameraListener = this.viewer.camera.changed.addEventListener(() => {
2223
+ this.hoverPicker.invalidate(), this.clearHover({ keepPointer: !0 }), this.scheduleHoverIndexRebuild();
2224
+ }), this.onPointerMoveBound = (o) => this.onPointerMove(o), this.onPointerLeaveBound = () => this.clearHover(), this.onPointerDownBound = () => this.clearHover(), this.onWheelBound = () => this.clearHover();
2225
+ const n = this.viewer.scene.canvas;
2226
+ n.addEventListener("pointermove", this.onPointerMoveBound), n.addEventListener("pointerleave", this.onPointerLeaveBound), n.addEventListener("pointerdown", this.onPointerDownBound), n.addEventListener("wheel", this.onWheelBound, { passive: !0 });
2227
+ }
2228
+ setTracks(t) {
2229
+ if (t.length !== 0) {
2230
+ for (const s of t) {
2231
+ const n = Tn(s);
2232
+ this.records.set(n.targetId, n);
2233
+ }
2234
+ this.refresh();
2235
+ }
2236
+ }
2237
+ getTracks(t) {
2238
+ var o;
2239
+ const s = t != null && t.length ? t : Array.from(this.records.keys()), n = [];
2240
+ for (const r of s) {
2241
+ const l = this.records.get(r);
2242
+ l && n.push({
2243
+ targetId: l.targetId,
2244
+ visible: l.visible,
2245
+ pointList: (o = l.pointList) == null ? void 0 : o.map(ii),
2246
+ trackLine: l.trackLine
2247
+ });
2248
+ }
2249
+ return n;
2250
+ }
2251
+ showTracks(t) {
2252
+ this.setVisible(t, !0);
2253
+ }
2254
+ hideTracks(t) {
2255
+ this.setVisible(t, !1);
2256
+ }
2257
+ removeTracks(t) {
2258
+ if (t.length !== 0) {
2259
+ for (const s of t)
2260
+ this.records.delete(s);
2261
+ this.refresh();
2262
+ }
2263
+ }
2264
+ clearTracks() {
2265
+ this.records.size !== 0 && (this.records.clear(), this.refresh());
2266
+ }
2267
+ setRenderPacket(t) {
2268
+ this.lastPacket = t;
2269
+ const s = this.getVisibleRecords();
2270
+ if (s.length === 0)
2271
+ return;
2272
+ const n = new Set(s.map((r) => r.targetId)), o = /* @__PURE__ */ new Set();
2273
+ for (let r = 0; r < t.ids.length; r++) {
2274
+ const l = t.ids[r];
2275
+ if (!l || t.count[r] !== 1 || !n.has(l))
2276
+ continue;
2277
+ const h = this.records.get(l);
2278
+ if (!h)
2279
+ continue;
2280
+ const c = f.fromDegrees(t.lon[r], t.lat[r], t.height[r]);
2281
+ h.currentPosition ? (f.clone(h.currentPosition, h.motionFrom), f.clone(c, h.motionTo), h.motionElapsedSec = 0, h.motionDurationSec = Math.max(0, t.moveDurationMs[r] / 1e3)) : (h.currentPosition = f.clone(c), f.clone(c, h.motionFrom), f.clone(c, h.motionTo), h.motionElapsedSec = 0, h.motionDurationSec = 0), o.add(l);
2282
+ }
2283
+ for (const r of s)
2284
+ o.has(r.targetId) || (r.currentPosition = null, r.motionElapsedSec = 0, r.motionDurationSec = 0);
2285
+ this.renderer.updateConnectors(this.toRenderRecords(s));
2286
+ }
2287
+ update(t) {
2288
+ const s = this.getVisibleRecords();
2289
+ if (s.length === 0)
2290
+ return;
2291
+ let n = !1;
2292
+ for (const o of s) {
2293
+ if (!o.currentPosition || o.motionDurationSec <= 0)
2294
+ continue;
2295
+ o.motionElapsedSec = Math.min(o.motionElapsedSec + t, o.motionDurationSec);
2296
+ const r = o.motionDurationSec <= 0 ? 1 : o.motionElapsedSec / o.motionDurationSec;
2297
+ f.lerp(o.motionFrom, o.motionTo, Rn(r), o.currentPosition), o.motionElapsedSec < o.motionDurationSec ? n = !0 : o.motionDurationSec = 0;
2298
+ }
2299
+ n && this.renderer.updateConnectors(this.toRenderRecords(s));
2300
+ }
2301
+ destroy() {
2302
+ this.hoverRafId && cancelAnimationFrame(this.hoverRafId), this.rebuildHoverIndexTimer && window.clearTimeout(this.rebuildHoverIndexTimer), this.clearHover();
2303
+ const t = this.viewer.scene.canvas;
2304
+ t.removeEventListener("pointermove", this.onPointerMoveBound), t.removeEventListener("pointerleave", this.onPointerLeaveBound), t.removeEventListener("pointerdown", this.onPointerDownBound), t.removeEventListener("wheel", this.onWheelBound), this.removeCameraListener(), this.renderer.destroy(), this.clear();
2305
+ }
2306
+ setVisible(t, s) {
2307
+ if (t.length === 0)
2308
+ return;
2309
+ let n = !1;
2310
+ for (const o of t) {
2311
+ const r = this.records.get(o);
2312
+ !r || r.visible === s || (r.visible = s, n = !0);
2313
+ }
2314
+ n && this.refresh();
2315
+ }
2316
+ refresh() {
2317
+ const t = this.getVisibleRecords();
2318
+ this.renderer.setTracks(this.toRenderRecords(t)), this.hoverPicker.setPoints(t.flatMap(
2319
+ (s) => s.cartesianPoints.map((n, o) => ({
2320
+ targetId: s.targetId,
2321
+ pointIndex: o,
2322
+ point: s.normalizedPoints[o],
2323
+ position: n
2324
+ }))
2325
+ )), this.clearHover(), this.lastPacket && this.setRenderPacket(this.lastPacket);
2326
+ }
2327
+ getVisibleRecords() {
2328
+ const t = [];
2329
+ for (const s of this.records.values())
2330
+ s.visible && s.normalizedPoints.length > 0 && t.push(s);
2331
+ return t;
2332
+ }
2333
+ toRenderRecords(t) {
2334
+ return t.map((s) => ({
2335
+ targetId: s.targetId,
2336
+ points: s.normalizedPoints,
2337
+ cartesianPoints: s.cartesianPoints,
2338
+ currentPosition: s.currentPosition
2339
+ }));
2340
+ }
2341
+ onPointerMove(t) {
2342
+ const s = this.viewer.scene.canvas.getBoundingClientRect();
2343
+ this.lastPointerPosition = new J(t.clientX - s.left, t.clientY - s.top), this.scheduleHoverPick(this.lastPointerPosition);
2344
+ }
2345
+ flushHoverPick() {
2346
+ if (this.hoverRafId = 0, !this.hoverPosition)
2347
+ return;
2348
+ const t = this.hoverPicker.pick(this.hoverPosition), s = t ? `${t.targetId}:${t.pointIndex}` : "";
2349
+ s !== this.currentHoverKey && (this.currentHoverKey = s, this.emit("hover", t));
2350
+ }
2351
+ clearHover(t = {}) {
2352
+ this.hoverPosition = null, t.keepPointer || (this.lastPointerPosition = null), this.currentHoverKey && (this.currentHoverKey = "", this.emit("hover", null));
2353
+ }
2354
+ scheduleHoverPick(t) {
2355
+ this.hoverPosition = J.clone(t, this.hoverPosition ?? new J()), !this.hoverRafId && (this.hoverRafId = requestAnimationFrame(() => this.flushHoverPick()));
2356
+ }
2357
+ scheduleHoverPickFromLastPointer() {
2358
+ this.lastPointerPosition && (this.hoverRafId || (this.hoverRafId = requestAnimationFrame(() => {
2359
+ this.hoverRafId = 0, this.lastPointerPosition && this.scheduleHoverPick(this.lastPointerPosition);
2360
+ })));
2361
+ }
2362
+ scheduleHoverIndexRebuild() {
2363
+ this.rebuildHoverIndexTimer && window.clearTimeout(this.rebuildHoverIndexTimer), this.rebuildHoverIndexTimer = window.setTimeout(() => {
2364
+ this.rebuildHoverIndexTimer = 0, this.hoverPicker.rebuild(), this.scheduleHoverPickFromLastPointer();
2365
+ }, 120);
2366
+ }
2367
+ }
2368
+ function Tn(i) {
2369
+ var s;
2370
+ if (!i || typeof i != "object")
2371
+ throw new Error("track must be an object.");
2372
+ if (typeof i.targetId != "string" || i.targetId.length === 0)
2373
+ throw new Error("track.targetId must be a non-empty string.");
2374
+ const e = Cn(i.pointList), t = e.length > 0 ? e : bn(i.trackLine, i.targetId);
2375
+ return {
2376
+ targetId: i.targetId,
2377
+ visible: i.visible ?? !0,
2378
+ pointList: (s = i.pointList) == null ? void 0 : s.map(ii),
2379
+ trackLine: i.trackLine,
2380
+ normalizedPoints: t,
2381
+ cartesianPoints: t.map((n) => f.fromDegrees(n.lon, n.lat, n.height)),
2382
+ currentPosition: null,
2383
+ motionFrom: f.clone(f.ZERO),
2384
+ motionTo: f.clone(f.ZERO),
2385
+ motionElapsedSec: 0,
2386
+ motionDurationSec: 0
2387
+ };
2388
+ }
2389
+ function Cn(i) {
2390
+ if (!(i != null && i.length))
2391
+ return [];
2392
+ const e = [];
2393
+ for (const t of i) {
2394
+ if (!t || typeof t != "object")
2395
+ continue;
2396
+ const s = Number(t.lon), n = Number(t.lat), o = Number(t.height), r = Pn(t.time);
2397
+ !Number.isFinite(s) || !Number.isFinite(n) || !Number.isFinite(o) || !Number.isFinite(r) || e.push({
2398
+ lon: s,
2399
+ lat: n,
2400
+ height: o,
2401
+ time: r,
2402
+ heading: xt(t.heading),
2403
+ speed: xt(t.speed),
2404
+ source: typeof t.source == "string" && t.source ? t.source : void 0
2405
+ });
2406
+ }
2407
+ return e.sort((t, s) => t.time - s.time), e;
2408
+ }
2409
+ function bn(i, e) {
2410
+ if (!i)
2411
+ return [];
2412
+ const t = /^\s*LINESTRING(?:\s+Z)?\s*\((.+)\)\s*$/i.exec(i);
2413
+ if (!t)
2414
+ return console.warn(`[tracks] ignored invalid LINESTRING for ${e}`), [];
2415
+ const s = [], n = t[1].split(",");
2416
+ for (let o = 0; o < n.length; o++) {
2417
+ const r = n[o].trim().split(/\s+/).map(Number);
2418
+ r.length < 2 || !Number.isFinite(r[0]) || !Number.isFinite(r[1]) || s.push({
2419
+ lon: r[0],
2420
+ lat: r[1],
2421
+ height: Number.isFinite(r[2]) ? r[2] : 0,
2422
+ time: o,
2423
+ source: "trackLine"
2424
+ });
2425
+ }
2426
+ return s.length === 0 && console.warn(`[tracks] ignored empty LINESTRING for ${e}`), s;
2427
+ }
2428
+ function Pn(i) {
2429
+ if (typeof i == "number")
2430
+ return i;
2431
+ if (typeof i == "string") {
2432
+ const e = Date.parse(i);
2433
+ if (Number.isFinite(e))
2434
+ return e;
2435
+ const t = Number(i);
2436
+ return Number.isFinite(t) ? t : Number.NaN;
2437
+ }
2438
+ return Number.NaN;
2439
+ }
2440
+ function xt(i) {
2441
+ if (i == null)
2442
+ return;
2443
+ const e = Number(i);
2444
+ return Number.isFinite(e) ? e : void 0;
2445
+ }
2446
+ function ii(i) {
2447
+ return {
2448
+ lon: i.lon,
2449
+ lat: i.lat,
2450
+ height: i.height,
2451
+ time: i.time,
2452
+ heading: i.heading,
2453
+ speed: i.speed,
2454
+ source: i.source
2455
+ };
2456
+ }
2457
+ function Rn(i) {
2458
+ const e = A.clamp(i, 0, 1);
2459
+ return 1 - Math.pow(1 - e, 3);
2460
+ }
2461
+ function kn() {
2462
+ return new Worker("/assets/renderWorker-118e8f3b.js");
2463
+ }
2464
+ const An = 40, Tt = 2, Ct = 1.25, Ln = 0.75, Hn = 0.3, bt = 0.35, Pt = 16, Rt = 200, Dn = 200, kt = 120, En = 512, _n = 48, On = 32, Bn = 64;
2465
+ class Nn extends qe {
2466
+ constructor(t, s) {
2467
+ var n, o, r, l, h, c, m, u, v;
2468
+ super();
2469
+ a(this, "config");
2470
+ a(this, "render");
2471
+ a(this, "models");
2472
+ a(this, "symbols");
2473
+ a(this, "selection");
2474
+ a(this, "tracks");
2475
+ /** 引擎就绪信号:内部 Web Worker 完成 init 握手后 resolve。可在加载依赖底座的其它组件前 await。 */
2476
+ a(this, "ready");
2477
+ a(this, "nodes", {
2478
+ visibleCount: 0,
2479
+ bufferCount: 0,
2480
+ renderedCount: 0,
2481
+ clusterCount: 0,
2482
+ lastMergeRadius: 0,
2483
+ pointRenderCount: 0,
2484
+ mergedPointRenderCount: 0,
2485
+ plainPointRenderCount: 0,
2486
+ lowModelRenderCount: 0,
2487
+ highModelRenderCount: 0,
2488
+ mergedLowModelRenderCount: 0,
2489
+ mergedHighModelRenderCount: 0,
2490
+ forcedPointMode: !1,
2491
+ level: 0,
2492
+ outsideLevel: 0
2493
+ });
2494
+ a(this, "quality", { tier: "high" });
2495
+ a(this, "worker");
2496
+ a(this, "resolveReady");
2497
+ a(this, "readyResolved", !1);
2498
+ a(this, "commitIntervalMs");
2499
+ a(this, "commitTimer", null);
2500
+ a(this, "rafId", 0);
2501
+ a(this, "paused", !1);
2502
+ a(this, "destroyed", !1);
2503
+ a(this, "total", 0);
2504
+ a(this, "commitRequestId", 0);
2505
+ a(this, "viewportRequestId", 0);
2506
+ a(this, "dataRevision", 0);
2507
+ a(this, "viewportRequestRevisions", /* @__PURE__ */ new Map());
2508
+ a(this, "globalViewportRequestIds", /* @__PURE__ */ new Set());
2509
+ a(this, "globalViewportRevision", -1);
2510
+ a(this, "targetQueryRequestId", 0);
2511
+ a(this, "targetQueryResolvers", /* @__PURE__ */ new Map());
2512
+ a(this, "viewportInFlight", !1);
2513
+ a(this, "viewportDirty", !1);
2514
+ a(this, "lastCommitSubmitAt", 0);
2515
+ a(this, "lastFrameAt", _());
2516
+ a(this, "lastPredictionViewportAt", 0);
2517
+ a(this, "lastSymbolsUpdateAt", 0);
2518
+ a(this, "stagedUpserts", 0);
2519
+ a(this, "stagedBatches", 0);
2520
+ a(this, "removeCameraListener");
2521
+ a(this, "inputHandler");
2522
+ a(this, "selectedIds", /* @__PURE__ */ new Set());
2523
+ a(this, "selectedTargets", /* @__PURE__ */ new Map());
2524
+ a(this, "hoverRequestSerial", 0);
2525
+ a(this, "pickRequestSerial", 0);
2526
+ a(this, "contextMenuRequestSerial", 0);
2527
+ a(this, "hoverPickPosition", null);
2528
+ a(this, "hoverPickRafId", 0);
2529
+ a(this, "lastHoverPickAt", 0);
2530
+ a(this, "lastHoverPointerSample", null);
2531
+ a(this, "hoverPointerSpeedPxPerMs", 0);
2532
+ a(this, "pointerButtonsMask", 0);
2533
+ a(this, "wheelSuppressPickUntil", 0);
2534
+ a(this, "cameraMoving", !1);
2535
+ a(this, "cameraMoveTrailingTimer", 0);
2536
+ a(this, "wheelSuppressResetTimer", 0);
2537
+ a(this, "cameraViewportThrottleTimer", 0);
2538
+ a(this, "lastCameraViewportAt", 0);
2539
+ a(this, "lastHoverId", null);
2540
+ a(this, "hoverTargetCache", /* @__PURE__ */ new Map());
2541
+ a(this, "labelDataById", /* @__PURE__ */ new Map());
2542
+ a(this, "latestRenderPacket", null);
2543
+ a(this, "hoverPickIndex", null);
2544
+ a(this, "hoverPickWarmupRafId", 0);
2545
+ a(this, "cameraRevision", 0);
2546
+ a(this, "labelConfig");
2547
+ this.viewer = t, this.config = xi(s), this.labelConfig = this.config.label, this.commitIntervalMs = this.config.data.commitIntervalMs, this.render = new Hs(t.scene, this.config.fadeMs, {
2548
+ targetTypes: this.config.renderTypes.map(Be),
2549
+ label: this.labelConfig,
2550
+ labelTextResolver: (d) => this.nameplateText(d)
2551
+ }), this.selection = new pn(t.scene, this.config.renderTypes), this.tracks = new xn(t, this.config.pick.pixelThreshold), this.config.groundSymbols && (this.symbols = new Qt(t.scene, {
2552
+ typeStyles: this.config.renderTypes.map(Be),
2553
+ capacity: this.config.poolSize,
2554
+ pixelSize: this.config.groundSymbolPixelSize
2555
+ }), t.scene.primitives.add(this.symbols), this.render.setDirectionalHandledExternally(!0)), this.models = new fs(
2556
+ t,
2557
+ this.config.renderTypes.map(Be),
2558
+ this.config.frame.maxLowModelRenderItems,
2559
+ Math.max(this.config.animatedCapacity, this.config.frame.maxModelRenderItems),
2560
+ this.config.animatedCapacity,
2561
+ this.config.fadeMs
2562
+ ), this.render.setAnchorPositionResolver((d, p) => {
2563
+ var g;
2564
+ return (g = this.getRenderedTargetFrame(d, p)) == null ? void 0 : g.position;
2565
+ }), this.ready = new Promise((d) => {
2566
+ this.resolveReady = d;
2567
+ }), this.worker = new kn(), this.worker.onmessage = (d) => this.handleWorkerMessage(d.data), this.worker.postMessage({
2568
+ type: "init",
2569
+ config: {
2570
+ maxVisible: ((n = this.config.merge) == null ? void 0 : n.maxVisible) ?? this.config.poolSize,
2571
+ rootLimit: ((o = this.config.merge) == null ? void 0 : o.globalRootLimit) ?? 500,
2572
+ maxLevels: ((r = this.config.merge) == null ? void 0 : r.globalMaxLevels) ?? 64,
2573
+ cameraMergeBaseHeight: ((l = this.config.merge) == null ? void 0 : l.cameraMergeBaseHeight) ?? 1e5,
2574
+ cameraMergeStepHeight: ((h = this.config.merge) == null ? void 0 : h.cameraMergeStepHeight) ?? 1e4,
2575
+ cameraMergeStepRadius: ((c = this.config.merge) == null ? void 0 : c.cameraMergeStepRadius) ?? 100,
2576
+ globalViewportHeight: ((m = this.config.merge) == null ? void 0 : m.globalViewportHeight) ?? 45e4,
2577
+ globalCacheIntervalMs: ((u = this.config.merge) == null ? void 0 : u.globalRebuildIntervalMs) ?? 3e5,
2578
+ innerRatio: ((v = this.config.merge) == null ? void 0 : v.innerRatio) ?? 0.6,
2579
+ viewportBufferRatio: this.config.cull.viewportBufferRatio,
2580
+ viewportBufferMinMeters: this.config.cull.viewportBufferMinMeters,
2581
+ pointAbove: this.config.lod.pointAbove,
2582
+ animatedBelow: this.config.lod.animatedBelow,
2583
+ predictSeconds: this.config.predictSeconds,
2584
+ predictFitSeconds: this.config.predictFitSeconds,
2585
+ targetTypes: this.config.renderTypes.map((d, p) => ({
2586
+ type: d.type,
2587
+ category: p,
2588
+ targetDomain: d.targetDomain,
2589
+ forceHighModelInLowLod: d.forceHighModelInLowLod,
2590
+ iconPath: d.iconPath,
2591
+ defaultColor: Xn(d.defaultColor),
2592
+ smoothMove: d.smoothMove,
2593
+ smoothMoveMinCameraHeight: d.smoothMoveMinCameraHeight,
2594
+ smoothMoveDurationMs: d.smoothMoveDurationMs,
2595
+ predictMove: d.predictMove,
2596
+ predictMinCameraHeight: d.predictMinCameraHeight,
2597
+ predictSeconds: d.predictSeconds,
2598
+ predictFitSeconds: d.predictFitSeconds
2599
+ }))
2600
+ }
2601
+ }), this.removeCameraListener = this.viewer.camera.changed.addEventListener(() => {
2602
+ this.requestViewportThrottled(), this.noteCameraMovement();
2603
+ }), this.inputHandler = new Wt(this.viewer.scene.canvas), this.inputHandler.setInputAction((d) => {
2604
+ this.handleContextMenuAt(d.position);
2605
+ }, N.RIGHT_CLICK), this.config.pick.enabled && (this.inputHandler.setInputAction((d) => {
2606
+ this.handlePickAt(d.position);
2607
+ }, N.LEFT_CLICK), this.config.pick.hover && (this.bindHoverSuppressionInput(), this.inputHandler.setInputAction((d) => {
2608
+ this.scheduleHoverPick(d.endPosition);
2609
+ }, N.MOUSE_MOVE))), this.startCommitLoop(), this.startRenderLoop();
2610
+ }
2611
+ get targetCount() {
2612
+ return this.total;
2613
+ }
2614
+ setData(t) {
2615
+ if (this.destroyed)
2616
+ return;
2617
+ this.replaceLabelData(t);
2618
+ const s = this.postWithTiming({ type: "set-data", targets: t });
2619
+ this.stagedUpserts = t.length, this.stagedBatches = 1, this.emit("perf", { phase: "worker-submit", full: t.length, batches: 1, upserts: t.length, submitMs: s }), this.config.data.leading && this.commitNow();
2620
+ }
2621
+ applyIncremental(t) {
2622
+ var r, l;
2623
+ if (this.destroyed)
2624
+ return;
2625
+ this.applyLabelIncremental(t);
2626
+ const s = ((r = t.upserts) == null ? void 0 : r.length) ?? 0, n = ((l = t.removes) == null ? void 0 : l.length) ?? 0, o = this.postWithTiming({ type: "incremental", payload: t });
2627
+ this.stagedUpserts += s, this.stagedBatches++, this.emit("perf", { phase: "worker-submit", full: this.total, batches: this.stagedBatches, upserts: s, submitMs: o }), this.config.data.leading && this.total === 0 && this.commitNow(), (s || n) && this.emit("dirty", {
2628
+ added: t.upserts ?? [],
2629
+ updated: [],
2630
+ removed: t.removes ?? []
2631
+ });
2632
+ }
2633
+ applyRealtimeUpsert(t) {
2634
+ this.destroyed || t.length === 0 || (this.upsertLabelData(t), this.worker.postMessage({ type: "realtime-upsert", targets: t }));
2635
+ }
2636
+ applyRealtimeRemove(t) {
2637
+ this.destroyed || t.length === 0 || (this.removeLabelData(t), this.worker.postMessage({ type: "realtime-remove", ids: t.slice() }));
2638
+ }
2639
+ applyPacked(t) {
2640
+ var r;
2641
+ if (this.destroyed)
2642
+ return;
2643
+ t.replacePending && this.labelDataById.clear();
2644
+ const s = Fn(t), n = this.postWithTiming({ type: "stage-packed", payload: t }, s), o = ((r = t.ids) == null ? void 0 : r.length) ?? t.lon.length;
2645
+ this.stagedUpserts = t.replacePending ? o : this.stagedUpserts + o, this.stagedBatches = t.replacePending ? 1 : this.stagedBatches + 1, this.emit("perf", { phase: "worker-submit", full: this.total, batches: this.stagedBatches, upserts: o, submitMs: n }), this.config.data.leading && this.total === 0 && this.commitNow();
2646
+ }
2647
+ applyTargetStyle(t) {
2648
+ this.destroyed || t.length === 0 || this.worker.postMessage({ type: "style-patch", patches: t });
2649
+ }
2650
+ setBoxedTargetIds(t) {
2651
+ this.setSelectedTargetIds(t), this.viewer.scene.requestRender();
2652
+ }
2653
+ setLabelConfig(t) {
2654
+ this.labelConfig = Ke({ ...this.labelConfig, ...t }), this.render.setLabelOptions(this.labelConfig, (s) => this.nameplateText(s));
2655
+ }
2656
+ async selectTarget(t, s = !0) {
2657
+ s && this.clearSelection(!1), this.selectedIds.add(t), this.selection.setSelectedIds(Array.from(this.selectedIds));
2658
+ const n = await this.getPickedNode(t);
2659
+ return n && this.selectedTargets.set(t, n), this.emitSelection(), n;
2660
+ }
2661
+ async selectTargets(t, s = !0) {
2662
+ s && this.clearSelection(!1);
2663
+ for (const o of t)
2664
+ this.selectedIds.add(o);
2665
+ this.selection.setSelectedIds(Array.from(this.selectedIds));
2666
+ const n = await Promise.all(t.map((o) => this.getPickedNode(o)));
2667
+ for (const o of n)
2668
+ o && this.selectedTargets.set(o.id, o);
2669
+ return this.emitSelection(), n.filter((o) => o != null);
2670
+ }
2671
+ unselectTarget(t) {
2672
+ this.selectedIds.delete(t), this.selectedTargets.delete(t), this.selection.setSelectedIds(Array.from(this.selectedIds)), this.emitSelection();
2673
+ }
2674
+ clearSelection(t = !0) {
2675
+ this.selectedIds.clear(), this.selectedTargets.clear(), this.selection.setSelectedIds([]), t && this.emitSelection();
2676
+ }
2677
+ flushNow() {
2678
+ this.commitNow();
2679
+ }
2680
+ getTargetSnapshot(t) {
2681
+ if (this.destroyed)
2682
+ return Promise.resolve(null);
2683
+ const s = ++this.targetQueryRequestId;
2684
+ return new Promise((n) => {
2685
+ this.targetQueryResolvers.set(s, n), this.worker.postMessage({ type: "target-query", requestId: s, id: t });
2686
+ });
2687
+ }
2688
+ pause() {
2689
+ this.paused = !0;
2690
+ }
2691
+ resume() {
2692
+ this.paused = !1, this.requestViewport("resume");
2693
+ }
2694
+ destroy() {
2695
+ var t, s;
2696
+ this.destroyed || (this.destroyed = !0, this.readyResolved || (this.readyResolved = !0, this.resolveReady()), this.commitTimer != null && window.clearInterval(this.commitTimer), this.rafId && cancelAnimationFrame(this.rafId), this.hoverPickWarmupRafId && cancelAnimationFrame(this.hoverPickWarmupRafId), this.cancelPendingHoverPick(), this.cameraMoveTrailingTimer && window.clearTimeout(this.cameraMoveTrailingTimer), this.wheelSuppressResetTimer && window.clearTimeout(this.wheelSuppressResetTimer), this.cameraViewportThrottleTimer && window.clearTimeout(this.cameraViewportThrottleTimer), (t = this.removeCameraListener) == null || t.call(this), this.worker.postMessage({ type: "destroy" }), this.worker.terminate(), this.models.destroy(), this.tracks.destroy(), this.selection.destroy(), this.render.destroy(), this.symbols && this.viewer.scene.primitives.remove(this.symbols), (s = this.inputHandler) == null || s.destroy(), this.clear());
2697
+ }
2698
+ startCommitLoop() {
2699
+ this.commitIntervalMs <= 0 || (this.commitTimer = window.setInterval(() => this.commitNow(), this.commitIntervalMs));
2700
+ }
2701
+ startRenderLoop() {
2702
+ const t = (s) => {
2703
+ if (this.destroyed)
2704
+ return;
2705
+ const n = Math.max(0, (s - this.lastFrameAt) / 1e3);
2706
+ this.lastFrameAt = s;
2707
+ const o = _();
2708
+ this.isModelRenderActive() && this.models.update(n), this.render.update(n), this.selection.update(n), this.tracks.update(n);
2709
+ const r = _() - o;
2710
+ r >= 16 && this.emit("perf", {
2711
+ phase: "tick-slow",
2712
+ at: _(),
2713
+ totalMs: r,
2714
+ flushMs: 0,
2715
+ ingestMs: 0,
2716
+ scanMs: 0,
2717
+ visualMs: 0,
2718
+ motionMs: 0,
2719
+ renderMs: r,
2720
+ rendered: this.nodes.renderedCount
2721
+ }), this.viewportDirty && !this.viewportInFlight ? (this.viewportDirty = !1, this.requestViewport("dirty-frame")) : this.shouldRefreshPredictionViewport(s) && this.requestViewport("predict-frame"), this.rafId = requestAnimationFrame(t);
2722
+ };
2723
+ this.rafId = requestAnimationFrame(t);
2724
+ }
2725
+ commitNow() {
2726
+ this.destroyed || this.paused || (this.lastCommitSubmitAt = _(), this.worker.postMessage({ type: "commit", requestId: ++this.commitRequestId }));
2727
+ }
2728
+ // 相机移动触发的视口裁剪做 leading+trailing 节流:立即响应一次,期间的连续
2729
+ // 事件合并,停止/间隔满足后再补一次 trailing,确保最终画面与相机一致。
2730
+ requestViewportThrottled() {
2731
+ if (this.destroyed || this.paused)
2732
+ return;
2733
+ const t = _(), s = t - this.lastCameraViewportAt;
2734
+ if (s >= kt) {
2735
+ this.lastCameraViewportAt = t, this.requestViewport("camera");
2736
+ return;
2737
+ }
2738
+ this.cameraViewportThrottleTimer || (this.cameraViewportThrottleTimer = window.setTimeout(() => {
2739
+ this.cameraViewportThrottleTimer = 0, this.lastCameraViewportAt = _(), this.requestViewport("camera-trailing");
2740
+ }, kt - s));
2741
+ }
2742
+ requestViewport(t) {
2743
+ var v, d;
2744
+ if (this.destroyed || this.paused)
2745
+ return;
2746
+ const s = this.viewer.scene.camera.positionCartographic, n = s.height, o = A.toDegrees(s.longitude), r = A.toDegrees(s.latitude), l = A.toDegrees(this.viewer.camera.pitch), h = n >= (((v = this.config.merge) == null ? void 0 : v.globalViewportHeight) ?? 45e4);
2747
+ if (h && this.globalViewportRevision === this.dataRevision && !this.viewportInFlight)
2748
+ return;
2749
+ if (this.viewportInFlight) {
2750
+ this.viewportDirty = !0;
2751
+ return;
2752
+ }
2753
+ this.viewportInFlight = !0;
2754
+ const c = ++this.viewportRequestId;
2755
+ this.viewportRequestRevisions.set(c, this.dataRevision), h && this.globalViewportRequestIds.add(c);
2756
+ const m = h ? { west: -180, east: 180, south: -85, north: 85 } : this.currentBounds(), u = h ? void 0 : Vn(this.config.horizonCull, n, l);
2757
+ this.worker.postMessage({
2758
+ type: "viewport",
2759
+ requestId: c,
2760
+ bounds: m,
2761
+ global: h,
2762
+ cameraHeight: n,
2763
+ cameraLon: o,
2764
+ cameraLat: r,
2765
+ cameraPitch: l,
2766
+ horizonCullDistance: u,
2767
+ maxRender: ((d = this.config.merge) == null ? void 0 : d.maxVisible) ?? this.config.poolSize
2768
+ });
2769
+ }
2770
+ handleWorkerMessage(t) {
2771
+ if (this.destroyed)
2772
+ return;
2773
+ if (t.type === "ready") {
2774
+ this.readyResolved || (this.readyResolved = !0, this.resolveReady()), this.requestViewport("ready");
2775
+ return;
2776
+ }
2777
+ if (t.type === "input") {
2778
+ this.emit("perf", {
2779
+ phase: "input",
2780
+ kind: t.kind,
2781
+ upserts: t.upserts,
2782
+ removes: t.removes,
2783
+ pendingBatches: t.pendingBatches
2784
+ });
2785
+ return;
2786
+ }
2787
+ if (t.type === "commit-done") {
2788
+ this.total = t.size, this.stagedBatches = 0, this.stagedUpserts = 0, (t.added || t.updated || t.removed) && this.dataRevision++, this.emit("perf", {
2789
+ phase: "worker-done",
2790
+ added: t.added,
2791
+ updated: t.updated,
2792
+ removed: t.removed,
2793
+ size: t.size,
2794
+ computeMs: t.computeMs,
2795
+ roundTripMs: _() - this.lastCommitSubmitAt
2796
+ }), this.emit("packedDirty", {
2797
+ added: void 0,
2798
+ updated: void 0,
2799
+ removed: []
2800
+ }), this.requestViewport("commit");
2801
+ return;
2802
+ }
2803
+ if (t.type === "realtime-done") {
2804
+ this.total = t.size, this.dataRevision++, this.emit("perf", {
2805
+ phase: "worker-done",
2806
+ added: t.upserts,
2807
+ updated: 0,
2808
+ removed: t.removes,
2809
+ size: t.size,
2810
+ computeMs: t.computeMs,
2811
+ roundTripMs: 0
2812
+ }), this.requestViewport("realtime");
2813
+ return;
2814
+ }
2815
+ if (t.type === "style-done") {
2816
+ t.updated > 0 && (this.dataRevision++, this.requestViewport("style"));
2817
+ return;
2818
+ }
2819
+ if (t.type === "target-info") {
2820
+ const o = this.targetQueryResolvers.get(t.requestId);
2821
+ o && (this.targetQueryResolvers.delete(t.requestId), o(t.target));
2822
+ return;
2823
+ }
2824
+ if (t.type === "viewport-cache-ready") {
2825
+ this.globalViewportRevision = -1, this.requestViewport("cache-ready");
2826
+ return;
2827
+ }
2828
+ this.viewportInFlight = !1;
2829
+ const s = this.viewportRequestRevisions.get(t.packet.requestId);
2830
+ this.viewportRequestRevisions.delete(t.packet.requestId);
2831
+ const n = this.globalViewportRequestIds.delete(t.packet.requestId);
2832
+ if (t.packet.requestId < this.viewportRequestId || s !== this.dataRevision) {
2833
+ this.viewportDirty = !1, this.requestViewport("stale-data");
2834
+ return;
2835
+ }
2836
+ n && s != null && (this.globalViewportRevision = s), this.applyRenderPacket(t.packet), this.viewportDirty && (this.viewportDirty = !1, this.requestViewport("queued"));
2837
+ }
2838
+ applyRenderPacket(t) {
2839
+ const s = _();
2840
+ this.latestRenderPacket = t, this.hoverPickIndex = null;
2841
+ const n = this.isModelRenderActive(), o = n ? this.models.setPacket(t) : [];
2842
+ n || this.models.suspend(), this.render.setModelTargetIds(o, n), this.render.setPacket(t), this.updateSymbolsThrottled(t), this.selection.setPacket(t), this.tracks.setRenderPacket(t), this.scheduleHoverPickIndexWarmup(), this.applyStats(t.stats), this.applyActualRenderStats(t, this.models.renderStats()), this.viewer.scene.requestRender();
2843
+ const r = _() - s;
2844
+ (r >= 12 || t.computeMs >= 16) && this.emit("perf", {
2845
+ phase: "tick-slow",
2846
+ at: _(),
2847
+ totalMs: r + t.computeMs,
2848
+ flushMs: 0,
2849
+ ingestMs: 0,
2850
+ scanMs: t.computeMs,
2851
+ visualMs: 0,
2852
+ motionMs: 0,
2853
+ renderMs: r,
2854
+ rendered: t.stats.rendered
2855
+ });
2856
+ }
2857
+ updateSymbolsThrottled(t) {
2858
+ if (!this.symbols)
2859
+ return;
2860
+ const s = _();
2861
+ this.lastSymbolsUpdateAt > 0 && s - this.lastSymbolsUpdateAt < 1e3 || (this.lastSymbolsUpdateAt = s, this.symbols.setPacket(t));
2862
+ }
2863
+ applyStats(t) {
2864
+ this.nodes.visibleCount = t.rawInView, this.nodes.bufferCount = Math.max(0, t.rawInBuffer - t.rawInView), this.nodes.renderedCount = t.rendered, this.nodes.clusterCount = t.clusters, this.nodes.lastMergeRadius = t.lastMergeRadius, this.nodes.pointRenderCount = t.pointCount, this.nodes.lowModelRenderCount = t.lowModelCount, this.nodes.highModelRenderCount = t.highModelCount, this.nodes.plainPointRenderCount = t.plainPointCount, this.nodes.mergedPointRenderCount = t.mergedPointCount, this.nodes.mergedLowModelRenderCount = t.mergedLowModelCount, this.nodes.mergedHighModelRenderCount = t.mergedHighModelCount, this.nodes.forcedPointMode = t.forcedPointMode, this.nodes.level = t.level, this.nodes.outsideLevel = t.outsideLevel;
2865
+ }
2866
+ applyActualRenderStats(t, s) {
2867
+ const n = s.low + s.high, o = Math.max(0, t.ids.length - n), r = t.stats.clusters;
2868
+ this.nodes.lowModelRenderCount = s.low, this.nodes.highModelRenderCount = s.high, this.nodes.pointRenderCount = o, this.nodes.mergedPointRenderCount = Math.min(o, r), this.nodes.plainPointRenderCount = Math.max(0, o - this.nodes.mergedPointRenderCount), this.nodes.mergedLowModelRenderCount = 0, this.nodes.mergedHighModelRenderCount = 0;
2869
+ }
2870
+ shouldRefreshPredictionViewport(t) {
2871
+ if (this.viewportInFlight || this.paused || this.destroyed || !this.isModelRenderActive() || !this.latestRenderPacket || !zn(this.latestRenderPacket))
2872
+ return !1;
2873
+ const s = 1e3 / Math.max(1, this.config.updateFps);
2874
+ return t - this.lastPredictionViewportAt < s ? !1 : (this.lastPredictionViewportAt = t, !0);
2875
+ }
2876
+ async handlePickAt(t) {
2877
+ const s = this.pickTargetId(t, Pt), n = ++this.pickRequestSerial;
2878
+ if (!s) {
2879
+ this.clearSelection(), this.emit("pick", null);
2880
+ return;
2881
+ }
2882
+ const o = await this.selectTarget(s, !0);
2883
+ n === this.pickRequestSerial && this.emit("pick", o);
2884
+ }
2885
+ async handleContextMenuAt(t) {
2886
+ const s = ++this.contextMenuRequestSerial, n = this.pickTargetId(t, Pt), o = this.pickGroundCartesian(t, new f());
2887
+ let r = null;
2888
+ if (n && (r = this.hoverTargetCache.get(n) ?? await this.getPickedNode(n)), s !== this.contextMenuRequestSerial)
2889
+ return;
2890
+ if (r) {
2891
+ const c = this.getRenderedTargetPosition(r.id, new f()) ?? f.fromDegrees(r.data.lon, r.data.lat, r.data.height, void 0, new f());
2892
+ this.emit("contextmenu", {
2893
+ kind: "target",
2894
+ target: r,
2895
+ screenX: t.x,
2896
+ screenY: t.y,
2897
+ cartesian: c,
2898
+ lon: r.data.lon,
2899
+ lat: r.data.lat,
2900
+ height: r.data.height
2901
+ });
2902
+ return;
2903
+ }
2904
+ if (!o) {
2905
+ this.emit("contextmenu", null);
2906
+ return;
2907
+ }
2908
+ const l = A.toDegrees, h = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(o);
2909
+ this.emit("contextmenu", {
2910
+ kind: "ground",
2911
+ target: null,
2912
+ screenX: t.x,
2913
+ screenY: t.y,
2914
+ cartesian: f.clone(o, new f()),
2915
+ lon: l(h.longitude),
2916
+ lat: l(h.latitude),
2917
+ height: h.height
2918
+ });
2919
+ }
2920
+ bindHoverSuppressionInput() {
2921
+ var t, s, n, o, r, l, h;
2922
+ (t = this.inputHandler) == null || t.setInputAction(() => {
2923
+ this.pointerButtonsMask |= 1, this.onViewManipulationStart();
2924
+ }, N.LEFT_DOWN), (s = this.inputHandler) == null || s.setInputAction(() => {
2925
+ this.pointerButtonsMask &= -2;
2926
+ }, N.LEFT_UP), (n = this.inputHandler) == null || n.setInputAction(() => {
2927
+ this.pointerButtonsMask |= 2, this.onViewManipulationStart();
2928
+ }, N.RIGHT_DOWN), (o = this.inputHandler) == null || o.setInputAction(() => {
2929
+ this.pointerButtonsMask &= -3;
2930
+ }, N.RIGHT_UP), (r = this.inputHandler) == null || r.setInputAction(() => {
2931
+ this.pointerButtonsMask |= 4, this.onViewManipulationStart();
2932
+ }, N.MIDDLE_DOWN), (l = this.inputHandler) == null || l.setInputAction(() => {
2933
+ this.pointerButtonsMask &= -5;
2934
+ }, N.MIDDLE_UP), (h = this.inputHandler) == null || h.setInputAction(() => {
2935
+ this.noteWheelInteraction();
2936
+ }, N.WHEEL);
2937
+ }
2938
+ scheduleHoverPick(t) {
2939
+ if (!(this.destroyed || !this.config.pick.hover)) {
2940
+ if (this.noteHoverPointerSample(t), this.hoverPickPosition) {
2941
+ const s = Math.abs(t.x - this.hoverPickPosition.x), n = Math.abs(t.y - this.hoverPickPosition.y);
2942
+ if (s < Tt && n < Tt)
2943
+ return;
2944
+ J.clone(t, this.hoverPickPosition);
2945
+ } else
2946
+ this.hoverPickPosition = J.clone(t);
2947
+ this.shouldSkipHoverPick() || this.hoverPickRafId || (this.hoverPickRafId = requestAnimationFrame(() => this.flushHoverPick()));
2948
+ }
2949
+ }
2950
+ flushHoverPick() {
2951
+ if (this.hoverPickRafId = 0, this.destroyed || !this.hoverPickPosition || this.shouldSkipHoverPick())
2952
+ return;
2953
+ const t = _();
2954
+ if (t - this.lastHoverPickAt < An) {
2955
+ this.hoverPickRafId = requestAnimationFrame(() => this.flushHoverPick());
2956
+ return;
2957
+ }
2958
+ this.lastHoverPickAt = t, this.handleHoverAt(this.hoverPickPosition);
2959
+ }
2960
+ async handleHoverAt(t) {
2961
+ if (this.hoverPointerSpeedPxPerMs > Hn) {
2962
+ this.lastHoverId != null && (this.lastHoverId = null, this.hoverRequestSerial++, this.selection.setHoveredId(null), this.emit("hover", null));
2963
+ return;
2964
+ }
2965
+ const s = this.pickIndexedTargetId(t, 1);
2966
+ if (s === this.lastHoverId)
2967
+ return;
2968
+ this.lastHoverId = s;
2969
+ const n = ++this.hoverRequestSerial;
2970
+ if (!s) {
2971
+ this.selection.setHoveredId(null), this.emit("hover", null);
2972
+ return;
2973
+ }
2974
+ this.selection.setHoveredId(s);
2975
+ const o = this.hoverTargetCache.get(s);
2976
+ if (o) {
2977
+ this.emit("hover", o);
2978
+ return;
2979
+ }
2980
+ const r = await this.getPickedNode(s);
2981
+ n === this.hoverRequestSerial && (r && this.cacheHoverTarget(r), this.selection.setHoveredId((r == null ? void 0 : r.id) ?? null), this.emit("hover", r));
2982
+ }
2983
+ pickIndexedTargetId(t, s) {
2984
+ const n = this.ensureHoverPickIndex();
2985
+ if (!n)
2986
+ return null;
2987
+ const o = Math.floor(t.x / n.cellSize), r = Math.floor(t.y / n.cellSize);
2988
+ let l = null, h = Number.POSITIVE_INFINITY;
2989
+ for (let c = r - 1; c <= r + 1; c++)
2990
+ for (let m = o - 1; m <= o + 1; m++) {
2991
+ const u = n.bins.get(At(m, c));
2992
+ if (u)
2993
+ for (const v of u) {
2994
+ const d = Math.max(1, s, n.hitRadius[v]), p = d * d, g = n.windowX[v] - t.x, y = n.windowY[v] - t.y, w = g * g + y * y;
2995
+ if (w > p || w > h)
2996
+ continue;
2997
+ const M = n.ids[v];
2998
+ !M || M.startsWith("cluster:") || (h = w, l = M);
2999
+ }
3000
+ }
3001
+ return l;
3002
+ }
3003
+ ensureHoverPickIndex() {
3004
+ var m;
3005
+ const t = this.latestRenderPacket;
3006
+ if (!t || t.ids.length === 0)
3007
+ return null;
3008
+ const s = this.viewer.scene.canvas;
3009
+ if (this.hoverPickIndex && this.hoverPickIndex.requestId === t.requestId && this.hoverPickIndex.cameraRevision === this.cameraRevision && this.hoverPickIndex.canvasWidth === s.clientWidth && this.hoverPickIndex.canvasHeight === s.clientHeight)
3010
+ return this.hoverPickIndex;
3011
+ const n = new Float32Array(t.ids.length), o = new Float32Array(t.ids.length), r = new Float32Array(t.ids.length);
3012
+ let l = this.config.pick.pixelThreshold * Ct;
3013
+ o.fill(Number.NaN), r.fill(Number.NaN);
3014
+ for (let u = 0; u < t.ids.length; u++) {
3015
+ if (!(t.flags[u] & Bn) || t.count[u] !== 1)
3016
+ continue;
3017
+ const v = Ae.wgs84ToWindowCoordinates(
3018
+ this.viewer.scene,
3019
+ f.fromDegrees(t.lon[u], t.lat[u], t.height[u])
3020
+ );
3021
+ if (!v)
3022
+ continue;
3023
+ const d = v.x, p = v.y;
3024
+ if (!Number.isFinite(d) || !Number.isFinite(p) || d < 0 || p < 0 || d > s.clientWidth || p > s.clientHeight)
3025
+ continue;
3026
+ const g = t.category[u] ?? 0, y = ((m = this.config.renderTypes[g]) == null ? void 0 : m.type) ?? "", w = $t(y, t.size[u], t.count[u] > 1), M = Math.max(1, w * 0.5 * Ln);
3027
+ n[u] = M, l = Math.max(l, M), o[u] = d, r[u] = p;
3028
+ }
3029
+ const h = Math.max(_n, l * 2), c = /* @__PURE__ */ new Map();
3030
+ for (let u = 0; u < t.ids.length; u++) {
3031
+ const v = o[u], d = r[u];
3032
+ if (!Number.isFinite(v) || !Number.isFinite(d))
3033
+ continue;
3034
+ const p = At(Math.floor(v / h), Math.floor(d / h)), g = c.get(p);
3035
+ g ? g.push(u) : c.set(p, [u]);
3036
+ }
3037
+ return this.hoverPickIndex = {
3038
+ requestId: t.requestId,
3039
+ ids: t.ids.slice(),
3040
+ cameraRevision: this.cameraRevision,
3041
+ canvasWidth: s.clientWidth,
3042
+ canvasHeight: s.clientHeight,
3043
+ cellSize: h,
3044
+ bins: c,
3045
+ windowX: o,
3046
+ windowY: r,
3047
+ hitRadius: n
3048
+ }, this.hoverPickIndex;
3049
+ }
3050
+ pickTargetId(t, s) {
3051
+ const n = this.pickIndexedTargetId(
3052
+ t,
3053
+ Math.max(18, this.config.pick.pixelThreshold * 1.25) * Ct
3054
+ );
3055
+ if (n)
3056
+ return n;
3057
+ const o = this.viewer.scene.pick(t, 1, 1), r = Lt(o);
3058
+ if (r || s <= 0)
3059
+ return r;
3060
+ const l = this.viewer.scene.drillPick(t, s, 1, 1) ?? [];
3061
+ for (const h of l) {
3062
+ const c = Lt(h);
3063
+ if (c)
3064
+ return c;
3065
+ }
3066
+ return null;
3067
+ }
3068
+ getRenderedTargetFrame(t, s = new f()) {
3069
+ var n;
3070
+ return this.models.getTargetFrame(t, s) ?? this.render.getTargetFrame(t, s) ?? ((n = this.symbols) == null ? void 0 : n.getTargetFrame(t, s));
3071
+ }
3072
+ getRenderedTargetPosition(t, s = new f()) {
3073
+ const n = this.latestRenderPacket;
3074
+ if (!n)
3075
+ return null;
3076
+ const o = n.ids.indexOf(t);
3077
+ return o < 0 || n.count[o] !== 1 ? null : f.fromDegrees(n.lon[o], n.lat[o], n.height[o], void 0, s);
3078
+ }
3079
+ pickGroundCartesian(t, s) {
3080
+ const n = this.viewer.scene;
3081
+ if (n.pickPositionSupported && typeof n.pickPosition == "function") {
3082
+ const h = n.pickPosition(t);
3083
+ if (h)
3084
+ return f.clone(h, s);
3085
+ }
3086
+ const r = this.viewer.camera.getPickRay(t);
3087
+ if (!r)
3088
+ return null;
3089
+ const l = n.globe.pick(r, n);
3090
+ return l ? f.clone(l, s) : null;
3091
+ }
3092
+ shouldSkipHoverPick() {
3093
+ return this.pointerButtonsMask !== 0 || this.cameraMoving || _() < this.wheelSuppressPickUntil;
3094
+ }
3095
+ noteHoverPointerSample(t) {
3096
+ const s = _(), n = this.lastHoverPointerSample;
3097
+ if (!n) {
3098
+ this.lastHoverPointerSample = { x: t.x, y: t.y, at: s }, this.hoverPointerSpeedPxPerMs = 0;
3099
+ return;
3100
+ }
3101
+ const o = Math.max(1, s - n.at), r = t.x - n.x, l = t.y - n.y, h = Math.sqrt(r * r + l * l) / o;
3102
+ this.hoverPointerSpeedPxPerMs = h * bt + this.hoverPointerSpeedPxPerMs * (1 - bt), n.x = t.x, n.y = t.y, n.at = s;
3103
+ }
3104
+ cancelPendingHoverPick() {
3105
+ this.hoverPickRafId && (cancelAnimationFrame(this.hoverPickRafId), this.hoverPickRafId = 0);
3106
+ }
3107
+ onViewManipulationStart() {
3108
+ this.cancelPendingHoverPick(), this.lastHoverPointerSample = null, this.hoverPointerSpeedPxPerMs = 0, this.lastHoverId != null && (this.lastHoverId = null, this.hoverRequestSerial++, this.selection.setHoveredId(null), this.emit("hover", null));
3109
+ }
3110
+ noteWheelInteraction() {
3111
+ this.lastHoverPointerSample = null, this.hoverPointerSpeedPxPerMs = 0, this.wheelSuppressPickUntil = _() + Rt, this.wheelSuppressResetTimer && window.clearTimeout(this.wheelSuppressResetTimer), this.wheelSuppressResetTimer = window.setTimeout(() => {
3112
+ this.wheelSuppressResetTimer = 0, this.wheelSuppressPickUntil = 0;
3113
+ }, Rt), this.onViewManipulationStart();
3114
+ }
3115
+ noteCameraMovement() {
3116
+ this.config.pick.hover && (this.cameraRevision++, this.hoverPickIndex = null, this.cameraMoving = !0, this.lastHoverPointerSample = null, this.hoverPointerSpeedPxPerMs = 0, this.onViewManipulationStart(), this.cameraMoveTrailingTimer && window.clearTimeout(this.cameraMoveTrailingTimer), this.cameraMoveTrailingTimer = window.setTimeout(() => {
3117
+ this.cameraMoveTrailingTimer = 0, this.cameraMoving = !1, this.scheduleHoverPickIndexWarmup();
3118
+ }, Dn));
3119
+ }
3120
+ scheduleHoverPickIndexWarmup() {
3121
+ this.destroyed || !this.config.pick.hover || this.hoverPickWarmupRafId || this.hoverPickIndex || !this.latestRenderPacket || (this.hoverPickWarmupRafId = requestAnimationFrame(() => {
3122
+ this.hoverPickWarmupRafId = 0, !(this.destroyed || this.cameraMoving || !this.latestRenderPacket || this.hoverPickIndex) && this.ensureHoverPickIndex();
3123
+ }));
3124
+ }
3125
+ cacheHoverTarget(t) {
3126
+ if (this.hoverTargetCache.set(t.id, t), this.hoverTargetCache.size <= En)
3127
+ return;
3128
+ const s = this.hoverTargetCache.keys().next().value;
3129
+ s && this.hoverTargetCache.delete(s);
3130
+ }
3131
+ async getPickedNode(t) {
3132
+ const s = await this.getTargetSnapshot(t);
3133
+ if (!s)
3134
+ return null;
3135
+ const n = Gn(s), o = this.labelDataById.get(t);
3136
+ return o ? {
3137
+ ...n,
3138
+ data: {
3139
+ ...n.data,
3140
+ nationality: o.nationality,
3141
+ customInfo: o.customInfo
3142
+ }
3143
+ } : n;
3144
+ }
3145
+ replaceLabelData(t) {
3146
+ this.labelDataById.clear(), this.upsertLabelData(t);
3147
+ }
3148
+ applyLabelIncremental(t) {
3149
+ var s, n;
3150
+ (s = t.removes) != null && s.length && this.removeLabelData(t.removes), (n = t.upserts) != null && n.length && this.upsertLabelData(t.upserts);
3151
+ }
3152
+ upsertLabelData(t) {
3153
+ for (const s of t)
3154
+ this.labelDataById.set(s.id, s);
3155
+ this.hoverTargetCache.clear();
3156
+ }
3157
+ removeLabelData(t) {
3158
+ for (const s of t)
3159
+ this.labelDataById.delete(s);
3160
+ this.hoverTargetCache.clear();
3161
+ }
3162
+ nameplateText(t) {
3163
+ var c, m, u, v;
3164
+ const s = t.data ?? this.labelDataById.get(t.id), n = s && s !== t.data ? { ...t, data: s, type: s.type ?? t.type } : t, o = (m = (c = this.labelConfig).resolve) == null ? void 0 : m.call(c, n);
3165
+ if (o !== void 0)
3166
+ return o;
3167
+ if (n.count > 1)
3168
+ return `merged x${n.count}`;
3169
+ if (!s)
3170
+ return t.id;
3171
+ const r = (u = this.labelConfig.byType) == null ? void 0 : u[n.type];
3172
+ if ((r == null ? void 0 : r.maxCameraHeight) != null && n.cameraHeight > r.maxCameraHeight)
3173
+ return null;
3174
+ const l = (r == null ? void 0 : r.fields) ?? this.labelConfig.fields, h = [];
3175
+ for (const d of l) {
3176
+ if (!Yn(d, n.cameraHeight))
3177
+ continue;
3178
+ const p = d.source === "custom" ? (v = s.customInfo) == null ? void 0 : v[d.key] : s[d.key], g = Zn(p, d.fallback);
3179
+ g && h.push(this.labelConfig.showFieldLabels === !1 || !d.label ? g : `${d.label}: ${g}`);
3180
+ }
3181
+ return h.length ? h : null;
3182
+ }
3183
+ setSelectedTargetIds(t) {
3184
+ this.selectedIds.clear();
3185
+ for (const s of t)
3186
+ this.selectedIds.add(s);
3187
+ this.selection.setSelectedIds(Array.from(this.selectedIds)), Promise.all(t.map((s) => this.getPickedNode(s))).then((s) => {
3188
+ this.selectedTargets.clear();
3189
+ for (const n of s)
3190
+ n && this.selectedTargets.set(n.id, n);
3191
+ this.emitSelection();
3192
+ });
3193
+ }
3194
+ emitSelection() {
3195
+ const t = [];
3196
+ for (const s of this.selectedIds) {
3197
+ const n = this.selectedTargets.get(s);
3198
+ n && t.push(n);
3199
+ }
3200
+ this.emit("selection", t);
3201
+ }
3202
+ isModelRenderActive() {
3203
+ return this.viewer.scene.camera.positionCartographic.height <= this.config.lod.pointAbove;
3204
+ }
3205
+ currentBounds() {
3206
+ const t = this.viewer.camera.computeViewRectangle();
3207
+ if (!t)
3208
+ return { west: -180, east: 180, south: -85, north: 85 };
3209
+ const s = A.toDegrees(t.west), n = A.toDegrees(t.east), o = A.toDegrees(t.south), r = A.toDegrees(t.north);
3210
+ return !Number.isFinite(s) || !Number.isFinite(n) || n <= s ? { west: -180, east: 180, south: -85, north: 85 } : { west: s, east: n, south: o, north: r };
3211
+ }
3212
+ postWithTiming(t, s) {
3213
+ const n = _();
3214
+ return this.worker.postMessage(t, s ?? []), _() - n;
3215
+ }
3216
+ }
3217
+ function Fn(i) {
3218
+ const e = [];
3219
+ return K(e, i.lon), K(e, i.lat), K(e, i.height), K(e, i.speedH), K(e, i.speedV), K(e, i.heading), K(e, i.secrecy), K(e, i.renderColor), K(e, i.animate), K(e, i.animateColor), e;
3220
+ }
3221
+ function K(i, e) {
3222
+ e && e.buffer instanceof ArrayBuffer && !i.includes(e.buffer) && i.push(e.buffer);
3223
+ }
3224
+ function zn(i) {
3225
+ for (let e = 0; e < i.flags.length; e++)
3226
+ if (i.flags[e] & On)
3227
+ return !0;
3228
+ return !1;
3229
+ }
3230
+ function _() {
3231
+ return typeof performance < "u" ? performance.now() : Date.now();
3232
+ }
3233
+ function At(i, e) {
3234
+ return `${i}:${e}`;
3235
+ }
3236
+ function Vn(i, e, t) {
3237
+ if (i.enabled && !(e > i.maxCameraHeight) && !(t < i.pitchThreshold))
3238
+ return Wn(
3239
+ e * i.cameraHeightMultiplier,
3240
+ i.minDistance,
3241
+ i.maxDistance
3242
+ );
3243
+ }
3244
+ function Wn(i, e, t) {
3245
+ return Math.max(e, Math.min(t, i));
3246
+ }
3247
+ function Be(i) {
3248
+ return {
3249
+ type: i.type,
3250
+ targetDomain: i.targetDomain,
3251
+ iconPath: i.iconPath,
3252
+ defaultColor: i.defaultColor,
3253
+ pointHeadingOffset: i.pointHeadingOffset,
3254
+ lowModel: i.lowModel,
3255
+ highModel: i.highModel,
3256
+ lowModelUrl: i.lowModelUrl,
3257
+ highModelUrl: i.highModelUrl,
3258
+ scale: i.scale,
3259
+ modelHeadingOffset: i.modelHeadingOffset,
3260
+ modelPitchOffset: i.modelPitchOffset,
3261
+ modelRollOffset: i.modelRollOffset,
3262
+ predictMove: i.predictMove,
3263
+ predictMinCameraHeight: i.predictMinCameraHeight,
3264
+ predictSeconds: i.predictSeconds,
3265
+ predictFitSeconds: i.predictFitSeconds
3266
+ };
3267
+ }
3268
+ function Xn(i) {
3269
+ const e = i.startsWith("#") ? i.slice(1) : i;
3270
+ if (e.length !== 6 && e.length !== 8)
3271
+ return 16777215;
3272
+ const t = e.length === 8 ? e.slice(0, 6) : e, s = Number.parseInt(t, 16);
3273
+ return Number.isFinite(s) ? s : 16777215;
3274
+ }
3275
+ function Lt(i) {
3276
+ var t, s, n;
3277
+ if (!i)
3278
+ return null;
3279
+ const e = [i.id, (t = i.primitive) == null ? void 0 : t.id, (s = i.collection) == null ? void 0 : s.id, (n = i.id) == null ? void 0 : n.id];
3280
+ for (const o of e) {
3281
+ const r = Un(o);
3282
+ if (r)
3283
+ return r;
3284
+ }
3285
+ return null;
3286
+ }
3287
+ function Un(i) {
3288
+ if (typeof i == "string")
3289
+ return i;
3290
+ if (!i || typeof i != "object")
3291
+ return null;
3292
+ const e = i;
3293
+ return typeof e.targetId == "string" ? e.targetId : typeof e.id == "string" ? e.id : null;
3294
+ }
3295
+ function Gn(i) {
3296
+ return {
3297
+ id: i.id,
3298
+ type: i.type,
3299
+ data: {
3300
+ id: i.id,
3301
+ type: i.type,
3302
+ lon: i.lon,
3303
+ lat: i.lat,
3304
+ height: i.height,
3305
+ speedH: i.speedH,
3306
+ speedV: 0,
3307
+ heading: i.heading,
3308
+ renderColor: i.renderColor,
3309
+ openAnimate: i.openAnimate,
3310
+ animateColor: i.animateColor,
3311
+ nationality: i.nationality,
3312
+ customInfo: i.customInfo,
3313
+ extra: i.hidden ? { hidden: !0 } : void 0
3314
+ }
3315
+ };
3316
+ }
3317
+ function Zn(i, e) {
3318
+ if (i == null || i === "")
3319
+ return e ?? "";
3320
+ if (typeof i == "string")
3321
+ return i;
3322
+ if (typeof i == "number" || typeof i == "boolean" || typeof i == "bigint")
3323
+ return String(i);
3324
+ if (i instanceof Date)
3325
+ return i.toISOString();
3326
+ try {
3327
+ return JSON.stringify(i);
3328
+ } catch {
3329
+ return e ?? "";
3330
+ }
3331
+ }
3332
+ function Yn(i, e) {
3333
+ return !(i.minCameraHeight != null && e < i.minCameraHeight || i.maxCameraHeight != null && e > i.maxCameraHeight);
3334
+ }
3335
+ function si() {
3336
+ const i = /* @__PURE__ */ new Map(), e = /* @__PURE__ */ new Map(), t = {
3337
+ register(s, n, o) {
3338
+ if (i.has(s))
3339
+ throw new Error(`[web-event-bus] Action "${s}" is already registered.`);
3340
+ i.set(s, {
3341
+ action: s,
3342
+ handler: n,
3343
+ owner: o == null ? void 0 : o.owner,
3344
+ description: o == null ? void 0 : o.description
3345
+ });
3346
+ },
3347
+ unregister(s) {
3348
+ i.delete(s);
3349
+ },
3350
+ unregisterAll(s) {
3351
+ for (const [n, o] of i)
3352
+ o.owner === s && i.delete(n);
3353
+ },
3354
+ emit(s, n) {
3355
+ const o = e.get(s);
3356
+ if (o)
3357
+ for (const r of o)
3358
+ try {
3359
+ r(n);
3360
+ } catch (l) {
3361
+ console.error(`[web-event-bus] Listener error on "${s}":`, l);
3362
+ }
3363
+ },
3364
+ on(s, n) {
3365
+ return e.has(s) || e.set(s, /* @__PURE__ */ new Set()), e.get(s).add(n), () => {
3366
+ t.off(s, n);
3367
+ };
3368
+ },
3369
+ off(s, n) {
3370
+ const o = e.get(s);
3371
+ o && (o.delete(n), o.size === 0 && e.delete(s));
3372
+ },
3373
+ async invoke(s, n) {
3374
+ const o = i.get(s);
3375
+ if (!o)
3376
+ throw new Error(`[web-event-bus] Action "${s}" is not registered. Cannot invoke.`);
3377
+ return await o.handler(n);
3378
+ },
3379
+ has(s) {
3380
+ return i.has(s);
3381
+ },
3382
+ inspect() {
3383
+ return Array.from(i.values()).map(({ handler: s, ...n }) => n);
3384
+ }
3385
+ };
3386
+ return t;
3387
+ }
3388
+ var Ne = "__WEB_EVENT_BUS__";
3389
+ function Kn() {
3390
+ if (typeof window > "u")
3391
+ throw new Error("[web-event-bus] getGlobalBus() requires a browser environment (window).");
3392
+ return window[Ne] || (window[Ne] = si()), window[Ne];
3393
+ }
3394
+ const U = {
3395
+ scene: {
3396
+ perf: "mtf.scene.perf",
3397
+ dirty: "mtf.scene.dirty",
3398
+ packedDirty: "mtf.scene.packedDirty",
3399
+ pick: "mtf.scene.pick",
3400
+ hover: "mtf.scene.hover",
3401
+ selection: "mtf.scene.selection",
3402
+ contextmenu: "mtf.scene.contextmenu"
3403
+ },
3404
+ track: {
3405
+ hover: "mtf.track.hover"
3406
+ },
3407
+ site: {
3408
+ contextmenu: "mtf.site.contextmenu",
3409
+ pick: "mtf.site.pick",
3410
+ hover: "mtf.site.hover"
3411
+ }
3412
+ }, b = {
3413
+ framework: {
3414
+ addTarget: "mtf.framework.addTarget",
3415
+ updateTarget: "mtf.framework.updateTarget",
3416
+ setTargetData: "mtf.framework.setTargetData",
3417
+ upsertTargetData: "mtf.framework.upsertTargetData",
3418
+ removeTargetData: "mtf.framework.removeTargetData",
3419
+ applyTargetIncremental: "mtf.framework.applyTargetIncremental",
3420
+ setTargetColor: "mtf.framework.setTargetColor",
3421
+ setTargetGlow: "mtf.framework.setTargetGlow",
3422
+ hideTarget: "mtf.framework.hideTarget",
3423
+ showTarget: "mtf.framework.showTarget",
3424
+ disappearTarget: "mtf.framework.disappearTarget",
3425
+ appearTarget: "mtf.framework.appearTarget",
3426
+ setNameplateConfig: "mtf.framework.setNameplateConfig",
3427
+ selectTarget: "mtf.framework.selectTarget",
3428
+ selectTargets: "mtf.framework.selectTargets",
3429
+ unselectTarget: "mtf.framework.unselectTarget",
3430
+ clearSelection: "mtf.framework.clearSelection",
3431
+ boxTarget: "mtf.framework.boxTarget",
3432
+ unboxTarget: "mtf.framework.unboxTarget",
3433
+ locateTarget: "mtf.framework.locateTarget",
3434
+ registerContextMenuItem: "mtf.framework.registerContextMenuItem",
3435
+ showContextMenu: "mtf.framework.showContextMenu",
3436
+ closeContextMenu: "mtf.framework.closeContextMenu",
3437
+ destroy: "mtf.framework.destroy"
3438
+ },
3439
+ tracks: {
3440
+ setTracks: "mtf.tracks.setTracks",
3441
+ getTracks: "mtf.tracks.getTracks",
3442
+ showTracks: "mtf.tracks.showTracks",
3443
+ hideTracks: "mtf.tracks.hideTracks",
3444
+ removeTracks: "mtf.tracks.removeTracks",
3445
+ clearTracks: "mtf.tracks.clearTracks"
3446
+ },
3447
+ site: {
3448
+ setData: "mtf.site.setData",
3449
+ clear: "mtf.site.clear",
3450
+ pickAt: "mtf.site.pickAt",
3451
+ destroy: "mtf.site.destroy"
3452
+ }
3453
+ }, qn = "cesium-multi-target-framework";
3454
+ let Ht = 0;
3455
+ function $n() {
3456
+ return Kn();
3457
+ }
3458
+ function ni() {
3459
+ try {
3460
+ return $n();
3461
+ } catch {
3462
+ return null;
3463
+ }
3464
+ }
3465
+ function Ho() {
3466
+ return si();
3467
+ }
3468
+ function jn(i, e = {}) {
3469
+ const t = e.bus ?? ni(), s = e.owner ?? ai("framework");
3470
+ if (!t)
3471
+ return ri(s);
3472
+ const n = [], o = [];
3473
+ return e.registerActions !== !1 && Qn(t, i, s, e.replaceExisting === !0, o), e.bridgeEvents !== !1 && n.push(...to(t, i)), oi(t, s, n, o);
3474
+ }
3475
+ function Jn(i, e = {}) {
3476
+ const t = e.bus ?? ni(), s = e.owner ?? ai("site");
3477
+ if (!t)
3478
+ return ri(s);
3479
+ const n = [], o = [];
3480
+ return e.registerActions !== !1 && eo(t, i, s, e.replaceExisting === !0, o), e.bridgeEvents !== !1 && n.push(...io(t, i)), oi(t, s, n, o);
3481
+ }
3482
+ function Qn(i, e, t, s, n) {
3483
+ P(i, b.framework.addTarget, ({ target: o }) => e.addTarget(o), t, s, n), P(i, b.framework.updateTarget, ({ target: o }) => e.updateTarget(o), t, s, n), P(i, b.framework.setTargetData, ({ targets: o }) => e.setTargetData(o), t, s, n), P(i, b.framework.upsertTargetData, ({ targets: o }) => e.upsertTargetData(o), t, s, n), P(i, b.framework.removeTargetData, ({ ids: o }) => e.removeTargetData(o), t, s, n), P(i, b.framework.applyTargetIncremental, ({ payload: o }) => e.applyTargetIncremental(o), t, s, n), P(i, b.framework.setTargetColor, ({ id: o, color: r, options: l }) => e.setTargetColor(o, r, l), t, s, n), P(i, b.framework.setTargetGlow, ({ id: o, enabled: r, color: l, options: h }) => e.setTargetGlow(o, r, l, h), t, s, n), P(i, b.framework.hideTarget, ({ id: o, options: r }) => e.hideTarget(o, r), t, s, n), P(i, b.framework.showTarget, ({ id: o, options: r }) => e.showTarget(o, r), t, s, n), P(i, b.framework.disappearTarget, ({ id: o, options: r }) => e.disappearTarget(o, r), t, s, n), P(i, b.framework.appearTarget, ({ id: o, options: r }) => e.appearTarget(o, r), t, s, n), P(i, b.framework.setNameplateConfig, ({ config: o }) => e.setNameplateConfig(o), t, s, n), P(i, b.framework.selectTarget, ({ id: o, options: r }) => e.selectTarget(o, r), t, s, n), P(i, b.framework.selectTargets, ({ ids: o, options: r }) => e.selectTargets(o, r), t, s, n), P(i, b.framework.unselectTarget, ({ id: o }) => e.unselectTarget(o), t, s, n), P(i, b.framework.clearSelection, () => e.clearSelection(), t, s, n), P(i, b.framework.boxTarget, ({ id: o, enabled: r, options: l }) => e.boxTarget(o, r, l), t, s, n), P(i, b.framework.unboxTarget, ({ id: o, options: r }) => e.unboxTarget(o, r), t, s, n), P(i, b.framework.locateTarget, ({ id: o, options: r }) => e.locateTarget(o, r), t, s, n), P(i, b.framework.registerContextMenuItem, ({ item: o }) => e.registerContextMenuItem(o), t, s, n), P(i, b.framework.showContextMenu, ({ context: o }) => e.showContextMenu(o), t, s, n), P(i, b.framework.closeContextMenu, () => e.closeContextMenu(), t, s, n), P(i, b.framework.destroy, () => e.destroy(), t, s, n), P(i, b.tracks.setTracks, ({ tracks: o }) => e.tracks.setTracks(o), t, s, n), P(i, b.tracks.getTracks, (o) => e.tracks.getTracks(o == null ? void 0 : o.targetIds), t, s, n), P(i, b.tracks.showTracks, ({ targetIds: o }) => e.tracks.showTracks(o), t, s, n), P(i, b.tracks.hideTracks, ({ targetIds: o }) => e.tracks.hideTracks(o), t, s, n), P(i, b.tracks.removeTracks, ({ targetIds: o }) => e.tracks.removeTracks(o), t, s, n), P(i, b.tracks.clearTracks, () => e.tracks.clearTracks(), t, s, n);
3484
+ }
3485
+ function eo(i, e, t, s, n) {
3486
+ P(i, b.site.setData, ({ sites: o }) => e.setData(o), t, s, n), P(i, b.site.clear, () => e.clear(), t, s, n), P(i, b.site.pickAt, ({ position: o, thresholdPx: r }) => e.pickAt(o, r), t, s, n), P(i, b.site.destroy, () => e.destroy(), t, s, n);
3487
+ }
3488
+ function to(i, e) {
3489
+ return [
3490
+ e.scene.on("perf", (t) => G(i, U.scene.perf, t)),
3491
+ e.scene.on("dirty", (t) => G(i, U.scene.dirty, t)),
3492
+ e.scene.on("packedDirty", (t) => G(i, U.scene.packedDirty, t)),
3493
+ e.scene.on("pick", (t) => G(i, U.scene.pick, t)),
3494
+ e.scene.on("hover", (t) => G(i, U.scene.hover, t)),
3495
+ e.scene.on("selection", (t) => G(i, U.scene.selection, t)),
3496
+ e.scene.on("contextmenu", (t) => G(i, U.scene.contextmenu, t)),
3497
+ e.tracks.on("hover", (t) => G(i, U.track.hover, t))
3498
+ ];
3499
+ }
3500
+ function io(i, e) {
3501
+ return [
3502
+ e.on("contextmenu", (t) => G(i, U.site.contextmenu, t)),
3503
+ e.on("pick", (t) => G(i, U.site.pick, t)),
3504
+ e.on("hover", (t) => G(i, U.site.hover, t))
3505
+ ];
3506
+ }
3507
+ function P(i, e, t, s, n, o) {
3508
+ if (i.has(e)) {
3509
+ if (!n)
3510
+ return;
3511
+ i.unregister(e);
3512
+ }
3513
+ i.register(e, t, { owner: s }), o.push(e);
3514
+ }
3515
+ function G(i, e, t) {
3516
+ try {
3517
+ i.emit(e, t);
3518
+ } catch {
3519
+ }
3520
+ }
3521
+ function oi(i, e, t, s) {
3522
+ let n = !1;
3523
+ return {
3524
+ active: !0,
3525
+ owner: e,
3526
+ dispose() {
3527
+ if (!n) {
3528
+ n = !0;
3529
+ for (const o of t.splice(0))
3530
+ o();
3531
+ for (const o of s.splice(0))
3532
+ so(i, o, e) && i.unregister(o);
3533
+ }
3534
+ }
3535
+ };
3536
+ }
3537
+ function ri(i) {
3538
+ return {
3539
+ active: !1,
3540
+ owner: i,
3541
+ dispose() {
3542
+ }
3543
+ };
3544
+ }
3545
+ function ai(i) {
3546
+ return Ht++, `${qn}:${i}:${Ht}`;
3547
+ }
3548
+ function so(i, e, t) {
3549
+ try {
3550
+ return i.inspect().some((s) => s.action === e && s.owner === t);
3551
+ } catch {
3552
+ return !1;
3553
+ }
3554
+ }
3555
+ class $e {
3556
+ constructor(e, t) {
3557
+ a(this, "scene");
3558
+ a(this, "viewer");
3559
+ a(this, "tracks");
3560
+ /** 引擎就绪信号(转发自 scene.ready):可在加载依赖底座的其它组件前 await。 */
3561
+ a(this, "ready");
3562
+ a(this, "boxedTargetIds", /* @__PURE__ */ new Set());
3563
+ a(this, "contextMenuItems", /* @__PURE__ */ new Map());
3564
+ a(this, "contextMenuRoot");
3565
+ a(this, "contextMenuList");
3566
+ a(this, "removeSceneContextMenuListener");
3567
+ a(this, "eventBusBinding");
3568
+ a(this, "handleDocumentPointerDownBound");
3569
+ a(this, "handleKeyDownBound");
3570
+ a(this, "activeContextMenuContext", null);
3571
+ const s = no(t);
3572
+ this.viewer = e, this.scene = new Nn(e, s), this.ready = this.scene.ready, this.tracks = this.scene.tracks, this.contextMenuRoot = ho(), this.contextMenuList = document.createElement("div"), this.contextMenuList.className = "mtf-context-menu-list", this.contextMenuRoot.appendChild(this.contextMenuList), document.body.appendChild(this.contextMenuRoot), this.removeSceneContextMenuListener = this.scene.on("contextmenu", (n) => {
3573
+ this.handleSceneContextMenu(n);
3574
+ }), this.handleDocumentPointerDownBound = (n) => this.handleDocumentPointerDown(n), this.handleKeyDownBound = (n) => this.handleDocumentKeyDown(n), document.addEventListener("pointerdown", this.handleDocumentPointerDownBound, !0), document.addEventListener("keydown", this.handleKeyDownBound), this.eventBusBinding = jn(this, { replaceExisting: !0 });
3575
+ }
3576
+ setData(e) {
3577
+ this.setTargetData(e);
3578
+ }
3579
+ upsert(e) {
3580
+ this.upsertTargetData(e);
3581
+ }
3582
+ remove(e) {
3583
+ this.removeTargetData(e);
3584
+ }
3585
+ addTarget(e) {
3586
+ return this.updateTarget(e);
3587
+ }
3588
+ updateTarget(e) {
3589
+ const [t] = Te([e], this.scene.config.nodeTypes);
3590
+ return this.scene.applyRealtimeUpsert([t]), t;
3591
+ }
3592
+ setTargetData(e) {
3593
+ this.scene.setData(Te(e, this.scene.config.nodeTypes));
3594
+ }
3595
+ upsertTargetData(e) {
3596
+ this.scene.applyIncremental({ upserts: Te(e, this.scene.config.nodeTypes) });
3597
+ }
3598
+ removeTargetData(e) {
3599
+ this.scene.applyRealtimeRemove(e);
3600
+ }
3601
+ applyTargetIncremental(e) {
3602
+ var t;
3603
+ this.scene.applyIncremental({
3604
+ upserts: e.upserts ? Te(e.upserts, this.scene.config.nodeTypes) : void 0,
3605
+ removes: (t = e.removes) == null ? void 0 : t.slice()
3606
+ });
3607
+ }
3608
+ setTargetColor(e, t, s) {
3609
+ const n = oe(e);
3610
+ ke(t, "color");
3611
+ const o = ne(s);
3612
+ this.scene.applyTargetStyle(n.map((r, l) => ({
3613
+ id: r,
3614
+ styleKind: "color",
3615
+ clearBefore: o && l === 0,
3616
+ renderColor: t
3617
+ })));
3618
+ }
3619
+ setTargetGlow(e, t = !0, s, n) {
3620
+ const o = oe(e);
3621
+ s && ke(s, "color");
3622
+ const r = ne(n);
3623
+ this.scene.applyTargetStyle(o.map((l, h) => ({
3624
+ id: l,
3625
+ styleKind: "glow",
3626
+ clearBefore: r && h === 0,
3627
+ openAnimate: t,
3628
+ animateType: t ? "发光" : void 0,
3629
+ animateColor: s
3630
+ })));
3631
+ }
3632
+ hideTarget(e, t) {
3633
+ const s = oe(e), n = ne(t);
3634
+ this.scene.applyTargetStyle(s.map((o, r) => ({
3635
+ id: o,
3636
+ styleKind: "hidden",
3637
+ clearBefore: n && r === 0,
3638
+ hidden: !0
3639
+ })));
3640
+ }
3641
+ showTarget(e, t) {
3642
+ const s = oe(e), n = ne(t);
3643
+ this.scene.applyTargetStyle(s.map((o, r) => ({
3644
+ id: o,
3645
+ styleKind: "hidden",
3646
+ clearBefore: n && r === 0,
3647
+ hidden: !1
3648
+ })));
3649
+ }
3650
+ disappearTarget(e, t) {
3651
+ this.hideTarget(e, t);
3652
+ }
3653
+ appearTarget(e, t) {
3654
+ this.showTarget(e, t);
3655
+ }
3656
+ setNameplateConfig(e) {
3657
+ this.scene.setLabelConfig(e);
3658
+ }
3659
+ async selectTarget(e, t) {
3660
+ ie(e, "id");
3661
+ const s = await this.scene.selectTarget(e, ne(t));
3662
+ return s ? Dt(s) : null;
3663
+ }
3664
+ async selectTargets(e, t) {
3665
+ const s = oe(e);
3666
+ return (await this.scene.selectTargets(s, ne(t))).map(Dt);
3667
+ }
3668
+ unselectTarget(e) {
3669
+ ie(e, "id"), this.boxedTargetIds.delete(e), this.scene.unselectTarget(e);
3670
+ }
3671
+ clearSelection() {
3672
+ this.boxedTargetIds.clear(), this.scene.clearSelection();
3673
+ }
3674
+ boxTarget(e, t = !0, s) {
3675
+ const n = oe(e);
3676
+ ne(s) && this.boxedTargetIds.clear();
3677
+ for (const o of n)
3678
+ t ? this.boxedTargetIds.add(o) : this.boxedTargetIds.delete(o);
3679
+ this.scene.setBoxedTargetIds(Array.from(this.boxedTargetIds));
3680
+ }
3681
+ unboxTarget(e, t) {
3682
+ this.boxTarget(e, !1, t);
3683
+ }
3684
+ async locateTarget(e, t = {}) {
3685
+ ie(e, "id");
3686
+ const s = await this.scene.getTargetSnapshot(e);
3687
+ if (!s)
3688
+ return null;
3689
+ const n = t.range ?? t.height ?? 18e3, o = f.fromDegrees(s.lon, s.lat, s.height), r = Ye.eastNorthUpToFixedFrame(o), l = new wi(
3690
+ A.toRadians(t.heading ?? 0),
3691
+ A.toRadians(t.pitch ?? -65),
3692
+ n
3693
+ );
3694
+ return this.viewer.camera.flyToBoundingSphere(
3695
+ new Ze(o, 1),
3696
+ {
3697
+ duration: t.duration ?? 0.8,
3698
+ offset: l,
3699
+ complete: () => {
3700
+ this.viewer.camera.lookAtTransform(r, l), this.viewer.camera.lookAtTransform(R.IDENTITY);
3701
+ }
3702
+ }
3703
+ ), s;
3704
+ }
3705
+ registerContextMenuItem(e) {
3706
+ var s;
3707
+ if (ie(e.key, "context menu item key"), ie(e.label, "context menu item label"), typeof e.onClick != "function")
3708
+ throw new Error("context menu item onClick must be a function.");
3709
+ const t = {
3710
+ ...e,
3711
+ targetKinds: (s = e.targetKinds) != null && s.length ? [...e.targetKinds] : ["target"],
3712
+ order: e.order ?? 0
3713
+ };
3714
+ return this.contextMenuItems.set(t.key, t), () => {
3715
+ this.contextMenuItems.get(t.key) === t && (this.contextMenuItems.delete(t.key), this.activeContextMenuContext && this.renderContextMenu(this.activeContextMenuContext));
3716
+ };
3717
+ }
3718
+ async showContextMenu(e) {
3719
+ await this.renderContextMenu(e);
3720
+ }
3721
+ closeContextMenu() {
3722
+ this.activeContextMenuContext = null, this.contextMenuRoot.style.display = "none", this.contextMenuRoot.style.left = "-9999px", this.contextMenuRoot.style.top = "-9999px", this.contextMenuList.innerHTML = "";
3723
+ }
3724
+ destroy() {
3725
+ this.eventBusBinding.dispose(), this.closeContextMenu(), this.removeSceneContextMenuListener(), document.removeEventListener("pointerdown", this.handleDocumentPointerDownBound, !0), document.removeEventListener("keydown", this.handleKeyDownBound), this.contextMenuRoot.remove(), this.scene.destroy();
3726
+ }
3727
+ /**
3728
+ * 异步工厂:构造实例并等待引擎就绪后再 resolve。
3729
+ * 适合「初始化完成后再加载依赖底座的其它组件」的接入方:`const mt = await MultiTargetFramework.create(viewer, options);`
3730
+ * 若需在就绪前挂事件/调方法,请改用同步 `new MultiTargetFramework(...)` 再 `await mt.ready`。
3731
+ */
3732
+ static async create(e, t) {
3733
+ const s = new $e(e, t);
3734
+ return await s.ready, s;
3735
+ }
3736
+ async handleSceneContextMenu(e) {
3737
+ if (!e) {
3738
+ this.closeContextMenu();
3739
+ return;
3740
+ }
3741
+ const t = await this.toContextMenuContext(e);
3742
+ if (!t) {
3743
+ this.closeContextMenu();
3744
+ return;
3745
+ }
3746
+ await this.renderContextMenu(t);
3747
+ }
3748
+ async toContextMenuContext(e) {
3749
+ if (e.kind === "target" && e.target) {
3750
+ const t = await this.scene.getTargetSnapshot(e.target.id);
3751
+ return t ? {
3752
+ screenX: e.screenX,
3753
+ screenY: e.screenY,
3754
+ cartesian: e.cartesian ? f.clone(e.cartesian, new f()) : void 0,
3755
+ target: {
3756
+ kind: "target",
3757
+ id: t.id,
3758
+ type: t.type,
3759
+ data: t
3760
+ },
3761
+ viewer: this.viewer,
3762
+ scene: this.scene,
3763
+ framework: this
3764
+ } : null;
3765
+ }
3766
+ return e.kind === "ground" && e.lon != null && e.lat != null && e.height != null ? {
3767
+ screenX: e.screenX,
3768
+ screenY: e.screenY,
3769
+ cartesian: e.cartesian ? f.clone(e.cartesian, new f()) : void 0,
3770
+ target: {
3771
+ kind: "ground",
3772
+ lon: e.lon,
3773
+ lat: e.lat,
3774
+ height: e.height
3775
+ },
3776
+ viewer: this.viewer,
3777
+ scene: this.scene,
3778
+ framework: this
3779
+ } : null;
3780
+ }
3781
+ async renderContextMenu(e) {
3782
+ const t = this.resolveVisibleContextMenuItems(e);
3783
+ if (t.length === 0) {
3784
+ this.closeContextMenu();
3785
+ return;
3786
+ }
3787
+ this.activeContextMenuContext = e, this.contextMenuList.innerHTML = "";
3788
+ for (const s of t) {
3789
+ const n = document.createElement("button");
3790
+ n.type = "button", n.className = "mtf-context-menu-item", n.textContent = s.label, n.addEventListener("click", () => {
3791
+ this.closeContextMenu(), s.onClick(e);
3792
+ }), this.contextMenuList.appendChild(n);
3793
+ }
3794
+ this.contextMenuRoot.style.display = "block", this.contextMenuRoot.style.left = `${e.screenX}px`, this.contextMenuRoot.style.top = `${e.screenY}px`, requestAnimationFrame(() => this.repositionContextMenu());
3795
+ }
3796
+ resolveVisibleContextMenuItems(e) {
3797
+ const t = Array.from(this.contextMenuItems.values());
3798
+ return t.sort((s, n) => (s.order ?? 0) - (n.order ?? 0) || s.label.localeCompare(n.label, "zh-CN")), t.filter((s) => s.targetKinds.includes(e.target.kind) ? s.visible ? s.visible(e) !== !1 : !0 : !1);
3799
+ }
3800
+ repositionContextMenu() {
3801
+ if (this.contextMenuRoot.style.display === "none")
3802
+ return;
3803
+ const e = 8, t = this.contextMenuRoot.offsetWidth, s = this.contextMenuRoot.offsetHeight, n = Math.max(e, window.innerWidth - t - e), o = Math.max(e, window.innerHeight - s - e), r = Number.parseFloat(this.contextMenuRoot.style.left || "0"), l = Number.parseFloat(this.contextMenuRoot.style.top || "0"), h = Math.min(Math.max(e, r), n), c = Math.min(Math.max(e, l), o);
3804
+ this.contextMenuRoot.style.left = `${h}px`, this.contextMenuRoot.style.top = `${c}px`;
3805
+ }
3806
+ handleDocumentPointerDown(e) {
3807
+ if (this.contextMenuRoot.style.display === "none")
3808
+ return;
3809
+ const t = e.target;
3810
+ t instanceof Node && this.contextMenuRoot.contains(t) || this.closeContextMenu();
3811
+ }
3812
+ handleDocumentKeyDown(e) {
3813
+ e.key === "Escape" && this.closeContextMenu();
3814
+ }
3815
+ }
3816
+ function Do(i, e) {
3817
+ return $e.create(i, e);
3818
+ }
3819
+ function no(i) {
3820
+ if (!i.targetTypes.length)
3821
+ throw new Error("MultiTargetFramework requires at least one target type config.");
3822
+ return {
3823
+ ...i.scene ?? {},
3824
+ nodeTypes: i.targetTypes.map(oo)
3825
+ };
3826
+ }
3827
+ function oo(i) {
3828
+ return {
3829
+ name: i.name ?? i.type,
3830
+ type: i.type,
3831
+ targetDomain: i.targetDomain,
3832
+ forceHighModelInLowLod: i.forceHighModelInLowLod,
3833
+ iconPath: i.iconPath,
3834
+ defaultColor: i.defaultColor,
3835
+ highModel: i.highModel,
3836
+ lowModel: i.lowModel,
3837
+ highModelUrl: i.highModelUrl,
3838
+ lowModelUrl: i.lowModelUrl,
3839
+ pointPixelSize: i.pointPixelSize,
3840
+ pointHeadingOffset: i.pointHeadingOffset,
3841
+ scale: i.scale,
3842
+ modelHeadingOffset: i.modelHeadingOffset,
3843
+ modelPitchOffset: i.modelPitchOffset,
3844
+ modelRollOffset: i.modelRollOffset,
3845
+ smoothMove: i.smoothMove ?? !1,
3846
+ smoothMoveMinCameraHeight: i.smoothMoveMinCameraHeight ?? 25e3,
3847
+ smoothMoveDurationMs: i.smoothMoveDurationMs ?? i.moveAnimationDurationMs ?? 400,
3848
+ predictMove: i.predictMove ?? i.predict ?? !1,
3849
+ predictMinCameraHeight: i.predictMinCameraHeight ?? 25e3,
3850
+ predictSeconds: i.predictSeconds,
3851
+ predictFitSeconds: i.predictFitSeconds
3852
+ };
3853
+ }
3854
+ function Te(i, e) {
3855
+ return i.map((t, s) => {
3856
+ if (!t || typeof t != "object")
3857
+ throw new Error(`Invalid target at index ${s}.`);
3858
+ if (ao(t, `targets[${s}]`), ie(t.id, `targets[${s}].id`), ie(t.type, `targets[${s}].type`), !e.has(t.type))
3859
+ throw new Error(`Unknown target type "${t.type}" at index ${s}.`);
3860
+ return re(t.lon, `targets[${s}].lon`), re(t.lat, `targets[${s}].lat`), re(t.height, `targets[${s}].height`), re(t.speedH, `targets[${s}].speedH`), re(t.speedV, `targets[${s}].speedV`), re(t.heading, `targets[${s}].heading`), t.renderColor && ke(t.renderColor, `targets[${s}].renderColor`), t.animateColor && ke(t.animateColor, `targets[${s}].animateColor`), t.nationality != null && lo(t.nationality, `targets[${s}].nationality`), t.customInfo != null && co(t.customInfo, `targets[${s}].customInfo`), { ...t };
3861
+ });
3862
+ }
3863
+ const ro = /* @__PURE__ */ new Set([
3864
+ "id",
3865
+ "type",
3866
+ "lon",
3867
+ "lat",
3868
+ "height",
3869
+ "speedH",
3870
+ "speedV",
3871
+ "heading",
3872
+ "renderColor",
3873
+ "openAnimate",
3874
+ "animateType",
3875
+ "animateColor",
3876
+ "nationality",
3877
+ "customInfo",
3878
+ "track",
3879
+ "secrecy",
3880
+ "extra"
3881
+ ]);
3882
+ function ao(i, e) {
3883
+ for (const t of Object.keys(i))
3884
+ if (!ro.has(t))
3885
+ throw new Error(`${e}.${t} is not part of StandardTargetData.`);
3886
+ }
3887
+ function oe(i) {
3888
+ const e = typeof i == "string" ? [i] : i.slice();
3889
+ if (e.length === 0)
3890
+ throw new Error("target id list must not be empty.");
3891
+ for (let t = 0; t < e.length; t++)
3892
+ ie(e[t], `ids[${t}]`);
3893
+ return e;
3894
+ }
3895
+ function ne(i) {
3896
+ return (i == null ? void 0 : i.clearBefore) ?? (i == null ? void 0 : i.clearBefor) ?? !0;
3897
+ }
3898
+ function Dt(i) {
3899
+ var e;
3900
+ return {
3901
+ id: i.id,
3902
+ type: i.type,
3903
+ lon: i.data.lon,
3904
+ lat: i.data.lat,
3905
+ height: i.data.height,
3906
+ heading: i.data.heading,
3907
+ speedH: i.data.speedH,
3908
+ renderColor: i.data.renderColor ?? "",
3909
+ openAnimate: i.data.openAnimate ?? !1,
3910
+ animateColor: i.data.animateColor ?? "",
3911
+ hidden: ((e = i.data.extra) == null ? void 0 : e.hidden) === !0,
3912
+ nationality: i.data.nationality,
3913
+ customInfo: i.data.customInfo
3914
+ };
3915
+ }
3916
+ function ie(i, e) {
3917
+ if (typeof i != "string" || i.length === 0)
3918
+ throw new Error(`${e} must be a non-empty string.`);
3919
+ }
3920
+ function lo(i, e) {
3921
+ if (typeof i != "string")
3922
+ throw new Error(`${e} must be a string.`);
3923
+ }
3924
+ function re(i, e) {
3925
+ if (typeof i != "number" || !Number.isFinite(i))
3926
+ throw new Error(`${e} must be a finite number.`);
3927
+ }
3928
+ function ke(i, e) {
3929
+ if (!/^#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(i))
3930
+ throw new Error(`${e} must be #RRGGBB or #RRGGBBAA.`);
3931
+ }
3932
+ function co(i, e) {
3933
+ if (!i || typeof i != "object" || Array.isArray(i))
3934
+ throw new Error(`${e} must be an object.`);
3935
+ }
3936
+ function ho() {
3937
+ uo();
3938
+ const i = document.createElement("div");
3939
+ return i.className = "mtf-context-menu", i.style.display = "none", i.style.left = "-9999px", i.style.top = "-9999px", i;
3940
+ }
3941
+ let Et = !1;
3942
+ function uo() {
3943
+ if (Et)
3944
+ return;
3945
+ Et = !0;
3946
+ const i = document.createElement("style");
3947
+ i.dataset.mtfContextMenu = "true", i.textContent = `
3948
+ .mtf-context-menu {
3949
+ position: fixed;
3950
+ z-index: 9999;
3951
+ min-width: 144px;
3952
+ background: #ffffff;
3953
+ color: #111111;
3954
+ border: 1px solid rgba(15, 23, 42, 0.14);
3955
+ border-radius: 8px;
3956
+ box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
3957
+ padding: 6px;
3958
+ box-sizing: border-box;
3959
+ }
3960
+ .mtf-context-menu-list {
3961
+ display: grid;
3962
+ gap: 2px;
3963
+ }
3964
+ .mtf-context-menu-item {
3965
+ appearance: none;
3966
+ width: 100%;
3967
+ min-height: 34px;
3968
+ padding: 8px 12px;
3969
+ border: 0;
3970
+ border-radius: 6px;
3971
+ background: transparent;
3972
+ color: #111111;
3973
+ text-align: left;
3974
+ cursor: pointer;
3975
+ font: 500 13px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
3976
+ }
3977
+ .mtf-context-menu-item:hover {
3978
+ background: rgba(15, 23, 42, 0.08);
3979
+ }
3980
+ `, document.head.appendChild(i);
3981
+ }
3982
+ class fo {
3983
+ constructor(e, t, s) {
3984
+ a(this, "renderer");
3985
+ a(this, "typeByName", /* @__PURE__ */ new Map());
3986
+ this.renderer = new Ut(e, s);
3987
+ for (const n of t)
3988
+ this.typeByName.set(n.type, n);
3989
+ }
3990
+ setSites(e) {
3991
+ const t = [];
3992
+ for (const s of e) {
3993
+ const n = this.typeByName.get(s.type), o = n == null ? void 0 : n.lowModel;
3994
+ !n || !(o != null && o.url) || t.push({
3995
+ id: s.id,
3996
+ url: o.url,
3997
+ modelKey: mo(n),
3998
+ modelStyle: {
3999
+ url: o.url,
4000
+ scale: o.scale,
4001
+ headingOffset: o.headingOffset,
4002
+ pitchOffset: o.pitchOffset,
4003
+ rollOffset: o.rollOffset
4004
+ },
4005
+ position: f.fromDegrees(s.lon, s.lat, s.height),
4006
+ heading: s.heading ?? 0,
4007
+ smoothMove: !1,
4008
+ moveDurationMs: 0
4009
+ });
4010
+ }
4011
+ this.renderer.setCandidates(t);
4012
+ }
4013
+ clear() {
4014
+ this.renderer.clear();
4015
+ }
4016
+ update(e) {
4017
+ this.renderer.update(e);
4018
+ }
4019
+ destroy() {
4020
+ this.renderer.destroy();
4021
+ }
4022
+ }
4023
+ function mo(i) {
4024
+ const e = i.lowModel;
4025
+ return [
4026
+ i.type,
4027
+ (e == null ? void 0 : e.url) ?? "",
4028
+ (e == null ? void 0 : e.scale) ?? 1,
4029
+ (e == null ? void 0 : e.headingOffset) ?? 0,
4030
+ (e == null ? void 0 : e.pitchOffset) ?? 0,
4031
+ (e == null ? void 0 : e.rollOffset) ?? 0
4032
+ ].join("|");
4033
+ }
4034
+ class po {
4035
+ constructor(e) {
4036
+ a(this, "buckets", /* @__PURE__ */ new Map());
4037
+ a(this, "sites", []);
4038
+ this.cellDeg = e;
4039
+ }
4040
+ build(e) {
4041
+ this.sites = e, this.buckets.clear();
4042
+ for (let t = 0; t < e.length; t++) {
4043
+ const s = e[t], n = yo(s.lon, s.lat, this.cellDeg);
4044
+ let o = this.buckets.get(n);
4045
+ o || (o = [], this.buckets.set(n, o)), o.push(t);
4046
+ }
4047
+ }
4048
+ query(e) {
4049
+ if (this.sites.length === 0)
4050
+ return [];
4051
+ const t = [], s = /* @__PURE__ */ new Set(), n = go(e);
4052
+ for (const o of n) {
4053
+ const r = Xe(o.west, this.cellDeg), l = Xe(o.east, this.cellDeg), h = Ue(o.south, this.cellDeg), c = Ue(o.north, this.cellDeg);
4054
+ for (let m = h; m <= c; m++)
4055
+ for (let u = r; u <= l; u++) {
4056
+ const v = this.buckets.get(`${u}:${m}`);
4057
+ if (v)
4058
+ for (const d of v) {
4059
+ if (s.has(d))
4060
+ continue;
4061
+ const p = this.sites[d];
4062
+ vo(e, p.lon, p.lat) && (s.add(d), t.push(d));
4063
+ }
4064
+ }
4065
+ }
4066
+ return t;
4067
+ }
4068
+ }
4069
+ function go(i) {
4070
+ return i.east >= i.west ? [i] : [
4071
+ { west: i.west, east: 180, south: i.south, north: i.north },
4072
+ { west: -180, east: i.east, south: i.south, north: i.north }
4073
+ ];
4074
+ }
4075
+ function vo(i, e, t) {
4076
+ return t >= i.south && t <= i.north ? i.east >= i.west ? e >= i.west && e <= i.east : e >= i.west || e <= i.east : !1;
4077
+ }
4078
+ function yo(i, e, t) {
4079
+ return `${Xe(i, t)}:${Ue(e, t)}`;
4080
+ }
4081
+ function Xe(i, e) {
4082
+ return Math.floor((wo(i) + 180) / e);
4083
+ }
4084
+ function Ue(i, e) {
4085
+ return Math.floor((Mo(i, -90, 90) + 90) / e);
4086
+ }
4087
+ function wo(i) {
4088
+ let e = i;
4089
+ for (; e < -180; )
4090
+ e += 360;
4091
+ for (; e > 180; )
4092
+ e -= 360;
4093
+ return e;
4094
+ }
4095
+ function Mo(i, e, t) {
4096
+ return Math.min(t, Math.max(e, i));
4097
+ }
4098
+ const Fe = 22, _t = 2, Io = 48;
4099
+ class Eo extends qe {
4100
+ constructor(t, s) {
4101
+ super();
4102
+ a(this, "options");
4103
+ a(this, "stats", {
4104
+ total: 0,
4105
+ inView: 0,
4106
+ iconCount: 0,
4107
+ lowModelCount: 0,
4108
+ lowModelEligibleCount: 0,
4109
+ mode: "icon"
4110
+ });
4111
+ a(this, "iconRenderer");
4112
+ a(this, "lowModelRenderer");
4113
+ a(this, "spatialIndex");
4114
+ a(this, "typeIndex", /* @__PURE__ */ new Map());
4115
+ a(this, "typeColor", []);
4116
+ a(this, "visibleSites", []);
4117
+ a(this, "sites", []);
4118
+ a(this, "screenPickIndex", null);
4119
+ a(this, "hoverPosition", null);
4120
+ a(this, "hoverRafId", 0);
4121
+ a(this, "lastHoverSiteId", null);
4122
+ a(this, "destroyed", !1);
4123
+ a(this, "lastUpdateAt", 0);
4124
+ a(this, "lastFrameAt", ze());
4125
+ a(this, "rafId", 0);
4126
+ a(this, "removeCameraListener");
4127
+ a(this, "inputHandler");
4128
+ a(this, "eventBusBinding");
4129
+ this.viewer = t, this.options = So(s);
4130
+ const n = this.options.siteTypes;
4131
+ n.forEach((r, l) => {
4132
+ this.typeIndex.set(r.type, l);
4133
+ const h = D.fromCssColorString(r.defaultColor);
4134
+ this.typeColor.push([h.red, h.green, h.blue, h.alpha]);
4135
+ });
4136
+ const o = Math.max(16, ...n.map((r) => r.pointPixelSize * 2));
4137
+ this.iconRenderer = new Qt(t.scene, {
4138
+ typeStyles: n.map((r) => ({ type: r.type, iconPath: r.iconPath, defaultColor: r.defaultColor })),
4139
+ pixelSize: o
4140
+ }), t.scene.primitives.add(this.iconRenderer), this.lowModelRenderer = new fo(t.scene, this.options.siteTypes, this.options.fadeMs), this.spatialIndex = new po(this.options.indexCellDeg), this.removeCameraListener = this.viewer.camera.changed.addEventListener(() => this.scheduleRefresh()), this.inputHandler = new Wt(this.viewer.scene.canvas), this.inputHandler.setInputAction((r) => {
4141
+ this.handleContextMenuAt(r.position);
4142
+ }, N.RIGHT_CLICK), this.inputHandler.setInputAction((r) => {
4143
+ this.emit("pick", this.pickAt(r.position));
4144
+ }, N.LEFT_CLICK), this.inputHandler.setInputAction((r) => {
4145
+ this.scheduleHoverAt(r.endPosition);
4146
+ }, N.MOUSE_MOVE), this.rafId = requestAnimationFrame((r) => this.tick(r)), this.eventBusBinding = Jn(this, { replaceExisting: !0 });
4147
+ }
4148
+ /** 屏幕坐标拾取最近站点(实例化符号/低模无法 drillPick,按位置最近命中)。 */
4149
+ pickAt(t, s = 22) {
4150
+ return this.nearestSiteAtScreen(t, s);
4151
+ }
4152
+ setData(t) {
4153
+ this.destroyed || (this.sites = To(t, this.options.siteTypesByType), this.spatialIndex.build(this.sites), this.stats.total = this.sites.length, this.refresh(!0));
4154
+ }
4155
+ clear() {
4156
+ this.sites = [], this.spatialIndex.build(this.sites), this.iconRenderer.setInstances([]), this.lowModelRenderer.clear(), this.visibleSites = [], this.screenPickIndex = null, this.clearHover(), this.stats.total = 0, this.stats.inView = 0, this.stats.iconCount = 0, this.stats.lowModelCount = 0, this.stats.lowModelEligibleCount = 0;
4157
+ }
4158
+ destroy() {
4159
+ var t;
4160
+ this.destroyed || (this.destroyed = !0, this.eventBusBinding.dispose(), this.rafId && cancelAnimationFrame(this.rafId), (t = this.removeCameraListener) == null || t.call(this), this.inputHandler.destroy(), this.clearHover(), this.viewer.scene.primitives.remove(this.iconRenderer), this.lowModelRenderer.destroy(), this.clear());
4161
+ }
4162
+ tick(t) {
4163
+ if (this.destroyed)
4164
+ return;
4165
+ const s = Math.max(0, (t - this.lastFrameAt) / 1e3);
4166
+ this.lastFrameAt = t, this.lowModelRenderer.update(s), this.rafId = requestAnimationFrame((n) => this.tick(n));
4167
+ }
4168
+ scheduleRefresh() {
4169
+ ze() - this.lastUpdateAt < this.options.updateThrottleMs || this.refresh(!1);
4170
+ }
4171
+ refresh(t) {
4172
+ if (this.destroyed)
4173
+ return;
4174
+ const s = ze();
4175
+ if (!t && s - this.lastUpdateAt < this.options.updateThrottleMs)
4176
+ return;
4177
+ if (this.lastUpdateAt = s, this.sites.length === 0) {
4178
+ this.iconRenderer.setInstances([]), this.lowModelRenderer.clear(), this.visibleSites = [], this.screenPickIndex = null, this.clearHover(), this.stats.inView = 0, this.stats.iconCount = 0, this.stats.lowModelCount = 0, this.stats.lowModelEligibleCount = 0;
4179
+ return;
4180
+ }
4181
+ const n = Co(this.viewer), r = this.spatialIndex.query(n).map((d) => this.sites[d]), h = this.viewer.scene.camera.positionCartographic.height <= this.options.modelSwitchHeight, c = r.filter((d) => {
4182
+ var g;
4183
+ const p = this.options.siteTypesByType.get(d.type);
4184
+ return !!((g = p == null ? void 0 : p.lowModel) != null && g.url);
4185
+ }), m = h ? c.slice(0, this.options.maxVisibleLowModels) : [], u = new Set(m.map((d) => d.id)), v = h ? r.filter((d) => !u.has(d.id)) : r;
4186
+ this.iconRenderer.setInstances(
4187
+ v.map((d) => {
4188
+ const p = this.typeIndex.get(d.type) ?? 0;
4189
+ return { id: d.id, lon: d.lon, lat: d.lat, height: d.height, heading: d.heading, color: this.typeColor[p], iconIndex: p };
4190
+ })
4191
+ ), this.lowModelRenderer.setSites(m), this.visibleSites = r, this.screenPickIndex = this.buildScreenPickIndex(r), this.repickHover(), this.stats.inView = r.length, this.stats.lowModelEligibleCount = c.length, this.stats.lowModelCount = m.length, this.stats.iconCount = v.length, this.stats.mode = h ? "low-model" : "icon";
4192
+ }
4193
+ handleContextMenuAt(t) {
4194
+ const s = this.nearestSiteAtScreen(t, Fe);
4195
+ s && this.emit("contextmenu", {
4196
+ site: s,
4197
+ screenX: t.x,
4198
+ screenY: t.y,
4199
+ cartesian: f.fromDegrees(s.lon, s.lat, s.height)
4200
+ });
4201
+ }
4202
+ scheduleHoverAt(t) {
4203
+ if (!this.destroyed) {
4204
+ if (this.hoverPosition) {
4205
+ const s = Math.abs(t.x - this.hoverPosition.x), n = Math.abs(t.y - this.hoverPosition.y);
4206
+ if (s < _t && n < _t)
4207
+ return;
4208
+ J.clone(t, this.hoverPosition);
4209
+ } else
4210
+ this.hoverPosition = J.clone(t);
4211
+ this.hoverRafId || (this.hoverRafId = requestAnimationFrame(() => this.flushHover()));
4212
+ }
4213
+ }
4214
+ flushHover() {
4215
+ if (this.hoverRafId = 0, this.destroyed || !this.hoverPosition)
4216
+ return;
4217
+ const t = this.nearestSiteAtScreen(this.hoverPosition, Fe), s = (t == null ? void 0 : t.id) ?? null;
4218
+ s !== this.lastHoverSiteId && (this.lastHoverSiteId = s, this.emit("hover", t));
4219
+ }
4220
+ repickHover() {
4221
+ this.hoverPosition && (this.hoverRafId || (this.hoverRafId = requestAnimationFrame(() => this.flushHover())));
4222
+ }
4223
+ clearHover() {
4224
+ this.hoverRafId && (cancelAnimationFrame(this.hoverRafId), this.hoverRafId = 0), this.hoverPosition = null, this.lastHoverSiteId !== null && (this.lastHoverSiteId = null, this.emit("hover", null));
4225
+ }
4226
+ buildScreenPickIndex(t) {
4227
+ const s = this.viewer.scene.canvas;
4228
+ if (t.length === 0 || s.clientWidth <= 0 || s.clientHeight <= 0)
4229
+ return null;
4230
+ const n = new Float32Array(t.length), o = new Float32Array(t.length);
4231
+ n.fill(Number.NaN), o.fill(Number.NaN);
4232
+ const r = new f();
4233
+ for (let c = 0; c < t.length; c++) {
4234
+ const m = t[c];
4235
+ f.fromDegrees(m.lon, m.lat, m.height, void 0, r);
4236
+ const u = Ae.wgs84ToWindowCoordinates(this.viewer.scene, r);
4237
+ u && (!Number.isFinite(u.x) || !Number.isFinite(u.y) || u.x < 0 || u.y < 0 || u.x > s.clientWidth || u.y > s.clientHeight || (n[c] = u.x, o[c] = u.y));
4238
+ }
4239
+ const l = Math.max(Io, Fe * 2), h = /* @__PURE__ */ new Map();
4240
+ for (let c = 0; c < t.length; c++) {
4241
+ const m = n[c], u = o[c];
4242
+ if (!Number.isFinite(m) || !Number.isFinite(u))
4243
+ continue;
4244
+ const v = Ot(Math.floor(m / l), Math.floor(u / l)), d = h.get(v);
4245
+ d ? d.push(c) : h.set(v, [c]);
4246
+ }
4247
+ return {
4248
+ canvasWidth: s.clientWidth,
4249
+ canvasHeight: s.clientHeight,
4250
+ cellSize: l,
4251
+ bins: h,
4252
+ windowX: n,
4253
+ windowY: o
4254
+ };
4255
+ }
4256
+ // 实例化符号/低模无法 drillPick,改用屏幕索引命中(refresh/相机节流时重建)。
4257
+ nearestSiteAtScreen(t, s) {
4258
+ const n = this.screenPickIndex;
4259
+ if (!n)
4260
+ return null;
4261
+ const o = this.viewer.scene.canvas;
4262
+ if (n.canvasWidth !== o.clientWidth || n.canvasHeight !== o.clientHeight)
4263
+ return this.screenPickIndex = this.buildScreenPickIndex(this.visibleSites), this.nearestSiteAtScreen(t, s);
4264
+ let r = null, l = s * s;
4265
+ const h = Math.floor(t.x / n.cellSize), c = Math.floor(t.y / n.cellSize);
4266
+ for (let m = c - 1; m <= c + 1; m++)
4267
+ for (let u = h - 1; u <= h + 1; u++) {
4268
+ const v = n.bins.get(Ot(u, m));
4269
+ if (v)
4270
+ for (const d of v) {
4271
+ const p = n.windowX[d] - t.x, g = n.windowY[d] - t.y, y = p * p + g * g;
4272
+ y <= l && (l = y, r = this.visibleSites[d] ?? null);
4273
+ }
4274
+ }
4275
+ return r;
4276
+ }
4277
+ }
4278
+ function Ot(i, e) {
4279
+ return `${i}:${e}`;
4280
+ }
4281
+ function So(i) {
4282
+ var s;
4283
+ if (!((s = i.siteTypes) != null && s.length))
4284
+ throw new Error("SiteLayer requires at least one site type.");
4285
+ if (!Number.isFinite(i.modelSwitchHeight) || i.modelSwitchHeight <= 0)
4286
+ throw new Error("SiteLayer modelSwitchHeight must be a positive number.");
4287
+ const e = i.siteTypes.map(xo), t = /* @__PURE__ */ new Map();
4288
+ for (const n of e)
4289
+ t.set(n.type, n);
4290
+ return {
4291
+ siteTypes: e,
4292
+ siteTypesByType: t,
4293
+ modelSwitchHeight: i.modelSwitchHeight,
4294
+ maxVisibleLowModels: Math.max(0, i.maxVisibleLowModels ?? 3e3),
4295
+ updateThrottleMs: Math.max(16, i.updateThrottleMs ?? 100),
4296
+ indexCellDeg: bo(i.indexCellDeg ?? 0.25, 0.02, 10),
4297
+ fadeMs: Math.max(0, i.fadeMs ?? 250)
4298
+ };
4299
+ }
4300
+ function xo(i) {
4301
+ if (!i || typeof i != "object")
4302
+ throw new Error("Invalid site type config.");
4303
+ if (typeof i.type != "string" || i.type.length === 0)
4304
+ throw new Error("site type must be a non-empty string.");
4305
+ if (typeof i.iconPath != "string" || i.iconPath.length === 0)
4306
+ throw new Error(`site type "${i.type}" iconPath is required.`);
4307
+ return {
4308
+ ...i,
4309
+ name: i.name ?? i.type,
4310
+ defaultColor: i.defaultColor ?? "#ffffff",
4311
+ pointPixelSize: Math.max(6, i.pointPixelSize ?? 12)
4312
+ };
4313
+ }
4314
+ function To(i, e) {
4315
+ return i.map((t, s) => {
4316
+ if (!t || typeof t != "object")
4317
+ throw new Error(`Invalid site at index ${s}.`);
4318
+ if (typeof t.id != "string" || t.id.length === 0)
4319
+ throw new Error(`sites[${s}].id must be a non-empty string.`);
4320
+ if (typeof t.type != "string" || !e.has(t.type))
4321
+ throw new Error(`sites[${s}].type "${t.type}" is not registered.`);
4322
+ return Ce(t.lon, `sites[${s}].lon`), Ce(t.lat, `sites[${s}].lat`), Ce(t.height, `sites[${s}].height`), t.heading != null && Ce(t.heading, `sites[${s}].heading`), { ...t };
4323
+ });
4324
+ }
4325
+ function Co(i) {
4326
+ const e = i.camera.computeViewRectangle();
4327
+ return e ? {
4328
+ west: A.toDegrees(e.west),
4329
+ east: A.toDegrees(e.east),
4330
+ south: A.toDegrees(e.south),
4331
+ north: A.toDegrees(e.north)
4332
+ } : { west: -180, east: 180, south: -85, north: 85 };
4333
+ }
4334
+ function Ce(i, e) {
4335
+ if (typeof i != "number" || !Number.isFinite(i))
4336
+ throw new Error(`${e} must be a finite number.`);
4337
+ }
4338
+ function bo(i, e, t) {
4339
+ return Math.min(t, Math.max(e, i));
4340
+ }
4341
+ function ze() {
4342
+ return typeof performance < "u" ? performance.now() : Date.now();
4343
+ }
4344
+ const li = "KGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIHEoZSxyLHMsbixvKXtsZXQgdT1uLGY9bztpZih1PT1udWxsfHxmPT1udWxsKXtsZXQgYz0wLHg9MDtmb3IobGV0IGE9MDthPHM7YSsrKWMrPWVbYV0seCs9clthXTt1PWMvcyxmPXgvc31jb25zdCBBPTExMTMyMCpNYXRoLmNvcyhmKk1hdGguUEkvMTgwKSxkPW5ldyBGbG9hdDY0QXJyYXkocyksST1uZXcgRmxvYXQ2NEFycmF5KHMpO2ZvcihsZXQgYz0wO2M8cztjKyspZFtjXT0oZVtjXS11KSpBLElbY109KHJbY10tZikqMTExMzIwO3JldHVybnt4czpkLHlzOkksbG9uMDp1LGxhdDA6Zn19ZnVuY3Rpb24gWChlKXtyZXR1cm4gZSY9NjU1MzUsZT0oZXxlPDw4KSYxNjcxMTkzNSxlPShlfGU8PDQpJjI1MjY0NTEzNSxlPShlfGU8PDIpJjg1ODk5MzQ1OSxlPShlfGU8PDEpJjE0MzE2NTU3NjUsZX1mdW5jdGlvbiBKKGUscil7cmV0dXJuKFgoZSl8WChyKTw8MSk+Pj4wfWNvbnN0IGI9MTEscD0xPDxiLEY9cC0xLHo9bmV3IEludDMyQXJyYXkocCksQz1uZXcgSW50MzJBcnJheSgxNik7ZnVuY3Rpb24gTihlKXtyZXR1cm57Y2FwOmUsa2V5czpuZXcgVWludDMyQXJyYXkoZSksaWR4QTpuZXcgSW50MzJBcnJheShlKSxpZHhCOm5ldyBJbnQzMkFycmF5KGUpLHNvcnRlZEtleXM6bmV3IFVpbnQzMkFycmF5KGUpLGNsdXN0ZXJPZjpuZXcgSW50MzJBcnJheShlKSxoZWFkczpuZXcgSW50MzJBcnJheShlKSxzaXplczpuZXcgSW50MzJBcnJheShlKX19ZnVuY3Rpb24gVihlLHIpe2lmKHI8PWUuY2FwKXJldHVybjtjb25zdCBzPU1hdGgubWF4KHIsZS5jYXAqMik7ZS5jYXA9cyxlLmtleXM9bmV3IFVpbnQzMkFycmF5KHMpLGUuaWR4QT1uZXcgSW50MzJBcnJheShzKSxlLmlkeEI9bmV3IEludDMyQXJyYXkocyksZS5zb3J0ZWRLZXlzPW5ldyBVaW50MzJBcnJheShzKSxlLmNsdXN0ZXJPZj1uZXcgSW50MzJBcnJheShzKSxlLmhlYWRzPW5ldyBJbnQzMkFycmF5KHMpLGUuc2l6ZXM9bmV3IEludDMyQXJyYXkocyl9Y29uc3QgVz0oZSxyKT0+KHtjb3VudDpyLGxldmVsOjAsY2VsbE1ldGVyczplLGNsdXN0ZXJDb3VudDowLGNsdXN0ZXJPZjpuZXcgSW50MzJBcnJheSgwKSxoZWFkSW5kZXg6bmV3IEludDMyQXJyYXkoMCksY2x1c3RlclNpemU6bmV3IEludDMyQXJyYXkoMCksbGV2ZWxzOltdfSk7ZnVuY3Rpb24gJChlLHIscyxuLG8sdSxmLG0pe2xldCBBPTEvMCxkPTEvMCxJPS0xLzAsYz0tMS8wO2ZvcihsZXQgdD0wO3Q8bjt0Kyspe2NvbnN0IGw9clt0XSxpPXNbdF07bDxBJiYoQT1sKSxpPGQmJihkPWkpLGw+SSYmKEk9bCksaT5jJiYoYz1pKX1jb25zdCB4PTEvbztsZXQgYT1vLEU9TWF0aC5tYXgoKEktQSkqeCwoYy1kKSp4KTtmb3IoO0U+PTY1NTM1OylhKj0yLEUvPTI7Y29uc3QgTz0xL2EsaD1lLmtleXM7bGV0IHc9MDtmb3IobGV0IHQ9MDt0PG47dCsrKXtjb25zdCBsPShyW3RdLUEpKk98MCxpPShzW3RdLWQpKk98MCxMPUoobCxpKTtoW3RdPUwsTD53JiYodz1MKX1jb25zdCBUPXc+MD8zMi1NYXRoLmNsejMyKHcpOjEsRz1NYXRoLm1heCgxLE1hdGguY2VpbChUL2IpKTtsZXQgdj1lLmlkeEEsZz1lLmlkeEI7Zm9yKGxldCB0PTA7dDxuO3QrKyl2W3RdPXQ7Y29uc3QgUz1lLnNvcnRlZEtleXM7Zm9yKGxldCB0PTA7dDxHO3QrKyl7Y29uc3QgbD10KmIsaT10PT09Ry0xO3ouZmlsbCgwKTtmb3IobGV0IHk9MDt5PG47eSsrKXpbaFt2W3ldXT4+PmwmRl0rKztsZXQgTD0wO2ZvcihsZXQgeT0wO3k8cDt5Kyspe2NvbnN0IF89elt5XTt6W3ldPUwsTCs9X31mb3IobGV0IHk9MDt5PG47eSsrKXtjb25zdCBfPXZbeV0sUT1oW19dLFo9eltRPj4+bCZGXSsrO2dbWl09XyxpJiYoU1taXT1RKX1jb25zdCBhZT12O3Y9ZyxnPWFlfWNvbnN0IHNlPXY7Qy5maWxsKDApO2xldCBZPVNbMF07Zm9yKGxldCB0PTE7dDxuO3QrKyl7Y29uc3QgbD1TW3RdLGk9bF5ZO1k9bCxpIT09MCYmQ1szMS1NYXRoLmNsejMyKGkpPj4xXSsrfWNvbnN0IEg9W107bGV0IEI9MCxNPW4sRD0wO2ZvcihsZXQgdD0xNTt0Pj0wO3QtLSlEKz1DW3RdO2ZvcihsZXQgdD0wO3Q8Zjt0Kyspe2NvbnN0IGw9MStEO2lmKEgucHVzaCh7bGV2ZWw6dCxjZWxsTWV0ZXJzOmEqKDE8PHQpLGNsdXN0ZXJzOmx9KSxCPXQsTT1sLGw8PXUpYnJlYWs7dDwxNiYmKEQtPUNbdF0pfWNvbnN0IHJlPTIqQixQPWUuY2x1c3Rlck9mLFU9ZS5oZWFkcyxrPWUuc2l6ZXM7ay5maWxsKDAsMCxNKTtsZXQgUj0tMSxqPS0xO2ZvcihsZXQgdD0wO3Q8bjt0Kyspe2NvbnN0IGw9c2VbdF0saT1TW3RdPj4+cmU7KHQ9PT0wfHxpIT09aikmJihSKyssVVtSXT1sLGo9aSksUFtsXT1SLGtbUl0rK31jb25zdCBuZT1tP1Auc3ViYXJyYXkoMCxuKTpQLnNsaWNlKDAsbiksbGU9bT9VLnN1YmFycmF5KDAsTSk6VS5zbGljZSgwLE0pLG9lPW0/ay5zdWJhcnJheSgwLE0pOmsuc2xpY2UoMCxNKTtyZXR1cm57Y291bnQ6bixsZXZlbDpCLGNlbGxNZXRlcnM6YSooMTw8QiksY2x1c3RlckNvdW50Ok0sY2x1c3Rlck9mOm5lLGhlYWRJbmRleDpsZSxjbHVzdGVyU2l6ZTpvZSxsZXZlbHM6SH19ZnVuY3Rpb24gZWUoZT0wKXtjb25zdCByPU4oTWF0aC5tYXgoMSxlKSk7cmV0dXJuKHMsbixvLHU9e30pPT57Y29uc3QgZj11LmJhc2VDZWxsTWV0ZXJzPz8yMDA7cmV0dXJuIG88PTA/VyhmLG8pOihWKHIsbyksJChyLHMsbixvLGYsdS5tYXhDbHVzdGVycz8/M2U0LHUubWF4TGV2ZWxzPz8yMCwhMCkpfX1jb25zdCB0ZT1lZSgpO2Z1bmN0aW9uIEsoZSxyKXtyZXR1cm4gZSYmZS5ieXRlTGVuZ3RoPj1yKjQ/bmV3IEludDMyQXJyYXkoZSwwLHIpOm5ldyBJbnQzMkFycmF5KHIpfXNlbGYub25tZXNzYWdlPWU9Pntjb25zdHtqb2JJZDpyLGxvbkJ1ZjpzLGxhdEJ1ZjpuLGNvdW50Om8sYmFzZTp1LG1heDpmLGxvbjA6bSxsYXQwOkF9PWUuZGF0YSxkPW5ldyBGbG9hdDY0QXJyYXkocywwLG8pLEk9bmV3IEZsb2F0NjRBcnJheShuLDAsbyksYz1wZXJmb3JtYW5jZS5ub3coKSx4PXEoZCxJLG8sbSxBKSxhPXRlKHgueHMseC55cyxvLHtiYXNlQ2VsbE1ldGVyczp1LG1heENsdXN0ZXJzOmZ9KSxFPWEuY2x1c3RlckNvdW50LE89SyhlLmRhdGEucmV0Q2x1c3Rlck9mLG8pO08uc2V0KGEuY2x1c3Rlck9mLnN1YmFycmF5KDAsbykpO2NvbnN0IGg9SyhlLmRhdGEucmV0SGVhZCxmKTtoLnNldChhLmhlYWRJbmRleC5zdWJhcnJheSgwLEUpKTtjb25zdCB3PUsoZS5kYXRhLnJldFNpemUsZik7dy5zZXQoYS5jbHVzdGVyU2l6ZS5zdWJhcnJheSgwLEUpKTtjb25zdCBUPXBlcmZvcm1hbmNlLm5vdygpLWM7c2VsZi5wb3N0TWVzc2FnZSh7am9iSWQ6cixsb25CdWY6cyxsYXRCdWY6bixjbHVzdGVyT2Y6Ty5idWZmZXIsaGVhZDpoLmJ1ZmZlcixzaXplOncuYnVmZmVyLGNsdXN0ZXJDb3VudDpFLGxldmVsOmEubGV2ZWwsY2VsbE1ldGVyczphLmNlbGxNZXRlcnMsY29tcHV0ZU1zOlR9LFtzLG4sTy5idWZmZXIsaC5idWZmZXIsdy5idWZmZXJdKX19KSgpOwo=", Bt = typeof window < "u" && window.Blob && new Blob([atob(li)], { type: "text/javascript;charset=utf-8" });
4345
+ function Po() {
4346
+ let i;
4347
+ try {
4348
+ if (i = Bt && (window.URL || window.webkitURL).createObjectURL(Bt), !i)
4349
+ throw "";
4350
+ return new Worker(i);
4351
+ } catch {
4352
+ return new Worker("data:application/javascript;base64," + li);
4353
+ } finally {
4354
+ i && (window.URL || window.webkitURL).revokeObjectURL(i);
4355
+ }
4356
+ }
4357
+ function _o() {
4358
+ const i = new Po();
4359
+ let e = 1, t = !1, s = new Float64Array(0), n = new Float64Array(0), o = null, r = null, l = null, h = null, c = new Float64Array(0), m = new Float64Array(0), u = null;
4360
+ function v(p) {
4361
+ s.length < p && (s = new Float64Array(p), n = new Float64Array(p));
4362
+ }
4363
+ function d(p, g, y, w, M) {
4364
+ v(p), M && (s.set(M.lons.subarray(0, p)), n.set(M.lats.subarray(0, p)));
4365
+ const I = s.buffer, C = n.buffer, k = e++;
4366
+ t = !0, h = { resolve: y, startMs: w };
4367
+ const S = {
4368
+ jobId: k,
4369
+ lonBuf: I,
4370
+ latBuf: C,
4371
+ count: p,
4372
+ base: g.baseCellMeters ?? 200,
4373
+ max: g.maxClusters ?? 3e4,
4374
+ lon0: g.lon0 ?? 0,
4375
+ lat0: g.lat0 ?? 0
4376
+ }, T = [I, C];
4377
+ o && (S.retClusterOf = o, T.push(o)), r && (S.retHead = r, T.push(r)), l && (S.retSize = l, T.push(l)), o = r = l = null, i.postMessage(S, T);
4378
+ }
4379
+ return i.onmessage = (p) => {
4380
+ const g = p.data;
4381
+ t = !1, s = new Float64Array(g.lonBuf), n = new Float64Array(g.latBuf);
4382
+ const y = h;
4383
+ h = null;
4384
+ const w = g.clusterCount;
4385
+ if (o = g.clusterOf, r = g.head, l = g.size, y == null || y.resolve({
4386
+ clusterOf: new Int32Array(g.clusterOf),
4387
+ headIndex: new Int32Array(g.head, 0, w),
4388
+ clusterSize: new Int32Array(g.size, 0, w),
4389
+ clusterCount: w,
4390
+ level: g.level,
4391
+ cellMeters: g.cellMeters,
4392
+ computeMs: g.computeMs,
4393
+ roundTripMs: performance.now() - ((y == null ? void 0 : y.startMs) ?? performance.now())
4394
+ }), u) {
4395
+ const M = u;
4396
+ u = null, d(M.count, M.options, M.resolve, M.startMs, { lons: c, lats: m });
4397
+ }
4398
+ }, {
4399
+ run(p, g, y, w = {}) {
4400
+ return new Promise((M) => {
4401
+ if (!t) {
4402
+ d(y, w, M, performance.now(), { lons: p, lats: g });
4403
+ return;
4404
+ }
4405
+ u && u.resolve(null), c.length < y && (c = new Float64Array(y), m = new Float64Array(y)), c.set(p.subarray(0, y)), m.set(g.subarray(0, y)), u = { count: y, options: w, resolve: M, startMs: performance.now() };
4406
+ });
4407
+ },
4408
+ inputBuffers(p) {
4409
+ if (t)
4410
+ throw new Error("inputBuffers 只能在 Worker 空闲时调用(输入缓冲此刻已被 transfer)");
4411
+ return v(p), { lons: s.subarray(0, p), lats: n.subarray(0, p) };
4412
+ },
4413
+ runReusing(p, g = {}) {
4414
+ return new Promise((y) => {
4415
+ if (t)
4416
+ throw new Error("runReusing 仅限串行使用:上一次任务尚未返回");
4417
+ d(p, g, y, performance.now(), null);
4418
+ });
4419
+ },
4420
+ terminate() {
4421
+ i.terminate(), h = null, u = null, o = r = l = null;
4422
+ }
4423
+ };
4424
+ }
4425
+ const Nt = 111320;
4426
+ function Oo(i, e, t, s, n) {
4427
+ let o = s, r = n;
4428
+ if (o == null || r == null) {
4429
+ let u = 0, v = 0;
4430
+ for (let d = 0; d < t; d++)
4431
+ u += i[d], v += e[d];
4432
+ o = u / t, r = v / t;
4433
+ }
4434
+ const l = Math.cos(r * Math.PI / 180), h = Nt * l, c = new Float64Array(t), m = new Float64Array(t);
4435
+ for (let u = 0; u < t; u++)
4436
+ c[u] = (i[u] - o) * h, m[u] = (e[u] - r) * Nt;
4437
+ return { xs: c, ys: m, lon0: o, lat0: r };
4438
+ }
4439
+ function Ft(i) {
4440
+ return i &= 65535, i = (i | i << 8) & 16711935, i = (i | i << 4) & 252645135, i = (i | i << 2) & 858993459, i = (i | i << 1) & 1431655765, i;
4441
+ }
4442
+ function Ro(i, e) {
4443
+ return (Ft(i) | Ft(e) << 1) >>> 0;
4444
+ }
4445
+ const Ge = 11, je = 1 << Ge, zt = je - 1, ue = new Int32Array(je), be = new Int32Array(16);
4446
+ function ci(i) {
4447
+ return {
4448
+ cap: i,
4449
+ keys: new Uint32Array(i),
4450
+ idxA: new Int32Array(i),
4451
+ idxB: new Int32Array(i),
4452
+ sortedKeys: new Uint32Array(i),
4453
+ clusterOf: new Int32Array(i),
4454
+ heads: new Int32Array(i),
4455
+ sizes: new Int32Array(i)
4456
+ };
4457
+ }
4458
+ function ko(i, e) {
4459
+ if (e <= i.cap)
4460
+ return;
4461
+ const t = Math.max(e, i.cap * 2);
4462
+ i.cap = t, i.keys = new Uint32Array(t), i.idxA = new Int32Array(t), i.idxB = new Int32Array(t), i.sortedKeys = new Uint32Array(t), i.clusterOf = new Int32Array(t), i.heads = new Int32Array(t), i.sizes = new Int32Array(t);
4463
+ }
4464
+ const hi = (i, e) => ({
4465
+ count: e,
4466
+ level: 0,
4467
+ cellMeters: i,
4468
+ clusterCount: 0,
4469
+ clusterOf: new Int32Array(0),
4470
+ headIndex: new Int32Array(0),
4471
+ clusterSize: new Int32Array(0),
4472
+ levels: []
4473
+ });
4474
+ function di(i, e, t, s, n, o, r, l) {
4475
+ let h = 1 / 0, c = 1 / 0, m = -1 / 0, u = -1 / 0;
4476
+ for (let x = 0; x < s; x++) {
4477
+ const H = e[x], O = t[x];
4478
+ H < h && (h = H), O < c && (c = O), H > m && (m = H), O > u && (u = O);
4479
+ }
4480
+ const v = 1 / n;
4481
+ let d = n, p = Math.max((m - h) * v, (u - c) * v);
4482
+ for (; p >= 65535; )
4483
+ d *= 2, p /= 2;
4484
+ const g = 1 / d, y = i.keys;
4485
+ let w = 0;
4486
+ for (let x = 0; x < s; x++) {
4487
+ const H = (e[x] - h) * g | 0, O = (t[x] - c) * g | 0, j = Ro(H, O);
4488
+ y[x] = j, j > w && (w = j);
4489
+ }
4490
+ const M = w > 0 ? 32 - Math.clz32(w) : 1, I = Math.max(1, Math.ceil(M / Ge));
4491
+ let C = i.idxA, k = i.idxB;
4492
+ for (let x = 0; x < s; x++)
4493
+ C[x] = x;
4494
+ const S = i.sortedKeys;
4495
+ for (let x = 0; x < I; x++) {
4496
+ const H = x * Ge, O = x === I - 1;
4497
+ ue.fill(0);
4498
+ for (let V = 0; V < s; V++)
4499
+ ue[y[C[V]] >>> H & zt]++;
4500
+ let j = 0;
4501
+ for (let V = 0; V < je; V++) {
4502
+ const ve = ue[V];
4503
+ ue[V] = j, j += ve;
4504
+ }
4505
+ for (let V = 0; V < s; V++) {
4506
+ const ve = C[V], Je = y[ve], Qe = ue[Je >>> H & zt]++;
4507
+ k[Qe] = ve, O && (S[Qe] = Je);
4508
+ }
4509
+ const ui = C;
4510
+ C = k, k = ui;
4511
+ }
4512
+ const T = C;
4513
+ be.fill(0);
4514
+ let z = S[0];
4515
+ for (let x = 1; x < s; x++) {
4516
+ const H = S[x], O = H ^ z;
4517
+ z = H, O !== 0 && be[31 - Math.clz32(O) >> 1]++;
4518
+ }
4519
+ const L = [];
4520
+ let E = 0, B = s, Z = 0;
4521
+ for (let x = 15; x >= 0; x--)
4522
+ Z += be[x];
4523
+ for (let x = 0; x < r; x++) {
4524
+ const H = 1 + Z;
4525
+ if (L.push({ level: x, cellMeters: d * (1 << x), clusters: H }), E = x, B = H, H <= o)
4526
+ break;
4527
+ x < 16 && (Z -= be[x]);
4528
+ }
4529
+ const Q = 2 * E, q = i.clusterOf, ee = i.heads, $ = i.sizes;
4530
+ $.fill(0, 0, B);
4531
+ let X = -1, le = -1;
4532
+ for (let x = 0; x < s; x++) {
4533
+ const H = T[x], O = S[x] >>> Q;
4534
+ (x === 0 || O !== le) && (X++, ee[X] = H, le = O), q[H] = X, $[X]++;
4535
+ }
4536
+ const me = l ? q.subarray(0, s) : q.slice(0, s), pe = l ? ee.subarray(0, B) : ee.slice(0, B), ge = l ? $.subarray(0, B) : $.slice(0, B);
4537
+ return {
4538
+ count: s,
4539
+ level: E,
4540
+ cellMeters: d * (1 << E),
4541
+ clusterCount: B,
4542
+ clusterOf: me,
4543
+ headIndex: pe,
4544
+ clusterSize: ge,
4545
+ levels: L
4546
+ };
4547
+ }
4548
+ function Bo(i = 0) {
4549
+ const e = ci(Math.max(1, i));
4550
+ return (t, s, n, o = {}) => {
4551
+ const r = o.baseCellMeters ?? 200;
4552
+ return n <= 0 ? hi(r, n) : (ko(e, n), di(
4553
+ e,
4554
+ t,
4555
+ s,
4556
+ n,
4557
+ r,
4558
+ o.maxClusters ?? 3e4,
4559
+ o.maxLevels ?? 20,
4560
+ !0
4561
+ ));
4562
+ };
4563
+ }
4564
+ function No(i, e, t, s = {}) {
4565
+ const n = s.baseCellMeters ?? 200;
4566
+ if (t <= 0)
4567
+ return hi(n, t);
4568
+ const o = ci(t);
4569
+ return di(
4570
+ o,
4571
+ i,
4572
+ e,
4573
+ t,
4574
+ n,
4575
+ s.maxClusters ?? 3e4,
4576
+ s.maxLevels ?? 20,
4577
+ !1
4578
+ );
4579
+ }
4580
+ const Fo = "0.2.0";
4581
+ export {
4582
+ Si as DEFAULT_ANIMATED_POOL,
4583
+ Mi as DEFAULT_LOD,
4584
+ Ii as DEFAULT_POOL,
4585
+ ye as DEFAULT_SCENE,
4586
+ qe as EventEmitter,
4587
+ b as MTF_ACTION_NAMES,
4588
+ U as MTF_EVENT_NAMES,
4589
+ $e as MultiTargetFramework,
4590
+ Nn as MultiTargetScene,
4591
+ Eo as SiteLayer,
4592
+ Pe as TARGET_DOMAINS,
4593
+ xn as TrackManager,
4594
+ Fo as VERSION,
4595
+ jn as bindFrameworkEventBus,
4596
+ Jn as bindSiteLayerEventBus,
4597
+ No as clusterProgressive,
4598
+ _o as createClusterWorkerClient,
4599
+ Ho as createFrameworkEventBus,
4600
+ Do as createMultiTargetFramework,
4601
+ Bo as createQuadClusterer,
4602
+ $n as getFrameworkEventBus,
4603
+ Oo as lonLatToLocalPlane,
4604
+ ni as tryGetFrameworkEventBus
4605
+ };