📜  给定三点的多边形的最小面积(1)

📅  最后修改于: 2023-12-03 15:11:39.370000             🧑  作者: Mango

给定三点的多边形的最小面积

在计算机图形学中,给定三个点的坐标,我们可以计算出由这三个点构成的三角形的面积。如果在平面直角坐标系中给出一组点,如何计算由这些点构成的多边形的最小面积呢?接下来,我们将会介绍两种解决方案。

方案一:Shoelace 公式

Shoelace 公式(鞋带公式)最初是由古希腊数学家做广义概率论的 Archimedes 提出的。它被称为“鞋带公式”,是因为它只需要知道多边形各个顶点的坐标,及其按逆时针顺序连接时的顺序就可以计算任意多边形面积。

算法总体思路:

  1. 对于一个 n 个顶点面积已知的多边形,从其任意一点出发,沿着其顶点逆时针方向进行遍历,并依次将相邻两点以一条线段连接起来,生成 n 条线段;
  2. 计算上述线段与 x 轴的有向交叉线 L,然后按 x 坐标值大小进行排序;
  3. 依次将相邻两条线段记为 l1 和 l2,将其组成的梯形的(有向)面积记为 area(l1, l2);
  4. 递归累加所有梯形的面积,直到最终的多边形被分解为 n-2 个三角形。这样就可以得到原多边形的面积。

标准库中 sample:

def shoelace_formula(points: List[Tuple[float, float]]) -> float:
    n = len(points)
    twice_area = 0.0
    for i in range(n):
        j = (i + 1) % n
        twice_area += points[i][0] * points[j][1] - points[j][0] * points[i][1]
    return abs(twice_area) / 2.0
方案二:利用向量叉积计算向量的面积

向量的叉积是计算一个向量和另一个向量之间形成的平行四边形(把向量两个首尾相连形成的图形)的有向面积时产生的。使用叉积计算多边形面积的算法很容易实现。

我们仍然可以从任意点出发,以逆时针顺序遍历所有多边形的点。当遍历每一条边时,将其转换为向量,记录这个向量的起点和终点(当然,我们已经按逆时针顺序进行了遍历)。

用两个向量 u 和 v 来表示平面上的一条线段,可以将这条线段所对应的平行四边形的面积写为:

$$A = |u \times v| = |u| |v| \sin \theta$$

其中 $\theta$ 为 u 和 v 的夹角,向量 $\times$ 表示向量的叉积运算。通过将所有两条相邻边所对应向量的面积进行累加即可得到原多边形的面积。用向量计算多边形面积的算法复杂度为 $O(n)$。

标准库中 sample:

def vector_cross_area(points: List[Tuple[float, float]]) -> float:
    # 先计算多边形重心,方便后面计算向量
    sx, sy, area = 0.0, 0.0, 0.0
    n = len(points)
    for i in range(n):
        j = (i + 1) % n
        t = points[i][0] * points[j][1] - points[j][0] * points[i][1]
        area += t
        sx += (points[i][0] + points[j][0]) * t
        sy += (points[i][1] + points[j][1]) * t
    area /= 2.0
    sx /= 6.0 * area
    sy /= 6.0 * area
    # 计算向量和叉积
    s = 0.0
    for i in range(n):
        j = (i + 1) % n
        s += (points[i][0] - sx) * (points[j][1] - sy) - (points[j][0] - sx) * (points[i][1] - sy)
    return abs(s) / 2.0
总结

以上介绍了两种计算给定三个点的多边形的最小面积的方法。Shoelace 公式更加简单易懂,但它的时间复杂度为 $O(n \log n)$,并且容易出现精度误差。向量计算法复杂度更低,而且数学上更加稳定。可以根据不同的需要选择不同的方法。