From ef11ab85c1277d62794289ad2141a62f2285f424 Mon Sep 17 00:00:00 2001 From: Vivek Seth Date: Thu, 5 May 2016 14:39:02 -0400 Subject: Added address.nearbyLocation() method Returns a random GPS coordinate located within a distance of the given GPS coordinate --- lib/address.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'lib') diff --git a/lib/address.js b/lib/address.js index 6a9e3beb..dec80d8f 100644 --- a/lib/address.js +++ b/lib/address.js @@ -101,6 +101,50 @@ var address = { longitude: function () { return (faker.random.number(360 * 10000) / 10000.0 - 180.0).toFixed(4); + }, + + nearbyLocation: function(location, radius, isMetric) { + function randomFloat(min, max) { + return Math.random() * (max-min) + min; + } + function degreesToRadians(degrees) { + return degrees * (Math.PI/180.0); + } + function radiansToDegrees(radians) { + return radians * (180.0/Math.PI); + } + function kilometersToMiles(miles) { + return miles * 0.621371; + } + function boundaryLocation(location, bearing, distance, isMetric) { + var R = 6378.137; // Radius of the Earth (http://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html) + var d = isMetric ? distance : kilometersToMiles(distance); // Distance in km + + lat1 = degreesToRadians(location[0]); //Current lat point converted to radians + lon1 = degreesToRadians(location[1]); //Current long point converted to radians + + lat2 = Math.asin(Math.sin(lat1) * Math.cos(d/R) + + Math.cos(lat1) * Math.sin(d/R) * Math.cos(bearing)); + + lon2 = lon1 + Math.atan2( + Math.sin(bearing) * Math.sin(d/R) * Math.cos(lat1), + Math.cos(d/R) - Math.sin(lat1) * Math.sin(lat2)); + + return [radiansToDegrees(lat2), radiansToDegrees(lon2)]; + } + + location = location || [faker.latitude(), faker.longitude()] + radius = radius || 10.0; + isMetric = isMetric || false; + + // This is a heuristic to approximate the circular region defined by location and radius. + topLeftBoundary = boundaryLocation(location, degreesToRadians(45), radius, isMetric); + bottomRightBoundary = boundaryLocation(location, degreesToRadians(45), -radius, isMetric); + + randLat = randomFloat(topLeftBoundary[0], bottomRightBoundary[0]).toFixed(4); + randLong = randomFloat(topLeftBoundary[1], bottomRightBoundary[1]).toFixed(4); + + return [randLat, randLong]; } }; -- cgit v1.2.3 From e8f51dcddd2586fcce12635850a6692b414869ef Mon Sep 17 00:00:00 2001 From: Vivek Seth Date: Thu, 5 May 2016 14:52:13 -0400 Subject: Use term 'coordinate' instead of 'location' --- lib/address.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/address.js b/lib/address.js index dec80d8f..6d9748fd 100644 --- a/lib/address.js +++ b/lib/address.js @@ -103,7 +103,7 @@ var address = { return (faker.random.number(360 * 10000) / 10000.0 - 180.0).toFixed(4); }, - nearbyLocation: function(location, radius, isMetric) { + nearbyGPSCoordinate: function(coordinate, radius, isMetric) { function randomFloat(min, max) { return Math.random() * (max-min) + min; } @@ -116,12 +116,12 @@ var address = { function kilometersToMiles(miles) { return miles * 0.621371; } - function boundaryLocation(location, bearing, distance, isMetric) { + function boundaryCoordinate(coordinate, bearing, distance, isMetric) { var R = 6378.137; // Radius of the Earth (http://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html) var d = isMetric ? distance : kilometersToMiles(distance); // Distance in km - lat1 = degreesToRadians(location[0]); //Current lat point converted to radians - lon1 = degreesToRadians(location[1]); //Current long point converted to radians + lat1 = degreesToRadians(coordinate[0]); //Current lat point converted to radians + lon1 = degreesToRadians(coordinate[1]); //Current long point converted to radians lat2 = Math.asin(Math.sin(lat1) * Math.cos(d/R) + Math.cos(lat1) * Math.sin(d/R) * Math.cos(bearing)); @@ -137,9 +137,9 @@ var address = { radius = radius || 10.0; isMetric = isMetric || false; - // This is a heuristic to approximate the circular region defined by location and radius. - topLeftBoundary = boundaryLocation(location, degreesToRadians(45), radius, isMetric); - bottomRightBoundary = boundaryLocation(location, degreesToRadians(45), -radius, isMetric); + // This is a heuristic to approximate the circular region defined by coordinate and radius. + topLeftBoundary = boundaryCoordinate(coordinate, degreesToRadians(45), radius, isMetric); + bottomRightBoundary = boundaryCoordinate(coordinate, degreesToRadians(45), -radius, isMetric); randLat = randomFloat(topLeftBoundary[0], bottomRightBoundary[0]).toFixed(4); randLong = randomFloat(topLeftBoundary[1], bottomRightBoundary[1]).toFixed(4); -- cgit v1.2.3 From bec87b1acb708cba7b13173d3e240ce9dfb4bb27 Mon Sep 17 00:00:00 2001 From: Vivek Seth Date: Thu, 5 May 2016 14:52:29 -0400 Subject: If no input params return random coordinate --- lib/address.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/address.js b/lib/address.js index 6d9748fd..684914ce 100644 --- a/lib/address.js +++ b/lib/address.js @@ -133,7 +133,10 @@ var address = { return [radiansToDegrees(lat2), radiansToDegrees(lon2)]; } - location = location || [faker.latitude(), faker.longitude()] + // If there is no coordinate, the best we can do is return a random GPS coordinate. + if (coordinate === undefined) { + return [this.latitude(), this.longitude()] + } radius = radius || 10.0; isMetric = isMetric || false; -- cgit v1.2.3 From 43495cc4c07061610d318eb2b31e6b7075810f33 Mon Sep 17 00:00:00 2001 From: Vivek Seth Date: Fri, 6 May 2016 01:57:53 -0400 Subject: Fixed bug where variables were being leaked to global namespace --- lib/address.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/address.js b/lib/address.js index 684914ce..5fa924d4 100644 --- a/lib/address.js +++ b/lib/address.js @@ -120,13 +120,13 @@ var address = { var R = 6378.137; // Radius of the Earth (http://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html) var d = isMetric ? distance : kilometersToMiles(distance); // Distance in km - lat1 = degreesToRadians(coordinate[0]); //Current lat point converted to radians - lon1 = degreesToRadians(coordinate[1]); //Current long point converted to radians + var lat1 = degreesToRadians(coordinate[0]); //Current lat point converted to radians + var lon1 = degreesToRadians(coordinate[1]); //Current long point converted to radians - lat2 = Math.asin(Math.sin(lat1) * Math.cos(d/R) + + var lat2 = Math.asin(Math.sin(lat1) * Math.cos(d/R) + Math.cos(lat1) * Math.sin(d/R) * Math.cos(bearing)); - lon2 = lon1 + Math.atan2( + var lon2 = lon1 + Math.atan2( Math.sin(bearing) * Math.sin(d/R) * Math.cos(lat1), Math.cos(d/R) - Math.sin(lat1) * Math.sin(lat2)); -- cgit v1.2.3 From 0bfeb93c594ef31d4002eac6356a81b9e19fbb80 Mon Sep 17 00:00:00 2001 From: Vivek Seth Date: Fri, 6 May 2016 01:58:21 -0400 Subject: Ensure longitude points are within range [-180, 180] --- lib/address.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/address.js b/lib/address.js index 5fa924d4..f6e5be12 100644 --- a/lib/address.js +++ b/lib/address.js @@ -130,6 +130,13 @@ var address = { Math.sin(bearing) * Math.sin(d/R) * Math.cos(lat1), Math.cos(d/R) - Math.sin(lat1) * Math.sin(lat2)); + // Keep longitude in range [-180, 180] + if (lon2 > degreesToRadians(180)) { + lon2 = lon2 - degreesToRadians(360); + } else if (lon2 < degreesToRadians(-180)) { + lon2 = lon2 + degreesToRadians(360); + } + return [radiansToDegrees(lat2), radiansToDegrees(lon2)]; } -- cgit v1.2.3 From 08e264b10ffceaf7a389753f56331d09a68eafe2 Mon Sep 17 00:00:00 2001 From: Vivek Seth Date: Fri, 6 May 2016 01:58:48 -0400 Subject: Using different heuristic for producing a random GPS coordinate this approach will not result in a uniform distribution, but will instead concentrate points in the center. --- lib/address.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/address.js b/lib/address.js index f6e5be12..dde53b0d 100644 --- a/lib/address.js +++ b/lib/address.js @@ -116,7 +116,7 @@ var address = { function kilometersToMiles(miles) { return miles * 0.621371; } - function boundaryCoordinate(coordinate, bearing, distance, isMetric) { + function coordinateWithOffset(coordinate, bearing, distance, isMetric) { var R = 6378.137; // Radius of the Earth (http://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html) var d = isMetric ? distance : kilometersToMiles(distance); // Distance in km @@ -147,14 +147,12 @@ var address = { radius = radius || 10.0; isMetric = isMetric || false; - // This is a heuristic to approximate the circular region defined by coordinate and radius. - topLeftBoundary = boundaryCoordinate(coordinate, degreesToRadians(45), radius, isMetric); - bottomRightBoundary = boundaryCoordinate(coordinate, degreesToRadians(45), -radius, isMetric); + // TODO: implement either a gaussian/uniform distribution of points in cicular region. + // Possibly include param to function that allows user to choose between distributions. - randLat = randomFloat(topLeftBoundary[0], bottomRightBoundary[0]).toFixed(4); - randLong = randomFloat(topLeftBoundary[1], bottomRightBoundary[1]).toFixed(4); - - return [randLat, randLong]; + // This approach will likely result in a higher density of points near the center. + var randomCoord = coordinateWithOffset(coordinate, degreesToRadians(Math.random() * 360.0), radius, isMetric); + return [randomCoord[0].toFixed(4), randomCoord[1].toFixed(4)]; } }; -- cgit v1.2.3