如何判断一个多边形是否合法 (Swift 代码实现)

栏目: Swift · 发布时间: 7年前

内容简介:利用无人机对一片区域进行测绘前,我们会先在地图上框选一个区域,然后再规划飞行的路线,而需要测绘的这片区域往往是一个多边形。在首先我们要确定一个标准:我们可以看出前面两个分别是凹多边形和凸多边形,而最后一张则是我们所说的不合法多边形,可以看出这个不合法的多边形的特征就是:

利用无人机对一片区域进行测绘前,我们会先在地图上框选一个区域,然后再规划飞行的路线,而需要测绘的这片区域往往是一个多边形。在 MeshKit iOS 中,我们加入了多边形区域的编辑功能,其中就涉及判断用户所编辑出来的多边形是否合法的问题。

首先我们要确定一个标准: 怎么样才算一个不合法的多边形 ?我们可以简单地通过下面这幅图来解释一下:

如何判断一个多边形是否合法 (Swift 代码实现)

我们可以看出前面两个分别是凹多边形和凸多边形,而最后一张则是我们所说的不合法多边形,可以看出这个不合法的多边形的特征就是: 它存在某条边与另外一条边相交的情况

那么要判断一个多边形是否合法,我们只要判断组成多边形的所有线段是否存在相交的情况即可,当然,我们这里所说的相交是 规范相交 ,即 交点不在线段的端点上

好了,那么现在的问题可以简化成: 如何判断两条线段是否规范相交

算法解析

这里我们需要借助 向量的叉积 来进行判断。

叉积,又称向量积,是对三维空间中的两个向量的二元运算。

这里推荐 3Blue1Brown 的视频 来快速回顾一下叉积的概念(下面的两幅截图来自此视频)。我们只需知道叉积的结果是有正负的,比如我们以向量 为标准,如下图,向量 在 的 顺时针方向 ,那么 :

如何判断一个多边形是否合法 (Swift 代码实现)

如果向量 在 的 逆时针方向 ,那么 :

如何判断一个多边形是否合法 (Swift 代码实现)

那么我们如何利用叉积的特性运用到判断线段是否相交上呢?

我们先看下面最直接的一个线段相交的情况:

如何判断一个多边形是否合法 (Swift 代码实现)

线段 和 线段 明显存在一个交点,从上面这张图我们可以做一个简单的结论: 如果一条的线段的两个端点在另外一条线段两侧,那么这两条线段可能相交 ,注意这里说的是可能相交,稍后会讲到另外一种情况。

我们可以将上面的图转换为向量的情况来看:

如何判断一个多边形是否合法 (Swift 代码实现)

是不是觉得似曾相识,这跟上面提到的叉积的情况是不是很类似? 向量 在 向量 在 的顺时针方向,那么:

用 A 表示 的叉积结果,用 B 表示 的叉积结果,那么 一条的线段的两个端点在另外一条线段两侧 这个几何现象可以用这个公式表示 :

我们前面提到 如果一条的线段的两个端点在另外一条线段两侧,那么这两条线段可能相交 ,为什么是可能相交呢?如果我们将 线段 往右边移动一下,会存在下面这种情况:

如何判断一个多边形是否合法 (Swift 代码实现)
从上图可以看出,线段 的两个端点在线段

两侧,但是它们并没有相交。

那么如何排除这种情况呢?其实很简单,我们之前都是以线段 作为主视角,如果将主视角换成线段 ,那么我们很容易看出 线段 的两个端点并没有在 线段 的两侧。所以我们再次看回上面相交的那幅图,为了能够充分的判断两条线段相交,这次以 为主视角看待这个问题,求叉积:

如何判断一个多边形是否合法 (Swift 代码实现)
向量 在 的逆时针方向,那么: 向量 在 的顺时针方向,那么:

综上,我们可以得出:

当 && 的时候,两条线段规范相交。 至于向量的叉积如何运算,这里就不细写了,给出一张计算草稿给大家过目一下:

如何判断一个多边形是否合法 (Swift 代码实现)

示例代码

根据计算草稿的内容,我们就很容易通过代码来实现了:

private func isIntersect(line1: (CGPoint, CGPoint), line2: (CGPoint, CGPoint)) -> Bool {
    let p1 = line1.0
    let p2 = line1.1
    let q1 = line2.0
    let q2 = line2.1

    let a1 = (p2.x - p1.x) * (q1.y - p1.y) - (q1.x - p1.x) * (p2.y - p1.y)
    let a2 = (p2.x - p1.x) * (q2.y - p1.y) - (q2.x - p1.x) * (p2.y - p1.y)
    
    let b1 = (q2.x - q1.x) * (p1.y - q1.y) - (p1.x - q1.x) * (q2.y - q1.y)
    let b2 = (q2.x - q1.x) * (p2.y - q1.y) - (p2.x - q1.x) * (q2.y - q1.y)
    
    if a1 * a2 < 0 && b1 * b2 < 0 {
        return true
    }
    return false
}
复制代码

由于笔者能力有限,文中如有错误还请各位读者不吝赐教。


以上所述就是小编给大家介绍的《如何判断一个多边形是否合法 (Swift 代码实现)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro Git

Pro Git

Scott Chacon / Apress / 2009-8-27 / USD 34.99

Git is the version control system developed by Linus Torvalds for Linux kernel development. It took the open source world by storm since its inception in 2005, and is used by small development shops a......一起来看看 《Pro Git》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试