S01E21:球体与球体相交形成的圆环

2,179 阅读2分钟

说明

如果两个球体表面相交,那么相交处会形成一个圆环。如果是包含关系,即一个球在另一个球体内部,则不会有这个圆环。那么这个相交形成的圆环,圆心在哪里,半径又是多少呢?

几何

如图,3D 球体的相交,会形成一个空间中圆环,这个圆环所在平面,垂直于两球心连线。 所以,我们可以将问题简化,简化到二维平面上处理。选取任意一个过球心连线的平面,会得到下面的图形,其中点 E 坐标就是圆心,DE 长(或EB 长)就是半径。

这里我们来推导一下:假设向量 CE = x*CA,这里 x 是未知数,范围 0~1

因为 DE 垂直于 AC,所以根据勾股定理直角三角形 DEC 可得公式:DE * DE = DC * DC - EC * EC

根据勾股定理直角三角形 ADE 可得公式:DE * DE = AD * AD - AE * AE

合并这两个公式可得到:

DC * DC  - (x * CA) * (x * CA) = AD * AD - ((1-x) * CA) * ((1-x) * CA)
// 移项后得到
(x * CA) * (x * CA) - ((1-x) * CA) * ((1-x) * CA) = DC * DC - AD * AD
// 展开并化简
(2x-1) * CA * CA = DC * DC - AD * AD
// 最后求得 x
x = 0.5 * (DC * DC - AD * AD )/(CA * CA) + 0.5

由于 DC 和 AD 分别两个球体的半径,而 CA 则是球心间的距离,所以我们可以求出 x 的确定值。再根据CE = x*CA得到圆环中心 E 的坐标。而半径只能通过勾股定理最后开平方得到。

代码

static func intersectionCircle(sphere1:Sphere, sphere2:Sphere) -> (simd_float3, Float)? {
    if !isSurfaceIntersection(sphere1: sphere1, sphere2: sphere2) {
        return nil
    }
    let x = 0.5 * ((sphere1.radius * sphere1.radius - sphere2.radius * sphere2.radius) / distance_squared(sphere1.position, sphere2.position)) + 0.5
    
    let vector = x * (sphere2.position - sphere1.position)
    let position = sphere1.position + vector
    
    let radius = sqrtf(sphere1.radius * sphere1.radius - length_squared(vector))
    return (position, radius)
}