线段交点
线段交点问题,通常给出4个点的坐标,求出交点坐标,我们通过交点构造出向量,利用向量的知识求解。
图示
从图中可以看到,4个端点p1,p2,p3,p4,交点x,以及向量p1p2、p1p3、p2p4、p3p4,以及通过p3到直线p1p2的距离h1,p4到p1p2的距离h2,以及通过向量p1p2、p1p3所围成的平行四边形。
推导交点坐标
1、先求出h1、h2的长度,进而求出h1比h2
我们利用外积模的几何意义:|axb|=|a|x|b|sinθ=所围成平行四边形面积,在求出向量p1p2的模长,用所围成平行四边形面积➗p1p2模长,求出h1高度,同理求出h2高度!
再看下一幅图
从图中可以看到直角坐标系,以及向量ox,op3,p3x
2、求出ox向量,即x点坐标
当有了h1比h2后,我们可以求出向量p3x,用p3p4✖(h1➗(h1+h2))
(因为两个三角形h1p3x、p2p4x全等,所以对应的边成比例)
向量p3x=ox-op3推导出ox=p3x+op3,从而求得x点坐标!
对上述过程的化简
我们可以不用求出h1h2,只需要求出两个向量积,因为我们需要的是h1比h2,在求h1、h2的过程中,所对应的平行四边形为同一个底边p1p2,所以在h1比h2的时候会约去!
实现代码
测试用例
输入
3
0 0 2 0 1 1 1 -1
0 0 1 1 0 1 1 0
0 0 1 1 1 0 0 1
输出
(1,1)
(0.5,0.5)
(0.5,0.5)
#include <bits/stdc++.h>
using namespace std;
class Point
{
public:
double x,y;
Point(double x=0,double y=0):x(x),y(y) {}
//向量加法
Point operator+(Point p)
{
return Point(x+p.x,y+p.y);
}
//向量减法
Point operator-(Point p)
{
return Point(x-p.x,y+p.y);
}
//向量伸缩
Point operator*(double a)
{
return Point(x*a,y*a);
}
Point operator/(double a)
{
return Point(x/a,y/a);
}
//向量大小
double abs()
{
return sqrt(norm());
}
//向量范数
double norm()
{
return x*x+y*y;
}
};
typedef Point Vector;
//向量内积
double dot(Vector a,Vector b)
{
return a.x*b.x+a.y*b.y;
}
//向量外积
double cross(Vector a,Vector b)
{
return a.x*b.y-a.y*b.x;
}
Point getCrossPoint(Point p1,Point p2,Point p3,Point p4)
{
Vector p12(p2.x-p1.x,p2.y-p1.x);
Vector p13(p3.x-p1.x,p3.y-p1.y);
Vector p24(p4.x-p2.x,p4.y-p2.y);
Vector p34(p4.x-p3.x,p4.y-p3.y);
double d1=abs(cross(p13,p12));
double d2=abs(cross(p24,p12));
double h=d1/(d1+d2);
Point x=p34*h+p3;
return x;
}
int main()
{
int t;
cin>>t;//t组测试数据
int x1,y1,x2,y2,x3,y3,x4,y4;
while(t--)
{
cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
Point p1(x1,y1);
Point p2(x2,y2);
Point p3(x3,y3);
Point p4(x4,y4);
cout<<"("<<getCrossPoint(p1,p2,p3,p4).x<<","<<getCrossPoint(p1,p2,p3,p4).y<<")"<<endl;
}
return 0;
}