【计算几何】判断线段相交(跨立实验)

题意:有n条线段(编号为1n),按1n的顺序放在二维坐标系上(就是先放1号,再放2号……),要求输出最上面的那些线段的编号。(就是没有其他线段压在它上面的那些线段)
注意:有交点即为被压。

1.叉积

判断线段相交需要有关于叉积(外积,向量积)的预备知识。
a×b=a×b×sinθvec{a} imes vec{b}=|vec{a}| imes |vec{b}| imes sin heta
a(x1,y1),b(x2,y2),x1y2x2y1x1y2x2y1abvec{a}可以表示为(x1,y1),vec{b}可以表示为(x2,y2),则向量积的模(大小)为|x1*y2-x2*y1|,而我们要用的只是由x1*y2-x2*y1的正负判断两个向量的位置关系(正表示vec{a}由逆时针旋转更容易得到)vec{b}
(不用会证明)

性质:设两向量abvec{a},vec{b}的叉积的模为x。则有:
若x>0,则abvec{a}到vec{b}的转向为逆时针。
若x=0,则两向量的方向在同一直线上。
否则,abvec{a}到vec{b}的转向为顺时针。
(证明不用会)

2.跨立实验

在这里插入图片描述
如图,AB,CDoverrightarrow{AB},overrightarrow{CD}两个向量如果相交(交点不是向量端点),
当且仅当A>D>BB>C>AA->D->B的方向等于B->C->A的方向并且
C>A>DD>B>CC->A->D等于D->B->C。

特别地,当两个向量的交点为一个向量的一个端点,则通过叉积大小等于0来判断。
注意:上面纯属扯淡,主要看代码。

#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e4+10;
struct node{
	double x,y;
};
struct line{
	node p1,p2;
}list[N];
double mult(node p1,node p2,node p0)
{
	double x1,y1,x2,y2;
	x1=p1.x-p0.x;
	y1=p1.y-p0.y;
	x2=p2.x-p0.x;
	y2=p2.y-p0.y;
	return x1*y2-x2*y1;
}
bool check(line l1,line l2)
{
	node p1=l1.p1;
	node p2=l1.p2;
	node p3=l2.p1;
	node p4=l2.p2;
	if(mult(p3,p2,p1)*mult(p2,p4,p1)>0&&mult(p1,p4,p3)*mult(p4,p2,p3)>0)return true;
	if(	(mult(p3,p4,p1)==0&&min(p3.x,p4.x)<=p1.x&&p1.x<=max(p3.x,p4.x)&&min(p3.y,p4.y)<=p1.y&&p1.y<=max(p3.y,p4.y)) ||
		(mult(p3,p4,p2)==0&&min(p3.x,p4.x)<=p2.x&&p2.x<=max(p3.x,p4.x)&&min(p3.y,p4.y)<=p2.y&&p2.y<=max(p3.y,p4.y)) ||
		(mult(p1,p2,p3)==0&&min(p1.x,p2.x)<=p3.x&&p3.x<=max(p1.x,p2.x)&&min(p1.y,p2.y)<=p3.y&&p3.y<=max(p1.y,p2.y))	||
		(mult(p1,p2,p4)==0&&min(p1.x,p2.x)<=p4.x&&p4.x<=max(p1.x,p2.x)&&min(p1.y,p2.y)<=p4.y&&p4.y<=max(p1.y,p2.y)) ) return true;
	return false;
}
bool v[N];
int b[N];
int main()
{
	int n;scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lf%lf%lf%lf",&list[i].p1.x,&list[i].p1.y,&list[i].p2.x,&list[i].p2.y);
	int tot=0;
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
		{
			if(check(list[i],list[j]))
			{
				v[i]=1;
				break;
			}
		}
	for(int i=1;i<=n;i++)if(!v[i])b[++tot]=i;
	for(int i=1;i<tot;i++)printf("%d ",b[i]);
	printf("%d
",b[tot]);
	return 0;
}/*
提供一个数据 
2
0 0 0 1
0 2 0 3
*/

原文地址:https://www.cnblogs.com/zsyzlzy/p/12373919.html