/* * @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 }; }