import * as Cesium from 'cesium' import { MapTooltip } from './MapTooltip' import { DrawPolygon } from './DrawPolygon' /** * 飞到中心点并且所有点在可视范围 * @param positionsData 二维数组,每项为 [lon, lat] 或 三维数组 [lon, lat, height] * @param viewer Cesium.Viewer 实例 * @param multiple 缩放倍数-默认为4 * @param pitch 俯仰角-默认为-90 */ function flyVisual({ positionsData, viewer, multiple = 4, pitch = -90 }) { if (!Array.isArray(positionsData) || positionsData.length === 0) return // 如果是一个点,加两个点方便后续生成外包围盒 if (positionsData.length === 1) { const [lon, lat, height = 0] = positionsData[0] positionsData = [ [lon + 0.001, lat + 0.001, height], [lon - 0.001, lat - 0.001, height], [lon, lat, height], ] } const positions = positionsData.map(([lon, lat, height = 0]) => Cesium.Cartesian3.fromDegrees(Number(lon), Number(lat), Number(height || 0)) ) // 计算最高高度和中心点经纬度 let maxHeight = -Infinity let sumLon = 0, sumLat = 0 for (const [lon, lat, height] of positionsData) { sumLon += Number(lon) sumLat += Number(lat) maxHeight = Math.max(maxHeight, Number(height || 0)) } const centerLon = sumLon / positionsData.length const centerLat = sumLat / positionsData.length const boundingSphere = Cesium.BoundingSphere.fromPoints(positions) // 暂时飞向 BoundingSphere viewer.camera.flyToBoundingSphere(Cesium.BoundingSphere.fromPoints(positions), { duration: 0, offset: { heading: Cesium.Math.toRadians(0), pitch: Cesium.Math.toRadians(pitch), range: boundingSphere.radius * multiple, }, complete: () => { // 飞行完成后检查相机高度是否小于最高点 const cameraHeight = Cesium.Cartographic.fromCartesian(viewer.camera.position).height if (cameraHeight < maxHeight) { viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(centerLon, centerLat, maxHeight + 100), // 加100米缓冲 duration: 1.5, orientation: { heading: viewer.camera.heading, pitch: viewer.camera.pitch, roll: viewer.camera.roll, }, }) } }, }) } // 批量获取点数组经纬度对应高度信息 const getPointPositionsHeight = (data, viewer, droneHeight = null) => { return new Promise((resolve, reject) => { if (!data || !data.length) { resolve([]) return } // 假设 viewer 已经初始化并且 terrainProvider 是有效的 const terrainProvider = viewer?.terrainProvider // 创建 Cartographic 对象 const cartographics = data.map(item => { const { lng, lat } = item return Cesium.Cartographic.fromDegrees(Number(lng), Number(lat)) }) // 获取地形数据的Promise const promise = Cesium.sampleTerrainMostDetailed(terrainProvider, cartographics) // 使用 Cesium.when 处理 Promise promise .then(function (updatedPositions) { // 是一个数组,包含更新后的 Cartographic 对象 const newPosition = updatedPositions.map((item, index) => { const longitude = Cesium.Math.toDegrees(item.longitude) const latitude = Cesium.Math.toDegrees(item.latitude) let pointData = { ...data[index], longitude, latitude, ASL: Number(item.height), customHeight: Number(item.height), } if (droneHeight) pointData.TH = Number(item.height) + Number(droneHeight) return pointData }) resolve(newPosition) }) .catch(function (error) { console.log('获取高程时发生错误:', error) resolve(data.map(item => ({ ...item, ASL: 0, customHeight: 0, longitude: item.lng, latitude: item.lat }))) }) }) } export { MapTooltip, flyVisual, getPointPositionsHeight, DrawPolygon }