求两线段交点坐标

  1. 判断线段是否相交
  2. 求交点坐标

判断线段是否相交

a. 快速互斥实验

即线段的外接矩形相交,线段才会相交,以两条线段为对角线的矩形,如果不重合的话,那么两条线段一定不可能相交。看下图:

opencv求直线的交点_opencv求直线的交点

判断两直线互斥的依据:

1.线段ab的低点低于cd的最高点(可能重合)
2.cd的最左端小于ab的最右端(可能重合)
3.cd的最低点低于ab的最高点(加上条件1,两线段在竖直方向上重合)
4.ab的最左端小于cd的最右端(加上条件2,两直线在水平方向上重合)

综上4个条件,两条线段组成的矩形是重合的
即:

if(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&&min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y)) 
  return true;

或(即上面的取反):

if (min(a[0], b[0]) > max(c[0], d[0]))
		return false;
	if (min(a[1], b[1]) > max(c[1], d[1]))
		return false;
	if (min(c[0], d[0]) > max(a[0], b[0]))
		return false;
	if (min(c[1], d[1]) > max(a[1], b[1]))
		return false;

后面写法的好处是如果有不对可以立刻退出,不必计算后面内容。

b. 跨立实验

如果两条线段相交,那么必须跨立,就是以一条线段为标准,另一条线段的两端点一定在这条线段的两段,也就是说a b两点在线段cd的两端,c d两点在线段ab的两端

我们可以利用向量叉乘判断直线向量CD是否再线段AB之间,如图:

opencv求直线的交点_线代_02


(ca x cd)·(cb x cd)<=0 则说明ca cb相对于cd的方向不同,则线段a b在直线cd的两侧。

注意上式只能说明, AB线段在cd直线的两侧,因为向量cd是没有长度的,如果cd比较短,没有与ab相交,那么ab和cd还是不相交的。因此应该判断两次,即两条线段都要为直线,判断另一直线的两端点是否在它两边,若是则两线段相交。即判断直线cd在AB两侧,直线ab在cd两侧。

(ca x cd)·(cb x cd)<=0 && (ad x ab)·(ac x ab)<=0

另外

若仅仅满足跨立实验是不行的,如下面的情况:

opencv求直线的交点_互斥_03


即两条线段在同一条直线上。所以我们要同时满足两次跨立和快速排斥实验。下图是线段是否相交的判读图

opencv求直线的交点_线段相交_04

求交点坐标

使用线代求交点:
例如,已知两条直线的一般方程:Ax+By+C = 0
联立两方程,交点x,y为未知数,将其转换为矩阵形式,求解非齐次线性方程组的解。
例如求解直线2x-3y-3=0和x+y+2=0的交点。

Eigen::Matrix3f A;
	A << 2, -3, -3, 1, 1, 2, 0, 0, 1;
	Eigen::Vector3f B;
	B << 0, 0, 1;
	Eigen::Vector3f X1,X2,X3;
	X1 = A.lu().solve(B);
	X2 = A.colPivHouseholderQr().solve(B);

使用几何求交点:
已知两条线段相交,求交点
求交点具体见