Cesium教程(11)军事标绘 攻击箭头、 燕尾攻击箭头标绘与编辑

94 阅读1分钟

本学习系列将以Cesium + Vue3+Typescript+elementplus作为主要技术栈展开,后续会循序渐进,持续探索Cesium的高级功能。 详情请关注原文Cesium+Vue3学习系列(11)---态势标绘 攻击箭头、 燕尾攻击箭头标绘与编辑

上篇介绍态势标绘中的直箭头和细线箭头的标绘与编辑。本篇介绍攻击箭头与燕尾攻击箭头的标绘与编辑。先看效果

8.gif 1、新建攻击箭头类AttackArrow。主要的实现算法写在createAttackArrowPoints函数里。

mport EventDispatcher from "@/system/EventDispatcher/EventDispatcher";
import { CallbackProperty, Cartesian3, ClassificationType, Color, Entity, PolygonGraphics, Viewer } from "cesium";
import { BaseDraw, GeometryType } from "../BaseDraw";
import { createAttackArrowPoints } from "@/system/Utils/SituationUtil";
export default class AttackArrow extends BaseDraw {
    private tempCursor = new Cartesian3();
    constructor(viewer: Viewer, dispatcher: EventDispatcher) {
        super(viewer, dispatcher);
        this.geometryType = GeometryType.ATTACK_ARROW;
        this.minPointCount = 3;
    }
    protected buildFinalEntity(): Entity {
        const geometryPoints = createAttackArrowPoints(this.getPositions())
        return this.viewer.entities.add({
            polygon: new PolygonGraphics({
                hierarchy: new CallbackProperty(() => ({
                    positions: geometryPoints
                }), false),
                classificationType: ClassificationType.BOTH,
                material: Color.BLUE.withAlpha(0.4)
            })
        });
    }
    protected buildTempEntity(): Entity | undefined {
        if (this.getPositions().length < (this.minPointCount-1)) return undefined; 
        return this.viewer.entities.add({
            polygon: new PolygonGraphics({
                hierarchy: new CallbackProperty(() => ({
                    positions: createAttackArrowPoints([...this.getPositions(), this.tempCursor || new Cartesian3()])
                }), false),
                classificationType: ClassificationType.BOTH,
                material: Color.CYAN.withAlpha(0.3)
            })
        });
    }
    protected updateTempEntity(cursor: Cartesian3) {
        this.tempCursor = cursor;
    }
}

/**
 * 创建一条攻击箭头
 * @param positions 攻击箭头的控制点
 * @returns 攻击箭头的点数组
 */
export const createAttackArrowPoints = (positions: Cartesian3[]) => {
  const positionLength = positions.length;
  if (positionLength > 2 && positions[positionLength - 1].equals(positions[positionLength - 2])) {
    positions.pop();
  }
  const lnglatPoints = positions.map((pnt) => {
    return CoordinatesUtil.Cartesian2Wgs84Lonlat(pnt);
  });
  let [tailLeft, tailRight] = [lnglatPoints[0], lnglatPoints[1]];
  if (isClockWise(lnglatPoints[0], lnglatPoints[1], lnglatPoints[2])) {
    tailLeft = lnglatPoints[1];
    tailRight = lnglatPoints[0];
  }
  const midTail = CoordinatesUtil.MidPoint(tailLeft, tailRight);
  const bonePnts = [midTail].concat(lnglatPoints.slice(2));
  const headPnts = getArrowHeadPoints(bonePnts, tailLeft, tailRight);
  const [neckLeft, neckRight] = headPnts ? [headPnts[0] ?? [], headPnts[4] ?? []] : [[], []];
  const tailWidthFactor = MathDistance(tailLeft, tailRight) / wholeDistance(bonePnts);
  const bodyPnts = getArrowBodyPoints(bonePnts, neckLeft, neckRight, tailWidthFactor);
  const count = bodyPnts.length;
  let leftPnts = [tailLeft].concat(bodyPnts.slice(0, count / 2));
  leftPnts.push(neckLeft);
  let rightPnts = [tailRight].concat(bodyPnts.slice(count / 2, count));
  rightPnts.push(neckRight);
  leftPnts = getQBSplinePoints(leftPnts);
  rightPnts = getQBSplinePoints(rightPnts);
  const points = leftPnts.concat(headPnts ?? [], rightPnts.reverse());
  const temp = points.flat();
  const cartesianPoints = Cartesian3.fromDegreesArray(temp);
  return cartesianPoints;
}

以上是攻击箭头部分代码。完整源码可以在原文看到Cesium+Vue3学习系列(11)---态势标绘 攻击箭头、 燕尾攻击箭头标绘与编辑