Finding Longitude Angle when distance is known - node.js

I'm attempting to find the longitude (east-west) angle of a new point given that latitude does not also change.
Given: Starting Latitude, Starting Longitude, distance of travel in miles.
Desired result: Maximum and Minimum Longitude and Latitude degrees that are "distance of travel" from starting point.
Code below:
Attempt 1: Use "close enough" constants:
function(longitude, latitude, travelRadius, next){
var milesPerDegreeOfLongitude = 69.172;
var milesPerDegreeOfLatitude = 69.2;
var location = { longitude : longitude, latitude : latitude };
var longitudeDelta = (travelRadius / milesPerDegreeOfLongitude);
location.maxLongitude = longitude + longitudeDelta;
location.minLongitude = longitude - longitudeDelta;
var latitudeDelta = (travelRadius / milesPerDegreeOfLatitude);
location.maxLatitude = latitude + latitudeDelta;
location.minLatiude = latitude - latitudeDelta;
next(location);
}
^ This yields very close latitude, for a distance of 5 miles. But longitude for the same is about 3.93 miles as measured by google maps, too high of a variance.
Attempt 2: One radian is the angle for a line 3,958.761 miles long (the Earth's radius) therefore the angle for a line X miles long is X/3,958.761 radians.
function(longitude, latitude, travelRadius, next){
var radiusOfEarth = 3959.761;
//... omitting latitude ...
var distanceInRadians = (travelRadius / radiusOfEarth);
var degrees = (180 / Math.PI) * distanceInRadians;
location.maxLongitude = longitude + degrees;
location.minLongitude = longitude - degrees;
next(location)
}
^ And again I end up with about 3.93 miles on longitude distance. What could I do to get this right or at least within .5 miles of error?
Edit: attempt 3 using Mbo's suggestion:
var latitude = 37.7118042;
var longitude = -122.4458397;
var travelradius = 5;
function(latitude, longitude, travelRadius){
var milesPerDegreeOfLatitude = 69.172;
var milesPerDegreeOfLongitude = 69.172 * Math.cos(latitude)
var location = { longitude : longitude, latitude : latitude };
var latitudeDelta = (travelRadius / milesPerDegreeOfLatitude);
location.maxLatitude = latitude + latitudeDelta;
location.minLatiude = latitude - latitudeDelta;
var longitudeDelta = (travelRadius / milesPerDegreeOfLongitude);
location.maxLongitude = longitude + longitudeDelta;
location.minLongitude = longitude - longitudeDelta;
return location;
}
Outputs:
{
longitude: -122.4458397,
latitude: 37.7118042,
maxLongitude: -122.37355611704736,
minLongitude: -122.51812328295263,
maxLatitude: 37.784058535260115,
minLatiude: 37.63954986473989
}
Where Max longitude is ~3.85 miles from starting position. Still off, expecting something like: -122.3515 which is ~5 miles

milesPerDegreeOfLongitude is not constant value!
It depends on latitude. 69.172 is value for equator (zero latitude).
For other latitudes:
trueMilesPerDegreeOfLongitude = 69.172 * Cos(latitude)
Note that you code uses degrees, but Math.cos works with radians:
var latitude = 37.7118042;
var milesPerDegreeOfLongitude = 69.172 * Math.cos(latitude)
try something like
var milesPerDegreeOfLongitude = 69.172 * Math.cos(latitude * Math.Pi / 180)
My approx. calculation gives 0.09 for latitudeDelta and 122.44+-0.09 = 122.35, 122.53

Related

GeometryUtil.geodesicArea() returning massive values

I'm binding a popup to my polygons containing information about the area of the polygon, using the GeometryUtil.geodesicArea function. Here it is, pasted straight from the code:
geodesicArea: function (latLngs) {
var pointsCount = latLngs.length,
area = 0.0,
d2r = Math.PI / 180,
p1, p2;
if (pointsCount > 2) {
for (var i = 0; i < pointsCount; i++) {
p1 = latLngs[i];
p2 = latLngs[(i + 1) % pointsCount];
area += ((p2.lng - p1.lng) * d2r) *
(2 + Math.sin(p1.lat * d2r) + Math.sin(p2.lat * d2r));
}
area = area * 6378137.0 * 6378137.0 / 2.0;
}
return Math.abs(area);
}
When I draw a rectangle over the approximate area of Saskatchewan, Canada, using these coordinates:
0: {lat: 49.06465160956338, lng: -110.00904901708327}
1: {lat: 59.94790491663552, lng: -110.00904901708327}
2: {lat: 59.94790491663552, lng: -101.6155500597509}
3: {lat: 49.06465160956338, lng: -101.6155500597509}
roughly 651,900 sq km, it is returning 30610232650154772. If this number is assumed to be in square meters, it is to equal to roughly 30 billion square kilometers, which is well beyond the surface area of the entire earth, unless I'm missing something about what the meaning is of the numbers being returned.
What does this geodesic area function calculate? Is there some other way/function I should be using to get the area of a polygon?
Here is the code I'm using as well as calculated values line-by-line
You forgot the brackets in
area + = (p2.lng - p1.lng * d2r) *
necessary:
area + = ((p2.lng - p1.lng) * d2r) *
Just use Heron's formula and L.GeometryUtil.length() to achieve this:
Heron's formula

How we calculate distance between two co-ordinate. ArangoDB

I have a Users table that contains latitude and longitude attribute for every user. So I need to calculate the distance between two users in AQL Query.
I have done the same in Orientdb with the below query.
var laltitude = CURRENT_USER_laltitude;
var longitude = CURRENT_USER_longitude;
var query = "select distance(latitude, longitude,"+laltitude+","+longitude+") as distance from users";
First, create a js file distance.js (or whatever you want to name it) and put below code as below.
/* distance.js */
'use strict';
function gdistance(latitude1, longitude1, latitude2, longitude2, radius) {
if (!latitude1 || !longitude1 || !latitude2 || !longitude2) {
return null;
};
var lat1 = Number(latitude1), lon1 = Number(longitude1);
var lat2 = Number(latitude2), lon2 = Number(longitude2);
radius = (radius === undefined) ? 6371e3 : Number(radius);
var R = radius;
var φ1 = (lat1 * Math.PI / 180), λ1 = (lon1 * Math.PI / 180);
var φ2 = (lat2 * Math.PI / 180), λ2 = (lon2 * Math.PI / 180);
var Δφ = φ2 - φ1;
var Δλ = λ2 - λ1;
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2)
+ Math.cos(φ1) * Math.cos(φ2)
* Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Meters
var d2 = d / 1000; // Meters to KM
return d2;
}
module.exports = gdistance;
Now open Arango Console with arangosh. This will open with _system database by default. So if you have other than this database like me then use db._useDatabase("myDatabase") command to change database.
Now write below commands to add custom to your desired database.
Version 2.8
db._useDatabase("myDatabase");
var aqlfunctions = require("org/arangodb/aql/functions");
var f = require("/path/to/file/distance.js");
aqlfunctions.register("geo::gdistance", f, true)
Version 3.0+
db._useDatabase("myDatabase");
var aqlfunctions = require("#arangodb/aql/functions");
var f = require("/path/to/distance.js");
i.e.
var f = require("/home/ubuntu/distance.js");
var f = require("distance.js");
# If you want to remove this group's UDFs (User defined functions)
# aqlfunctions.unregisterGroup("geo");
aqlfunctions.register("geo::gdistance", f, true);
Now use in your AQL queries as below.
LET distance = geo::gdistance(attrbute_name.latitude, attrbute_name.longitude, #your_latitude, #your_longitude)
For more references with here.
Currently ArangoDB can only give you distances when you use the Geo index to return you the distance of your search start to the point matching your condition:
FOR doc IN WITHIN(##collection, #lat, #long, #radius, #distanceAttributeName)
RETURN doc
You could however use a user defined AQL function to extend AQL. User defined functions are implemented in Javascript, which is luckily used by Chris Veness to explain howto calculate distances
With ArangoDB 3.0 we most probably will support the arithmetic operations to calculate this in AQL.
I will edit this post with more details and examples soon.

Parse API - how do I narrow down results?

I am using the following code to get the locations for the nearest clinics in kms the code works sweet. But what I cant understand is how to get around the parse object only returning 100 objects so I guess my question should be how do i return just a subset that match the current long and lat of the clinics.
I call the below functions in my viewdIdLoadMethod
List<Clinics> _clicics;
_clicics =GetAllNearestFamousPlaces (54.269412, -0.93399086);
public List<Clinics> GetAllNearestFamousPlaces(double currentLatitude,double currentLongitude)
{
List<Clinics> Caldistance = new List<Clinics>();
var query = ParseObject.GetQuery("clinics");
query.FindAsync().ContinueWith(t =>
{
IEnumerable<ParseObject> results = t.Result;
foreach (var obj in results)
{
double distance = Distance(currentLatitude, currentLongitude, obj.Get<double>("lat"), obj.Get<double>("long"));
if (distance < 25) //nearbyplaces which are within 25 kms
{
Clinics dist = new Clinics();
dist.Name = obj.Get<string>("Name");
dist.Latitute = obj.Get<double>("lat");
dist.Longitude =obj.Get<double>("long");
Caldistance.Add(dist);
}
}
});
return Caldistance;
}
private double Distance(double lat1, double lon1, double lat2, double lon2)
{
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = (dist * 60 * 1.1515) / 0.6213711922; //miles to kms
return (dist);
}
private double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad)
{
return (rad * 180.0 / Math.PI);
}
This may not be syntactically correct - I don't actually use Parse so I'm guessing based on their docs
// assume your point of origin is 54.269412, -0.93399086
// each degree of lat/long is **roughly** 100 km so we'll fudge and +- .5 to narrow down the
// list of clinics
double lat = 54.269412;
double lng = -0.93399086;
double minLong = lng - 0.5;
double maxLong = lng + 0.5;
double minLat = lat - 0.5;
double maxLat = lat + 0.5;
var query = from clinic in ParseObject.GetQuery("clinics")
where clinic.Get<double>("lat") >= minLat
and clinic.Get<double>("lat") <= maxLat
and clinic.Get<double>("long") >= minLat
and clinic.Get<double>("long") <= maxLat
select clinic;
// 1000 is the max we can request at a time
query = query.Limit(1000);
// now execute your query to get the results, and then use your Distance() function to calculate
// the precise distance and remove results that are to far away, etc

how to get the all zipcode within the 5miles of distance

I would like all the zip codes which are within a 5 miles distance of a zip code input by the user.
See you have the centre coordinates for the circle and radius of the circle say 5 miles, now for every cordinate point in database, check the distance between Centre and that point by applying distance formula and check if it is less than radius,
In short,
C = point that is the center of the area
P = point we want to check for being inside the area
R = radius of the area
P is inside the area if
||P-C|| <= R
EDIT-
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}

