给定两条线段和
,端点表示为P1(x1,y1),P2(x2,y2),P3(x3,y3)和P4(x4,y4),假设两条线段的交点为P0(x0,y0),且
,
,那么P0可以表示为:
t和s在等于0或1时表示两条线段相交在端点,如果为其他值,表示两条线段不相交。将点坐标代入公式得:
利用公式消元法求得t和s:
t和s方程的分子和分母都是向量的叉乘:
如果,表示两条线段平行,如果端点在另一条线段上,则该端点为交点,否则不是。如果t和s有一个没有落在区间内
,则两条线段不相交。那么交点
的坐标为:
或
至此,整个求解过程介绍完成。
// 定义一个常量用于浮点数比较的阈值
const double EPSILON = 1.0e-6;
bool Intersection(double x1, double y1, double x2, double y2,
double x3, double y3, double x4, double y4,
double& x0, double& y0)
{
// 计算向量差
double dx1 = x2 - x1; // 线段1的x方向差
double dy1 = y2 - y1; // 线段1的y方向差
double dx2 = x4 - x3; // 线段2的x方向差
double dy2 = y4 - y3; // 线段2的y方向差
double dx3 = x3 - x1; // 线段1起点到线段2起点的x方向差
double dy3 = y3 - y1; // 线段1起点到线段2起点的y方向差
// 计算行列式(判断是否平行或重合)
double determinant = dx1 * dy2 - dy1 * dx2;
// 如果行列式接近0,表示两线段平行或重合
if (std::fabs(determinant) < EPSILON)
{
return false; // 无法计算交点
}
// 计算参数t和s,用于判断交点是否在线段范围内
double t = (dy2 * dx3 - dx2 * dy3) / determinant;
double s = (dy1 * dx3 - dx1 * dy3) / determinant;
// 检查t和s是否在[0, 1]范围内
if (t < 0 || t > 1 || s < 0 || s > 1)
{
return false; // 交点不在两条线段的范围内
}
// 计算交点坐标
x0 = x1 + t * dx1;
y0 = y1 + t * dy1;
return true;
}