/*
|
* @Author: GuLiMmo 2820890765@qq.com
|
* @Date: 2024-03-22 14:17:13
|
* @LastEditors: GuLiMmo 2820890765@qq.com
|
* @LastEditTime: 2024-04-17 11:12:20
|
* @FilePath: /bigScreen/src/utils/cesium/common.js
|
* @Description:
|
*/
|
import * as Cesium from 'cesium';
|
import JsZip from 'jszip';
|
import _ from 'lodash';
|
import axios from 'axios';
|
import { analyzeKmzFile, XMLToJSON } from './kmz';
|
import { getCenterPoint, getLnglatDist, getShortestDistance } from './mapUtil';
|
|
// 图斑航线计算
|
export const polygonRoutePlanning = (polygonList, startPostion) => {
|
// 起始点位
|
const { longitude, latitude } = startPostion;
|
// 计算中心点
|
const polygonCenterArr = polygonList.map((polygon) => {
|
const newPolygon = [
|
...new Set(polygon.map((lnglat) => lnglat.join(','))),
|
];
|
return {
|
center: getCenterPoint(polygon),
|
polygon: newPolygon.map((item) => item.split(',')),
|
};
|
});
|
// 机场到中心点的距离排序
|
const airportDistanceArr = polygonCenterArr.sort((prev, next) => {
|
const prevDistance = getLnglatDist(
|
longitude,
|
latitude,
|
prev.center.lng,
|
prev.center.lat,
|
);
|
const nextDistance = getLnglatDist(
|
longitude,
|
latitude,
|
next.center.lng,
|
next.center.lat,
|
);
|
return prevDistance - nextDistance;
|
});
|
|
const sortPolygon = [];
|
function getFirstPolygon(arr, start) {
|
const { slongitude, slatitude } = start;
|
// 机场到中心点的距离排序
|
const airportDistanceArr = arr.sort((prev, next) => {
|
const prevDistance = getLnglatDist(
|
slongitude,
|
slatitude,
|
prev.center.lng,
|
prev.center.lat,
|
);
|
const nextDistance = getLnglatDist(
|
slongitude,
|
slatitude,
|
next.center.lng,
|
next.center.lat,
|
);
|
return prevDistance - nextDistance;
|
});
|
const polygon = _.cloneDeep(airportDistanceArr[0]);
|
if (polygon === void 0) return;
|
sortPolygon.push(polygon);
|
airportDistanceArr.splice(0, 1);
|
if (airportDistanceArr.length > 0) {
|
getFirstPolygon(airportDistanceArr, {
|
slongitude: polygon.center.lng,
|
slatitude: polygon.center.lat,
|
});
|
}
|
}
|
getFirstPolygon(polygonCenterArr, {
|
slongitude: longitude,
|
slatitude: latitude,
|
});
|
// 计算图斑内点位飞行顺序
|
let result = [[longitude, latitude]];
|
sortPolygon.forEach((item, index) => {
|
const { polygon } = item;
|
// 取出当前图斑之前最后一个点
|
const prevPolygon = result[result.length - 1];
|
const [slng, slat] = prevPolygon;
|
const nextPolygon = airportDistanceArr[index + 1];
|
// 求出距离上一个点最近的点,作为第一个点
|
const sequence = polygon.sort((prev, next) => {
|
const [prevLng, prevLat] = prev;
|
const [nextLng, nextLat] = next;
|
const prevDistance = getLnglatDist(slng, slat, prevLng, prevLat);
|
const nextDistance = getLnglatDist(slng, slat, nextLng, nextLat);
|
return prevDistance - nextDistance;
|
});
|
// 第一个点位
|
const firstLnglat = [...sequence[0]];
|
// 去除第一个点位
|
const cloneSequence = _.cloneDeep(sequence);
|
cloneSequence.splice(0, 1);
|
if (nextPolygon) {
|
// 获取两个经纬度组两个最近的点位
|
const { index: lnglatIndex } = getShortestDistance(
|
cloneSequence,
|
nextPolygon.polygon,
|
);
|
const lastLnglat = _.cloneDeep(cloneSequence[lnglatIndex[0]]);
|
// 删除飞行的最后一个点
|
cloneSequence.splice(lnglatIndex[0], 1);
|
const centerLnglatList = cloneSequence.sort((prev, next) => {
|
const [prevLng, prevLat] = prev;
|
const [nextLng, nextLat] = next;
|
const prevDistance = getLnglatDist(
|
longitude,
|
latitude,
|
prevLng,
|
prevLat,
|
);
|
const nextDistance = getLnglatDist(
|
longitude,
|
latitude,
|
nextLng,
|
nextLat,
|
);
|
return prevDistance - nextDistance;
|
});
|
result = [...result, firstLnglat, ...centerLnglatList, lastLnglat];
|
} else {
|
// const last = polygon.sort((prev, next) => {
|
// const [prevLng, prevLat] = prev;
|
// const [nextLng, nextLat] = next;
|
// const prevDistance = getLnglatDist(longitude, latitude, prevLng, prevLat);
|
// const nextDistance = getLnglatDist(longitude, latitude, nextLng, nextLat);
|
// return prevDistance - nextDistance;
|
// });
|
result = [...result, ...sequence];
|
// result = [...result, ...last]
|
}
|
});
|
return result;
|
};
|
|
export const getWaylineFilePoints = async (fileUrl) => {
|
const fileRes = await analyzeKmzFile(fileUrl);
|
const waylineContent = await fileRes['fileInfoObj']?.['wpmz/waylines.wpml'];
|
const xml = XMLToJSON(waylineContent);
|
const placemarkArr = xml?.Document?.Folder.Placemark;
|
const points = placemarkArr.map((placemark) => {
|
const lnglat = placemark.Point.coordinates?.['#text'].split(',');
|
return {
|
longitude: lnglat[0],
|
latitude: lnglat[1],
|
};
|
});
|
return points;
|
};
|
|
// 传入方向,计算移动点位经纬度
|
export function movePosition(lon, lat, heading, direction) {
|
// 计算朝向角度的弧度值(Cesium 是基于地理坐标系,heading=0 指向正北)
|
const headingRad = Cesium.Math.toRadians(heading);
|
const moveStep = 0.00005; // 移动步长
|
let newLon = lon;
|
let newLat = lat;
|
|
switch (direction) {
|
case "W": // 向前(heading 方向)
|
newLon += moveStep * Math.sin(headingRad);
|
newLat += moveStep * Math.cos(headingRad);
|
break;
|
|
case "S": // 向后(反方向)
|
newLon -= moveStep * Math.sin(headingRad);
|
newLat -= moveStep * Math.cos(headingRad);
|
break;
|
|
case "D": // 向右(heading + 90°)
|
newLon += moveStep * Math.cos(headingRad);
|
newLat -= moveStep * Math.sin(headingRad);
|
break;
|
|
case "A": // 向左(heading - 90°)
|
newLon -= moveStep * Math.cos(headingRad);
|
newLat += moveStep * Math.sin(headingRad);
|
break;
|
|
default:
|
console.warn("无效方向");
|
return null;
|
}
|
|
return { longitude: newLon, latitude: newLat };
|
}
|