Cesium 常用标绘线、面、矩形、圆、曲面、曲线、攻击箭头、钳击箭头,标绘与修改。

news/2024/10/18 10:15:27/

前言:直接放效果图,符合就往下看,不符合出门右转。

在这里插入图片描述

由于篇幅有限,只贴出各个标绘的关键代码。

1、线段

  • 基于坐标点,加载不同的材质。
//动态加载
const entity = this._viewer.entities.add({polyline: {positions: new CallbackProperty(() => {return this._positions;}, false),show: true,material: Color.RED,width: 3,clampToGround: true //是否贴地}
});//静态const primitive = scene.groundPrimitives.add(new GroundPolylinePrimitive({geometryInstances: new GeometryInstance({geometry: new GroundPolylineGeometry({positions: line,width: this._width,}),id: this.id}),appearance: new PolylineMaterialAppearance({material:Material.fromType("Image", {image: this._imageUrl,repeat: this._repeat})}),}));

2、多边形

  • 基于做坐标点,加载不同的材质
//动态
const entity = this._viewer.entities.add({polygon: {hierarchy: new CallbackProperty(() => {return new PolygonHierarchy(this._positions)}, false),show: true,fill: true,material: Color.RED.withAlpha(0.5),//@ts-ignoreclampToGround: true,width: 3,outlineColor: Color.BLACK,outlineWidth: 1,outline: true}});
//静态
const  primite = scene.groundPrimitives.add(new GroundPrimitive({geometryInstances: new GeometryInstance({id: this._id,geometry: new PolygonGeometry({polygonHierarchy: {positions: positions,holes: []},}),}),appearance: new EllipsoidSurfaceAppearance({material: Material.fromType("Grid", this._grid)}),classificationType: ClassificationType.TERRAIN,})
)

3、绘制直线箭头

  • 根据箭头算法,提供两个点的坐标
//动态
const arrowEntity = this._viewer.entities.add({polygon: {hierarchy: new CallbackProperty(() => {const length = this._positions.length;const p1 = this._positions[0];const p2 = this._positions[length - 1];const firstPoint = this.cartesianToLatlng(p1);const endPoints = this.cartesianToLatlng(p2);let arrow = [];let res = this.fineArrow([firstPoint[0], firstPoint[1]], [endPoints[0], endPoints[1]]);if (res) {for (let i = 0; i < res.length; i++) {let cart3 = new Cartesian3(res[i].x, res[i].y, res[i].z);arrow.push(cart3);}return new PolygonHierarchy(arrow);}}, false),show: true,fill: true,material: Color.RED.withAlpha(0.5)}
})
  • 箭头算法
/*** * @param t 二维坐标* @param o 二维坐标* @returns 两点之间的距离*/
export function distance(t: number[], o: number[]) {return Math.sqrt(Math.pow(t[0] - o[0], 2) + Math.pow(t[1] - o[1], 2));
}
/*** * @param positionArr 点坐标数组* @returns 距离*/
export function wholeDistance(positionArr: number[][]) {let dis = 0;const length = positionArr.length - 1;for (let i = 0; i < length; i++) {dis += distance(positionArr[i], positionArr[i + 1]);}return dis;
}
export function getBaseLength(positionArr: number[][]) {return Math.pow(wholeDistance(positionArr), 0.99);
}/*** * @param t * @param o * @param e * @param r * @param n * @returns 获取第三个点的坐标 */
export function getThirdPoint(t: number[],o: number[],e: number,r: number,n: boolean = false
) {let g = getAzimuth(t, o),i = n ? g + e : g - e,s = r * Math.cos(i),a = r * Math.sin(i);return [o[0] + s, o[1] + a];
}
/*** * @param t * @param o * @returns 获取方位角*/
export function getAzimuth(t: number[], o: number[]): number {let e = 0,r = Math.asin(Math.abs(o[1] - t[1]) / distance(t, o));o[1] >= t[1] && o[0] >= t[0]? (e = r + Math.PI): o[1] >= t[1] && o[0] < t[0]? (e = 2 * Math.PI - r): o[1] < t[1] && o[0] < t[0]? (e = r): o[1] < t[1] && o[0] >= t[0]? (e = Math.PI - r): 0;return e;
}
fineArrowDefualParam() {return {tailWidthFactor: 0.15,neckWidthFactor: 0.2,headWidthFactor: 0.25,headAngle: Math['PI'] / 8.5,neckAngle: Math['PI'] / 0xd};
}
fineArrow(po1: number[], po2: number[]) {if ((po1.length < 2) || (po2.length < 2)) return;//画箭头的函数let tailWidthFactor = this.fineArrowDefualParam().tailWidthFactor;let neckWidthFactor = this.fineArrowDefualParam().neckWidthFactor;let headWidthFactor = this.fineArrowDefualParam().headWidthFactor;let headAngle = this.fineArrowDefualParam().headAngle;let neckAngle = this.fineArrowDefualParam().neckAngle;let o = [];o[0] = po1;o[1] = po2;var e = o[0],r = o[1],n = getBaseLength(o),g = n * tailWidthFactor,//尾部宽度因子i = n * neckWidthFactor,//脖子宽度银子s = n * headWidthFactor,//头部宽度因子a = getThirdPoint(r, e, Math.PI / 2, g, !0),l = getThirdPoint(r, e, Math.PI / 2, g, !1),u = getThirdPoint(e, r, headAngle, s, !1),c = getThirdPoint(e, r, headAngle, s, !0),p = getThirdPoint(e, r, neckAngle, i, !1),h = getThirdPoint(e, r, neckAngle, i, !0),d = [];d.push(a[0], a[1], p[0], p[1], u[0], u[1], r[0], r[1], c[0], c[1], h[0], h[1], l[0], l[1], e[0], e[1]);return Cartesian3.fromDegreesArray(d)
}

4、攻击箭头

  • 提供坐标点 绘制攻击箭头也叫燕尾箭头
import initXp from 'algorithm.js'
//动态
const xp = initXp()
const update = () => {//计算面if (positions.length < 3) {return null;}let lnglatArr = [], lnglat;for (var i = 0; i < positions.length; i++) {lnglat = this.cartesianToLatlng(positions[i]);lnglatArr.push(lnglat)}const res = xp.algorithm.tailedAttackArrow(lnglatArr);const returnData = res.polygonalPoint;return new PolygonHierarchy(returnData);}
this._viewer.entities.add({polygon: new PolygonGraphics({hierarchy: new CallbackProperty(update, false),show: true,fill: true,material: this.fillMaterial})
});function cartesianToLatlng(position: Cartesian3) {const latlng =this._viewer.scene.globe.ellipsoid.cartesianToCartographic(position);const lat = CesiumMath.toDegrees(latlng.latitude);const lng = CesiumMath.toDegrees(latlng.longitude);return [lng, lat];
}

5、钳击箭头

  • 一共需要提供五个点
 const update = () => {//计算面if (positions.length < 3) {return null;}var lnglatArr = [];for (var i = 0; i < positions.length; i++) {var lnglat = this.cartesianToLatlng(positions[i]);lnglatArr.push(lnglat)}const xp = initXp()let res = xp.algorithm.doubleArrow(lnglatArr);const returnData = res.polygonalPoint;return new PolygonHierarchy(returnData);
}
return this._viewer.entities.add({polygon: new PolygonGraphics({hierarchy: new CallbackProperty(update, false),show: true,fill: true,material: this.fillMaterial})
});function cartesianToLatlng(position: Cartesian3) {const latlng =this._viewer.scene.globe.ellipsoid.cartesianToCartographic(position);const lat = CesiumMath.toDegrees(latlng.latitude);const lng = CesiumMath.toDegrees(latlng.longitude);return [lng, lat];
}

6、矩形

  • 提供两个点
import { point } from "@turf/helpers"
import rhumbBearing from "@turf/rhumb-bearing"
import distance from "@turf/distance"
import destination from "@turf/destination"
const entity = this._viewer.entities.add({polygon: {hierarchy: new CallbackProperty(() => {if (this._positions[0] && this._positions[1] && this._positions[2]) {const r0 = Cartographic.fromCartesian(this._positions[0])const r1 = Cartographic.fromCartesian(this._positions[1]) // 辅助点const r2 = Cartographic.fromCartesian(this._positions[2])const p0 = point([r0.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])const p1 = point([r1.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])const p2 = point([r2.longitude * 180 / Math.PI, r2.latitude * 180 / Math.PI])const bearing1 = rhumbBearing(p0, p1)const bearing2 = rhumbBearing(p0, p2)const angle1 = bearing2 - bearing1// 对角长度const length = distance(p0, p2, { units: 'miles' })const len1 = Math.cos(angle1 / 180 * Math.PI) * lengthconst dest1 = destination(p0, len1, bearing1, { units: 'miles' })const angle2 = 90 - angle1const len2 = Math.cos(angle2 / 180 * Math.PI) * lengthconst dest2 = destination(p0, len2, 90 + bearing1, { units: 'miles' })//@ts-ignoreconst coordinates = [this._positions[0], Cartesian3.fromDegrees(...dest1.geometry.coordinates), this._positions[2], Cartesian3.fromDegrees(...dest2.geometry.coordinates)]return new PolygonHierarchy(coordinates)}}, false),material: this._color},
})

7、绘制椭圆

  • 绘制椭圆需要两个点,注意长轴必须大于短轴,长短轴一致时为圆
import { point } from "@turf/helpers"
import distance from "@turf/distance"
const entity = this._viewer.entities.add({//@ts-ignoreposition: new CallbackProperty(() => {return this._positions[0]}, false),ellipse: {// 半短轴(画圆:半短轴和半长轴一致即可)semiMinorAxis: new CallbackProperty(() => {const r0 = Cartographic.fromCartesian(this._positions[0])const r1 = Cartographic.fromCartesian(this._positions[1])const p0 = point([r0.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])let p3 = point([r1.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])if (this._isEllipse) {let p1 = point([r1.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])let p2 = point([r0.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])let len1, len2len1 = distance(p0, p1, { units: 'kilometers' }) * 1000len2 = distance(p0, p2, { units: 'kilometers' }) * 1000return len1 < len2 ? len1 : len2} else return distance(p0, p3, { units: 'kilometers' }) * 1000}, false),// 半长轴semiMajorAxis: new CallbackProperty(() => {const r0 = Cartographic.fromCartesian(this._positions[0])const r1 = Cartographic.fromCartesian(this._positions[1])const p0 = point([r0.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])let p3 = point([r1.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])if (this._isEllipse) {let p1 = point([r1.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])let p2 = point([r0.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])let len1, len2len1 = distance(p0, p1, { units: 'kilometers' }) * 1000len2 = distance(p0, p2, { units: 'kilometers' }) * 1000return len1 > len2 ? len1 : len2} else return distance(p0, p3, { units: 'kilometers' }) * 1000}, false),// 填充色material: this._color,},
});

8、绘制曲线

  • 绘制曲线利用bezier算法
import { lineString, bezierSpline } from '@turf/turf'
const entity = this._viewer.entities.add({polyline: {positions: new CallbackProperty(() => {const lngLatPoints = this._positions.map(i => this.cartesianToLatlng(i))const pos = bezierSpline(lineString(lngLatPoints)).geometry.coordinatesreturn Cartesian3.fromDegreesArray(pos.flat())}, false),show: true,material: Color.RED,width: 3,clampToGround: true //是否贴地}
});

9、绘制封闭曲面

  • 根据turf
 const entity = this._viewer.entities.add({polygon: {hierarchy: new CallbackProperty(() => {if (this._positions.length < 2) return []let pnts = []for (let p = 0; p < this._positions.length; p++) {pnts.push(this.cartesianToLatlng(this._positions[p]))}pnts.push(pnts[0], pnts[1])let normals: number[][] = []let pList: Cartesian3[] = []for (let i = 0; i < pnts.length - 2; i++) {let normalPoints = this.getBisectorNormals(this._t, pnts[i], pnts[i + 1], pnts[i + 2])normals = normals.concat(normalPoints)}let count = normals.lengthnormals = [normals[count - 1]].concat(normals.slice(0, count - 1))for (let i = 0; i < pnts.length - 2; i++) {let pnt1 = pnts[i]let pnt2 = pnts[i + 1]pList.push(this.latlngTocartesian(pnt1))for (let t = 0; t <= this._FITTING_COUNT; t++) {let pnt = this.getCubicValue(t / this._FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)pList.push(this.latlngTocartesian(pnt))}pList.push(this.latlngTocartesian(pnt2))}return new PolygonHierarchy(pList)}, false),show: true,fill: true,material: Color.RED.withAlpha(0.5),//@ts-ignoreclampToGround: true,width: 3,outlineColor: Color.BLACK,outlineWidth: 1,outline: true}});function getBisectorNormals(t: number, pnt1: number[], pnt2: number[], pnt3: number[]): number[][] {let normal = this.getNormal(pnt1, pnt2, pnt3)let bisectorNormalRight: number[] = []let bisectorNormalLeft: number[] = []let dt: number, x: number, y: numberlet dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])let uX = normal[0] / distlet uY = normal[1] / distlet d1 = this.mathDistance(pnt1, pnt2)let d2 = this.mathDistance(pnt2, pnt3)if (dist > this._ZERO_TOLERANCE) {if (this.isClockWise(pnt1, pnt2, pnt3)) {dt = t * d1x = pnt2[0] - dt * uYy = pnt2[1] + dt * uXbisectorNormalRight = [x, y]dt = t * d2x = pnt2[0] + dt * uYy = pnt2[1] - dt * uXbisectorNormalLeft = [x, y]} else {dt = t * d1x = pnt2[0] + dt * uYy = pnt2[1] - dt * uXbisectorNormalRight = [x, y]dt = t * d2x = pnt2[0] - dt * uYy = pnt2[1] + dt * uXbisectorNormalLeft = [x, y]}} else {x = pnt2[0] + t * (pnt1[0] - pnt2[0])y = pnt2[1] + t * (pnt1[1] - pnt2[1])bisectorNormalRight = [x, y]x = pnt2[0] + t * (pnt3[0] - pnt2[0])y = pnt2[1] + t * (pnt3[1] - pnt2[1])bisectorNormalLeft = [x, y]}return [bisectorNormalRight, bisectorNormalLeft]}getNormal(pnt1: number[], pnt2: number[], pnt3: number[]) {let dX1 = pnt1[0] - pnt2[0]let dY1 = pnt1[1] - pnt2[1]let d1 = Math.sqrt(dX1 * dX1 + dY1 * dY1)dX1 /= d1dY1 /= d1let dX2 = pnt3[0] - pnt2[0]let dY2 = pnt3[1] - pnt2[1]let d2 = Math.sqrt(dX2 * dX2 + dY2 * dY2)dX2 /= d2dY2 /= d2let uX = dX1 + dX2let uY = dY1 + dY2return [uX, uY]}function mathDistance(pnt1: number[], pnt2: number[]) {return (Math.sqrt(Math.pow((pnt1[0] - pnt2[0]), 2) + Math.pow((pnt1[1] - pnt2[1]), 2)))}function isClockWise(pnt1: number[], pnt2: number[], pnt3: number[]) {return ((pnt3[1] - pnt1[1]) * (pnt2[0] - pnt1[0]) > (pnt2[1] - pnt1[1]) * (pnt3[0] - pnt1[0]))}
  • 雷达在我之前博客中

http://www.ppmy.cn/news/702521.html

相关文章

14 动态主题类型Dynamic Topic Types

14 动态主题类型Dynamic Topic Types eProsima Fast DDS提供了一种动态方式来定义和使用主题类型和主题数据。我们的实现遵循用于DDS接口的OMG可扩展和动态主题类型。有关更多信息,您可以阅读DDS XTypes V1.2的规范。 动态主题类型提供了在没有与IDL相关的限制的情况下通过RTP…

Hive on Spark的小文件设置参数

Hive on Spark的小文件设置参数 参数调优 了解完了Spark作业运行的基本原理之后&#xff0c;对资源相关的参数就容易理解了。所谓的Spark资源参数调优&#xff0c;其实主要就是对Spark运行过程中各个使用资源的地方&#xff0c;通过调节各种参数&#xff0c;来优化资源使用的效…

nacos部署并配置权限

nacos部署并配置权限 部署 配置JDK环境 下载JDK 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ tar xf jdk-8u371-linux-x64.tar.gz配置环境变量 echo "JAVA_HOME/root/nacos/jdk1.8.0_371" >>/etc/profile echo "expor…

基于bootstrap的双边栏选择框_iphone自带Dock栏美化功能,你out了

在往期文章中一直在为大家分享iphone特效壁纸&#xff0c;很多小伙伴都有使用过&#xff0c;尤其是其中的隐藏Dock栏与Dock栏特效备受大家喜爱&#xff0c;纷纷转发现在网络上热度非常高&#xff0c;没有获取的小伙伴可以在本公众号会话框导航栏内点击功能然后选择特效壁纸进行…

安卓桌面壁纸_效仿安卓?iOS14或将支持“快应用” 功能 可玩性更强了

苹果将在6月份的WWDC大会上发布iOS14&#xff0c;而随着大会的临近&#xff0c;关于iOS14的消息也是时不时出现在大家面前。从泄露的iOS14测试版代码中可以看到即将到来的新功能&#xff0c;其中一个叫做Clips的API接口尤其受到关注。 这项功能接口为开发者提供&#xff0c;它允…

python27.dll是系统自带的吗_Windows 10自带6款超强工具!好用又免费!

01 免费激活微软Office软件 这算是系统自带吗&#xff1f;轩爸觉得算&#xff0c;很多时候我们购买的电脑&#xff0c;都是系统自带了免费微软Office软件哦&#xff01;可小伙伴们知道如何激活它吗&#xff1f; 以小米笔记本为例&#xff0c;小米笔记本全系以及RedmiBook机型预…

怎么把html变成桌面壁纸,怎么把抖音视频设置成桌面 抖音视频设置壁纸教程

想要把喜欢的抖音短视频设置成手机桌面壁纸吗&#xff0c;那怎么把抖音视频设置成桌面呢&#xff0c;这里带来抖音视频设置壁纸教程&#xff0c;图文攻略更易懂。 在抖音&#xff0c;当你遇到非常喜欢的短视频时&#xff0c;你肯定想把它保存下来&#xff0c;甚至设置成手机桌面…

用Applescript 实现自定义的动态壁纸

用Applescript 实现自定义的动态壁纸 1. 动态壁纸 Dynamic Wallpaper 讲到在苹果上整动态壁纸&#xff0c;就得先聊聊他自家的方案。最早苹果在macOS Mojave 里引入了这个概念&#xff0c;基于每天的不同时段去变化桌面的壁纸。其所用的技术是在设置壁纸时&#xff0c;用一个…