我会做以下事情:定义x,y的网格,对于网格,计算到所有圆的最小距离减去圆的半径。在生成的地图上,您可以选择比 X 更亮的任何像素,这意味着您可以在那里放置一个半径为 X 的圆而不会重叠。这是显示结果地图的代码和图像。如果你想让它更快,你可以使用低分辨率版本的地图。
import numpy as np,numpy.random
import matplotlib.pyplot as plt,matplotlib,scipy.optimize
maxx=2500
maxy=2500
maxrad=60 #max radius of the circle
ncirc=100 # number of circles
np.random.seed(1)
#define centers of circles
xc,yc=np.random.uniform(0,maxx,ncirc),np.random.uniform(0,maxy,ncirc)
rads=np.random.uniform(0,maxrad,ncirc)
#define circle radii
xgrid,ygrid=np.mgrid[0:maxx,0:maxy]
im=xgrid*0+np.inf
for i in range(ncirc):
im = np.minimum(im, ((xgrid - xc[i])**2 + (ygrid - yc[i])**2)**.5 - rads[i])
# im now stores the minimum radii of the circles which can
# be placed at a given position without overlap
#plotting
fig=plt.figure(1)
plt.clf()
plt.imshow(im.T,extent=(0, maxx, 0, maxy))
plt.colorbar()
ax = plt.gca()
for i in range(ncirc):
ax.add_patch(matplotlib.patches.Circle((xc[i], yc[i]), rads[i],
facecolor='none', edgecolor='red'))
plt.xlim(0, maxx)
plt.ylim(0, maxy)
plt.draw()
地图看起来像 voronoi 图,但不清楚是否可以利用。
更新:经过一番思考,有一个可能更快的解决方案适用于大量圈子。首先创建该区域的网格(比如 2500x2500)。用 1 填充圆圈内的所有像素,其他所有像素都用 0 填充。然后,您需要将此地图与圆形内核与您要放置的圆的所需半径进行卷积。生成的地图的像素必须为 0,可用于放置像素。这种方法的优点是可以适用于非常大的网格和圈数,并且卷积可以通过fft轻松完成。
这是显示第一个掩码的插图,以及与半径为 128 像素的圆形内核卷积后的掩码。右掩码中的所有零像素都是半径为 128 的新圆的可能位置。