题目:
题意:
每次给出两条直线,判断是否平行、重合、相交,相交的话就输出交点。
题解:
判断两条直线是否平行
两条直线两个方向向量平行(叉积为0)
判断两条直线是否重合
在平行的基础上,在两条直线上各选一个点组成一个方向向量在去与前两个中的任意一个判平行(叉积为0)
那相交的话就是既不平行也不重合呗
求交点的话其实是这样的
a⃗ =A⃗ +tB⃗
b⃗ =C⃗ +uD⃗
两条直线相交
A⃗ +tB⃗ =C⃗ +uD⃗
两边同时叉乘 D⃗ 得到
(A⃗ +tB⃗ )×D⃗ =(C⃗ +uD⃗ )×D⃗
因为
D⃗ ×D⃗ =0
所以
A⃗ ×D⃗ +tB⃗ ×D⃗ =C⃗ ×D⃗
解出参数
t=(C⃗ −A⃗ )×D⃗ /(B⃗ ×D⃗ )
带入一个含t的柿子就可以解出来啦
点积是满足交换律的,但叉积并不满足,但是满足反交换律,即
a⃗ ×b⃗ =−b⃗ ×a⃗
点积和叉积都满足加法的分配率
代码:
#include <cstdio>
using namespace std;
const double eps=1e-9;
struct vector
{
double x,y;
vector (double X=0,double Y=0){x=X;y=Y;}
};
struct line
{
vector x,v;
line(vector X=vector(0,0),vector Y=vector(0,0)){x=X; v=Y;}
};
vector operator +(vector a,vector b){return vector(a.x+b.x,a.y+b.y);}
vector operator -(vector a,vector b){return vector(a.x-b.x,a.y-b.y);}
vector operator *(vector a,double b){return vector(a.x*b,a.y*b);}
int dcmp(double x)
{
if (x<=eps && x>=-eps) return 0;
return (x>0)?1:-1;
}
double cj(vector x,vector y){return x.x*y.y-x.y*y.x;}
vector jd(vector a,vector b , vector c,vector d)//求交点坐标
{
vector v=a-c;
double t=cj(d,v)/cj(b,d);
return a+b*t;
}
int main()
{
int n;scanf("%d",&n);
printf("INTERSECTING LINES OUTPUT\n");
for (int i=1;i<=n;i++)
{
double x1,y1,x2,y2,x3,y3,x4,y4;
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
int x=dcmp(cj(vector(x1-x2,y1-y2),vector(x3-x4,y3-y4)));
int y=dcmp(cj(vector(x1-x2,y1-y2),vector(x1-x4,y1-y4)));
if (!x && !y) printf("LINE\n");
else
{
if (!x) printf("NONE\n");
else
{
vector p=jd(vector(x1,y1),vector(x1-x2,y1-y2),vector(x3,y3),vector(x3-x4,y3-y4));
printf("POINT %.2lf %.2lf\n",p.x,p.y);
}
}
}
printf("END OF OUTPUT");
}