import { Cesium } from '../../namespace'
/**
* 地图场景相关方法集
* @module Screen
*/
/**
* 返回点集的范围,默认弧度:[west, south, east, north]
* @method
* @param {Array<Cartesian3>} points 点集,笛卡尔坐标
* @param {Boolean} degrees 是否返回值为经纬度,true-返回值为经纬度值;false-返回值为弧度值
* @returns {Array<Number>} 四至范围 => [west, south, east, north]
*/
export const getExtent = (points, degrees) => {
let west = 100000000
let south = 100000000
let east = -100000000
let north = -100000000
for (let i = 0; i < points.length; i++) {
const cartographic = Cesium.Cartographic.fromCartesian(points[i])
const { longitude, latitude } = cartographic
west = Math.min(longitude, west)
south = Math.min(latitude, south)
east = Math.max(longitude, east)
north = Math.max(latitude, north)
}
if (degrees) {
west = Cesium.Math.toDegrees(west)
south = Cesium.Math.toDegrees(south)
east = Cesium.Math.toDegrees(east)
north = Cesium.Math.toDegrees(north)
}
return [west, south, east, north]
}
// 获取中心点
export function getCenter(viewer) {
const scene = viewer.scene
const target = pickCenterPoint(scene)
let bestTarget = target
const globe = scene.globe
const cartographic = scene.camera.positionCartographic.clone()
const height = globe.getHeight(cartographic)
cartographic.height = height || 0
bestTarget = Cesium.Ellipsoid.WGS84.cartographicToCartesian(cartographic)
const result = formatPosition(bestTarget)
// 获取地球中心点世界位置 与 摄像机的世界位置 之间的距离
const distance = Cesium.Cartesian3.distance(
bestTarget,
scene.camera.positionWC
)
result.cameraZ = distance
return result
}
function pickCenterPoint(scene) {
const canvas = scene.canvas
const center = new Cesium.Cartesian2(
canvas.clientWidth / 2,
canvas.clientHeight / 2
)
const ray = scene.camera.getPickRay(center)
const target = scene.globe.pick(ray, scene)
return target || scene.camera.pickEllipsoid(center)
}
function formatPosition(position) {
const cartographic = Cesium.Cartographic.fromCartesian(position)
const result = {}
result.y = formatNum(Cesium.Math.toDegrees(cartographic.latitude), 6)
result.x = formatNum(Cesium.Math.toDegrees(cartographic.longitude), 6)
result.z = formatNum(cartographic.height, 2)
return result
}
function formatNum(num, digits) {
return Number(num.toFixed(digits || 0))
}
function getScreenCenter(viewer) {
const result = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
viewer.canvas.clientWidth / 2,
viewer.canvas.clientHeight / 2
)
)
const curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result)
const lon = (curPosition.longitude * 180) / Math.PI
const lat = (curPosition.latitude * 180) / Math.PI
return { x: lon, y: lat }
}
// 切换场景模式
export function changeSV23D(viewer, type) {
const result = getCenter(viewer)
const curPosition = getScreenCenter(viewer)
const center = Cesium.Cartesian3.fromDegrees(curPosition.x, curPosition.y)
if (type === 'sceneView') {
viewer.scene.screenSpaceCameraController.enableTilt = true
let x = -90
let pitch
const handle3d = () => {
x += 1
pitch = viewer.camera.pitch
if (pitch < -0.6981317007977318) {
tilesTransform(viewer, getNavigationCenter(viewer), true)
} else {
viewer.scene.preUpdate.removeEventListener(handle3d)
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
}
}
viewer.scene.preUpdate.addEventListener(handle3d)
} else {
let pitch
let x = -Cesium.Math.toDegrees(Math.abs(viewer.camera.pitch))
const handle2d = () => {
x -= 1
pitch = viewer.camera.pitch
if (pitch > -1.5533430342749532) {
tilesTransform(viewer, getNavigationCenter(viewer), false)
} else {
const result = getCenter(viewer)
viewer.scene.preUpdate.removeEventListener(handle2d)
viewer.camera.lookAt(
center,
new Cesium.HeadingPitchRange(0, pitch, result.cameraZ)
)
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
viewer.scene.screenSpaceCameraController.enableTilt = false
}
}
viewer.scene.preUpdate.addEventListener(handle2d)
}
}
function tilesTransform(viewer, cartesian0, isUp) {
const camera = viewer.scene.camera
const mag = Cesium.Cartesian3.magnitude(cartesian0)
const radii = Cesium.Cartesian3.fromElements(
mag,
mag,
mag,
new Cesium.Cartesian3()
)
const newEllipsoid = Cesium.Ellipsoid.fromCartesian3(
radii,
new Cesium.Ellipsoid()
)
viewer.scene._screenSpaceCameraController._rotateFactor = 1.0
viewer.scene._screenSpaceCameraController._rotateRateRangeAdjustment = 1.0
camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z
const oldTransform = Cesium.Matrix4.clone(
camera.transform,
new Cesium.Matrix4()
)
const verticalTransform = Cesium.Transforms.eastNorthUpToFixedFrame(
cartesian0,
newEllipsoid,
new Cesium.Matrix4()
)
camera._setTransform(verticalTransform)
if (isUp) {
camera.rotateUp(camera.pitch > -0.4 ? 0 : 0.05)
} else {
camera.rotateDown(0.05)
}
camera._setTransform(oldTransform)
}
function getNavigationCenter(viewer) {
const scene = viewer.scene
//获取地图导航操作中心
const x = scene.canvas.clientWidth / 2
const y = scene.canvas.clientHeight / 2
const pick1 = new Cesium.Cartesian2(x, y)
const ray = scene.camera.getPickRay(pick1)
const cartesian0 = scene.globe.pick(ray, scene)
return cartesian0
}