两球碰撞当且仅当球心距离平方小于等于半径之和的平方,即 dist_sq

怎么算两个球心距离
判断球体关系的核心是球心距离与半径之和、半径之差的比较。先拿到两个球的中心坐标 center1 和 center2(比如 std::array<double></double> 或自定义结构体),再用欧氏距离公式算平方距离,避免开方——既快又稳:
double dx = center1[0] - center2[0]; double dy = center1[1] - center2[1]; double dz = center1[2] - center2[2]; double dist_sq = dx*dx + dy*dy + dz*dz;
注意:永远优先比较 dist_sq 和半径的平方,而不是调用 sqrt()。浮点误差小、性能高,且能规避 sqrt(-0.0) 等边界问题。
碰撞(相交)的判定条件是什么
两球发生碰撞(即有重叠区域,含相切)当且仅当球心距离 ≤ 半径之和。用平方形式写就是:
double r1 = sphere1.radius; double r2 = sphere2.radius; bool is_colliding = dist_sq <p>常见错误:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a> <p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>
- 误用
而非 <code>,导致相切时判定为“未碰撞” - 把
r1 + r2平方写成r1*r1 + r2*r2,漏掉交叉项 - 没处理
r1或r2为负数的情况(应提前校验半径非负)
怎么判断一个球完全包含另一个球
球 A 包含球 B(B 完全在 A 内部,含内切)的充要条件是:球心距 + B 的半径 ≤ A 的半径。注意方向性——不是对称关系:
// sphere1 是否包含 sphere2? bool contains = dist_sq = r2;
关键点:
- 必须加
r1 >= r2判断,否则当r1 时,<code>(r1 - r2)²仍为正,会导致误判 - 等号成立时是内切,属于包含;若要求“严格内部”,改用
并去掉等号 - 不要用
dist_sq + r2*r2 —— 数学等价但易溢出,尤其当半径很大时
要不要考虑浮点精度问题
实际工程中必须考虑。哪怕只差一个 ulp,也可能让相切变成“略分离”或“略穿透”。建议引入小阈值 EPS:
constexpr double EPS = 1e-9; bool is_colliding = dist_sq = r2 && dist_sq <p>但 <code>EPS</code> 不是越大越好:设太大可能把本不接触的球判为碰撞;设太小则起不到修正作用。典型场景下 <code>1e-9</code> 对 double 坐标足够,若坐标量级达 <code>1e6</code> 以上,需按比例放大 <code>EPS</code>(例如 <code>1e-3</code>)。没有银弹,得看你的数据范围。</p>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










