空间或平面判断两线段相交(求交点)
2.1. 解析几何算法
比如说,在平面中判断两线段相交,我们可以很容易通过解析几何来求解,联立两直线的代数方程:
(y−y2)/(y1−y2)=(x−x2)/(x1−x2)
然后对这个二元二次方程进行求解。很容易得到相应算法的代码:
//判断两线段相交
bool IsIntersect(double px1, double py1, double px2, double py2, double px3, double py3, double px4, double py4)
{
bool flag = false;
double d = (px2 - px1) * (py4 - py3) - (py2 - py1) * (px4 - px3);
if (d != 0)
{
double r = ((py1 - py3) * (px4 - px3) - (px1 - px3) * (py4 - py3)) / d;
double s = ((py1 - py3) * (px2 - px1) - (px1 - px3) * (py2 - py1)) / d;
if ((r >= 0) && (r <= 1) && (s >= 0) && (s <= 1))
{
flag = true;
}
}
return flag;
}
可以看出这个算法其实并不严密,其实缺少了对一些极端条件的判断,比如与坐标轴平行的情况,两直线平行的情况,还需要做额外的判断。同时用了很多乘法和除法,算法效率并不高。
2.2. 同侧法
这种算法的思想是:如果两条线段相交,那么一条线段的两端点必然位于另一条线段的两端点的异侧。那么问题就可以转换成点是否在一条线段的同侧。同侧判断可以通过向量叉乘的方法来实现,即判断最后叉乘的方向是否相同。
这个算法与平面中判断点在三角形内算法这篇文章介绍的同侧/异侧判断是一样的,我认为算是比较优秀快速的算法了。不过这个算法可以判断定性判断,无法定量判断准确的交点。而且实际使用过程中,似乎精度不太准确(个人实验结论,尤其是位于三角形边上的点)。
2.3. 向量方程法
2.3.1. 原理
已知空间中线段的起点O和终点E,那么显然方向向量D为:
D=E−O
这时,可以确定线段上某一点P为:
P=O+tD
其中,t为范围满足0<=t<=1的标量。
这个方程就是线段上某一点的向量方程。如果要求两线段的交点,很显然可以将两个线段进行联立:
{P=O1+t1D1P=O2+t2D2
上式-下式,有:
t1D1−t2D2=O2−O1=O12(1)
在平面上展开,也就是使用X和Y分量:
[D1.xD1.y−D2.x−D2.y][t1t2]=[O12.xO12.y]
那么这个问题就转换成了求解2行2列的线性方程组,如果有解,说明存在交点并直接求出。2行2列线性方程组直接使用克莱姆法则求解即可。
2.3.2. 实现
具体的C++实现代码如下:
//空间直线
template
class LineSegment
{
public:
Vec3 startPoint;
Vec3 endPoint;
Vec3 direction;
Vec3<T> min;
Vec3<T> max;LineSegment()
{
}LineSegment(Vec3<T> start, Vec3<T> end)
{startPoint = start;endPoint = end;direction = end - start;CalMinMax();
}inline void Set(Vec3<T> start, Vec3<T> end)
{startPoint = start;endPoint = end;direction = end - start;CalMinMax();
}inline void CalMinMax()
{min.x() = std::min<T>(startPoint.x(), endPoint.x());min.y() = std::min<T>(startPoint.y(), endPoint.y());min.z() = std::min<T>(startPoint.z(), endPoint.z());max.x() = std::max<T>(startPoint.x(), endPoint.x());max.y() = std::max<T>(startPoint.y(), endPoint.y());max.z() = std::max<T>(startPoint.z(), endPoint.z());
}//两条线段相交
inline static bool Intersection2D(LineSegment & line1, LineSegment & line2, Vec3<T>& insPoint)
{double D = -line1.direction.x() * line2.direction.y() + line1.direction.y() * line2.direction.x();if(D == 0.0){return false;}auto O12 = line2.startPoint - line1.startPoint;T D1 = -O12.x() * line2.direction.y() + O12.y() * line2.direction.x();T D2 = line1.direction.x() * O12.y() - line1.direction.y() * O12.x();T t1 = D1 / D;if(t1<0 || t1 > 1){return false;}T t2 = D2 / D;if(t2<0 || t2 > 1){return false;}insPoint = line1.startPoint + line1.direction * t1; //这样计算得到的Z值是不准确的return true;
}
};
USB Microphone https://www.soft-voice.com/
Wooden Speakers https://www.zeshuiplatform.com/
亚马逊测评 www.yisuping.cn
深圳网站建设www.sz886.com
空间或平面判断两线段相交(求交点)相关推荐
- python求交点坐标_Python - 两圆相交求交点坐标
Python - 两圆相交求交点坐标 Max.Bai 2016-05-16 Python - 两圆相交求交点坐标 三轴机械臂求坐标问题,其实转化为平面问题就是两圆相交求交点问题,交点算出来就可以用反三 ...
- 计算几何 快速排斥和跨立实验 判断两线段相交
线段P1P2, Q1Q2,判断其是否相交,通过快速排斥和跨立实验则说明相交 首先要知道:向量a×向量b(×为向量叉乘),若结果小于0,表示向量b在向量a的逆时针方向:若结果大于0,表示向量b在向量a的 ...
- 判断两线段相交[nyoj 1016 德莱联盟]
题目链接:点击打开链接 题目意思很简单,就是问两个线段是否可以相交. 思路很是简单,两个线段互相跨立就可以相交了.所谓跨立就是,一条线段的两个点在另一条线段的两侧. 这个题目的数据有点水,没有考虑到点 ...
- python判断两线段是否相交_c语言 判断两直线段是否相交
转了多人的放到一起比较!! //功能:求点在有向直线左边还是右边 //返回:0共线.1左边.-1右边 intleft_right(pointa,pointb,doublex,doubley) { do ...
- python 求两线段是否相交,如果相交求交点
代码如下,cal_point = False 不输出交点,cal_point = True 输出交点 def cross(p1,p2,p3):#跨立实验 x1=p2.x-p1.x y1 ...
- [GIS算法] 判断两线段是否相交的四种方案(快速排斥+跨立实验、参数方程求解、凸多边形、点在线的哪一侧)-附C语言实现
文章目录 算法一:快速排斥+跨立试验 代码 算法二:参数方程求解 代码 算法三:凸多边形 算法四:点在线的哪一侧 算法一:快速排斥+跨立试验 重点掌握 [原理]利用矢量的叉乘 [图解] 代码 #def ...
- hdu 1086(判断两线段是否相交)
题意:给出一些线段,问有多少个交点. 解题思路:这里实际就是一个线段相交的模型,下面这个图给出了思路. 如果两线段相交,则两线段必然相互跨立对方.若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ...
- 判断平面上两直线相交
直线相交 首先引出计算几何学中一个最基本的问题:如何判断向量在的顺时针方向还是逆时针方向? 把p0定为原点,p1的坐标是(x1,y1),p2的坐标是(x2,y2).向量的叉积(cross produc ...
- 两条直线求交点c语言,C§ 3.3.1两条直线的交点坐标(5页)-原创力文档
§ 3.1两条直线的交点坐标 学习目标 1.掌握判断两直线相交的方法:会求两直线交点坐标: 2.体会判断两直线相交中的数形结合思想. 学习过程 一.课前准备: (预习教材P112~ P114,找出疑 ...
- c语言直线和椭圆的交点,直线与椭圆相交求交点
已知a,b和直线上的两点,中心在原点,求直线与椭圆相交求交点坐标 #include #include #include void main() { double a,b,c,x1,x2,y1,y2,k ...
最新文章
- 二分搜索 POJ 2456 Aggressive cows
- Chart.js-雷达图分析(参数分析+例图)
- 数组字段查询不包含_不可不知的可变Java长数组
- 执行插件超过2分钟超时错误,如何办?
- Socket.io发送消息含义
- jpa原生query_Spring Data JPA原生SQL查询
- (最短路)Shopping
- java http 双向认证_HttpsURLConnection使用,并实现双向认证
- python怎样清除csv中的数据_使用d清除CSV文件中的数据
- 宾州州立计算机科学世界排名,宾州州立大学帕克分校qs世界排名
- 原型设计工具——“墨刀”的介绍与基本教程
- OpenSSL环境搭建(WIN10+VS2017)
- 为啥翻唱的也特别好听呢,听J Fla 的 despacito
- PrometheusAlert安装和其基本的使用
- 拥抱AI!人工智能如何在疫情期间重塑娱乐业?
- 机械/仪表领域北大核心期刊(摘自第九版)
- 如何查看笔记本电池损耗情况-不借助软件
- 第二届先导杯-在曙光超算平台编译cp2k(二)
- 工业互联网如何做到增加30%营收还能节省80%成本?
- 史上最短命 Windows 系统!比尔盖茨研发,用过几乎都是差评...
热门文章
- 硬盘配置raid5时碰见unconfiguration bad问题记录
- 《正在爆发的互联网革命》
- 分享一下Android开发11年,我眼中程序员的三六九等
- 【全示例通过】防沉迷实名认证系统接口测试代码(包含Golang和Java版本)
- 智能家庭系统micropython实现2
- HackTheBox Behind The Scenes 逆向题目分析
- 我要自学网视频教程ajax,这么逆天的自学网站,还是第一次见,难怪考不上清华北大...
- 20120814打工者的悲哀
- linux awk 命令
- CET.4 一次过备考纪要