判断两线段是否相交

给定两线段 (P_1P_2)(P_3P_4),要求判断他们是否相交。

通过两个步骤完成判断:

  1. 快速排斥实验。如果两个线段相交,那么分别以这两个线段为对角线的矩形一定相交(包括只有公共边或只有公共点的相交)。我们首先判断这两个线段是否满足这个条件。
  2. 跨立实验。如果这两个线段幸运的通过了上面那个实验,那么将接着接受跨立实验的考验。如果把其中一个线段看做矢量,那么另外一个线段的两个端点必然分别在这个矢量的左右两侧。我们分别把这两个线段当做矢量判断一次,如果都成立,那么这两个线段必有交点。

其实还有一些特殊的情况(例如两线段的叉积为 (0)),但是通过对特殊情况的枚举我们发现这两个实验可以正确的验证所有的情况,这也许就是这两个实验的妙处所在吧。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

const double eps=1e-10;
struct Point
{
	double x,y;
	
	Point () {}
	Point (double X,double Y) : x(X),y(Y) {}
	Point operator - (const Point a) { return Point(x-a.x,y-a.y); }
	double operator * (const Point a) { return x*a.y-y*a.x; }
	void read() { scanf("%lf %lf",&x,&y); }
}P1,P2,P3,P4;

void init()
{
	P1.read(),P2.read(),P3.read(),P4.read();
}

bool Both_Point(Point P1,Point P2,Point P3,Point P4)
{
	if(!(max(P1.x,P2.x)+eps>=min(P3.x,P4.x)&&min(P1.x,P2.x)<=max(P3.x,P4.x)+eps))
		return 0;
	if(!(max(P1.y,P2.y)+eps>=min(P3.y,P4.y)&&min(P1.y,P2.y)<=max(P3.y,P4.y)+eps))
		return 0;
	if(((P2-P1)*(P3-P1))*((P2-P1)*(P4-P1))>eps)
		return 0;
	if(((P4-P3)*(P1-P3))*((P4-P3)*(P2-P3))>eps)
		return 0;
	return 1;
}

void work()
{
	if(Both_Point(P1,P2,P3,P4))
		puts("YES");
	else
		puts("NO");
}

int main()
{
	init();
	work();
	return 0;
}
由于博主比较菜,所以有很多东西待学习,大部分文章会持续更新,另外如果有出错或者不周之处,欢迎大家在评论中指出!
原文地址:https://www.cnblogs.com/With-penguin/p/13200560.html