Adding one or more attractors to a set of random 2D points
<p>Given a set of pseudorandom 2D points generated like so:</p>

<pre><code>points = random.sample([[x, y] for x in xrange(width) for y in yrange(height)], 100)
</code></pre>

<p>I would like to be able to add one or more non random attractor points around which the other points will be drawn. I don't plan to animate this so it doesn't need to be very efficient but I would like to be able to specify how the random points are drawn to each of the attractor points (for instance based on the square of the distance and a given gravitational constant) and then feed my points to a function that returns a modified version of the original list:</p>

<pre><code>points = random.sample([[x, y] for x in xrange(width) for y in xrange(height)], 100)

attractors = [(25, 102), (456, 300), (102, 562)]

def attract(random_points_list, attractor_points_list):
    (...)
    return modified_points_list

new_points_list = attract(points, attractors)
</code></pre>

<p>This new points list would then be used to seed a Voronoi diagram (not part of this question).</p>

<p>You said you want to be able to change the function, so we need to add a function <code>f</code> to the arguments of <code>attract</code>. This function should need one arguments, the distance of the point, and it should return a number.</p>

<pre><code>import math


def attract(random_point_list, attractor_point_list, f = lambda x: 1/x**2):
    for x0, y0 in attractor_point_list:
        x0, y0 = float(x0), float(y0)
        modified_point_list = []
        for x, y in random_point_list:
            rx, ry = x0 - x, y0 - y  # the relative position of the attractor
            distance = math.sqrt(rx**2 + ry**2)
            attraction = f(d)
            modified_point_list.append((x + attraction*rx/distance, y + attraction*ry/distance))  # (rx, ry) is a vector with length distance -&gt; by dividing with distance we get a vector (rx / distance, ry / distance) with length 1. Multiplying it with attraction, we get the difference of the original and the new location.
        random_point_list = modified_point_list
    return modified_point_list
</code></pre>

python game-physics voronoi