最小覆盖圆问题

200 阅读1分钟

  最小覆盖圆解决的问题是在平面上有n个散点。计算一个半径最小的圆能 包含所有的点。在网上搜索相关资料,在文章的最后列举一些参考的资料。

随机增量法解决最小覆盖圆的问题

  对于一系列散点的最小覆盖圆,它满足如下性质,其中第二条性质和第三条性质必须满足其一。

  • 存在且唯一

  • 圆上有三个点集中的点

  • 点集中有两个点是圆的直径

  那么根据这些规律,如果已经计算出前i1i-1个点的最小圆,在加入第ii个点后,最小圆有以下几种情况:

  • i1i-1个点的最小圆(包含第ii个点的情况)
  • i1i-1个点中的两个点与第ii个点确定的圆
  • i1i-1个点中的一个点与第ii个点作为直径的圆

  增量法计算最小覆盖圆的过程,就是不断地加点,然后根据新加的点是否在圆内,当不在圆内时重复定圆。   在不考虑只有一个点,两个点的边界情况。算法流程描述如下:

  1. 输入n个点

  2. 随机打乱顶点在数组中的位置(为了获得更好的时间复杂度)

  3. 由顶点P0P_0P1P_1计算最小圆C(A)C(A)

  4. 枚举顶点P2P_2-PnP_n,对于PiP_i作如下判断

    • PiP_iC(A)C(A)内,则C(A)C(A)不变,继续下一个点,否则进行下一步
    • 计算P0P_0PiP_i为直径的圆,记为C(i)C(i),枚举点P1P_1Pi1P_{i-1},对于PjP_j作如下判断
      • 顶点PjP_j在圆C(i)C(i)内,则C(i)C(i)保持不变,继续下一个顶点,否则进行下一步
      • 计算PjP_jPiP_i为直径的圆,记为C(j)C(j)。然后枚举顶点P0P_0Pj1P_j-1,对于对于PkP_k作如下判断
        • PkP_k不在圆C(j)C(j)内时,则更新C(j)C(j)PiP_iPjP_jPkP_k构成的圆。
      • 枚举完PkP_k之后,更新C(i)C(i)C(j)C(j)
    • 枚举完PjP_j之后,更新C(A)C(A)C(i)C(i)

  在Unity上使用C#的实现如下,会有一定的GC,但都能通过其他技巧优化。

image-20240924173033277.png

关于两点作为直径计算一个圆

  这个比较简单,就是两点坐标相加乘以0.5,半径为距离的一半。

image-20240924173148797.png

关于三点定圆的公式

  这个问题会比上面的复杂一点,不过是可以推导出计算公式,这里就不推了。直接抄吧。

Cx=(y2y1)(y32y12+x32x12)+(y1y3)(y22y12+x22x12)2(x3x1)(y2y1)2(x2x1)(y3y1)Cy=(x2x1)(x32x12+y32y12)+(x1x3)(x22x12+y22y12)2(y3y1)(x2x1)2(y2y1)(x3x1)R=xCC_x = \frac{(y_2-y_1)(y_3^2-y_1^2+x_3^2-x_1^2)+(y_1-y_3)(y_2^2-y_1^2+x_2^2-x_1^2)}{2(x_3-x_1)(y_2-y_1)-2(x_2-x_1)(y_3-y_1)}\\ C_y = \frac{(x_2-x_1)(x_3^2-x_1^2+y_3^2-y_1^2)+(x_1-x_3)(x_2^2-x_1^2+y_2^2-y_1^2)}{2(y_3-y_1)(x_2-x_1)-2(y_2-y_1)(x_3-x_1)}\\ R = \sqrt{x-C}

  圆心坐标就是上面的公式,半径就是取其中一个输入的顶点,计算其与圆心的距离

参考资料

【计算几何】随机增量

最小圆覆盖

最小圆覆盖(经典算法-三点定圆)