Richard
Richard

Reputation: 65610

Generate random xy values within two-dimensional circular radius?

I have some points that are located in the same place, with WGS84 latlngs, and I want to 'jitter' them randomly so that they don't overlap.

Right now I'm using this crude method, which jitters them within a square:

r['latitude'] = float(r['latitude']) + random.uniform(-0.0005, 0.0005)
r['longitude'] = float(r['longitude']) + random.uniform(-0.0005, 0.0005)

How could I adapt this to jitter them randomly within a circle?

I guess I want a product x*y = 0.001 where x and y are random values. But I have absolutely no idea how to generate this!

(I realise that really I should use something like this to account for the curvature of the earth's surface, but in practice a simple circle is probably fine :) )

Upvotes: 0

Views: 1320

Answers (3)

Berserker
Berserker

Reputation: 1112

The basic idea is, you generate a vector with x = radius of circle y = 0. You then rotate the vector by a random angle between 0 and 360, or 0 to 2 pi radians.

You then apply this displacement vector and you have your random jitter in a circle.

An example from one of my scripts:

    def get_randrad(pos, radius):
        radius = random() * radius
        angle = random() * 2 * pi
        return (int(pos[0] + radius * cos(angle)),
                int(pos[1] + radius * sin(angle)))

pos beeing the target location and radius beeing the "jitter" range.

As pjs pointed out, add

radius *= math.sqrt(random())

for uniform distribution

Upvotes: 1

MMc
MMc

Reputation: 46

Merely culling results that fall outside your circle will be sufficient.

If you don't want to throw out some percentage of random results, you could choose a random angle and distance, to ensure all your values fall within the radius of your circle. It's important to note, with this solution, that the precision of the methods you use to extrapolate an angle into a vector will skew your distribution to be more concentrated in the center.

If you make a vector out of your x,y values, and then do something like randomize the length of said vector to fall within your circle, your distribution will no longer be uniform, so I would steer clear of that approach, if uniformity is your biggest concern.

The culling approach is the most evenly distributed, of the three I mentioned, although the random angle/length approach is usually fine, except in cases involving very fine precision and granularity.

Upvotes: 0

tzaman
tzaman

Reputation: 47870

One simple way to generate random samples within a circle is to just generate square samples as you are, and then reject the ones that fall outside the circle.

Upvotes: 1

Related Questions