两圆相交当且仅当 |r1−r2| r1+r2 或 d
判断两圆是否相交及交点个数
两圆交点是否存在,取决于圆心距
d与两半径r1、r2的关系。直接计算前必须先分类:
— 若d > r1 + r2:外离,无交点;
— 若d :内含(或内离),无交点;
— 若d == 0 && r1 == r2:同心圆重合,无穷多交点(通常视为退化情况,按题意忽略);
— 其余情况:有 0、1 或 2 个交点。特别地,d == r1 + r2或d == 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*eysol2 = 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::vectorcircle_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构造方式。
0
0
相关文章
C++怎么解决“无法打开包括文件”错误_C++项目附加包含目录配置教程【排查】
C++中std::async返回值怎么获取_C++异步编程future用法详解【指南】
C++中static_cast与dynamic_cast的区别_C++强类型转换安全分析【考点】
C++如何实现简单的XML节点读取_C++快速解析配置文件数据方法【实例】
C++如何实现简单的依赖注入框架_C++解耦组件注册与发现机制【架构】
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门AI工具










