Cesium中用到的图形技术——Computing the horizon occlusion point

本文详细介绍了如何计算地形瓦片在椭球体遮挡下的地平线遮挡点,涉及几何、三角函数和坐标变换。通过计算特定角度的三角函数值,可以确定地形瓦片顶点的地平线遮挡点,从而判断其是否被遮挡。这种方法适用于静态几何体,但对变化的几何体则需要反复计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

译者注:本文翻译自Cesium官方博文《Computing the horizon occlusion point》,by KEVIN RING。

你厌倦了地平线剔除吗? 太好了,我也没有!

上一次,我们解释了地平线剔除是关于什么的,并展示了一种非常有效的方法来测试一个点是否被椭圆体遮挡。然而,我们想要测试遮挡的对象很少是简单的点。特别是,我们希望能够测试地形瓦片是否被椭球体遮挡。但是地形瓦片是由数千个顶点组成的复杂对象。

Deron Ohlarik在上一篇博客文章中谈到了此问题,他解释说,对于任何任意几何图形,我们都可以计算与几何图形有特殊关系的点的位置(我们称为水平遮挡点)。无论观察者从哪个方向接近几何体,该点都会同时或在几何体的任何部分变为可见之前对观察者可见。这正是我们所需要的!但是,如何计算这样的点的许多细节留给读者练习。此外,还不清楚这种方法是否可以推广到椭球而不是球体。该博客旨在填补这两个空白。

再次,这里介绍的技术完全归功于Frank Stoner。

让我们来看看我们的情况。和以前一样,我们通过将每个分量 X、Y和Z乘以沿该轴的椭球半径的倒数,将所有坐标转换到椭球尺度空间。

imglink0

在此图中,地球以蓝色显示,地形图块以棕色显示。在尺度空间中,地球是一个单位球体。围绕地形图块的边界球的中心显示为点C。边界球不是缩放空间中的球体,但这与我们无关,因为我们将只使用它的中心。

首先,我们任意决定我们的地平线遮挡点将位于这条中心线OC的某个位置,OC是从地球中心到地形图块边界球中心的向量。我们只需要计算它沿该向量的距离。点V是地形图块中的一个顶点。点H是从V的角度看地平线上的一个点。从V的角度看,有无数个地平线点,在单位球面上形成一个圆,但这些地平线点中只有两个点通过V形成一个向量,或与中心线相交。一个显示为实线HP。另一个显示为连接到V为虚线。在虚线上,与中心线的交点出现在点V之前,所以它会比另一个交点更靠近椭球的中心,我们不需要关心它。如果点V是地形图块中的唯一顶点,那么此图中的点P将是我们的地平线遮挡点。对于多个顶点,我们对每个顶点重复 P 的计算,然后选择离椭圆体最远的那个。

那么我们如何计算给定地形瓦片顶点的P点呢?让我们标记下图中的各个角度。

imglink1

在标记角α和β之后,通过简单的三角形角的知识,我们可以通过他们表达其他的角。

接下来,根据正弦定律:
∥ O P ⃗ ∥ s i n ( 90 + β ) = ∥ O V ⃗ ∥ s i n ( 90 − ( α + β ) ) \frac{\lVert \vec{OP} \rVert }{sin(90+β)} = \frac{\lVert \vec{OV} \rVert}{sin(90-(α+β))} sin(90+β)OP =sin(90(α+β))OV

根据三角函数 s i n ( 90 + θ ) = c o s ( θ ) sin(90+θ) = cos(θ) sin(90+θ)=cos(θ),有:
∥ O P ⃗ ∥ c o s ( β ) = ∥ O V ⃗ ∥ c o s ( α + β ) \frac{\lVert \vec{OP} \rVert }{cos(β)} = \frac{\lVert \vec{OV} \rVert}{cos(α+β)} cos(β)OP =cos(α+β)OV

