POJ 1269 Intersecting Lines(叉乘应用及总结)

这篇博客介绍了如何在二维平面上判断两条线段是否相交,以及如果相交如何计算交点坐标。通过叉乘和向量平行的条件,可以确定线段的位置关系。当线段平行且共线时,它们可能是重合的;当线段不平行且叉乘结果异号时,表示线段相交。相交时,可以通过解二元一次方程组找到交点坐标。

在这里插入图片描述
在这里插入图片描述
题目大意:
给定两条直线判断两条直线的关系,是共线,平行还是相交。

思路:
对于叉乘,我们可以知道,判断一点在直线两侧可以用叉乘来判断。
在这里插入图片描述
在判断点与直线的位置时,可以通过该点与直线上两点的向量叉乘来判断其在直线左侧或是右侧或是线上,推广到线段间的关系:
通过画图可知,AB×AC两向量进行叉乘若结果>0则说明向量AC在向量AB的逆时针方向,结果<0则说明在AB的顺时针方向。当结果为0时说明两向量平行,但不能说明其共线。

在这里插入图片描述
此时我们需要任取两向量的两点组成一个新向量,对这个新向量与任意一条原向量进行叉乘若结果仍为0,即可说明两向量共线。

说完了向量平行的判断条件以及特殊情况共线,再来说一般情况的线段相交情况。

在这里插入图片描述

若两条线段相交,其俩点必在另一条线段两侧,这时我们利用点在线段两侧的判断性质,分别取两点连新向量与相交线段进行叉乘,对其结果进行判断若结果小于零即异号则说明两点在线段异侧则说明直线相交,若同号则说明两线段不相交。
在这里插入图片描述
但是也存在上图情况,两线段交于一点,也就是说在判断时任一叉乘为0也可判断为相交。
判断相交之后我们可以利用叉乘来求出交点坐标。

假设向量AB与CD相交于点P;

则有PA×PB=0,PC×PD=0PA×PB=0,PC×PD=0PA×PB=0,PC×PD=0

A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4)A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4)A(x1,y1)B(x2,y2)C(x3,y3)D(x4,y4)
则可得
(y1−y2)x0+(x2−x1)y0+x1y2−x2y1=0(y1-y2)x0+(x2-x1)y0+x1y2-x2y1=0(y1y2)x0+(x2x1)y0+x1y2x2y1=0
(y3−y4)x0+(x4−x3)y0+x3y4−x4y3=0(y3-y4)x0+(x4-x3)y0+x3y4-x4y3=0(y3y4)x0+(x4x3)y0+x3y4x4y3=0

即对二元一次方程组进行求解;

a1x+b1y+c1=0a1x+b1y+c1=0a1x+b1y+c1=0
a2x+b2y+c2=0a2x+b2y+c2=0a2x+b2y+c2=0

最后得
x=(c2∗b1−b2∗c1)/(a1∗b2−a2∗b1)x=(c2*b1-b2*c1)/(a1*b2-a2*b1)x=(c2b1b2c1)/(a1b2a2b1)
y=(a2∗c1−a1∗c2)/(a1∗b2−a2∗b1)y=(a2*c1-a1*c2)/(a1*b2-a2*b1)y=(a2c1a1c2)/(a1b2a2b1)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<queue>

#define fr for
#define pi 3.1415926535
#define me(a,b,c) memset(a,b,sizeof c)
#define cut cout
#define eps 0.000000001
//#define x first
//#define y second

using namespace std;

typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e6 + 10;
int n;

int t;
struct point {
	double x, y;

}a[110],b[110];

double cross(point a,point b,point c) {
	return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y);
}

double parrel(point a, point b, point c, point d) {
	return (b.x - a.x) * (d.y - c.y) - (d.x - c.x) * (b.y - a.y);
}
int main() {
	cin >> t;
    puts("INTERSECTING LINES OUTPUT");
	while (t--)
	{
		point x, y, z, c;
		cin >> x.x >> x.y >> y.x >> y.y >> z.x >> z.y >> c.x >> c.y;
		if (parrel(x, y, z, c) == 0)
			if (cross(x, y, z) == 0) 
				puts("LINE");
			else puts("NONE");
		else {
			double a1 = y.y - x.y, b1 = y.x - x.x, c1 = x.x * y.y - y.x * x.y;
			double a2 = c.y - z.y, b2 = c.x - z.x, c2 = z.x * c.y - c.x * z.y;
			double xx = (c1 * b2 - c2 * b1) / (a2 * b1 - b2 * a1);
			double yy = (a2 * c1 - a1 * c2) / (a1 * b2 - a2 * b1);
			printf("POINT %.2lf %.2lf\n", -xx, yy);

		}
		

		
		
	}
    puts("END OF OUTPUT");

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值