判断线段相交,朴素的方法(初中直线方程的判断方法),就是先计算两条直线的交点,然后再判断交点是否在其中一条的线段上。这也是笔者能唯一想到的方法,后来抱着试试看有没有更好方法的想法,搜了一下网络。哦, 真有,即所谓的快速排斥和跨立实验。
请参考:
https://www.cnblogs.com/TangMoon/archive/2017/09/29/7611115.html
快速排斥很容易理解,跨立实验,要用到矢量计算。要理解叉乘和点乘的概念。
参考:
https://zhuanlan.zhihu.com/p/359975221
有关矢量乘法,本人早已忘得精光了,因此,我要得只是结论,也不想探究其本质了。当时学的时候,就对矢量不感兴趣,没想到现在用上了。
本人的C#代码
/// <summary>
/// judge if the 2 segments intersected.
/// From ————————————————
/// 版权声明:本文为CSDN博主「Siannodel_」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。
///原文链接:https://blog.csdn.net/qq826309057/article/details/70942061
/// </summary>
/// <returns></returns>
public static bool SegIntersectedSeg(PointF l1_p1, PointF l1_p2, PointF l2_p1, PointF l2_p2)
{
//快速排斥实验
if ((l1_p1.X > l1_p2.X ? l1_p1.X : l1_p2.X) < (l2_p1.X < l2_p2.X ? l2_p1.X : l2_p2.X) ||
(l1_p1.Y > l1_p2.Y ? l1_p1.Y : l1_p2.Y) < (l2_p1.Y < l2_p2.Y ? l2_p1.Y : l2_p2.Y) ||
(l2_p1.X > l2_p2.X ? l2_p1.X : l2_p2.X) < (l1_p1.X < l1_p2.X ? l1_p1.X : l1_p2.X) ||
(l2_p1.Y > l2_p2.Y ? l2_p1.Y : l2_p2.Y) < (l1_p1.Y < l1_p2.Y ? l1_p1.Y : l1_p2.Y))
{
return false;
}
//跨立实验
//
var Z1 = ((l1_p1.X - l2_p1.X) * (l2_p2.Y - l2_p1.Y) - (l1_p1.Y - l2_p1.Y) * (l2_p2.X - l2_p1.X));
var Z2 = ((l1_p2.X - l2_p1.X) * (l2_p2.Y - l2_p1.Y) - (l1_p2.Y - l2_p1.Y) * (l2_p2.X - l2_p1.X));
var Z3 = ((l2_p1.X - l1_p1.X) * (l1_p2.Y - l1_p1.Y) - (l2_p1.Y - l1_p1.Y) * (l1_p2.X - l1_p1.X));
var Z4 = ((l2_p2.X - l1_p1.X) * (l1_p2.Y - l1_p1.Y) - (l2_p2.Y - l1_p1.Y) * (l1_p2.X - l1_p1.X));
// floating calculation error processing
Z1 = ZeroProcess(Z1);
Z2 = ZeroProcess(Z2);
Z3 = ZeroProcess(Z3);
Z4= ZeroProcess(Z4);
if (Z1*Z2 > 0 || Z3 *Z4 > 0)
{
return false;
}
return true;
}
说明:参考代码中用的都是理论值,但是实际应用中,计算都有误差,笔者在调试过程当中,发现由于误差导致判断错误,因此根据实际情况对误差做了近似处理,主要是0 的判断。采用浮点数计算时,对于本算法用的点的精度(计算机屏幕分辨率的量级)而言,小数点后面三位就够了。因此增加了一个0 值处理的函数,代码如下:
private static float ZeroProcess(float f)
{
if (Math.Abs(f) < 1e-3){
f = 0;
}
return f;
}
上述代码在1920*1280 分辨率,调试通过。
maraSun 2022–4-32 BJFWDQ
关注SHFY,关注国家发展。