球体 – 球体相交和圆球相交

我有代码为圆圈交集。 但是我需要把它扩展到三维。 我如何计算:

  • 两个球体的交点圆的半径和中心
  • 一个球体和一个圆的交点?

给定两个球体(sc0,sr0)(sc1,sr1) ,我需要计算一个以ci中心,半径为ri的交点。
此外,给定一个球体(sc0,sr0)和一个圆(cc0, cr0) ,我需要计算两个交点(pi0, pi1)
我已经检查了这个链接和这个链接,但我不明白他们背后的逻辑和如何编码。

我尝试了ProGAL库球面 – 球面 – 球面相交,但结果坐标是四舍五入的。 我需要精确的结果。

Solutions Collecting From Web of "球体 – 球体相交和圆球相交"

球体交叉点

让我们从更明显的一个球体开始吧。 这与2D中的圆圈情况几乎相同。 我们可以在包含球体中心之间的线的任何平面上投影,以获得相同的2D图像:

将问题减少到2D

在这里,第一个球体有中心c_1和半径r_1c_2r_2 ,它们的交点有中心c_i和半径r_i 。 令d = ||c_2 - c_1|| ,球体之间的距离。

边缘情况:

正如前面指出的那样,如果r_1 + r_2 < d那么根本就没有交集。 球体之间有一个分离。

如果r_1 + r_2 == d ,则交点为单点,位于从c_1c_2的直线上的r_1距离,或者: c_i = c_1 + (c_2 - c_1) * r_1/d

如果d + min(r_1, r_2) = max(r_1, r_2)这也可能发生在另一侧。 在这种情况下,单个交点位于较大的球面上,在c_i = c_larger + (c_smaller - c_larger) * r_larger/d

最后,如果一个圆完全包含在另一个圆中,使得d + min(r_1, r_2) < max(r_1, r_2) ,那么再次没有交集。

边缘案例

典型的交叉点

好吧,现在有点肉。

我们来定义c_i = c_1 + h * (c_2 - c_1)h某个值。 请注意,在一个圆包围另一个圆的中心的情况下, h可以是负数或大于1。 幸运的是,这些符号将“正常工作”,所以我们不需要为这种情况添加任何特殊的逻辑。

剩下的,有趣的案例

我们可以使用毕达哥拉斯定理,用r_ihd表示r_1r_2 ,然后求解方程组来求h:

对于h解的方程组

 h = 1/2 + (r_1 * r_1 - r_2 * r_2)/(2 * d*d) 

我们可以把它分解成上面的c_i的公式来find交点圆的中心。 然后,扭转我们早期的毕达哥拉斯关系之一:

 r_i = sqrt(r_1*r_1 - h*h*d*d) 

所以,现在我们有了我们交集的中心和半径。 现在我们可以围绕分离轴旋转,得到我们全面的解决scheme。 圆位于垂直于分离轴的平面上,所以可以用n_i = (c_2 - c_2)/d作为该平面的法线。

我们光荣的交集

在select与这个法线垂直的切线和刻度t_ib_i ,可以在这个圆上写下任意一点:

 p_i(theta) = c_i + r_i * (t_i * cos(theta) + b_i sin(theta)); 

由于毛球定理 ,没有一种通用的方法来select切线/二进制使用。 我的建议是select一个不平行于n_i的坐标轴,并设置t_i = normalize(cross(axis, n_i))b_i = cross(t_i, n_i)等。


球圈交叉口

一个平面/二维的圆只能与自身平面内的东西相交。 所以,第一件事是:找出那个平面与我们的球体相交的地方。

片

给定一个中心和半径分别为c_cr_c的圆,在(单位)法向n的平面上,以及一个中心和半径为c_sr_s的球体。

圆的平面从球体中心切出球体d = dot(n, c_c - c_s)单位。 再次,如果法线指向球体的中心,这可能是负面的,但是符号将会出现。

如果abs(d) > r_s则没有交集。 我们的飞机完全通过球体上方/下方。

如果有一个交点,它将在我们原来的圆和在这个平面与圆球相交的地方形成一个新的圆,中心c_p = c_s + d*n

如果d == r_s那么这是与飞机的唯一交点; 否则我们有一个半径r_p的圆,我们可以用毕达哥拉斯定理find:

 r_p = sqrt(r_s*r_s - d*d) 

现在我们已经把问题简化成了我们已经知道如何解决的圆圈。 根据上面的边界情况检查所涉及的距离/半径将让我们照顾不相交和单点交集的情况。

看起来很熟悉

如果两个圆重叠超过一个点,我们可以使用Sphere-Sphere检查中的公式来查找c_ir_i

不过,我们只有两个点位于圆的平面上,而不是完整的交点。

为了expression这些点,我们可以在平面上定义一个切向量,

 t = normalize(cross(c_p - c_c, n)) 

那么我们的交点是:

 p_0 = c_i - t * r_i p_1 = c_i + t * r_i 

我们完成了。 :d

我希望有帮助!