/* * @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 } } /** * 添加蓝色滤镜 * @param options * @param viewer * @param layer */ export const addBlueFilter = (options, viewer, layer) => { if (layer){ layer.brightness = 0.6 // 亮度(默认值) layer.contrast = 1.8 // 对比度(负值降低对比度) layer.hue = 1 // 色相(弧度值,3.0可能导致紫色) layer.saturation = 0 // 增加饱和度强化蓝色 layer.gamma = 0.3 // 伽马校正(小于1.0使颜色更鲜艳) } const { bInvertColor, bFilterColor, filterColor } = options const color = new Cesium.Color.fromCssColorString(filterColor) const filterRGB = [ Math.round(color.red * 255), Math.round(color.green * 255), Math.round(color.blue * 255) ] let fragShader = viewer.scene.globe._surfaceShaderSet.baseFragmentShaderSource.sources for (let i = 0; i < fragShader.length; i++) { const strS = 'color = czm_saturation(color, textureSaturation);\n#endif\n' let strT = 'color = czm_saturation(color, textureSaturation);\n#endif\n' if (bInvertColor) { strT += ` color.r = 1.0 - color.r; color.g = 1.0 - color.g; color.b = 1.0 - color.b; ` } if (bFilterColor) { strT += ` color.r = color.r * ${filterRGB[0]}.0/255.0; color.g = color.g * ${filterRGB[1]}.0/255.0; color.b = color.b * ${filterRGB[2]}.0/255.0; ` } fragShader[i] = fragShader[i].replace(strS, strT) } }