最小覆盖圆解决的问题是在平面上有n个散点。计算一个半径最小的圆能 包含所有的点。在网上搜索相关资料,在文章的最后列举一些参考的资料。
随机增量法解决最小覆盖圆的问题
对于一系列散点的最小覆盖圆,它满足如下性质,其中第二条性质和第三条性质必须满足其一。
-
存在且唯一
-
圆上有三个点集中的点
-
点集中有两个点是圆的直径
那么根据这些规律,如果已经计算出前i−1个点的最小圆,在加入第i个点后,最小圆有以下几种情况:
- 前i−1个点的最小圆(包含第i个点的情况)
- 前i−1个点中的两个点与第i个点确定的圆
- 前i−1个点中的一个点与第i个点作为直径的圆
增量法计算最小覆盖圆的过程,就是不断地加点,然后根据新加的点是否在圆内,当不在圆内时重复定圆。
在不考虑只有一个点,两个点的边界情况。算法流程描述如下:
-
输入n个点
-
随机打乱顶点在数组中的位置(为了获得更好的时间复杂度)
-
由顶点P0和P1计算最小圆C(A)
-
枚举顶点P2-Pn,对于Pi作如下判断
- Pi在C(A)内,则C(A)不变,继续下一个点,否则进行下一步
- 计算P0和Pi为直径的圆,记为C(i),枚举点P1到Pi−1,对于Pj作如下判断
- 顶点Pj在圆C(i)内,则C(i)保持不变,继续下一个顶点,否则进行下一步
- 计算Pj和Pi为直径的圆,记为C(j)。然后枚举顶点P0到Pj−1,对于对于Pk作如下判断
- Pk不在圆C(j)内时,则更新C(j)为Pi,Pj和Pk构成的圆。
- 枚举完Pk之后,更新C(i)为C(j)
- 枚举完Pj之后,更新C(A)为C(i)
在Unity上使用C#的实现如下,会有一定的GC,但都能通过其他技巧优化。

关于两点作为直径计算一个圆
这个比较简单,就是两点坐标相加乘以0.5,半径为距离的一半。

关于三点定圆的公式
这个问题会比上面的复杂一点,不过是可以推导出计算公式,这里就不推了。直接抄吧。
Cx=2(x3−x1)(y2−y1)−2(x2−x1)(y3−y1)(y2−y1)(y32−y12+x32−x12)+(y1−y3)(y22−y12+x22−x12)Cy=2(y3−y1)(x2−x1)−2(y2−y1)(x3−x1)(x2−x1)(x32−x12+y32−y12)+(x1−x3)(x22−x12+y22−y12)R=x−C
圆心坐标就是上面的公式,半径就是取其中一个输入的顶点,计算其与圆心的距离
参考资料
【计算几何】随机增量
最小圆覆盖
最小圆覆盖(经典算法-三点定圆)