Last active
September 13, 2016 06:35
-
-
Save siberex/95afb52ba438c189ccac1a6cc8d59e30 to your computer and use it in GitHub Desktop.
Random locations nearby specified location limited by radius
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Get random geo point [latitude, longitude] within some distance from specified geo point (lat, long) | |
* | |
* Points will be uniformly-distributed on multiple calls. | |
* | |
* → Demo is here: http://jsfiddle.net/siberex/f72ffn1x/ | |
* | |
* @param lat Latitude in degrees | |
* @param lng Longitude in degrees | |
* @param distance Distance in meters to limit point distribution to. | |
* If negative value is provided, points will be generated on exact distance (e.g. on circle border). | |
* @returns {*[]} Array with [latitude, longitude] | |
* | |
* @author Stepan Legachev <me@sib.li> | |
*/ | |
exports.getRandomLocation = function(lat, lng, distance = 10000) { | |
// Convert to radians | |
lat *= Math.PI / 180; | |
lng *= Math.PI / 180; | |
var radius; | |
// Distance should be set in meters, negative for exact distance | |
if (distance < 0) { | |
// Exact distance | |
radius = Math.abs(distance); | |
} else { | |
// Get uniformly-random distribution within peovided distance | |
// http://stackoverflow.com/questions/5837572/generate-a-random-point-within-a-circle-uniformly | |
radius = Math.random() + Math.random(); | |
radius = radius > 1 ? 2 - radius : radius; | |
radius *= distance ? distance : 10000; // multiply by distance meters | |
} | |
// Convert radius from meters to degrees to radians | |
// 111319.9 meters = one degree along the equator | |
radius /= 111319.9; | |
// Correction for the actual distance from equator is NOT needed here | |
// radius *= Math.cos(lat); | |
// Convert to radians | |
radius *= Math.PI / 180; | |
// Random angle | |
var angle = Math.random() * Math.PI * 2; | |
// Get a point {nLat,nLng} in a distance={radius} out on the {angle} radial from point {lat,lng} | |
// http://williams.best.vwh.net/avform.htm#LL | |
var nLng, | |
nLat = Math.asin( Math.sin(lat) * Math.cos(radius) + Math.cos(lat) * Math.sin(radius) * Math.cos(angle) ); | |
if (Math.cos(nLat) == 0) { | |
nLng = lng; | |
} else { | |
nLng = (lng - Math.asin( Math.sin(angle) * Math.sin(radius) / Math.cos(nLat) ) + Math.PI) % (Math.PI * 2) - Math.PI | |
} | |
// Convert to degrees | |
nLat *= 180 / Math.PI; | |
nLng *= 180 / Math.PI; | |
return [nLat, nLng]; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment