85 lines
4.1 KiB
Markdown
85 lines
4.1 KiB
Markdown
# 智能星球可交互图标聚类策略
|
||
|
||
智能星球的可交互图标由 `createInteractableLayer` 统一管理。图标仍然使用 Three.js `Points` 渲染,拾取、hover、locked、tooltip 和巡航焦点继续依赖 marker 的 `userData`;聚类策略只决定“哪些 marker 被合成一个 cluster dot”。
|
||
|
||
## 策略
|
||
|
||
`cluster.strategy` 支持三种模式:
|
||
|
||
- `stable-spherical`:稳定球面聚类。按地球局部 3D 坐标聚合,并用 zoom band 缓存拓扑;旋转和同档缩放只更新投影和尺寸,不重算谁和谁聚在一起。适合 BGP、超算/GPU 中心和 Earth interactable 这类半静态图层。
|
||
- `dynamic-screen`:动态屏幕聚类。保留原来的屏幕空间聚类逻辑,每帧按可见投影关系判断。适合船舶等高频实时图层,也可作为稳定策略的回退。
|
||
- `none`:不聚类。所有 marker 独立显示,适合低数量或需要精确展示的图层。
|
||
|
||
`cluster: false` 等价于 `strategy: "none"`。未显式声明 `strategy` 时,保持兼容行为:开启聚类的旧图层继续走 `dynamic-screen`。
|
||
|
||
## Stable Spherical
|
||
|
||
`stable-spherical` 的核心是把聚类身份从屏幕距离迁到球面距离:
|
||
|
||
- 每个 marker 使用 `icon_base_position` 作为真实地理锚点。
|
||
- 默认 zoom 超过 `2.5` 时强制关闭聚类,所有 marker 展开为原图标。
|
||
- 当前 zoom 只映射到离散 band;同一 band 内旋转地球或细微缩放不会重算拓扑。
|
||
- 跨 band、数据变更、图层显隐变化时才重新计算 cluster。
|
||
- cluster 质心由成员 3D 坐标平均后 normalize 回球壳半径,因此 cluster dot 刚性贴在地理质心投影上。
|
||
- cluster dot 不参与 2D 避让,避免被屏幕排斥推离真实地理位置。
|
||
- band 切换带有少量 hysteresis,避免缩放停在临界点时在两个 band 之间来回跳。
|
||
- 新生成的 marker / cluster dot 会执行短 scale + opacity ease;这只是渲染过渡,不改变 marker 的真实经纬度、拾取对象或 locked 状态。
|
||
|
||
稳定策略使用球面 bucket/hash 邻域查询,禁止用全量双循环。这样大多数帧只承担投影与材质尺寸更新,聚类成本只在 band 或数据版本变化时支付。
|
||
|
||
## 配置示例
|
||
|
||
```js
|
||
const computeCenterIconLayer = createInteractableLayer({
|
||
id: "computeCenters",
|
||
// ...
|
||
avoidance: SURFACE_AVOIDANCE_PROFILES.city,
|
||
cluster: {
|
||
strategy: "stable-spherical",
|
||
minCount: 2,
|
||
maxMarkersPerDot: 14,
|
||
transitionMs: 220,
|
||
bandHysteresis: 0.08,
|
||
disableAboveZoom: 2.5,
|
||
bands: [
|
||
{ key: "far", maxZoom: 1.7, distance: 15 },
|
||
{ key: "mid", maxZoom: 2.6, distance: 8 },
|
||
{ key: "near", maxZoom: 3.5, distance: 4 },
|
||
{ key: "detail", maxZoom: Infinity, distance: 0 },
|
||
],
|
||
},
|
||
});
|
||
```
|
||
|
||
实时层可以保留动态策略:
|
||
|
||
```js
|
||
const vesselIconLayer = createInteractableLayer({
|
||
id: "vessels",
|
||
// ...
|
||
cluster: {
|
||
strategy: "dynamic-screen",
|
||
enabled: true,
|
||
maxMarkersPerDot: 10,
|
||
},
|
||
});
|
||
```
|
||
|
||
## 调参原则
|
||
|
||
- `distance` 是球面 3D 距离阈值,单位与 `CONFIG.earthRadius` 一致。值越大,越容易聚合。
|
||
- 最远 band 用较大的 `distance` 降低视觉密度;最近 band 通常设为 `0`,让图标完全解散。
|
||
- `bandHysteresis` 控制 band 边界滞回。值太小容易临界闪烁,值太大会让切换略显迟钝。
|
||
- `transitionMs` 控制聚散过渡时间。建议保持在 160-260ms,过长会让实时层显得拖泥带水。
|
||
- `disableAboveZoom` 控制精细查看阈值。默认 `2.5`,超过后不再生成 cluster;设为 `false` 可关闭这个硬阈值。
|
||
- 高实时性图层优先用 `dynamic-screen`,避免数据频繁变更时触发稳定策略的拓扑重算。
|
||
- 若某图层出现异常,可临时切回 `dynamic-screen` 或 `cluster: false`。
|
||
|
||
## 验收重点
|
||
|
||
- 同一 zoom band 内旋转地球,cluster 不应闪烁或重新聚散。
|
||
- cluster dot 应跟随地球表面质心,不被避让逻辑推开。
|
||
- 放大到 detail band 后,应恢复该图层原本的图标纹理和点击行为。
|
||
- zoom 超过 250% 后不应再显示 cluster dot。
|
||
- vessel 等实时层更新后,图标和 cluster 应立即反映最新数据。
|