Find points within a distance using CQL3

I have a cassandra table with user name, latitude and longitude. I would like to get a list of users who are inside the circle with a given latitude, longitude and distance.
For example: my input Lat= 78.3232 and Long = 65.3234 and distance = 30 miles.
I would like to get a list of users who are within 30 miles distance from the point 78.3232 and 65.3234. Is it possible to solve this with single CQL3 query? Or can anyone give me a hint start solving this query?
There was no geospatial support for cassandra so I found a way to Implement it mathematically to generate box coordinates around the point (That was good enough for my work) and use query to get coordinates within boundary.
I'll post the code for others reference.
public class GeoOperations {
public static final int UPPER_LATITUDE = 0;
public static final int LOWER_LATITUDE = 1;
public static final int UPPER_LONGITUDE = 2;
public static final int LOWER_LONGITUDE = 3;
private static final double KM_TO_MILES = 0.621371;
private final double Latitude;
private final double Longitude;
double Boundary[];
public GeoOperations(double init_latitude, double init_longitude) {
Latitude = init_latitude;
Longitude = init_longitude;
Boundary = new double[4];
}
public void GenerateBoxCoordinates(double Distance) {
Distance = Distance * KM_TO_MILES;
double Lat_Factor = (Distance) / 69;
Boundary[UPPER_LATITUDE] = Latitude + Lat_Factor;
Boundary[LOWER_LATITUDE] = Latitude - Lat_Factor;
double Long_Factor = (Distance) / (3960 * 2 * Math.PI / 360 * Math.cos(Latitude));
Boundary[UPPER_LONGITUDE] = Longitude + Long_Factor;
Boundary[LOWER_LONGITUDE] = Longitude - Long_Factor;
for (double x : Boundary) {
System.out.println(x);
}
}
}
And then Used Simple CQL to find coordinates within ranges
if values are like this
UPPER_LATITUDE = 60
LOWER_LATITUDE = 40
UPPER_LONGITUDE = 10
LOWER_LONGITUDE = 5
Query will be something like this (actually I used kundera with Hibernate and used a JPA query. So I havent tested it but it should work)
SELECT * FROM Points_Tablle
WHERE LATITUDE > 40
AND LATITUDE < 60
AND LONGITUDE > 5
AND LONGITUDE < 10;
If you're using DataStax enterprise, you get Geospatial out of the box. Check out Patrick's Demo:
https://github.com/PatrickCallaghan/datastax-geospatial-demo

Resources