该程序以列表[r1,r2,... rn]作为输入,并输出圆的中心。
我之所以要求“小”,是因为“最小”半径会将其转换为一个更加困难的问题(最小版本已被证明是NP难/完全的 - 请参见问题末尾的脚注)。我们不需要最小值。如果圆形成的形状似乎相当圆形,那就足够了。
如果有帮助,您可以假设Rmax / Rmin <20。
低优先级的问题 - 程序应能处理2000多个圆。作为起点,即使100-200个圆也应该没问题。
您可能已经猜到,圆形不需要紧密地堆放在一起甚至不接触。
目标是设计一个视觉上令人愉悦的圆形排列方式,这些圆可以放入一个更大的圆中,并且不会留下太多空白空间(就像色盲测试图片中的圆形一样)。
![alt text](https://istack.dev59.com/PDKmk.webp)
import pylab
from matplotlib.patches import Circle
from random import gauss, randint
from colorsys import hsv_to_rgb
def plotCircles(circles):
# input is list of circles
# each circle is a tuple of the form (x, y, r)
ax = pylab.figure()
bx = pylab.gca()
rs = [x[2] for x in circles]
maxr = max(rs)
minr = min(rs)
hue = lambda inc: pow(float(inc - minr)/(1.02*(maxr - minr)), 3)
for circle in circles:
circ = Circle((circle[0], circle[1]), circle[2])
color = hsv_to_rgb(hue(circle[2]), 1, 1)
circ.set_color(color)
circ.set_edgecolor(color)
bx.add_patch(circ)
pylab.axis('scaled')
pylab.show()
def positionCircles(rn):
# You need rewrite this function
# As of now, this is a dummy function
# which positions the circles randomly
maxr = int(max(rn)/2)
numc = len(rn)
scale = int(pow(numc, 0.5))
maxr = scale*maxr
circles = [(randint(-maxr, maxr), randint(-maxr, maxr), r)
for r in rn]
return circles
if __name__ == '__main__':
minrad, maxrad = (3, 5)
numCircles = 400
rn = [((maxrad-minrad)*gauss(0,1) + minrad) for x in range(numCircles)]
circles = positionCircles(rn)
plotCircles(circles)
补充信息:在谷歌搜索结果中常被称为“圆形装配算法”的算法不适用于此问题。
另一个“圆形装配算法”的问题陈述如下:给定一个复合K(在这个上下文中称为单纯复合或简称为复合)和适当的边界条件,计算K对应圆形装配的半径...
它基本上从一个图形开始,说明哪些圆相互接触(图形的顶点表示圆,边表示圆之间的接触/切线关系)。必须找到圆的半径和位置,以满足图形所表示的接触关系。
另一个问题确实有一个有趣的观察结果(与此问题无关):
圆形装配定理 - 每个圆形装配都有一个对应的平面图(这是易于理解的部分),每个平面图都有一个对应的圆形装配(这是不太明显的部分)。图形和装配是彼此的对偶,并且是唯一的。
我们没有一个平面图或切线关系来开始解决我们的问题。
这篇文章 - 罗伯特·J·福勒,迈克·帕特森,史蒂文·L·塔尼莫托:平面上的最优装箱和覆盖问题是NP完全问题 - 证明了此问题的最小版本是NP完全问题。然而,该论文不易在网上获取。