两球内含当且仅当球心距加小球半径小于等于大球半径,即d + r r + r。

怎么用距离公式判断球体包含关系
两个三维球体是否发生包含,本质是看小球的整个空间是否完全落在大球内部。核心判断依据只有一个:distance(center1, center2) + radius_small 。注意不是“小于”,而是“小于等于”——当两球心重合且半径相等时,属于完全重合,也视为包含(内含)。
实际写代码时别直接手算欧氏距离再开根号,先平方再比较更高效、无精度损失:
double dx = c1.x - c2.x; double dy = c1.y - c2.y; double dz = c1.z - c2.z; double dist_sq = dx*dx + dy*dy + dz*dz; // 判断 c2 是否被 c1 包含:即 c2 是小球,c1 是大球 bool c2_in_c1 = dist_sq + c2.r*c2.r <h3>为什么不能只比半径大小就下结论</h3><p>常见误区是看到 <code>r1 > r2</code> 就认为球1一定包含球2——完全错误。球心距离才是关键变量。哪怕 <code>r1</code> 比 <code>r2</code> 大很多,只要两球心足够远,依然不相交;反之,<code>r1</code> 略小于 <code>r2</code> 但球心几乎重合,也可能出现球1被球2包含(即反向包含)。</p>
- 必须显式区分“球A包含球B”和“球B包含球A”两种情况,不能靠半径大小自动推断方向
- 若需判断“是否存在包含关系(任一方向)”,要分别检查
c1 contains c2和c2 contains c1 - 若两球半径相等,只有球心重合时才互相包含;否则最多相交或分离
浮点数比较时容易踩的坑
用 直接比较浮点运算结果在边界情况下可能失效。比如两球刚好内切时,<code>dist_sq + r_small*r_small 理论上应等于 r_large*r_large,但因计算误差可能略大,导致误判为“不包含”。
稳妥做法是引入一个小的容差值 eps(如 1e-9),改用:
bool c2_in_c1 = dist_sq + c2.r*c2.r <p>注意:<code>eps</code> 加在右边,不是两边都加;也不建议用 <code>abs(a-b) ,因为这里本质是单向不等式约束。</code></p><h3>要不要考虑相交或相离的中间状态</h3><p>包含关系只是球体相对位置的一种特例。如果业务逻辑还需区分“相交但不包含”“外离”“内切”“外切”,可以在同一距离计算基础上扩展:</p>
-
dist_sq > (r1 + r2)*(r1 + r2)→ 外离 -
dist_sq == (r1 + r2)*(r1 + r2)→ 外切(用带eps的近似判断) -
dist_sq (r1 - r2)*(r1 - r2)→ 相交但互不包含 -
dist_sq == (r1 - r2)*(r1 - r2)→ 内切
所有这些判断都复用同一个 dist_sq,避免重复计算。真正容易被忽略的是:当 r1 时,<code>(r1 - r2)*(r1 - r2) 仍为正,但此时内切/内含的主从关系已反转——得确保半径差取绝对值,或提前交换角色再算。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











