POJ1269 计算几何直线与直线的关系

本文介绍如何通过外积判断两条直线是否共线,并提供了一个C++模板用于判断两线段之间的关系(共线、平行或相交),以及如何求解线段交点的坐标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:判断直线关系:共线,平行,交点

外积判断共线

模板代码如下:

#include
#include
#include
#include
typedef long long int ll;
using   namespace    std;
const double eps = 1e-8;
const double PI = acos(-1.0);
int sgn(double x)
{
	if(fabs(x) < eps)return 0;
	if(x < 0)return -1;
	else return 1;
}
struct point
{
	double x,y;
	point() {}  point(double _x,double _y)
	{
		x = _x;
		y = _y;
	}  point operator -(const point &b)const
	{
		return point(x - b.x,y - b.y);

	}
	double operator ^(const point &b)const	//叉积
	{
		return x*b.y - y*b.x;
	}
	double operator *(const point &b)const //点积
	{
		return x*b.x + y*b.y;     //绕原点旋转角度B(弧度值),后x,y的变化
	}
	void transXY(double B)
	{
		double tx = x,ty = y;
		x = tx*cos(B) - ty*sin(B);
		y = tx*sin(B) + ty*cos(B);
	}
};
struct line
{
	point s,e;
	line() {}
	line(point _s,point _e)
	{
		s = _s;
		e = _e;
	}
} lines[1005];
double xmult(point p0,point p1,point p2) //计算p0p1 X p0p2
{
	return (p1-p0)^(p2-p0);
}
bool isbanana(point s1,point e1,point s2,point e2) //判断线段P1P2 与线段P3P4是否相交
{
	return ( (max(s1.x,e1.x)+eps>min(s2.x,e2.x))&&
	         (max(s2.x,e2.x)+eps>min(s1.x,e1.x))&&
	         (max(s1.y,e1.y)+eps>min(s2.y,e2.y))&&
	         (max(s2.y,e2.y)+eps>min(s1.y,e1.y))&&
	         (xmult(s1,s2,e1)*xmult(s1,e1,e2)+eps>0)&&(xmult(s2,s1,e2)*xmult(s2,e2,e1)+eps>0) );
}
int linetoline(point p1,point p2,point p3,point p4)//判断线段P1P2与线段P3P4的关系
{
	if(sgn(xmult(p1,p3,p4))==0&&sgn(xmult(p2,p3,p4))==0)
	{
		return -2;//说明共线,共线不一定有交点  //PS 这种忽略了一种 共线但是没交点的情况
	}
	if(sgn((p1.x-p2.x)*(p3.y-p4.y)-(p1.y-p2.y)*(p3.x-p4.x))==0)//说明平行
	{
		return -1;
	}
	if(!isbanana(p1,p2,p3,p4))//无交点 
	{
		return 0;
	}
	return 1;
}
point bananapoint(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
//返回直线p1p2 直线p3p4的交点 如果是直线就先判线段关系
{
	point res=point(0.0,0.0);
	double a1=y1-y2,b1=x2-x1,c1=x1*y2-x2*y1;
	double a2=y3-y4,b2=x4-x3,c2=x3*y4-x4*y3;
	double x=(c2*b1-c1*b2)/(b2*a1-b1*a2);
	double y=(a2*c1-a1*c2)/(b2*a1-b1*a2);
	if(y==0)y=fabs(y);
	if(x==0)x=fabs(x);
	res.x=x;
	res.y=y;
	return res;
}
int main()
{
	int T;
	cout<<"INTERSECTING LINES OUTPUT"<>T;
	while(T--)
	{
		double x1,y1,x2,y2,x3,y3,x4,y4;
		cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
		point p1=point(x1,y1);
		point p2=point(x2,y2);
		point p3=point(x3,y3);
		point p4=point(x4,y4);
		int ans=linetoline(p1,p2,p3,p4);
		if(ans==-2)
		{
			printf("LINE\n");
			continue;
		}
		if(ans==-1)
		{
			printf("NONE\n");
			continue;
		}
//		if(ans==0)
//		{
//			printf("NONE\n");
//			continue;
//		}
		point pans=bananapoint(p1.x,p1.y,p2.x,p2.y,p3.x,p3.y,p4.x,p4.y);
		printf("POINT %.2f %.2f\n",pans.x,pans.y);//C++ 用%.2lf  
	}
	cout<<"END OF OUTPUT"<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值