两条直线的交点(叉积)

/*在两条直线相交时,求相交点
 方法1:可以直线方程来求解,但是效率低下,而且程序繁琐。
 方法2:使用叉积公式求交点,即高效又简便。

  介绍方法2:
    设mul(p1,p2,p0)为p1p0与p0p1的叉积,即mul(p1,p2,p0)=(p1-p0)^(p2-p0)。
    该叉积可以看做由点p0,p1,p2和p1+p2四个点围成的平行四边形的阴影面积,
  即三角形p1p2p0面积s(p1p2p0)=mul(p1,p2,p0)/2;

    四边形ABCD,线段AB与CD交于点P。从D点出发引一条AB的垂线DD',从C点出发引一条AB的垂线CC',
  由于三角形DD'P与三角形CC'P相似,因此|DD'|/|CC'|=|DP|/|PC|;由因为S(ABD)=(DD'*AB)/2,
  S(ABC)=(CC'*AB)/2;
  ==>|DP|/|PC|=S(ABD)/S(ABC)=|AD*AB|/|AC*AB|=|mul(D,B,A)|/|mul(C,B,A)|
  又因为|DP|/|PC|=(x(D)-x(P))/(x(P)-x(C))=(y(D)-y(P))/(y(P)-y(C));
  x(p)=(S(ABD)*x(C)+S(ABC)*x(D))/(S(ABD)+S(ABC))
      =(mul(D,B,A)*x(C)-mul(C,B,A)*x(D))/mul(D,C,A)-mul(C,B,A);
  x(p)=(S(ABD)*y(C)+S(ABC)*y(D))/(S(ABD)+S(ABC))
      =(mul(D,B,A)*y(C)-mul(C,B,A)*y(D))/mul(D,C,A)-mul(C,B,A);
*/




/* poj 1269
例子:
Sample Input
5
0 0 4 4 0 4 4 0
5 0 7 6 1 0 2 3
5 0 7 6 3 -6 4 -3
2 0 2 27 1 5 18 5
0 3 4 0 1 2 2 5
Sample Output
INTERSECTING LINES OUTPUT
POINT 2.00 2.00
NONE
LINE
POINT 2.00 5.00
POINT 1.07 2.20
END OF OUTPUT
解题思路:
计算a1=mul(p1,p2,p3) a2=mul(p1,p2,p4);
若a1==0&&a2==0,则重叠
若a1与a2同号,两者平行
若a1与a2异号,相交
 p=((a2*p3.x-a1*p4.x)/(a2-a1),(a2*p3.y-a1*p4.y)/(a2-a1));
*/
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
const double epsi=1e-10;
struct Point
{
	double x,y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	Point operator -(const Point &op) const
	{
		return Point(x-op.x,y-op.y);
	}
	double operator ^(const Point &op) const
	{
		return x*op.y-y*op.x;
	}
};
inline int sign(const double &x)
{
	if(x>epsi) return 1;
	if(x<-epsi) return -1;
	return 0;
}
inline double sqr( const double &x)
{
	return x*x;
}
inline double dis(const Point &p1,const Point &p2)
{
	return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));
}
inline double mul(const Point &p0,const Point &p1,const Point &p2)
{
	return (p1-p0)^(p2-p0);
}
inline int cross(const Point &p1,const Point &p2,const Point &p3,const Point &p4,Point &p)
{
	double a1=mul(p1,p2,p3),a2=mul(p1,p2,p4);
	if(sign(a1)==0&&sign(a2)==0) return 2;//重叠
	if(sign(a1-a2)==0) return 0;//平行
	p.x=(a2*p3.x-a1*p4.x)/(a2-a1);
	p.y=(a2*p3.y-a1*p4.y)/(a2-a1);
	return 1;//相交
}
Point p1,p2,p3,p4,p;
int main()
{
	int test=0;
	printf("INTERSECTING LINES OUTPUT\n");
	scanf("%d",&test);
	while(test--)
	{
		scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y,&p3.x,&p3.y,&p4.x,&p4.y);
		int fm=cross(p1,p2,p3,p4,p);
		if(fm==0) printf("NONE\n");
        else if(fm==2) printf("LINE\n");
		else printf("POINT %.2lf %.2lf\n",p.x,p.y);
	}
	printf("END OF OUTPUT\n");
	return 0;
}


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

u014068781

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值