码迷,mamicode.com
首页 > 其他好文 > 详细

判断线段相交

时间:2016-04-16 18:36:06      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

 1 float cross(const Point &point0, const Point &point1)
 2 {
 3     return point0.first * point1.second - point0.second * point1.first;
 4 }
 5 
 6 bool isLineIntersect(const Point &point0, const Point &point1, const Point &point2, const Point &point3)
 7 {
 8     auto value0 = cross(
 9         std::make_pair(point1.first - point0.first, point1.second - point0.second),
10         std::make_pair(point3.first - point0.first, point3.second - point0.second));
11     auto value1 = cross(
12         std::make_pair(point1.first - point0.first, point1.second - point0.second),
13         std::make_pair(point2.first - point0.first, point2.second - point0.second));
14     auto value2 = cross(
15         std::make_pair(point3.first - point2.first, point3.second - point2.second),
16         std::make_pair(point0.first - point2.first, point0.second - point2.second));
17     auto value3 = cross(
18         std::make_pair(point3.first - point2.first, point3.second - point2.second),
19         std::make_pair(point1.first - point2.first, point1.second - point2.second));
20     return value0 < 0 != value1 < 0 && value2 < 0 != value3 < 0;
21 }

原理很简单,

通过向量叉积可以得到垂直于2个向量的向量.

通过两条线段互相分割, 叉积符号是否不同就可以判断线段是否相交.

例如线段, p0p1, p2p3.

先用p0p1分割p2p3:

p0p1 * p0p2

p0p1 * p0p3

再用p2p3分割p0p1:

p2p3 * p2p0

p2p3 * p2p1

如果

p0p1 * p0p2 < 0 !=p0p1 * p0p3 < 0 && 

p2p3 * p2p0 < 0 != p2p3 * p2p1 < 0

成立则线段相交.

 

这个问题困扰了我很多年, 我尝试着研究, 因为学识太浅, 无法理解其中的奥秘.

直到我明白了向量计算的含义才焕然大悟.

向量叉积是垂直于2个向量的向量, 

在2D坐标系里, 通过2D向量得到叉积是一个3D向量,

这个3D向量垂直于2个2D向量, 脑补一下, 这个3D向量必然平行于z轴.

平行z轴有正负2个方向, 这个方向取决于坐标系是左手还是右手. 向量叉乘是顺时针还是逆时针.

说的有点隐晦, 当理解向量计算之后, 判断线段相交只是一个很简单的问题.

判断线段相交

标签:

原文地址:http://www.cnblogs.com/mmc1206x/p/5398814.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!