/*
* 态势标绘通用方法
*/
import {
calculateAngle,
transformCartesianToWGS84,
transformWGS84ToCartesian,
} from './Coordinate';
import xp from './algorithm';
const Cesium = window.Cesium;
/**
* 获取静态资源路径
* @param url 路径
* @returns
*/
export const getAssetsData = (url) => {
return new URL(`../assets/${url}`, import.meta.url).href;
};
/**
* 创建随机(唯一)ID
* @param num
* @returns
*/
const newSessionid = (num) => {
let len = num || 32;
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let maxPos = chars.length;
let pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
};
/**
* 锁定视图
* @param viewer - 三维场景
* @param bool - 是否锁定
*/
const lockingMap = (viewer, bool) => {
// 如果为真,则允许用户旋转相机。如果为假,相机将锁定到当前标题。此标志仅适用于2D和3D。
viewer.scene.screenSpaceCameraController.enableRotate = bool;
// 如果为true,则允许用户平移地图。如果为假,相机将保持锁定在当前位置。此标志仅适用于2D和Columbus视图模式。
viewer.scene.screenSpaceCameraController.enableTranslate = bool;
// 如果为真,允许用户放大和缩小。如果为假,相机将锁定到距离椭圆体的当前距离
viewer.scene.screenSpaceCameraController.enableZoom = bool;
// 如果为真,则允许用户倾斜相机。如果为假,相机将锁定到当前标题。这个标志只适用于3D和哥伦布视图。
viewer.scene.screenSpaceCameraController.enableTilt = bool;
};
/**
* 创建贝塞尔点集
* @param anchorpoints
* @returns
*/
const createBezierPoints = (anchorpoints=[]) => {
let degrees = [];
for (let index = 0; index < anchorpoints.length; index++) {
const degree = transformCartesianToWGS84(anchorpoints[index]);
degrees.push(degree);
}
let numpoints = 100;
let points = [];
for (let i = 0; i <= numpoints; i++) {
let point = computeBezierPoints(degrees, i / numpoints);
const cartesian = transformWGS84ToCartesian(point);
points.push(cartesian);
}
return points;
};
/**
* 创建正多边形节点
* @param centerPoint
* @param endCartesian
* @param num
* @returns
*/
const getRegularPoints = (centerPoint, endCartesian, num) => {
const centerP = transformCartesianToWGS84(centerPoint);
let distance = 1;
if (endCartesian) {
const endDegree = transformCartesianToWGS84(endCartesian);
distance = Cesium.Cartesian3.distance(
new Cesium.Cartesian3.fromDegrees(centerP.x, centerP.y, 0),
new Cesium.Cartesian3.fromDegrees(endDegree.x, endDegree.y, 0)
);
}
let ellipse = new Cesium.EllipseOutlineGeometry({
center: centerPoint,
semiMajorAxis: distance,
semiMinorAxis: distance,
granularity: 0.0001, //0~1 圆的弧度角,该值非常重要,默认值0.02,如果绘制性能下降,适当调高该值可以提高性能
});
let geometry = new Cesium.EllipseOutlineGeometry.createGeometry(ellipse);
let circlePoints = [];
let values = geometry.attributes.position.values;
if (!values) return;
let posNum = values.length / 3; //数组中以笛卡尔坐标进行存储(每3个值一个坐标)
for (let i = 0; i < posNum; i++) {
let curPos = new Cesium.Cartesian3(
values[i * 3],
values[i * 3 + 1],
values[i * 3 + 2]
);
circlePoints.push(curPos);
}
let resultPoints = [];
let pointsapart = Math.floor(circlePoints.length / num);
for (let j = 0; j < num; j++) {
resultPoints.push(circlePoints[j * pointsapart]);
}
return resultPoints;
};
/**
* 创建攻击箭头节点
* @param positions
* @returns
*/
const getAttackArrowPoints = (positions=[]) => {
let lnglatArr = [];
for (let i = 0; i < positions.length; i++) {
let lnglat = transformCartesianToWGS84(positions[i]);
lnglatArr.push([lnglat.x, lnglat.y]);
}
let res = xp.algorithm.tailedAttackArrow(lnglatArr);
let index = JSON.stringify(res.polygonalPoint).indexOf('null');
let points = [];
if (index == -1) points = res.polygonalPoint;
return points;
};
/**
* 创建直角箭头节点
* @param anchorpoints
* @returns
*/
const getRightAngleArrowPoints = (anchorpoints=[]) => {
let degreePoints = [];
for (let index = 0; index < anchorpoints.length; index++) {
const degree = transformCartesianToWGS84(anchorpoints[index]);
degreePoints.push(degree);
}
let pointlist = calculateMorePoints(degreePoints);
let degreesArray = [];
pointlist.forEach((item) => {
degreesArray.push(item.x, item.y);
});
return Cesium.Cartesian3.fromDegreesArray(degreesArray);
};
function calculateMorePoints(anchorpoints=[]) {
let ratio = 6;
let pointsR=[];
if (anchorpoints.length > 2) {
let l = 0,
w,
pointS,
pointE;
for (let i = 0; i < anchorpoints.length - 1; i++) {
pointS = anchorpoints[i]; //取出首尾两个点
pointE = anchorpoints[i + 1];
l += Math.sqrt(
(pointE.y - pointS.y) * (pointE.y - pointS.y) +
(pointE.x - pointS.x) * (pointE.x - pointS.x)
);
}
w = l / ratio;
let points_C_l = []; //定义左右控制点集合
let points_C_r = [];
let point_t_l = { x: undefined, y: undefined }; //定义尾部左右的起始点
let point_t_r = { x: undefined, y: undefined };
//计算中间的所有交点
for (let j = 0; j < anchorpoints.length - 2; j++) {
let pointU_1 = anchorpoints[j]; //第一个用户传入的点
let pointU_2 = anchorpoints[j + 1]; //第二个用户传入的点
let pointU_3 = anchorpoints[j + 2]; //第三个用户传入的点
//计算向量
let v_U_1_2 = { x: pointU_2.x - pointU_1.x, y: pointU_2.y - pointU_1.y };
let v_U_2_3 = { x: pointU_3.x - pointU_2.x, y: pointU_3.y - pointU_2.y };
let v_lr_1_2 = calculateVector(v_U_1_2, Math.PI / 2, w / 2);
let v_l_1_2 = v_lr_1_2[0];
let v_r_1_2 = v_lr_1_2[1];
let v_lr_2_3 = calculateVector(v_U_2_3, Math.PI / 2, w / 2);
let v_l_2_3 = v_lr_2_3[0];
let v_r_2_3 = v_lr_2_3[1];
//获取左右
let point_l_1 = { x: pointU_1.x + v_l_1_2.x, y: pointU_1.y + v_l_1_2.y };
let point_r_1 = { x: pointU_1.x + v_r_1_2.x, y: pointU_1.y + v_r_1_2.y };
let point_l_2 = { x: pointU_2.x + v_l_2_3.x, y: pointU_2.y + v_l_2_3.y };
let point_r_2 = { x: pointU_2.x + v_r_2_3.x, y: pointU_2.y + v_r_2_3.y };
//向量v_U_1_2和向量v-point_l_1和point_r_1是平行的
//如果向量a=(x1,y1),b=(x2,y2),则a//b等价于x1y2-x2y1=0
//得到(x-point_l_1.x)*v_U_1_2.y=v_U_1_2.x*(y-point_l_1.y)
//得到(point_l_2.x-x)*v_U_2_3.y=v_U_2_3.x*(point_l_2.y-y)
//可以求出坐边的交点(x,y),即控制点
let point_C_l = calculateIntersection(
v_U_1_2,
v_U_2_3,
point_l_1,
point_l_2
);
let point_C_r = calculateIntersection(
v_U_1_2,
v_U_2_3,
point_r_1,
point_r_2
);
//定义中间的控制点
let point_C_l_c;
let point_C_r_c;
if (j == 0) {
//记录下箭头尾部的左右两个端点
point_t_l = point_l_1;
point_t_r = point_r_1;
//计算第一个曲线控制点