I am trying to generate a set of points that do not fall within the range of each other in a fixed area. My approach is given below:
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
Is there a good way to terminate this algorithm without making it enter an infinite loop? I do have a threshold check but are there better ways to do this?
This article about poisson disk sampling may be interesting to you. The author explains a strategy for selecting points that aren’t too close to each other, and even provides sample code in a few languages, including Python.
The problem with the strategy you outlined is, as you noted, that if you want to select a lot of points, or you want the points to be quite far apart, the performance can become atrocious. The poisson disk scheme has better performance characteristics, I believe.