我正在尝试生成一组在固定区域内不在彼此范围内的点。我的方法如下:
import collections
from random import uniform
X = 100.0
Y = 100.0
points = 10
radius = 10
def in_circle(c_x, c_y, radius, x, y):
dist_squared = (c_x - x)**2 + (c_y - y)**2
return dist_squared <= radius ** 2
current = collections.defaultdict(lambda: [])
threshold = 0
for point in range(1, points+1):
cX = uniform(1.0, X)
cY = uniform(1.0, Y)
for cur in current:
while in_circle(current[cur][0], current[cur][1], 2*radius, cX, cY):
cX = uniform(1.0, X)
cY = uniform(1.0, X)
threshold += 1
if threshold >= 1e+05:
print "Cannot satisfy constraints"
sys.exit(1)
threshold = 0
current[point] = [cX, cY]
print cX, cY
有没有一种很好的方法来终止这个算法而不让它进入无限循环?我确实有一个阈值检查,但有没有更好的方法来做到这一点?
答案 0 :(得分:3)
This article可能对你很有意思。作者解释了选择彼此不太接近的点的策略,甚至提供了几种语言的示例代码,包括Python。
正如您所指出的,您所概述的策略的问题是,如果您想要选择很多分数,或者您希望分数相差很远,那么性能就会变得非常糟糕。我相信泊松盘方案具有更好的性能特征。
答案 1 :(得分:2)
你能否将区域细分为方形 side&gt; =点之间的最小允许距离然后随机挑选一些?
例如,这些是你的点边界,“编号”从0到j:
0 1 2 3 4
5 6 7 8 9
a b c d e
f g h i j
然后你创建一个方形索引的数组(在这个例子中为0到j),randomly shuffle it,最后用bc4j25e1670dfgh89ai3结束,并从它的开头取出你需要点的多个索引,例如: 5:bc4j2。然后将点放在所选正方形的中心(或左上角):
0 1 * 3 *
5 6 7 8 9
a * * d e
f g h i *
答案 2 :(得分:2)
这类问题称为circle packing。关于mathworld的文章表明,单位正方形的最密集的已知填充物是已知的(并且可以通过缩放x和y将该问题转换为该问题)。该文章中的图像展示了两种密集的球形填料(方形和六边形)。
至于您是否可以插入新的圈子,voronoi diagram可能有助于衡量最大剩余未采样区域。在某些情况下,评估四叉树或空间散列等未占用区域的其他近似方法也可能就足够了