C++如何求两个圆的交点坐标_C++计算几何基础算法实现【数学】

6次阅读

两圆相交当且仅当 |r1−r2| r1+r2 或 d

C++如何求两个圆的交点坐标_C++计算几何基础算法实现【数学】

判断两圆是否相交及交点个数

两圆交点是否存在,取决于圆心距 d 与两半径 r1r2 的关系。直接计算前必须先分类:
— 若 d > r1 + r2:外离,无交点;
— 若 d :内含(或内离),无交点;
— 若 d == 0 && r1 == r2:同心圆重合,无穷多交点(通常视为退化情况,按题意忽略);
— 其余情况:有 0、1 或 2 个交点。特别地,d == r1 + r2d == abs(r1 - r2) 时为相切,仅 1 个交点。

用向量投影法解交点坐标(推荐)

设圆 A 圆心为 p1 = (x1, y1),半径 r1;圆 B 圆心为 p2 = (x2, y2),半径 r2。核心思路是:先求出两圆心连线上的垂足位置(即公共弦中点),再沿垂直方向偏移得到两个交点。
关键中间量:
d = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))(圆心距);
a = (r1*r1 - r2*r2 + d*d) / (2*d)(从 p1 到垂足的投影长度);
h = sqrt(r1*r1 - a*a)(垂足到交点的垂直距离)。
然后构造单位方向向量:
— 沿 p1→p2 方向单位向量:ex = ((x2-x1)/d, (y2-y1)/d)
— 垂直单位向量:ey = (-ey.y, ey.x) 或直接用 (-(y2-y1)/d, (x2-x1)/d)

两个交点为:
sol1 = p1 + a*ex + h*ey
sol2 = p1 + a*ex - h*ey

注意浮点误差与退化情形处理

实际编码中,h 可能因浮点误差变成极小负数(如 -1e-15),直接开方会得到 NaN。务必做容错判断:
— 计算 h_sq = r1*r1 - a*a 后,先检查 h_sq → 视为无交点;
— 若 h_sq 但大于 -1e-10,设 h = 0(即相切);
d 接近 0 时(同心),要单独判断避免除零;
— 所有比较都应使用带 epsilon 的近似判断,而非 ==

立即学习C++免费学习笔记(深入)”;

常见错误:
— 忘记对 h_sq 截断导致 sqrt(negative)
— 单位向量未归一化(尤其当 d 很小时,未除 d 会导致方向错误);
— 垂直向量构造符号写反((dy, -dx) 是顺时针旋转90°,需确认是否符合你坐标系习惯)。

c++ 实现要点与轻量示例

无需依赖几何库,用 std::sqrt 和基本运算即可。结构建议封装为函数:

struct Point { double x, y; }; std::vector circle_intersection(Point p1, double r1, Point p2, double r2) {     double dx = p2.x - p1.x, dy = p2.y - p1.y;     double d = std::sqrt(dx*dx + dy*dy);     if (d > r1 + r2 || d < std::abs(r1 - r2) || d < 1e-10) return {}; 
double a = (r1*r1 - r2*r2 + d*d) / (2*d); double h_sq = r1*r1 - a*a; if (h_sq zuojiankuohaophpcn -1e-10) return {}; double h = (h_sq zuojiankuohaophpcn 0) ? 0 : std::sqrt(h_sq);  Point ex = {dx/d, dy/d}; Point ey = {-dy/d, dx/d}; // 注意:这是左手法则下的垂直向量  Point p = {p1.x + a*ex.x, p1.y + a*ex.y}; std::vectorzuojiankuohaophpcnPointyoujiankuohaophpcn res; res.push_back({p.x + h*ey.x, p.y + h*ey.y}); if (h youjiankuohaophpcn 1e-10) res.push_back({p.x - h*ey.x, p.y - h*ey.y}); return res;

}

这个实现没做输入校验,但覆盖了绝大多数实用场景。真正容易被忽略的是:垂直向量方向影响交点顺序,而某些题目(如求“上方交点”)会依赖该方向定义——务必根据你的坐标系 y 轴正向(屏幕坐标 vs 数学坐标)确认 ey 构造方式。

text=ZqhQzanResources