利用无人机对一片区域进行测绘前,我们会先在地图上框选一个区域,然后再规划飞行的路线,而需要测绘的这片区域往往是一个多边形。这就涉及判断多边形是否合法的问题。
首先我们要确定一个标准:怎么样才算一个不合法的多边形 ?我们可以简单地通过下面这幅图来解释一下:
![f028b4f979ad56213d8591c3f59f386d.png](https://i-blog.csdnimg.cn/blog_migrate/16f03b4a73b578889dd38e2c170f9e45.jpeg)
我们可以看出前面两个分别是凹多边形和凸多边形,而最后一张则是我们所说的不合法多边形,可以看出这个不合法的多边形的特征就是:它存在某条边与另外一条边相交的情况 。
那么要判断一个多边形是否合法,我们只要判断组成多边形的所有线段是否存在相交的情况即可,当然,我们这里所说的相交是 规范相交 ,即 交点不在线段的端点上 。
好了,那么现在的问题可以简化成:如何判断两条线段是否规范相交 。
这里我们需要借助 向量的叉积 来进行判断。
叉积,又称向量积,是对三维空间中的两个向量的二元运算。
这里推荐 3Blue1Brown 的 视频 来快速回顾一下叉积的概念(下面的两幅截图来自此视频)。我们只需知道叉积的结果是有正负的,比如我们以向量
![46b9044a9e3709666bf5f707e6295cf1.png](https://i-blog.csdnimg.cn/blog_migrate/1c319640e310115f28be6747653a1d0a.png)
如果向量
![0e64782d4d983bbf9a121db0608cba0f.png](https://i-blog.csdnimg.cn/blog_migrate/915c73fa15e6eb171c78b18ec02a1490.png)
那么我们如何利用叉积的特性运用到判断线段是否相交上呢?
我们先看下面最直接的一个线段相交的情况:
![a8a7f4f340cd753707e05f1ab288e671.png](https://i-blog.csdnimg.cn/blog_migrate/99f50090fa903ef928b447b19c9871ee.png)
线段
我们可以将上面的图转换为向量的情况来看:
![000782e3378ad83834c35bd1de94151a.png](https://i-blog.csdnimg.cn/blog_migrate/dbd7dadb06ba37474868b6afab24a2f7.png)
是不是觉得似曾相识,这跟上面提到的叉积的情况是不是很类似?
向量
向量
用 A 表示
用 B 表示
那么 一条的线段的两个端点在另外一条线段两侧 这个几何现象可以用这个公式表示 :
A*B < 0
我们前面提到 如果一条的线段的两个端点在另外一条线段两侧,那么这两条线段可能相交 ,为什么是可能相交呢?如果我们将 线段
![f65b42bdaab092fe116da0a0cf4fb5d1.png](https://i-blog.csdnimg.cn/blog_migrate/872889a0df574cd5fa85a770e5ce59f3.png)
从上图可以看出,线段
那么如何排除这种情况呢?其实很简单,我们之前都是以线段
![9de818d44c820e3b0ca405319247ad30.png](https://i-blog.csdnimg.cn/blog_migrate/67bd77dcc15a23f766e671b9525a4b72.png)
向量
向量
综上,我们可以得出:
当 A * B < 0 && C * D < 0 的时候,两条线段规范相交。
至于向量的叉积如何运算,这里就不细写了,给出一张计算草稿给大家过目一下:
![b3f2ab7d985b95411daa55bf84f9a81f.png](https://i-blog.csdnimg.cn/blog_migrate/4435035ce477480cef9f349b2ba63d0d.jpeg)
根据计算草稿的内容,我们就很容易通过代码(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
}