I use the following function to generate random geo-coordinates within a given radius from the starting point:
function randomGeo(center, radius) { var y0 = center.latitude; var x0 = center.longitude; var rd = radius / 111300; var u = Math.random(); var v = Math.random(); var w = rd * Math.sqrt(u); var t = 2 * Math.PI * v; var x = w * Math.cos(t); var y = w * Math.sin(t); var xp = x / Math.cos(y0); return { 'latitude': y + y0, 'longitude': xp + x0 }; }
I do this in a loop, several times, using a radius of 2000 m and the following starting point:
location: {
I expect all of these results to be within 2,000 m; instead, I see values โโover 10,000 m:
[ { latitude: 51.73256540025445, longitude: -1.3358092771716716 }, // 3838.75070783092 { latitude: 51.7214165686511, longitude: -1.1644147572878725 }, // 3652.1890457730474 { latitude: 51.71721400063117, longitude: -1.2082082568884593 }, // 8196.861603477768 { latitude: 51.73583824510363, longitude: -1.0940424351649711 }, // 5104.820455873758 { latitude: 51.74017571473442, longitude: -1.3150742602532257 }, // 4112.3279147866215 { latitude: 51.73496163915278, longitude: -1.0379454413532996 }, // 9920.01459343298 { latitude: 51.73582333121239, longitude: -1.0939302282840453 }, // 11652.160906253064 { latitude: 51.72145745285658, longitude: -1.2491630482776055 }, // 7599.550622138115 { latitude: 51.73036335927129, longitude: -1.3516902043395063 }, // 8348.276271205428 { latitude: 51.748104753808924, longitude: -1.2669212014250266 }, // 8880.760669882042 { latitude: 51.72010719621805, longitude: -1.327161328951446 }, // 8182.466715589904 { latitude: 51.725727610071125, longitude: -1.0691503599266818 } ] // 2026.3687763449955
Given that I (shamelessly!) Plugged this solution from another place (although I saw several similar implementations), I canโt understand where the math goes wrong.
(Also, in case you want it, this is how I calculate the distance. Pretty accurately, this is correct.)
function distance(lat1, lon1, lat2, lon2) { var R = 6371000; var a = 0.5 - Math.cos((lat2 - lat1) * Math.PI / 180) / 2 + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * (1 - Math.cos((lon2 - lon1) * Math.PI / 180)) / 2; return R * 2 * Math.asin(Math.sqrt(a)); }