求线段的交点即求线段交点的坐标。若已确定两线段相交,可以通过解析几何中的直线方程来求解交点,这里介绍另外的一种方法。叉积multi(p1,p2,p0)可以看做是由点P1,P2,P0和P1+P2,这四个点围成的平行四边形的面积(如下图所示),及三角形P0P1P2的面积S=1/2 multi(P1,P2,P0)
在下图中,线段AB和CD相交于点P。
我们分别从D点和C点做AB的垂线DD1和CC1,由于△DD1P∽△CC1P,因此我们有|DD1| / |CC1|=|DP| / |CP|。又因为S△ABD=DD1*AB/2,S△ABC=CC1*AB/2,所以:
|DP| / |CP|=S△ABD/S△ABC=|AD × AB| / |AC × AB|=|multi(D,B,A)| / |multi(C,B,A)|
又因为|DP| / |CP|=(XD-XP)/(XP-XC)=(YD-YP)/(YP-YC)
所以有:
XP=(S△ABD * XC + S△ABC * XD)/(S△ABD + S△ABC)
=(multi(D,B,A)* XC - multi(C,B,A)* XD)/(multi(D,B,A)- multi(C,B,A))
YP=(S△ABD * YC + S△ABC * YD)/(S△ABD + S△ABC)
=(multi(D,B,A)* YC - multi(C,B,A)* YD)/(multi(D,B,A)- multi(C,B,A))
由此得出计算线段u和v交点的算法,参考代码如下:
#include
using namespace std;
typedef struct node
{
double x,y;
}point;
typedef struct line
{
point start,end;
}segment;
double multi(point p1,point p2,point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
point intersection(segment u,segment v)
{
point p;
p.x=(multi(v.end,u.end,u.start)*v.start.x-multi(v.start,u.end,u.start)*v.end.x)/(multi(v.end,u.end,u.start)-multi(v.start,u.end,u.start));
p.y=(multi(v.end,u.end,u.start)*v.start.y-multi(v.start,u.end,u.start)*v.end.y)/(multi(v.end,u.end,u.start)-multi(v.start,u.end,u.start));
return p;
}
int main()
{
segment u,v;
scanf("%lf%lf%lf%lf",&u.start.x,&u.start.y,&u.end.x,&u.end.y);
scanf("%lf%lf%lf%lf",&v.start.x,&v.start.y,&v.end.x,&v.end.y);
point p=intersection(u,v);
printf("%lf %lf\n",p.x,p.y);
return 0;
}