热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【C++笔记】如何判断2个线段相交

判断2个线段相交有很多方法,最直接的方法就是直接计算两条直线的交点,然后看看交点是否分别在这两条线段上。这样的方法很容易理解,但是代码实现

判断 2 个线段相交有很多方法,最直接的方法就是直接计算两条直线的交点,然后看看交点是否分别在这两条线段上。这样的方法很容易理解,但是代码实现比较麻烦。

还有一种常用的方法是通过向量叉积来判断的,这种方法不需要算出直线方程,在代码实现上比较简便。 
用这种方法判别线段是否相交一般分为两步: 
1. 快速排斥实验 
2. 跨立实验

快速排斥实验

我们首先判断两条线段在 x 以及 y 坐标的投影是否有重合。 
也就是判断下一个线段中 x 较大的端点是否小于另一个线段中 x 较小的段点,若是,则说明两个线段必然没有交点,同理判断下 y。

这里写图片描述 
如上图所示,代码表示如下:

max(C.x,D.x).x,B.x) || max(C.y,D.y).y,B.y) ||
max(A.x,B.x).x,D.x) || max(A.y,B.y).y,C.y)

如果上面的四条判断有一个为真,则代表两线段必不可交,否则应该进行第二步判断。 
显然,上图通不过快速排斥实验。

跨立实验


矢量叉积

计算矢量叉积是与直线和线段相关算法的核心部分。 
设矢量 P = (x1, y1),Q = ( x2, y2 ),则矢量叉积定义为:P × Q = x1*y2 - x2*y1,其结果是一个矢量,与为 P Q 向量所在平面的法向量。显然有性质 P × Q = - ( Q × P ) 和 P × ( - Q ) = - ( P × Q )。 
叉积的一个非常重要性质是可以通过它的符号判断两矢量相互之间的顺逆时针关系: 
  若 P × Q > 0 , 则 P 在 Q 的顺时针方向。 
  若 P × Q <0 , 则 P 在 Q 的逆时针方向。 
  若 P × Q &#61; 0 , 则 P 与 Q 共线&#xff0c;但可能同向也可能反向。

通过叉积来判断线段相交

这里写图片描述 
如果两线段相交那么就意味着它们互相跨立&#xff0c;即如上图点 A 和 B 分别在线段 CD 两侧&#xff0c;点 C 和 D 分别在线 AB 两侧。 
判断 A 点与 B 点是否在线段 DC 的两侧&#xff0c;即向量 A-D 与向量 B-D 分别在向量 C-D 的两端&#xff0c;也就是其叉积是异号的&#xff0c;即 (AD)×(CD)(BD)×(CD)<0(A−D)×(C−D)∗(B−D)×(C−D)<0。 
同时也要证明 C 点与 D 点在线段 AB 的两端&#xff0c;两个同时满足&#xff0c;则表示线段相交。

然后我们来看看临界情况&#xff0c;也就是上式恰好等于 0 的情况下&#xff1a;

这里写图片描述

当出现如上图所示的情况的时候&#xff0c;(AD)×(CD)(BD)×(CD)&#61;0(A−D)×(C−D)∗(B−D)×(C−D)&#61;0&#xff0c;显然&#xff0c;这种情况是相交的。只要将等号直接补上即可。

再接得想一想&#xff0c;如果没有第一步的快速排斥实验&#xff0c;仅判断第二步&#xff0c;会出现什么问题&#xff1f;

这里写图片描述

当出现如上所示的情况的时候&#xff0c;叉积都为 0, 可以通过跨立实验&#xff0c;但是两个线段并没有交点。不过还好&#xff0c;这种情况在第一步快速排斥已经被排除了。

代码

struct Line {double x1;double y1;double x2;double y2;
};bool intersection(const Line &l1, const Line &l2)
{//快速排斥实验if ((l1.x1 > l1.x2 ? l1.x1 : l1.x2) <(l2.x1 l1.y2 ? l1.y1 : l1.y2) <(l2.y1 l2.x2 ? l2.x1 : l2.x2) <(l1.x1 l2.y2 ? l2.y1 : l2.y2) <(l1.y1 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;
}



推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 如何在跨函数中使用内存?
    本文介绍了在跨函数中使用内存的方法,包括使用指针变量、动态分配内存和静态分配内存的区别。通过示例代码说明了如何正确地在不同函数中使用内存,并提醒程序员在使用动态分配内存时要手动释放内存,以防止内存泄漏。 ... [详细]
author-avatar
910621rh_270
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有