次のようにします。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()

マップはボロノイ図のように見えますが、それを利用できるかどうかは不明です。
更新:いくつかの考えの後、多数のサークルで機能する可能性のあるより高速なソリューションがあります。まず、エリアのグリッドを作成します(たとえば、2500x2500)。円の内側にあるすべてのピクセルを1で塗りつぶし、それ以外はすべてゼロで塗りつぶします。次に、配置する円の必要な半径を持つ円形カーネルでこのマップを畳み込む必要があります。結果のマップは、ピクセルの配置に使用できるピクセルで0を持っている必要があります。この方法の利点は、非常に大きなグリッドと数の円に対して機能し、畳み込みをfftで簡単に実行できることです。
これは、最初のマスクと、半径128ピクセルの円形カーネルとの畳み込み後のマスクを示す図です。右側のマスクのすべてのゼロピクセルは、半径128の新しい円の可能な位置です。
