Skip to content

军事标绘编辑

MilitaryPlotEditor 在自有 CustomDataSource 中提供军标绘制、选择、控制点拖动、整体平移和 GeoJSON 管理。

能力边界

编辑器复用 generateMilitarySymbol 的纯几何算法,不复制军标算法,也不改造通用 DrawManager

  • DrawManager 适合点、线、普通面和矩形的一次性绘制。
  • MilitaryPlotEditor 处理不同军标的固定/最少控制点规则、实时变形、选择柄和持久化。
  • 军标是地图注记,不是 ScenarioEntity 装备。编辑器不会调用 viewer.createEntity(),也不会创建或删除任何业务装备。
  • 若军标需要关联装备,装备仍须通过 viewer.createEntity() 创建,可在军标 properties 中保存装备 id。

快速开始

ts
import {
  MilitaryPlotEditor,
  MilitarySymbolType,
} from '@nexa/gis-cesium'

const editor = new MilitaryPlotEditor({
  viewer,
  onChange: ({ plot, source }) => {
    console.log(plot.id, source)
  },
})

editor.addPlot({
  id: 'attack-01',
  name: '进攻方向',
  type: MilitarySymbolType.ATTACK_ARROW,
  controlPoints: [
    [116.39, 39.91],
    [116.40, 39.90],
    [116.42, 39.91],
  ],
})

editor.startDraw(MilitarySymbolType.CIRCLE)

// 页面卸载时释放一个 handler、全部编辑柄和自有数据源。
editor.destroy()

绘制规则

固定点数类型达到点数后自动完成:

点数类型
2正圆、椭圆、矩形、直箭头、突击方向
3扇形、集结地
4钳击

可变点数类型使用右键完成:

最少点数类型
2折线、分队战斗、分队战斗尾
3多边形、曲线面、进攻方向、进攻方向尾

右键在控制点不足时取消绘制。拖动过程中右键会回滚到拖动前控制点。

API

MilitaryPlotEditor

API说明
plots当前编辑器管理的只读军标记录
selectedPlot当前选中军标
isDrawing / isDragging当前交互状态
addPlot(definition)添加军标注记
getPlot(id)查询军标
updatePlot(id, patch)原子更新控制点、高度、属性或样式
removePlot(id)移除一条自有军标
clear()只清理本编辑器军标
startDraw(type, draft?)开始绘制
cancelDraw()取消绘制并清理预览
select(id)选择军标;传 undefined 取消选择
importGeoJson(collection, options?)导入源案例兼容 GeoJSON
exportGeoJson()导出控制点 GeoJSON
enable() / disable()幂等启用或禁用交互
cancelDrag()回滚未提交拖动
destroy()释放交互和自有数据源

MilitaryPlotEditorOptions

参数类型默认值说明
viewerCesium.Viewer-Cesium Viewer
enabledbooleantrue是否立即启用
dataSourceNamestringmilitary-plot-editor自有数据源名称
styleMilitaryPlotStyle黄色/红色选中默认样式
positionPicker(screen) => Cartesian3 | undefined内置三级回退自定义取点策略
onSelect(plot) => void-选择变化回调
onChange(event) => void-数据提交回调

默认取点依次使用:

  1. scene.pickPositionSupported && scene.pickPosition()
  2. scene.globe.pick(camera.getPickRay())
  3. camera.pickEllipsoid()

全程只使用 Cesium 公共 API。

数据定义

ts
interface MilitaryPlotDefinition {
  id?: string
  type: MilitarySymbolType
  name?: string
  controlPoints: readonly Point2D[]
  height?: number
  properties?: Readonly<Record<string, unknown>>
  style?: MilitaryPlotStyle
}

控制点统一为 WGS84 [经度, 纬度]。一个军标使用统一椭球高度;整体移动保持所有点之间的经纬差,并将经度归一到 [-180, 180)

GeoJSON

导出数据保存原始控制点,而不是拟合后的数百个轮廓点,因此可继续编辑:

ts
const collection = editor.exportGeoJson()

const restored = new MilitaryPlotEditor({ viewer })
restored.importGeoJson(collection, { clearExisting: true })

Polygon 军标使用 geometry.type = "Polygon"coordinates[0] 是控制点;折线使用 LineString。属性兼容源案例的 plotCodeplotBaseplotTypeplotNamestyle.height

导入会先校验完整集合,再按需清空已有数据;任一要素非法时不会产生部分导入或误清空。

选择与拖动

  • 选中军标变为红色。
  • 蓝色点编辑单个控制点。
  • 红色点整体移动;正圆的红点是圆心,蓝点是半径控制点。
  • 拖动时编辑器精确保存并恢复相机旋转、平移、倾斜开关和鼠标样式。
  • 松开只触发一次 update;右键、禁用或销毁会回滚未提交拖动。

onChange.source 可为 drawvertex-dragmove-dragapiimport

所有权与清理

ts
const unrelated = viewer.entities.add({ /* 其他模块实体 */ })
const editor = new MilitaryPlotEditor({ viewer })

editor.clear()
// unrelated 仍存在

editor.destroy()
// 只移除 editor 的 CustomDataSource;Viewer 与业务装备仍存在

不要用 viewer.entities.removeAll() 清理案例。编辑器自有数据源异步加入 Viewer 时也处理了立即销毁竞态,不会在卸载后残留数据源。

浏览器验收

  1. 打开“军事标绘编辑”,确认 6 个内联代表性军标出现,无外部 JSON、图片或远程 3D Tiles 请求。
  2. 单击黄色符号,确认变红并出现蓝色控制点与红色整体移动点。
  3. 拖动蓝点,确认轮廓实时重算;拖动红点,确认整体平移且不变形。
  4. 正圆只显示半径柄和圆心移动柄。
  5. 分别验证固定点数自动完成、可变点数右键完成、控制点不足右键取消。
  6. 拖动途中右键取消,确认控制点、相机控制和鼠标样式恢复。
  7. 导出 GeoJSON,确认控制点数量与当前军标一致。
  8. 清空后确认其他 Viewer 实体未被删除;离开案例再返回无重复 handler、编辑柄或数据源。

限制

  • 逐帧编辑仅重算当前军标;超大 fittingCount 仍可能增加拖动开销。
  • pickPosition 可能落在 3D 模型表面。需要固定地面高度时应注入 positionPicker
  • bbox 中心平移适合一般区域;跨 180° 经线或极区的大跨度军标应由调用方提供更适合的编辑策略。

相关链接