介绍
射线法是一种很简单直观的判断平面内点是否在多边形内的方法。除了射线法还有很多其他的方法,今天就再介绍一种通过回转数来判断的方法。
平面中的闭合曲线关于一个点的回转数(又叫卷绕数),代表了曲线绕过该点的总次数。下面这张图动态演示了回转数的概念:图中红色曲线关于点(人所在位置)的回转数为 2。
回转数是拓扑学中的一个基本概念,具有很重要的性质和用途。本文并不打算在这一点上展开论述,这需要具备相当的数学知识,否则会非常乏味和难以理解。我们暂时只需要记住回转数的一个特性就行了:
当回转数为 0 时,点在闭合曲线外部。
对于给定的点和多边形,回转数应该怎么计算
-
用线段分别连接点和多边形的全部顶点。
-
计算所有点与相邻顶点连线的夹角
-
计算所有点与相邻顶点连线的夹角
-
最后根据角度累加值计算回转数。看过本文开头的介绍,很容易理解 360°(2π)相当于一次回转。
代码实现中需要注意的问题
-
平面直角坐标系内一个角的取值范围是 -π 到 π 这个区间
-
我们只能先计算两条线与 X 正轴夹角,再取两者差值。这个差值的结果就有可能超出 -π 到 π 这个区间,因此我们还需要处理差值超出取值区间的情况。
-
这里用到的辅助函数atan2
atan2介绍
atan2() 函数的功能是求 y/x 的反正切值。atan2() 是 atan() 的增强版,能够确定角度所在的象限。
返回值
返回 y/x 的反正切值,以弧度表示,取值范围为(-π,π]
。如上图所示,tan(θ) = y/x,θ = atan2(y, x)。
当 (x, y) 在象限中时:
-
当 (x, y) 在第一象限,0 < θ < π/2
-
当 (x, y) 在第二象限,π/2 < θ ≤ π
-
当 (x, y) 在第三象限,-π < θ < -π/2
-
当 (x, y) 在第四象限,-π/2 < θ < 0
当 (x, y) 在象限的边界(也就是坐标轴)上时:
-
当 y 是 0,且 x 为非负值,θ = 0
-
当 y 是 0,且 x 是负值,θ = π
-
当 y 是正值,且 x 是 0,θ = π/2
-
当 y 是负值,且 x 是 0,θ = -π/2
由此可知,一般情况下用 atan() 即可,当对所求出角度的象限有特殊要求时,应使用 atan2()。