∥ O P ⃗ ∥ = ∥ O V ⃗ ∥ c o s ( β ) c o s ( α + β ) \lVert \vec{OP} \rVert = \frac{\lVert \vec{OV} \rVert cos(β)}{cos(α+β)} OP =cos(α+β)OV cos(β)

β是直角三角形中的角,因此有:
c o s ( β ) = ∥ O H ⃗ ∥ ∥ O V ⃗ ∥ = 1 ∥ O V ⃗ ∥ cos(β) = \frac{\lVert \vec{OH} \rVert}{\lVert \vec{OV} \rVert} = \frac{1}{\lVert \vec{OV} \rVert} cos(β)=OV OH =OV 1

∥ O P ⃗ ∥ = ∥ O V ⃗ ∥ 1 ∥ O V ⃗ ∥ c o s ( α + β ) \lVert \vec{OP} \rVert = \frac{\lVert \vec{OV} \rVert \frac{1}{\lVert \vec{OV} \rVert}}{cos(α+β)} OP =cos(α+β)OV OV 1

∥ O P ⃗ ∥ = 1 c o s ( α + β ) \lVert \vec{OP} \rVert = \frac{1}{cos(α+β)} OP =cos(α+β)1

然后,我们使用复合角公式:
c o s ( α + β ) = c o s ( α ) c o s ( β ) − s i n ( α ) s i n ( β ) cos(α+β) = cos(α)cos(β) - sin(α)sin(β) cos(α+β)=cos(α)cos(β)sin(α)sin(β)

∥ O P ⃗ ∥ = 1 c o s ( α ) c o s ( β ) − s i n ( α ) s i n ( β ) \lVert \vec{OP} \rVert = \frac{1}{cos(α)cos(β) - sin(α)sin(β)} OP =cos(α)cos(β)sin(α)sin(β)1

我们已经知道如何去计算 c o s ( β ) cos(β) cos(β)。同样通过勾股定理,我们能计算 s i n ( β ) sin(β) sin(β)
s i n ( β ) = ∥ H V ⃗ ∥ ∥ O V ⃗ ∥ sin(β) = \frac{\lVert \vec{HV} \rVert}{\lVert \vec{OV} \rVert} sin(β)=OV HV
∥ H V ⃗ ∥ = ∥ O V ⃗ ∥ 2 − ∥ O H ⃗ ∥ 2 = ∥ O V ⃗ ∥ 2 − 1 \lVert \vec{HV} \rVert = \sqrt{\lVert \vec{OV} \rVert^2-\lVert \vec{OH} \rVert^2} = \sqrt{\lVert \vec{OV} \rVert^2-1} HV =OV 2OH 2 =OV 21
s i n ( β ) = ∥ O V ⃗ ∥ 2 − 1 ∥ O V ⃗ ∥ sin(β) = \frac{\sqrt{\lVert \vec{OV} \rVert^2-1}}{\lVert \vec{OV} \rVert} sin(β)=OV OV 21

通过点积的定义,我们能够计算 c o s ( α ) cos(α) cos(α)
O V ⃗ ⋅ O P ^ = ∥ O V ⃗ ∥ c o s ( α ) \vec{OV} \cdot \hat{OP} = \lVert \vec{OV} \rVert cos(α) OV OP^=OV cos(α)

c o s ( α ) = O V ⃗ ⋅ O P ^ ∥ O V ⃗ ∥ cos(α) = \frac { \vec{OV} \cdot \hat{OP} } {\lVert \vec{OV} \rVert} cos(α)=OV OV OP^

c o s ( α ) = O V ^ ⋅ O P ^ cos(α) = \hat{OV} \cdot \hat{OP} cos(α)=OV^OP^

最后,通过矢量叉积的模,我们能够计算 s i n ( α ) sin(α) sin(α)
∥ O P ^ × O V ⃗ ∥ = ∥ O V ⃗ ∥ s i n ( α ) \lVert \hat{OP} \times \vec{OV} \rVert = \lVert \vec{OV} \rVert sin(α) OP^×OV =OV sin(α)

