Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I am trying to create random locations nearby my location. What i want is to create random latitude/longitude pairs inside a 200 meters circle surrounding my location.

This is the formula i came up with (with the help of people at StackOverFlow): (Random number between -1 and 1)*radius + (old longitude) = new longitude within radius of old longitude

(Random number between -1 and 1)*radius + (old latitude) = new latitude within radius of old latitude

The thing is that something weird is happening with my implementation because all the random locations are too near of my location center, it seems that the formula does not cover the whole radius.

Any idea of what could be wrong with my formula?

Edited to show the current java implementation:

public static Location getLocation(Location location, int radius) {
    Random random = new Random();

    // Convert radius from meters to degrees
    double radiusInDegrees = radius / METERS_IN_DEGREES;

    double x0 = location.getLongitude() * 1E6;
    double y0 = location.getLatitude() * 1E6;
    double u = random.nextInt(1001) / 1000;
    double v = random.nextInt(1001) / 1000;
    double w = radiusInDegrees * Math.sqrt(u);
    double t = 2 * Math.PI * v;
    double x = w * Math.cos(t);
    double y = w * Math.sin(t);

    // Adjust the x-coordinate for the shrinking of the east-west distances
    double new_x = x / Math.cos(y0);

    // Set the adjusted location
    Location newLocation = new Location("Loc in radius");
    newLocation.setLongitude(new_x + x0);
    newLocation.setLatitude(y + y0);

    return newLocation;
}

I am not sure what i am doing wrong, because the new locations are created in the middle of the sea :)

Any idea? thank you

share|improve this question
    
How do you implement this formula? Can you present this part of your code? May be your problem in Pseudorandom number generator ? –  Alex Markov May 21 '12 at 16:23
    
As far as the final question goes, procedures like this encounter such problems because (i) distances are incorrectly converted to degrees of latitude or longitude and (ii) the metric distortion of the coordinate system is not accounted for or is accounted for incorrectly. Using a projected coordinate system instead of a geographic coordinate system usually gets around both these problems. Doing that will expose a fundamental property of your formula, which might or might not be desirable: it generates locations within a rectangle around a location, not within a circle. –  whuber May 21 '12 at 18:33
    
Thanks Alex, the java code is posted at stackoverflow: stackoverflow.com/questions/10682743/… –  pindleskin May 22 '12 at 7:05
    
Re the edited code: (i) random.nextInt(1001)/1000 will return a value greater than 1 about 0.1% of the time. Why aren't you using random.nextDouble or random.nextFloat? (ii) Multiplying x0 and y0 by 1E6 is rather mysterious; it does not seem like it will produce correct results. –  whuber May 22 '12 at 15:09
    
True, i edited the method using nextDouble and got the rid of 1E6. Now, all the random generated locations have the same coordinates that my location. Thanks for the help, it seems that i am going to solve it anytime soon –  pindleskin May 22 '12 at 16:01
add comment

3 Answers 3

up vote 16 down vote accepted

This is tricky for two reasons: first, limiting the points to a circle instead of a square; second, accounting for distortions in the distance calculations.

Many GISes include capabilities that automatically and transparently handle both complications. However, the tags here suggest that a GIS-independent description of an algorithm may be desirable.

  1. To generate points uniformly, randomly, and independently within a circle of radius r around a location (x0, y0), start by generating two independent uniform random values u and v in the interval [0, 1). (This is what almost every random number generator provides you.) Compute

    w = r * sqrt(u)
    t = 2 * Pi * v
    x = w * cos(t) 
    y = w * sin(t)
    

    The desired random point is at location (x+x0, y+y0).

  2. When using geographic (lat,lon) coordinates, then x0 (longitude) and y0 (latitude) will be in degrees but r will most likely be in meters (or feet or miles or some other linear measurement). First, convert the radius r into degrees as if you were located near the equator. Here, there are about 111,300 meters in a degree.

    Second, after generating x and y as in step (1), adjust the x-coordinate for the shrinking of the east-west distances:

    x' = x / cos(y0)
    

    The desired random point is at location (x'+x0, y+y0). This is an approximate procedure. For small radii (less than a few hundred kilometers) that do not extend over either pole of the earth, it will usually be so accurate you cannot detect any error even when generating tens of thousands of random points around each center (x0,y0).

share|improve this answer
1  
Great explanation whuber, that is what i needed to know. Now i am going to implement it. Thanks –  pindleskin May 22 '12 at 7:06
1  
I edited the question to show some java implementation of the formula –  pindleskin May 22 '12 at 8:27
    
"there are about 111,300 meters in a degree" just for note the comma is used as thousand separator. radiusInDegrees=radius/111300 –  RMalke May 7 at 0:51
    
@eklam Thank you. I apologize for forgetting there are different conventions. It's good to know that the earth is not just 40 kilometers around :-). –  whuber May 7 at 13:58
add comment

The correct implementation is:

public static void getLocation(double x0, double y0, int radius) {
    Random random = new Random();

    // Convert radius from meters to degrees
    double radiusInDegrees = radius / 111000f;

    double u = random.nextDouble();
    double v = random.nextDouble();
    double w = radiusInDegrees * Math.sqrt(u);
    double t = 2 * Math.PI * v;
    double x = w * Math.cos(t);
    double y = w * Math.sin(t);

    // Adjust the x-coordinate for the shrinking of the east-west distances
    double new_x = x / Math.cos(y0);

    double foundLongitude = new_x + x0;
    double foundLatitude = y + y0;
    System.out.println("Longitude: " + foundLongitude + "  Latitude: " + foundLatitude );
}

I removed the dependency on external libraries to make it more accessible.

share|improve this answer
add comment

You can check the results of your calculations here. Scroll down to the section called "Destination point given distance and bearing from start point". There's even a simple JavaScript formula at the bottom to implement this. You will still need to generate a random bearing $\theta$ in radians (measured clockwise from north), though that should be pretty straight forward. These formulas assume a spherical earth (though it is ellipsoidal), which is good enough as it produces errors of up to 0.3%.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.