Background:
I am trying to create a coordinates generator for Unit Testing my code. I would like to try to test cases for methods like:
// Check if within 10km.
// Should pass because it is 0 - 10km from location
location.isWithin(generateLocation(location, 10), 10) === true
// Check if within 10km.
// Should fail because it is 20 - 25km from location
location.isWithin(generateLocation(location, 25, 20), 10) === false
I have tried lots of Stackoverflow answers I never found one answer to this problem.
What I have tried:
function generateNearbyLocation(latitude, longitude, max, min = 0) {
// Convert max in kilometers to degrees
const radiusInDegrees = (max * 1000) / 111300;
const u = Math.random();
const v = Math.random();
// random radius
const w = radiusInDegrees * Math.sqrt(u);
// random angle
const t = 2 * Math.PI * v;
const x = w * Math.cos(t);
const x1 = x / Math.cos(latitude);
const y1 = w * Math.sin(t);
// Not working attempt to add Minimum distance
// const newLatitude = latitude + (min * 1000 / 111300) + y1;
// const newLongitude = longitude + (min * 1000 / 111300) + x1;
const newLatitude = latitude + y1;
const newLongitude = longitude + x1;
const distance = getDistanceFromLatLonInKm(latitude, longitude, newLatitude, newLongitude);
return {
newLatitude,
newLongitude,
distance
};
}
This works but is not accurate. Even with max of 10, it sometimes generate 11km coordinates.
Here's a playground that I made: https://jsbin.com/hakemubogo/edit?js,console
EDIT
I found a much more accurate formula from another answer but still can't create minimum distance.
function generateLocation(latitude, longitude, max, min = 0) {
const EARTH_RADIUS = 6371; // km
const DEGREE = EARTH_RADIUS * 2 * Math.PI / 360 * 1000; // 1° latitude in meters
const r = (max * 1000) * Math.random() ** 0.5;
const theta = Math.random() * 2 * Math.PI; // random * (360deg in radians)
const dy = r * Math.sin(theta);
const dx = r * Math.cos(theta);
const newLatitude = latitude + dy / DEGREE;
const newLongitude = longitude + dx / (DEGREE * Math.cos(deg2rad(latitude)));
const distance = getDistanceFromLatLonInKm(latitude, longitude, newLatitude, newLongitude);
return {
newLatitude,
newLongitude,
distance
};
}