ss-dp/src/views/Home/MapCtrl/M3D/utils/cesutil.js

196 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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) )))
}