【C++】判断两条“线段”是否相交

发布于:2023-01-04 ⋅ 阅读:(209) ⋅ 点赞:(0)

判断两条直线是否相交,通过快速排斥实验和跨立实验进行判断。
快速排斥实验,主要原理:

如果l1.x的最小值比l2.x的最大值还要大,肯定没有交点
如果l1.y的最小值比l2.y的最大值还要大,肯定没有交点
反之如下:交换l1和l2的位置
如果l2.x的最小值比l1.x的最大值还要大,肯定没有交点
如果l2.y的最小值比l1.y的最大值还要大,肯定没有交点
在这里插入图片描述
在这里插入图片描述

跨立实验原理,主要原理:

进行叉积运算,向量AC×向量AB,向量AD×向量AB,如果两个向量(AC,AD)都排在两边,那么两个结果则分别指向纸内和纸外,这样,将上面叉积的结果进行点积运算,就可以得到一个负值。
当最终点积等于0的时候,说明两条重合,这时也符合条件(由于通过了第一步的快速排斥实验)
交换两条直线,同理。
综上,最终点积大于0的情况为两条直线不相交的情况
在这里插入图片描述

// An highlighted block
#include<iostream>
using namespace std;

struct Line {
	double x1;
	double y1;
	double x2;
	double y2;
};

// 快速排斥实验  Rapid rejection experiments
bool RapidRejExper(Line& l1, Line& l2) {
	if ((l1.x1 > l1.x2 ? l1.x1 : l1.x2) < (l2.x1 < l2.x2 ? l2.x1 : l2.x2) ||
		(l1.y1 > l1.y2 ? l1.y1 : l1.y2) < (l2.y1 < l2.y2 ? l2.y1 : l2.y2) ||
		(l2.x1 > l2.x2 ? l2.x1 : l2.x2) < (l1.x1 < l1.x2 ? l1.x1 : l1.x2) ||
		(l2.y1 > l2.y2 ? l2.y1 : l2.y2) < (l1.y1 < l1.y2 ? l1.y1 : l1.y2)) {
		return false;
	}
	return true;
}

// 跨立实验
bool Cross(Line& l1, Line& l2) {
	if ((((l1.x1 - l2.x1) * (l2.y2 - l2.y1) - (l1.y1 - l2.y1) * (l2.x2 - l2.x1)) *
		((l1.x2 - l2.x1) * (l2.y2 - l2.y1) - (l1.y2 - l2.y1) * (l2.x2 - l2.x1))) > 0 ||
		(((l2.x1 - l1.x1) * (l1.y2 - l1.y1) - (l2.y1 - l1.y1) * (l1.x2 - l1.x1)) *
			((l2.x2 - l1.x1) * (l1.y2 - l1.y1) - (l2.y2 - l1.y1) * (l1.x2 - l1.x1))) > 0)
	{
		return false;
	}
	return true;
}


int main() {
	Line l1, l2;
	cin >> l1.x1 >> l1.y1 >> l1.x2 >> l1.y2;
	cin >> l2.x1 >> l2.y1 >> l2.x2 >> l2.y2;
	if (RapidRejExper(l1, l2) && Cross(l1, l2)) {
		cout << "Yes";
	}
	else {
		cout << "No";
	}
}

针对评论区老哥"时光3"问题的解答

这个了解了,不过还是得到的结果和你列的不一样,能把你一步一步叉乘乘以叉乘展开得到这个结果的过程列一下吗?
另外,感觉判断两个点在一个边的两边,把四个点的坐标都用到了,算一次就可以了,再算这个边是不是在另一个边的两边是重复计算呀。

在这里插入图片描述
主要解答为什么要对称计算两条直线的问题。推理过程很简单,大概就是我上面列的式子的坐标形式了。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到