-1

I wrote a routine that distributes circles randomly (uniformly) with an arbitrary diameter in my study area.

def no_nearby_dots(new_dot, dots_sim, min_distance):
    for dot in dots_sim:
        if np.sqrt((dot[0] - new_dot[0]) ** 2 + (dot[1] - new_dot[1]) ** 2) <= min_distance:
            return False
    return True

while realizations < simulations:
    dots_sim = []
    new_dot = True
    dots_sim.append((np.random.uniform(xmin, xmax), np.random.uniform(ymin, ymax)))
    failed_attempts = 0
    while new_dot:
        xp = np.random.uniform(xmin, xmax)
        yp = np.random.uniform(ymin, ymax)
        if no_nearby_dots((xp, yp), dots_sim, diameter):
            dots_sim.append((xp, yp))
            failed_attempts = 0
        else:
            failed_attempts += 1
        if len(dots_sim) == n_sim:
            new_dot = False
        if failed_attempts > 2000:
            new_dot = False
            print('ERROR...exit loop')
            break

    x_sim = [dot[0] for dot in dots_sim]
    y_sim = [dot[1] for dot in dots_sim]

I want to introduce a second circle around the initial ones where the possibility of distributing points reduces exponentially towards the inner border -> I want to prevent a "hard" border, the points are allowed to occur anywhere on the plane but not closer than diameter, additionally they can only occur to a certain degree between diameter and diameter2.

Are there any ideas how to do that?

2 Answers2

1

Here is an idea.

Choose a random radius between diameter/2 and diameter2/2, then generate a random point in the circle formed by that radius. There are many ways to choose a radius that meets your requirements. For example, the following chooses a radius such that radii very close to diameter2/2 are much more likely to be chosen:

radius = (diameter1/2) + ((diameter2/2) - (diameter1/2)) * random.random()**(1/20)

Note that 1/20 is the 20th root of a uniform (0, 1) random number. Try changing 1/20 to a different value and see what happens.

There are other ways to choose a radius this way, and they can all be described by a probability density function (for more information, see the following answer: Generate a random point within a circle (uniformly), which shows how a linear density function leads to a uniform distribution of points in a circle).

Peter O.
  • 32,158
  • 14
  • 82
  • 96
0

I solved it, and this is what I did:

while realizations < simulations:
    dots_sim = []
    new_dot = True
    dots_sim.append((np.random.uniform(x_min, x_max), np.random.uniform(y_min, y_max)))
    failed_attempts = 0
    while new_dot:
        x = np.random.uniform(x_min, x_max)
        y = np.random.uniform(y_min, y_max)
        diameter_simulation = np.random.uniform(min_diameter, max_diameter)
        if no_nearby_dots((x, y), dots_sim, diameter_simulation):
            dots_sim.append((x, y))
            failed_attempts = 0
        else:
            failed_attempts += 1
        if len(dots_sim) == len(x_coordinate):
            new_dot = False
        if failed_attempts > 1000:
            new_dot = False
            print('ERROR... -> no more space to place QDs! -> exit loop!')
            break

What I did was creating diameters for my circles also using uniformly distributed numbers in an arbitrary interval, which smoothes my cumulative distribution function. This is the solution I needed, but it might not fit the initial question very well (or the question was formulated inaccurately in the first place :p)