Appearance
HedronPlotEditor 体对象标绘
在 Editor 自有
CustomDataSource中绘制、选择和编辑多边体、半球体与圆柱体,并以 GeoJSON 保存控制点。对齐源案例LabelPlotting/HedronPlot。
职责边界
- 体对象是地图标绘注记,不是
ScenarioEntity业务装备;Editor 不调用viewer.createEntity()。 - 标绘实体、绘制预览和编辑控制柄全部归 Editor 的
CustomDataSource所有。 - 若需要判断飞机等装备是否进入体域,装备必须先由
viewer.createEntity()创建,再传给updateTarget();Editor 只读取装备位置,不创建、更新或删除装备。 - 不复制源案例的远程底图、3D Tiles、JSON 或来源不明图片;模板使用内联自生成种子。
基础用法
ts
import { HedronPlotEditor } from '@nexa/gis-cesium'
const editor = new HedronPlotEditor({ viewer })
editor.addPlot({
id: 'restricted-zone',
type: 'cylinder',
name: '圆柱禁飞区',
controlPoints: [[106.445, 29.52, 100]],
style: { radius: 650, extrudedHeight: 1100 },
})
editor.startDraw('polyhedron') // 左键加点,至少 3 点后右键完成公共 API
ts
new HedronPlotEditor(options: HedronPlotEditorOptions)
readonly dataSource: CustomDataSource
readonly plots: readonly HedronPlotRecord[]
readonly selectedId?: string
readonly isDrawing: boolean
addPlot(definition: HedronPlotDefinition): HedronPlotRecord
updatePlot(id: string, patch: HedronPlotUpdatePatch): HedronPlotRecord
removePlot(id: string): boolean
clear(): void
select(id?: string): HedronPlotRecord | undefined
startDraw(type: HedronPlotType, draft?): void
cancelDraw(): void
contains(id: string, target: Cartesian3): boolean
updateTarget(target: CombatEntityLike, time?: JulianDate): readonly string[]
clearTarget(targetId: string): void
exportGeoJson(): HedronPlotGeoJsonFeatureCollection
importGeoJson(collection, options?): HedronPlotRecord[]
enable(): void
disable(): void
destroy(): void类型与点数
| 类型 | 控制点 | 样式 |
|---|---|---|
polyhedron | 至少 3 个;右键完成 | extrudedHeight |
hemisphere | 固定 1 个 | radius |
cylinder | 固定 1 个 | radius、extrudedHeight |
控制点统一使用 [longitude, latitude, height],角度为度、高度为椭球高米。radius 与 extrudedHeight 必须是有限正数。
交互
- 单击体对象选中并高亮;单击空白取消选择。
- 半球体和圆柱体拖动中心控制柄以移动位置。
- 多边体拖动蓝色控制柄编辑顶点。
- 拖动期间只暂时禁用相机
rotate / translate / tilt,结束、取消、禁用或销毁时精确恢复进入前状态与光标。 - 取点只使用公开 API,并按
scene.pickPosition→globe.pick→camera.pickEllipsoid回退。
动态装备进入/离开
ts
viewer.extend(viewerEntityMixin)
const fighter = viewer.createEntity({
id: 'fighter-01',
name: '目标机',
entityType: 'fighter',
components: [
{ id: 'position', type: 'PositionComponent', lon: 106.44, lat: 29.51, alt: 500 },
{ id: 'model', type: 'ModelComponent', url: '/static/J16.glb', scale: 1 },
],
modules: [],
})
const editor = new HedronPlotEditor({
viewer,
onTargetEnter: ({ target, plot }) => console.log(target.name, '进入', plot.name),
onTargetLeave: ({ target, plot }) => console.log(target.name, '离开', plot.name),
})
const removeTick = viewer.clock.onTick.addEventListener(clock => {
editor.updateTarget(fighter, clock.currentTime)
})
// cleanup
removeTick()
editor.destroy()updateTarget() 以装备 id 保存上一帧命中集合,只在状态跨越时触发一次 enter / leave,不会每帧重复通知。clearTarget() 会补发当前命中体域的离开事件并清理状态。
空间数学
包含判断统一在第一个控制点的局部 ENU 坐标系中完成:
- 半球:
z >= 0且三维距离不超过半径;修复源实现用完整球距离判断、下半球也会命中的问题。 - 圆柱:水平距离不超过半径,且局部高度位于
[0, extrudedHeight]。 - 多边体:局部 XY 点在多边形内,且局部高度位于拉伸范围内。
- 边界使用毫米级 epsilon 视为内部,减少动态目标贴边时的进入/离开抖动。
GeoJSON
Point 保存半球/圆柱中心,Polygon 保存多边体控制点;属性兼容源案例的 plotCode、plotBase: "HedronPlot"、plotType、plotName 和 style。导入先完整校验全部 Feature,clearExisting: true 下非法输入也不会清空已有标绘。
生命周期与源缺陷修复
- 一个公开
ScreenSpaceEventHandler负责全部交互,disable()/destroy()完整销毁。 - 不使用源案例的
viewer._element、_cesiumWidget或 React_reactInternals。 - 不调用
viewer.entities.removeAll();清理只影响 Editor 自有 DataSource。 - 处理
DataSourceCollection.add()异步完成与立即destroy()的竞态。 - 源实现创建的选择 handler、点/面编辑 handler 未完整销毁,且拖动仅把相机旋转强制恢复为
true;本实现按所有权和进入前状态恢复。