两圆位置关系由圆心距平方与半径和差平方比较判定:完全分离当dist_sq > (r1+r2)²,相交当(r1−r2)²
如何用圆心距和半径判断两圆位置关系
直接比较圆心距离与两圆半径之和、之差的绝对值,是唯一可靠且高效的几何判定方式。浮点误差必须处理,否则
==判定会失效。
- 设两圆圆心为
(x1, y1)、(x2, y2),半径为r1、r2,先算平方距离避免开方:dx = x2 - x1; dy = y2 - y1; dist_sq = dx*dx + dy*dy;- 完全分离(无交点):当
dist_sq > (r1 + r2) * (r1 + r2)时成立- 交叉(两个交点):当
dist_sq 且 <code>dist_sq > (r1 - r2) * (r1 - r2)时成立(注意用绝对值差的平方)- 包含(内含或内切):当
dist_sq 时,小圆完全在大圆内;等于时为内切为什么不能直接用
sqrt()比较距离开方引入额外浮点误差,且性能更低。所有比较都可基于平方距离完成,无需
sqrt()—— 这不是优化技巧,而是避免精度陷阱的必要做法。
sqrt(dist_sq)可能因舍入导致本该相等的值被判为不等,例如内切场景下dist == r1 - r2很难精确成立- 用平方比较等价但更稳定:
dist_sq == (r1 - r2) * (r1 - r2)虽仍需容忍误差,但至少避免了两次浮点运算叠加- 若必须容错,建议统一用
std::abs(dist_sq - target_sq) ,其中 <code>eps = 1e-9或根据坐标量级调整边界情况:同心圆、零半径、负半径怎么处理
数学上半径为 0 是合法点圆,但实际代码中必须提前校验输入,否则后续计算会失真或崩溃。
- 若
r1 ,应拒绝或按点圆逻辑单独处理(如 <code>r1 == 0时,仅当dist_sq == 0才“重合”)- 同心圆(
dist_sq == 0)属于包含的一种特例:若r1 != r2,则小圆严格内含于大圆;若相等,则完全重合(非分离也非交叉)- C++ 中不要依赖
std::hypot或std::sqrt处理这些情形——它们不解决根本的语义歧义,反而掩盖输入问题常见错误:把“相交”误判为“交叉包含”
“交叉包含”不是标准几何术语,用户实际想区分的是:分离 / 相切(外切或内切)/ 相交(两个交点)/ 包含(无交点,但一圆在另一圆内)。混淆会导致逻辑分支错误。
- 外切:
dist_sq == (r1 + r2) * (r1 + r2)- 内切:
dist_sq == (r1 - r2) * (r1 - r2)(且r1 != r2)- 真正“交叉”仅指有两个交点的情形,必须同时满足
dist_sq 和 <code>dist_sq > (r1 - r2)*(r1 - r2)- 很多业务逻辑(如碰撞检测)只关心“是否相交(含相切)”,此时只需判断
dist_sq 即可,不必细分实际写判定函数时,最容易被忽略的是半径合法性检查和浮点容差粒度——坐标范围越大,
eps就不能固定用1e-9;而一旦漏掉r 的 guard,后续所有距离比较都可能失去几何意义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!