s i n ( α ) = ∥ O P ^ × O V ^ ∥ sin(α) = \lVert \hat{OP} \times \hat{OV} \rVert sin(α)=OP^×OV^

通过以上的计算,我们就能够计算 O P OP OP的模了。汇总如下:

c o s ( β ) = 1 ∥ O V ⃗ ∥ cos(β) = \frac{1}{\lVert \vec{OV} \rVert} cos(β)=OV 1

s i n ( β ) = ∥ O V ⃗ ∥ 2 − 1 ∥ O V ⃗ ∥ sin(β) = \frac{\sqrt{\lVert \vec{OV} \rVert^2-1}}{\lVert \vec{OV} \rVert} sin(β)=OV OV 21

c o s ( α ) = O V ^ ⋅ O P ^ cos(α) = \hat{OV} \cdot \hat{OP} cos(α)=OV^OP^

s i n ( α ) = ∥ O P ^ × O V ^ ∥ sin(α) = \lVert \hat{OP} \times \hat{OV} \rVert sin(α)=OP^×OV^

∥ O P ⃗ ∥ = 1 c o s ( α ) c o s ( β ) − s i n ( α ) s i n ( β ) \lVert \vec{OP} \rVert = \frac{1}{cos(α)cos(β) - sin(α)sin(β)} OP =cos(α)cos(β)sin(α)sin(β)1

请记住,我们通过构造了解 O P ^ \hat{OP} OP^;我们选择它从椭圆体的中心指向地形图块的边界球体的中心。为了计算点P在椭球尺度空间中的位置,我们简单地将方向乘以上面计算的模。由于我们的遮挡测试使用缩放空间中表示的点,因此我们完成了。如果我们还想知道真实、未密封坐标中的位置,我们只需要将位置的每个分量乘以沿相应轴的椭球半径。

下面是 Cesium 中的代码,为了清晰起见略作调整:

function computeMagnitude(ellipsoid, position, scaledSpaceDirectionToPoint) {
    var scaledSpacePosition = ellipsoid.transformPositionToScaledSpace(position);
    var magnitudeSquared = scaledSpacePosition.magnitudeSquared();
    var magnitude = Math.sqrt(magnitudeSquared);
    var direction = scaledSpacePosition.divideByScalar(magnitude);

    // For the purpose of this computation, points below the ellipsoid
    // are considered to be on it instead.
    magnitudeSquared = Math.max(1.0, magnitudeSquared);
    magnitude = Math.max(1.0, magnitude);

    var cosAlpha = direction.dot(scaledSpaceDirectionToPoint);
    var sinAlpha = direction.cross(scaledSpaceDirectionToPoint).magnitude();
    var cosBeta = 1.0 / magnitude;
    var sinBeta = Math.sqrt(magnitudeSquared - 1.0) * cosBeta;

    return 1.0 / (cosAlpha * cosBeta - sinAlpha * sinBeta);
}

如您所见,此计算比我们上次描述的用于在地平线上测试该点的计算成本更高。可能可以通过使用前面描述的锥体测试测试每个顶点来优化它,并且如果发现顶点在锥体之外,则仅计算顶点的精确水平遮挡点。我将把它留给读者作为练习。

无论如何,这种计算的成本是它主要只适用于静态几何的主要原因。如果几何体相对于椭球体发生变化,则需要在每次变化时重复此计算。这可能会变得昂贵。

另外,在使用这种方法时,请记住一个重要的警告。在现实世界中,被WGS84椭球遮挡的物体不一定被地球的真实表面遮挡。这是因为地球表面实际上在世界部分地区略低于椭球体。根据您的应用,使用WGS84作为遮挡体积可能是可以接受的,或者您可能需要使用更保守的椭球。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

charlee44

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值