本学习系列将以Cesium + Vue3+Typescript+elementplus作为主要技术栈展开,后续会循序渐进,持续探索Cesium的高级功能。 详情请关注原文Cesium+Vue3学习系列(11)---态势标绘 攻击箭头、 燕尾攻击箭头标绘与编辑
上篇介绍态势标绘中的直箭头和细线箭头的标绘与编辑。本篇介绍攻击箭头与燕尾攻击箭头的标绘与编辑。先看效果
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)---态势标绘 攻击箭头、 燕尾攻击箭头标绘与编辑