我们使用 CesiumJS 作为“球面几何”应用程序中的覆盖层,它以已知大小(以像素为单位)渲染自己的球体,并且用户可以放大/缩小以更改其大小。 我们希望将 CesiumJS 添加为应用程序中的另一层,并渲染地球仪以匹配应用程序球体的大小。 在下面的屏幕显示中,红色圆圈是我们的球体(半径已知,以像素为单位,地球由CesiumJS渲染)
我们能够使用相机平截头体计算地球在相机投影平面上的投影尺寸(以像素为单位):
const frustum = camera.frustum as PerspectiveFrustum;
// Compute the projected area of a pixel at the globe XY-plane?
const pixelDimensions = frustum.getPixelDimensions(
scene.drawingBufferWidth,
scene.drawingBufferHeight,
camera.getMagnitude(), // distance of the camera from the projection plane?
(scene as any).pixelRatio,
tmpCartesian2
);
const globeRadius = CESIUM_GLOBE_RADIUS_IN_METERS / pixelDimensions.y
了解更多背景
CESIUM_GLOBE_RADIUS_IN_METERS
getPixelDimensions()
我们怀疑我们在第三个参数中提供了错误的值,但我们不知道在这里传递什么更好的值。
camera.getMagnitude()
给出了到地球中心的距离(当视图以地球为中心时,像这样),但是,您要寻找的是地球的可见边缘(而不是中间部分)地球)从那个角度来看。
看一下上面缩小的图片。您可以看到整个沙特阿拉伯,被红海(在其西边)和波斯湾(在其东边)包围,以及更东边的一些土地。但现在看一下放大的图片,是从相同的有利位置但更靠近地球拍摄的。波斯湾几乎消失在地平线上,但相机实际上离它更近了。随着相机靠近地球,可见地平线(地球的明显边缘)会发生变化。低空透视相机无法在曲率周围看到那么远的距离。从这些较低的高度,相机无法看到地球的整个半球。
不幸的是,这意味着您的距离和半径都不正确。地球的整个半径隐藏在靠近相机的部分后面。该相机可见的地平线在距离较近时半径较小。
要使其成为 2D 问题,请在圆附近绘制一个点,然后从连接该点的圆绘制切线。您需要计算这些切线与圆的接触位置,而不仅仅是圆的中间。