import { config } from "../../../../../config"; const { Cesium } = window; export function getPolygonHierarchy(geom) { if (typeof geom === 'string') { try { geom = JSON.parse(geom); } catch (e) { return null; } } const type = geom.type; let polygons = []; if (type === 'Polygon') { polygons.push(geom.coordinates); } else if (type === 'MultiPolygon') { polygons = geom.coordinates; } else if (type === 'LineString' || type === 'Ring') { polygons.push([geom.coordinates]); } else if (type === 'MultiLineString') { for (const item of geom.coordinates) { polygons.push([item]); } } if (polygons.length === 0) { return null; } const ret = []; for (const lines of polygons) { let positions = null; const holes = []; for (const linedata of lines) { const coordarr = []; for (const curpt of linedata) { const h = curpt[2] ? curpt[2] : 0; coordarr.push(curpt[0], curpt[1], h); } if (!positions) { positions = Cesium.Cartesian3.fromDegreesArrayHeights(coordarr); } else { holes.push({ positions: Cesium.Cartesian3.fromDegreesArrayHeights(coordarr), }); } } if (!positions) { return null; } let hierarchy; if (holes.length === 0) { hierarchy = positions; } else { hierarchy = { positions, holes, }; } ret.push(hierarchy); } return ret; } //根据经纬度和zoom获取相机位置 export function getCameraViewPosition(mapCenter) { const verticalHeight = zoomToHeight(mapCenter.zoom)//相机垂直高度 const lon = mapCenter.center[0] const lat = mapCenter.center[1] const pitchRad = Cesium.Math.toRadians(config.pitch3d);//相机俯仰角 const distance = verticalHeight / Math.abs(Math.sin(pitchRad)); // 2. 计算水平后退距离(朝向0度,所以后退方向是正南) const horizontalDistance = distance * Math.cos(Math.abs(pitchRad)); // 3. 计算相机在目标点ENU坐标系中的偏移 // 朝向0度时:东偏移=0,北偏移=-水平距离(向南),上偏移=高度 const eastOffset = 0; const northOffset = -horizontalDistance; // 向南 const upOffset = distance * Math.sin(Math.abs(pitchRad)); // 4. 将偏移应用到目标点 const targetCartesian = Cesium.Cartesian3.fromDegrees(lon, lat, 0); const transform = Cesium.Transforms.eastNorthUpToFixedFrame(targetCartesian); const destination = Cesium.Matrix4.multiplyByPoint( transform, new Cesium.Cartesian3(eastOffset, northOffset, upOffset), new Cesium.Cartesian3() ); return destination } //获取摄像机焦点经纬度和高度 export function getCameraViewCenter(viewer) { // 1. 获取屏幕中心点的射线(从相机到屏幕中心) const ray = viewer.camera.getPickRay(new Cesium.Cartesian2( viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2 )); // 2. 计算射线与地球表面的交点 const intersection = viewer.scene.globe.pick(ray, viewer.scene); if (intersection) { // 如果有交点(看向地球) const cartographic = Cesium.Cartographic.fromCartesian(intersection); return { lon: Cesium.Math.toDegrees(cartographic.longitude), lat: Cesium.Math.toDegrees(cartographic.latitude), height: heigjtToZoom(viewer.camera.positionCartographic.height)//cartographic.height }; } else { // 如果看向天空或太空,获取射线与椭球体的交点 const ellipsoid = viewer.scene.globe.ellipsoid; const intersection2 = viewer.scene.camera.pickEllipsoid( new Cesium.Cartesian2( viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2 ), ellipsoid ); if (intersection2) { const cartographic = Cesium.Cartographic.fromCartesian(intersection2); return { lon: Cesium.Math.toDegrees(cartographic.longitude), lat: Cesium.Cartographic.toDegrees(cartographic.latitude), height: 0 }; } } } /** * 获取屏幕中心点对准的地球表面点与摄像机之间的距离 * @param {Cesium.Viewer} viewer - Cesium的Viewer对象 * @returns {number|null} 距离(单位:米),如果中心点不在地球表面则返回null */ export function getDistanceFromCameraToCenterFocus(viewer) { // 获取屏幕中心点(Canvas的中心坐标) const canvas = viewer.canvas; const centerX = canvas.clientWidth / 2; const centerY = canvas.clientHeight / 2; // 获取屏幕中心点的三维射线 const ray = viewer.camera.getPickRay(new Cesium.Cartesian2(centerX, centerY)); if (!ray) { console.warn('无法获取屏幕中心点的射线'); return null; } // 计算射线与地球椭球体的交点 const ellipsoid = viewer.scene.globe.ellipsoid; const intersection = Cesium.IntersectionTests.rayEllipsoid(ray, ellipsoid); if (!intersection) { // 如果中心点没有对准地球(如指向天空),则尝试获取地形上的点 try { const centerPosition = viewer.scene.pickPosition(new Cesium.Cartesian2(centerX, centerY)); if (centerPosition) { const cameraPosition = viewer.camera.positionWC; return Cesium.Cartesian3.distance(cameraPosition, centerPosition); } } catch (error) { console.warn('无法获取屏幕中心点对应的地形位置'); return null; } return null; } // 获取交点坐标 const intersectionPoint = Cesium.Ray.getPoint(ray, intersection.start); // 获取相机位置(世界坐标) const cameraPosition = viewer.camera.positionWC; // 计算相机位置与交点之间的距离 const distance = Cesium.Cartesian3.distance(cameraPosition, intersectionPoint); return distance; } //openlayers的zoom转cesium的摄像机height export function zoomToHeight(olZoom) { return (120000000 / Math.pow(2, olZoom))+400 } //cesium的摄像机height转openlayers的zoom export function heigjtToZoom(height) { return Math.max(0, Math.min(28, Math.log2(120000000 / (height - 400) ))) }