您的位置:首页 > 其它

判断线段是否相交...并求出交点。

2013-08-05 07:55 399 查看
判断直线是否相交,貌似很容易,直接用一个向量叉乘公式:x1*y2-x2*y1.如果结果为0,则直线是平行或者重合,否则必然相交...

但如何判断两条线段是否相交呢?我们给出了两条线段的四个端点,这两条条线段必须跨过另一条线段则必然相交,所以只需要算出两个端点分别在一条线段的两侧就OK了,至于怎么算是否在端点两侧还是用到上面的叉乘公式,两个端点的结果的积为负数,则在两侧,当然这里有种特殊情况需要处理,就是叉乘等于零,也就是端点在线段的延伸线上,所以这里需要判断这个端点是否在另一条线段上就OK了...这个代码没有注释,给以后的我自己看的...

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct point
{
	int x;
	int y;
}p[5];
int fff(point a,point b,point c)
{
	point p1,p2;
	p1.x=a.x-c.x;
	p1.y=a.y-c.y;
	p2.x=b.x-c.x;
	p2.y=b.y-c.y;
	return (p1.x*p2.y-p1.y*p2.x);
}
int ffff(point a,point b,point c)
{
	point min,max;
	min.x=b.x;min.y=b.y;max.x=a.x;max.y=a.y;
	if (a.x<b.x)
	{
		min.x=a.x;
		max.x=b.x;
	}
	if (a.y<b.y)
	{
		min.y=a.y;
		max.y=b.y; 
	}
	if (c.x>=min.x && c.x<=max.x && c.y>=min.y && c.y<=max.y) return 1;
	else return 0;
}
int ff(point a,point b,point c,point d)
{
	int q,w,e,r;
	q=fff(a,b,c);
	w=fff(a,b,d);
	e=fff(c,d,a);
	r=fff(c,d,b);
	if (q*w<0 && e*r<0)
		return 1;
	else 
	{
		if (q==0 && ffff(a,b,c)) return 1;
		if (w==0 && ffff(a,b,d)) return 1;
		if (e==0 && ffff(c,d,a)) return 1;
		if (r==0 && ffff(c,d,b)) return 1;
	}
	return 0;
}
int main()
{
 	while (~scanf("%d%d%d%d%d%d%d%d",&p[0].x,&p[0].y,&p[1].x,&p[1].y,&p[2].x,&p[2].y,&p[3].x,&p[3].y))
	{
		if (ff(p[0],p[1],p[2],p[3])) printf("相交\n");
		else printf("不相交\n");
	}
	return 0;
}


求交点的公式:

void jiaodian()
{
	double t=(double)((p[0].x-p[2].x) * (p[2].y-p[3].y)-(p[0].y-p[2].y)*(p[2].x-p[3].x))
			/(double)((p[0].x-p[1].x) * (p[2].y-p[3].y)-(p[0].y-p[1].y)*(p[2].x-p[3].x));
	q.x=(p[1].x-p[0].x)*t;
	q.y=(p[1].y-p[0].y)*t;
	printf("交点为:(%lf,%lf)\n",q.x,q.y);
}


补充:上面求交点的公式貌似不对。我也不记得以前怎么搞到这个公式。还自认为对了。补充真正的公式和解法:/article/2654884.html

顺便粘上完整的代码。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
using namespace std;
//#define DEBUG
struct node
{
	double x,y;
	node (){}
	node (double a,double b):x(a),y(b){
	}
}p[5];
double js(node p1,node p2,node p3)
{
	node h1,h2;
	h1.x=p3.x-p1.x;
	h1.y=p3.y-p1.y;
	h2.x=p2.x-p1.x;
	h2.y=p2.y-p1.y;
	return (h1.x*h2.y-h1.y*h2.x);
}
int pd1(node p1,node p2,node p3)
{
	double t;
	if (p1.x>p2.x)
	{
		t=p1.x;
		p1.x=p2.x;
		p2.x=t;
	}
	if (p1.y>p2.y)
	{
		t=p1.y;
		p1.y=p2.y;
		p2.y=t;
	}
	if (p3.x>=p1.x && p3.x<=p2.x && p3.y>=p1.y && p3.y<=p2.y)
		return 1;
	else return 0;
}
int pd(node p1,node p2,node p3,node p4)
{
	double d1,d2,d3,d4;
	d1=js(p3,p4,p1);
	d2=js(p3,p4,p2);
	d3=js(p1,p2,p3);
	d4=js(p1,p2,p4);
	if (d1*d2<0 && d3*d4<0)
		return 1;
	else
	{
		if (d1==0 && pd1(p3,p4,p1)) return 1;
		if (d2==0 && pd1(p3,p4,p1)) return 1;
		if (d3==0 && pd1(p1,p2,p3)) return 1;
		if (d4==0 && pd1(p1,p2,p4)) return 1;
	}
	return 0;
}
node operator -(node a,node b)
{
	return node(a.x-b.x,a.y-b.y);
}
double cross(node a,node b)
{
	return (a.x*b.y)-(a.y*b.x);
}
void getp(node a,node b,node c,node d)
{
	node pp;
	pp.x=(c.x*cross(b-a,d-a)-d.x*cross(b-a,c-a))/((cross(b-a,d-a)-cross(b-a,c-a)));
	pp.y=(c.y*cross(b-a,d-a)-d.y*cross(b-a,c-a))/((cross(b-a,d-a)-cross(b-a,c-a)));
	printf("交点为:(%lf,%lf)\n",pp.x,pp.y);
	return;
}
int main()
{
	while (~scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p[1].x,&p[1].y,&p[2].x,&p[2].y,&p[3].x,&p[3].y,&p[4].x,&p[4].y))
	{
		if (pd(p[1],p[2],p[3],p[4]))
		{
			/*double t=(double)((p[1].x-p[3].x) * (p[3].y-p[4].y)-(p[1].y-p[3].y)*(p[3].x-p[4].x))
			/(double)((p[1].x-p[2].x) * (p[3].y-p[4].y)-(p[1].y-p[2].y)*(p[3].x-p[4].x));
			node q;
			q.x=(p[2].x-p[1].x)*t;
			q.y=(p[2].y-p[1].y)*t;
			printf("交点为:(%lf,%lf)\n",q.x,q.y);
			double lll=js(p[1],p[2],p[4]);
			cout<<lll<<endl;
			double k1=fabs(js(p[1],p[2],p[3])/js(p[1],p[2],p[4]));
			printf("交点为:(%lf,%lf)\n",(p[3].x+k1*p[4].x)/(1+k1),(p[3].y+k1*p[4].y)/(1+k1));*/
			getp(p[1],p[2],p[3],p[4]);
		}
		else printf("No\n");
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: