在知道一个使用两个点表示的线段,和另一个点,求另一个点是否在线段上
本文算法属于通用的算法,可以在 WPF 和 UWP 和 Xamarin 等上运行,基本上所有的 .NET 平台都能执行
如下图,如果点在线段上,那么修改线段颜色
假定有线段的定义如下
以上代码使用了 .NET 5 加 C# 9.0 的新语法
在传入一个点,求这个点是否在线段上,最简单理解的算法是根据两点之间直线距离最短,只需要求 P 点和线段的 AB 两点的距离是否等于 AB 的距离。如果相等,那么证明 P 点在线段 AB 上,代码如下
不使用 Vector 类,可以替换为如下计算方法。上面代码的 ap 等变量是使用 WPF 的两个点的相减能拿到 Vectore 类,而在 Vectore 类里面有 Length 属性而优化代码的。其实核心计算和下面代码相同。下面代码是 Tone Škoda 提供的,详细请看 https://stackoverflow.com/a/56850069/6116637
以下是另一个方法,以下方法性能比上面一个好,上面的方法需要用到平方再开方,计算复杂度会高一些
根据点和任意线段端点连接的线段和当前线段斜率相同,同时点在两个端点中间,就可以认为点在线段内
因为乘法性能更高,因此计算方法可以根据如下公式进行改进
在完成斜率判断之后,还需要判断点在两个端点中间,判断点是否在两个端点中间可以通过 x 和 y 两个分量都在两个端点中间作为判断条件,如下面公式
以下是代码
上面代码的 CrossProduct 是不用使用的,只是为了告诉大家,尽管乘法性能比较好,但是误差比较大。以上的 CrossProduct 使用了叉乘的方法,在本文末尾也会重新再讲一次
当然以上算法有漏洞,在于如果 A 和 B 两个点的 Y 坐标相同或 X 坐标相同的时候,那么以上算法不适合。可以先判断 CrossProduct 的值,如果是等于零,那么证明有 A 和 B 两个点的 Y 坐标相同或 X 坐标相同
以上代码放在 github 和 gitee 欢迎小伙伴访问
以上方法的计算有些重复,其实加上了 CrossProduct 只是为了水平和垂直的线段,其实可以做特殊处理优化水平和垂直的线段的计算,如下面代码
以上代码放在 github 和 gitee 欢迎小伙伴访问
除了以上方法之外,还可以通过叉积法求点是否在直线上,再通过判断与端点两点的差值从而判断点是否在线段上
叉积法又称向量法。计算方法就是将原本线段构成向量,再与所求点与线段任意端点构成的向量,两个向量之间的叉乘计算,求向量的叉乘结果与 0 判断,从而判断点是否在线段所在直线上。在 2D 几何的向量叉乘计算上,更准确来说是使用向量叉乘在二维空间中的推广
以上的 Vector2D 的 Det 的定义如下
可以看到这里介绍的叉乘方法本质上和上文所述的数学计算过程是相同的,只是所使用的概念不同
以上更多的数学定义代码我放在 github 和 gitee 欢迎访问
原文链接: http://blog.lindexi.com/post/WPF-%E5%9F%BA%E7%A1%80-2D-%E5%9B%BE%E5%BD%A2%E5%AD%A6%E7%9F%A5%E8%AF%86-%E5%88%A4%E6%96%AD%E7%82%B9%E6%98%AF%E5%90%A6%E5%9C%A8%E7%BA%BF%E6%AE%B5%E4%B8%8A
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。