内切指两圆有且仅有一个公共点且一圆完全在另一圆内部,判定条件为圆心距等于半径差绝对值且半径不等;需用容差比较浮点距离平方与半径差平方,排除半径非正、nan/inf等边界情况。

内切的数学定义必须先搞清
两个圆内切,是指它们有且仅有一个公共点,且一个圆完全在另一个圆内部(不包括边界重合的同心圆情况)。关键判断条件是:圆心距等于两圆半径之差的绝对值,且半径不等(否则为同心或重合,不算内切)。
注意:若 r1 == r2,则圆心距为 0 才“重合”,但重合不是内切;圆心距 > 0 时,相同半径的两圆不可能内切——只能外离、外切或相交。
- 设圆 A 圆心
(x1, y1)、半径r1,圆 B 圆心(x2, y2)、半径r2 - 计算圆心距平方:
dx*dx + dy*dy(避免开方,提高精度和性能) - 判断条件应为:
abs(r1 - r2) * abs(r1 - r2) == distSq,且r1 != r2
浮点数比较不能直接用 ==
实际代码中,r1 和 r2 很可能是 double 或 float,直接用 == 比较距离平方会因精度丢失误判。
正确做法是引入容差(epsilon),例如 1e-9 级别:
const double eps = 1e-9;
double distSq = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
double diffR = fabs(r1 - r2);
if (fabs(distSq - diffR * diffR) eps) {
// 内切成立
}
-
fabs(r1 - r2) > eps排除了半径几乎相等的情况,防止把近似同心当成内切 - 只对
distSq和diffR * diffR做差值比较,不单独开方,规避 sqrt 的额外误差和性能开销 - 若使用整数坐标+整数半径,可严格用
==,但需确保无溢出(如int平方可能溢出,建议转long long)
内切方向不影响判定逻辑
内切分两种情形:小圆在大圆内部相切(常见理解),或大圆“套”小圆(几何上等价,只是谁包含谁的问题)。判定公式 |r1 - r2| == d 自动涵盖两者,无需区分哪个半径更大。
- 只要满足条件,就说明存在唯一接触点,且一圆整体在另一圆闭包内(除切点外无其他交点)
- 如果还需知道“谁在内”,可加判断:
r1 > r2 && d == r1 - r2表示圆 B 在圆 A 内;反之亦然 - 切点坐标可后续计算(如用圆心连线按比例插值),但内切判定本身不需要它
容易漏掉的边界情况
真实场景中,以下情况常被忽略,导致误报内切:
- 一圆半径 ≤ 0:按几何定义,半径非正的“圆”无效,应提前校验
r1 > 0 && r2 > 0 - 圆心重合且半径不同:此时
d == 0,但|r1 - r2| > 0,显然不满足内切条件,代码自然排除——但若没写好 epsilon 判断,可能因浮点误差意外触发 - 输入坐标或半径为 NaN/Inf:建议在计算前用
std::isfinite()过滤,否则distSq可能为 NaN,导致比较恒为 false
内切判定本身很轻量,但浮点鲁棒性和边界防御才是实际落地时最常翻车的地方。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











