Search code examples
mathrandomweighted

Weighted random coordinates


This may be more of a search for a term, but solutions are also welcome. I'm looking to create n amount of random x,y coordinates. The issue I am having is that I would like the coordinates to be "weighted" or have more of a chance of falling closer to a specific point. I've created something close by using this pseudo code:

x = rand(100) //random integer between 0 and 100
x = rand(x) //random number between 0 and the previous rand value
//randomize x to positive or negative
//repeat for y

This works to pull objects toward 0,0 - however if you create enough points, you can see a pattern of the x and y axis. This is because the even if x manages to get to 100, the chances are high that y will then be closer to.

I'm looking to avoid the formation of this x,y line. Bonus points if there is a way to throw in multiple "weighted coordinates" that the random coordinates would sort of gravitate to, instead of statically to 0,0.


Solution

  • This is easier in polar coordinates. All you have to do is to generate a uniform random angle and a power distributed distance. Here's an example in Python:

    import math
    from random import random
    
    def randomPoint(aroundX, aroundY, scale, density):
      angle = random()*2*math.pi
    
      x = random()
      if x == 0:
        x = 0.0000001
    
      distance = scale * (pow(x, -1.0/density) - 1)
      return (aroundX + distance * math.sin(angle),
              aroundY + distance * math.cos(angle))
    

    Here's the distribution of randomPoint(0, 0, 1, 1):

    Points spread out, more dense at the origin

    We can shift it to center around another point like 1,2 with randomPoint(1, 2, 1, 1):

    Points spread out, more dense at the 1,2

    We can spread across a larger area by increasing the scale. Here's randomPoint(0, 0, 3, 1):

    Points spread out randomly over a larger area

    And we can change the shape, that is the tendency to flock together, by changing the density. randomPoint(0, 0, 1, 3):

    Points tightly centered around the origin