计算包含两个较小圆圈的最小圆的中心和半径

时间:2016-04-20 06:22:08

标签: python algorithm math

我试图找到一种计算中心坐标和覆盖两个较小圆圈的最小圆的半径的算法。我知道2个较小圆圈中心的半径和x,y坐标。

我在下面尝试了这个算法,即使两个圆重叠或相距很远也能正常工作,但只有当circle1和circle2位于同一个x或y轴上时才有效。

设c1,c2为circle1和circle 2; r是半径:

    if c1x >= c2x:
        if c1y >= c2y:
            c = ((c1x + c1r) + (c2x - c2r))/2, ((c1y + c1r) + (c2y - c2r))/2
            r = max(((c1x + c1r) - (c2x - c2r))/2, 
                     ((c1y + c1r) - (c2y - c2r))/2)
        elif c1y < c2y:
            c = ((c1x + c1r) + (c2x - c2r))/2, ((c2y + c2r) + (c1y - c1r))/2
            r = max(((c1x + c1r) - (c2x - c2r))/2, 
                     ((c2y + c2r) - (c1y - c1r))/2)
    elif if c1x < c2x:
        if c1y >= c2y:
            c = ((c2x + c2r) + (c1x - c1r))/2, ((c1y + c1r) + (c2y - c2r))/2
            r = max(((c2x + c2r) - (c1x - c1r))/2, 
                     ((c1y + c1r) - (c2y - c2r))/2)
        elif c1y < c2y:
            c = ((c2x + c2r) + (c1x - c1r))/2, ((c2y + c2r) + (c1y - c1r))/2
            r = max(((c2x + c2r) - (c1x - c1r))/2, 
                     ((c2y + c2r) - (c1y - c1r))/2)

3 个答案:

答案 0 :(得分:1)

覆盖圆圈参数(伪代码):

dx = c2x - c1x
dy = c2y - c1y
//center-center distance   
dc = Sqrt(dx**2 + dy**2)
rmin = Min(r1, r2)
rmax = Max(r1, r2)
if rmin + dc < rmax then
    covercenter = center of larger circle
    R = rmax
else
    R = 0.5 * (r1 + r2 + dc)
    x = c1x + (R - r1) * dx / dc
    y = c1y + (R - r1) * dy / dc

工作示例(蓝色覆盖): enter image description here

答案 1 :(得分:0)

如果您的算法在两个中心具有相同x或相同y的情况下有效,那么您可以将(x1, y1)(x2, y2)替换为(0, 0)和{{1} (只需在平面上应用适当的平移和旋转)。

答案 2 :(得分:0)

您应该在代码中遵循 DRY 原则(不要重复自己),并且不要多次复制公式。您将要制作复制粘贴错误或忘记修改其中一个副本。

我通过对小圆圈进行排序,将公式的所有变体分组在一起,以便我可以直接访问例如最左边的圆圈的x(cax)及其半径(caxr)或最低圆圈的y(cby)及其半径(cbyr)。

from math import sqrt

(cax, caxr), (cbx, cbxr) = sorted([(c1x, c1r), (c2x, c2r)], key=lambda t:t[0])
(cay, cayr), (cby, cbyr) = sorted([(c1y, c1r), (c2y, c2r)], key=lambda t:t[0])

x = (cax-caxr + cbx+cbxr) / 2
y = (cay-cayr + cby+cbyr) / 2

r = sqrt( ((cax-caxr) - (cbx+cbxr))**2 + ((cay-cayr) + (cby+cbyr))**2 ) / 2

See this code running on IDEone.com