I'm, writing an app that'll sort location by either name or distance from the user. Everything works as it should except getting the distance. Theoretically, I should be able to get the coordinates of the user through geolocation and I already have the coordinates to every location. Shouldn't I be able to run the haversine formula with these coordinates and attach the distance to each location via object.distance = d? Here is my code and a plunk to my project.
Plunker: http://plnkr.co/edit/nRQc7Ym0lsaK6jQwd626?p=preview
Code:
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope) {
$scope.ASiteLocs = [{
"name": "IL5077 BRUSSELS",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.58543899999999,38.955472,0"
}
}, {
"name": "IL5076 KAMPSVILLE",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.661923,39.29403,0"
}
}, {
"name": "IL5146 CARROLLTON",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.39965700000001,39.309142,0"
}
}, {
"name": "IL5153 GREENFIELD",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.208747,39.364077,0"
}
}];
$scope.SSiteLocs = [More Locations...];
$scope.SiteLocs = $scope.SSiteLocs.concat($scope.ASiteLocs);
repoSortOrder = "site.name";
navigator.geolocation.getCurrentPosition(GetLocation);
function GetLocation(location) {
Lat = location.coords.latitude;
Lon = location.coords.longitude;
}
angular.forEach($scope.SSiteLocs, function(object) {
object.carrier = 'Sprint';
getCoordDistance();
object.distance = $scope.d
});
angular.forEach($scope.ASiteLocs, function(object) {
object.carrier = 'AT&T';
getCoordDistance();
object.distance = $scope.d
});
angular.forEach($scope.SiteLocs, function(location) {
var clength = location.Point.coordinates.length;
if (location.Point.coordinates.substring(clength - 2, clength) === ",0") {
location.Point.coordinates = location.Point.coordinates.substring(0, clength - 2).split(",");
Lat = location.Point.coordinates[0];
Lon = location.Point.coordinates[1];
Com = ",";
location.Point.coordinates = Lon.concat(Com, Lat);
}
});
function getCoordDistance() {
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
var lat2 = Lat;
var lon2 = Lon;
var lat1 = 45;//Test Lat
var lon1 = -50;//Test Lon
var R = 3959; // Radius in miles
//has a problem with the .toRad() method below.
var x1 = lat2 - lat1;
var dLat = x1.toRad();
var x2 = lon2 - lon1;
var dLon = x2.toRad();
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
$scope.d = R * c;
}
});
In the code above when I use integers for the Lat/Lons in getCoordDistance() for instance, lat1 = 5,lat2 = 10,lon1 = 0,lon2 = 0 it works and adds the distance to each location. But when I try to use my location it fails. Any Ideas? Thanks in advance for any help.
I figured it out, My getCoordDistance() was undefined.
Related
$.getJSON("https://example.com//json/", function (data) {
var count = Object.keys(data).length;
for (var i = 0; i < count; i++) {
var lat = data[i].LAT;
var lng = data[i].LNG;
var locs = { lat: lat, lng: lng };
var check = arePointsNear(pos, locs, 2487);
if (check) listStations.push(data[i].ID);
}
console.log(listStations);
console.log(listStations[0]);
});
function arePointsNear(checkPoint, centerPoint, m) {
var km = m/1000;
var ky = 40000 / 360;
var kx = Math.cos(Math.PI * centerPoint.lat / 180) * ky;
var dx = Math.abs(centerPoint.lng - checkPoint.lng) * kx;
var dy = Math.abs(centerPoint.lat - checkPoint.lat) * ky;
return Math.sqrt(dx * dx + dy * dy) <= km;
}
Example json in data;
{
"ID": 359,
"NAME": "Atatürk Bulvarı 1",
"LOCATION": "0001 Atatürk Bulvarı 1",
"PARK_INFO": "2",
"PARK_CAPACITY": 18,
"START_TIME": {
"Ticks": 270000000000,
"Days": 0,
"Hours": 7,
"Milliseconds": 0,
"Minutes": 30,
"Seconds": 0,
"TotalDays": 0.3125,
"TotalHours": 7.5,
"TotalMilliseconds": 27000000,
"TotalMinutes": 450,
"TotalSeconds": 27000
},
"FINISH_TIME": {
"Ticks": 666000000000,
"Days": 0,
"Hours": 18,
"Milliseconds": 0,
"Minutes": 30,
"Seconds": 0,
"TotalDays": 0.77083333333333326,
"TotalHours": 18.5,
"TotalMilliseconds": 66600000,
"TotalMinutes": 1110,
"TotalSeconds": 66600
},
"DISTRICT_CODE": "20",
"ADRESS": "KEMALPAŞA MAHALLESİ ATATÜRK BULVARI 1 / EMİNÖNÜ",
"LNG": 28.9535382991555,
"LAT": 41.0112914996693,
"SUBS_PRICE": 0,
"FREE_TIME": 15
}
It is ok to pull json data from the relevant link. Sending the data to the arePointsNear function and verifying true-false is ok. When I write the console.log data written in the code in the bottom line (in for), 0.index is undefined.
By the way, variables are defined independently and globally at the top.
What should I do?
You might consider using $.each(). Assuming you're data is an Array of Objects, consider this example.
$(function() {
function arePointsNear(checkPoint, centerPoint, m) {
var km = m / 1000;
var ky = 40000 / 360;
var kx = Math.cos(Math.PI * centerPoint.lat / 180) * ky;
var dx = Math.abs(centerPoint.lng - checkPoint.lng) * kx;
var dy = Math.abs(centerPoint.lat - checkPoint.lat) * ky;
return Math.sqrt(dx * dx + dy * dy) <= km;
}
var pos;
var listStations = [];
$.getJSON("https://example.com/json/", function(data) {
$.each(data, function(index, location) {
if (arePointsNear(pos, {
lat: location.LAT,
lng: location.LNG
}, 2487)) {
listStations.push(location.ID);
}
});
console.log(listStations);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I want to find my friends by taking their location from their mobile phone who are near to me from my current location.
For example in my code below I have var cities, If I put 3,4 numbers of my friends so I can do this? Or can I do this making some other changes? Is it possible?
// Get User's Coordinate from their Browser
window.onload = function () {
// HTML5/W3C Geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(UserLocation);
}
// Default to Washington, DC
else
NearestCity(38.8951, -77.0367);
}
// Callback function for asynchronous call to HTML5 geolocation
function UserLocation(position) {
NearestCity(position.coords.latitude, position.coords.longitude);
}
// Convert Degress to Radians
function Deg2Rad(deg) {
return deg * Math.PI / 180;
}
function PythagorasEquirectangular(lat1, lon1, lat2, lon2) {
lat1 = Deg2Rad(lat1);
lat2 = Deg2Rad(lat2);
lon1 = Deg2Rad(lon1);
lon2 = Deg2Rad(lon2);
var R = 6371; // km
var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
var y = (lat2 - lat1);
var d = Math.sqrt(x * x + y * y) * R;
return d;
}
var lat = 20; // user's latitude
var lon = 40; // user's longitude
var cities = [
["city1", 10, 50, "blah"],
["city2", 40, 60, "blah"],
["city3", 25, 10, "blah"],
["city4", 5, 80, "blah"]
];
function NearestCity(latitude, longitude) {
var mindif = 99999;
var closest;
for (index = 0; index < cities.length; ++index) {
var dif = PythagorasEquirectangular(latitude, longitude, cities[index]
[1], cities[index][2]);
if (dif < mindif) {
closest = index;
mindif = dif;
}
}
// echo the nearest city
alert(cities[closest]);
}
I suggest using GeoFire for that purpose it is from firebase and has Geographical based queries and can do what you want in an easy way
I am using the Haversine formula to calculate the distance between two points on earth. I have the following code:
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope, $timeout) {
var myLat, myLon, locLat, locLon;
navigator.geolocation.watchPosition(GetLocation)
$scope.ASiteLocs = [{
"name": "IL5077 BRUSSELS",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.58543899999999,38.955472,0"
}
}, {
"name": "IL5076 KAMPSVILLE",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.661923,39.29403,0"
}
}, {
"name": "IL5146 CARROLLTON",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.39965700000001,39.309142,0"
}
}, {
"name": "IL5153 GREENFIELD",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.208747,39.364077,0"
}
}];
$scope.SSiteLocs = [];
$scope.SiteLocs = $scope.SSiteLocs.concat($scope.ASiteLocs);
repoSortOrder = "site.name";
function GetLocation(location, myLat, myLon) {
myLat = location.coords.latitude;
myLon = location.coords.longitude;
document.getElementById("lat").innerHTML = myLat;
document.getElementById("lon").innerHTML = myLon;
$timeout(function() {
calculate();
});
}
$scope.getCoordDistance = function(myLat, myLon, locLat, locLon) {
var lat1 = locLat; //41.887055
var lon1 = locLon; //-88.469233
var lat2 = myLat; //41.888668
var lon2 = myLon; //-87.640371
var R = 3959;
var x1 = lat2 - lat1;
var dLat = x1 * Math.PI / 180;
var x2 = lon2 - lon1;
var dLon = x2 * Math.PI / 180;
a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
};
angular.forEach($scope.SSiteLocs, function(object) {
object.carrier = 'Sprint';
});
angular.forEach($scope.ASiteLocs, function(object) {
object.carrier = 'AT&T';
});
var i = 0;
locX = 1;
var calculate = function() {
angular.forEach($scope.SiteLocs, function(location) {
var clength = location.Point.coordinates.length;
if (location.Point.coordinates.substring(clength - 2, clength) === ",0") {
location.Point.coordinates = location.Point.coordinates.substring(0, clength - 2).split(",");
Lat = location.Point.coordinates[0];
Lon = location.Point.coordinates[1];
Com = ",";
location.Point.coordinates = Lon.concat(Com, Lat);
myLat = Number(document.getElementById("lat").innerHTML)
myLon = Number(document.getElementById("lon").innerHTML)
locLat = Lat;
locLon = Lon;
d = $scope.getCoordDistance(myLat, myLon, locLat, locLon);
location.distance = d.toFixed(1);
if(i < 15){
console.log("********LOCATON " + locX + "***********")
console.log("myCoords: " + myLat + "," + myLon);
console.log("locCoords: " + locLat + "," + locLon);
console.log("d: " + d);
console.log("***************************")
i++;
locX++;
}
}
});
};
});
The results from the formula are up to about 9-10 thousand when they should be no where near that high. If I use the commented out coordinates it returns correctly (42.6 Miles)
Since the test coordinates work I know it is not a math problem. Does anybody know what is causing the formula to not work correctly?
EDIT
Here is a plunker of the full proj. if that helps. EDIT2 I discovered something odd, the results are different in different browsers, so, chrome displays one set of numbers and IE displays another, ect.
Your point coordinates are longitude latitude
BRUSSELS",
"
"Point": {
"coordinates": "-90.58543899999999,38.955472
In your code
Lat = location.Point.coordinates[0];
Lon = location.Point.coordinates[1];
Either change them in your object(preferable) See Google latlng class
"Point": {
"coordinates": "38.955472,-90.58543899999999
or
Lat = location.Point.coordinates[1];
Lon = location.Point.coordinates[0];
With your settings distance is aprox 9000 miles with coordinates transposed distance is aprox 200
In addition to what kirinthos said in his response, you can easily test this by comparing your results with Google Maps. I have a function in my app that does this. The point1 and point2 parameters are simple Latlng objects.I wanted the results in kilometers so I divide by 1000.
function calculateDistanceBetweenTwoPoints(point1, point2) {
return (google.maps.geometry.spherical.computeDistanceBetween(point1, point2) / 1000).toFixed(2);
}
You'll need the following in your HTML page:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,places"></script>
I'm not entirely sure, here, without testing it but it looks like the GetLocation function is overwriting the closure scope of the variables myLat and myLon by declaring them as function arguments, so you're assigning the value of location.coords.latitude into the function scope myLat variable, instead of the myLat declared at the beginning of your code block.
throw a console.log(myLat, myLon); into the beginning of getCoordDistance and check their values. I'll bet they're not what you expect.
edit: it actually may have been the lack of semicolons and stuff. here's a small snippet of your code re-calibrated to run in an isolated environment like jsbin.com. It appears to work fine. you were missing 4 semicolons, so unless this assignment is failing, it should work: myLon = Number(document.getElementById("lon").innerHTML)
there were complaints of variable "i" and "locX" not being defined
var myLat, myLon;
var ASiteLocs = [{
"name": "IL5077 BRUSSELS",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.58543899999999,38.955472,0"
}
}, {
"name": "IL5076 KAMPSVILLE",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.661923,39.29403,0"
}
}, {
"name": "IL5146 CARROLLTON",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.39965700000001,39.309142,0"
}
}, {
"name": "IL5153 GREENFIELD",
"styleUrl": "#waypoint",
"Point": {
"coordinates": "-90.208747,39.364077,0"
}
}];
var SSiteLocs = [];
var SiteLocs = SSiteLocs.concat(ASiteLocs);
function GetLocation(location, myLat, myLon) {
myLat = location.coords.latitude;
myLon = location.coords.longitude;
document.getElementById("lat").innerHTML = myLat;
document.getElementById("lon").innerHTML = myLon;
}
function getCoordDistance(myLat, myLon, locLat, locLon) {
var lat1 = locLat; //41.887055
var lon1 = locLon; //-88.469233
var lat2 = myLat; //41.888668
var lon2 = myLon; //-87.640371
var R = 3959;
var x1 = lat2 - lat1;
var dLat = x1 * Math.PI / 180;
var x2 = lon2 - lon1;
var dLon = x2 * Math.PI / 180;
a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
};
function calculate() {
SiteLocs.forEach(function(location) {
var clength = location.Point.coordinates.length;
if (location.Point.coordinates.substring(clength - 2, clength) === ",0") {
location.Point.coordinates = location.Point.coordinates.substring(0, clength - 2).split(",");
Lat = location.Point.coordinates[0];
Lon = location.Point.coordinates[1];
Com = ",";
location.Point.coordinates = Lon.concat(Com, Lat);
myLat = -90.208747;
myLon = 39.364077;
locLat = Lat;
locLon = Lon;
d = getCoordDistance(myLat, myLon, locLat, locLon);
location.distance = d.toFixed(1);
//console.log("********LOCATON " + locX + "***********");
console.log("myCoords: " + myLat + "," + myLon);
console.log("locCoords: " + locLat + "," + locLon);
console.log("d: " + d);
console.log("***************************");
}
});
};
I want to show specific information depending on where i am.
I have five cities with different information, and i want to show that city(information) that i'm closest to.
How to i do that the simplest way, using javascript.
Ex.
If i store the cities lat, long in an array
var cities = [
['new york', '111111', '222222', 'blablabla']
['boston', '111111', '222222', 'blablabla']
['seattle', '111111', '222222', 'blablabla']
['london', '111111', '222222', 'blablabla']
]
And with my current location(lat, long) i want the city that i'm closet to.
Here is a basic code example using HTML5 geolocation to get the user's position. It then calls NearestCity() and calculates the distance (km) from the location to each city. I passed on using the Haversine formulae and instead used the simpler Pythagoras formulae and an equirectangular projection to adjust for the curvature in longitude lines.
// Get User's Coordinate from their Browser
window.onload = function() {
// HTML5/W3C Geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(UserLocation);
}
// Default to Washington, DC
else
NearestCity(38.8951, -77.0367);
}
// Callback function for asynchronous call to HTML5 geolocation
function UserLocation(position) {
NearestCity(position.coords.latitude, position.coords.longitude);
}
// Convert Degress to Radians
function Deg2Rad(deg) {
return deg * Math.PI / 180;
}
function PythagorasEquirectangular(lat1, lon1, lat2, lon2) {
lat1 = Deg2Rad(lat1);
lat2 = Deg2Rad(lat2);
lon1 = Deg2Rad(lon1);
lon2 = Deg2Rad(lon2);
var R = 6371; // km
var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
var y = (lat2 - lat1);
var d = Math.sqrt(x * x + y * y) * R;
return d;
}
var lat = 20; // user's latitude
var lon = 40; // user's longitude
var cities = [
["city1", 10, 50, "blah"],
["city2", 40, 60, "blah"],
["city3", 25, 10, "blah"],
["city4", 5, 80, "blah"]
];
function NearestCity(latitude, longitude) {
var minDif = 99999;
var closest;
for (index = 0; index < cities.length; ++index) {
var dif = PythagorasEquirectangular(latitude, longitude, cities[index][1], cities[index][2]);
if (dif < minDif) {
closest = index;
minDif = dif;
}
}
// echo the nearest city
alert(cities[closest]);
}
With HTML5, you can pull the location of the user and then compares this example using a Haversine function (function below taken from here):
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)
}
You can calculate the distance by latitude with your location and the cities locations. And find the shortest and draw. To calculate you can read more in http://www.movable-type.co.uk/scripts/latlong.html
I am using geolocation to get the users current location and monitor it using the watchPosition method. However, is there a way of calculating the distance between the users starting position and current position? Below is my code:
var x = document.getElementById("info");
function getLocation() {
if(navigator.geolocation) {
navigator.geolocation.watchPosition(showPosition, showError, {
enableHighAccuracy: true,
maximumAge: 60000,
timeout: 27000
})
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
}
}
var flightPathCoordinates = [];
function showPosition(position) {
x.innerHTML = "Latitude: " + position.coords.latitude + "<br>Longitude: " + position.coords.longitude + "<br>Accuracy: " + position.coords.accuracy + "<br>Altitude: " + position.coords.altitude + "<br>Altitude Accuracy: " + position.coords.altitudeAccuracy + "<br>Heading: " + position.coords.heading + "<br>Speed: " + position.coords.speed + "<br>Speed (mph): " + position.coords.speed * 2.2369 + "<br>Speed (km): " + position.coords.speed * 3.6 + "<br>Timestamp: " + new Date(position.timestamp).toLocaleString() + "<br>Distance Travelled (km): " + calculateDistance(position.coords.latitude, position.coords.longitude, position.coords.latitude, position.coords.longitude);
// Distance Calculator
function calculateDistance(lat1, lon1, lat2, lon2) {
if(typeof (Number.prototype.toRad) === "undefined") {
Number.prototype.toRad = function () {
return this * Math.PI / 180;
}
}
var R = 6371; // km
var dLat = (lat2 - lat1).toRad();
var dLon = (lon2 - lon1).toRad();
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
}
Number.prototype.toRad = function () {
return this * Math.PI / 180;
}
lat = position.coords.latitude;
lon = position.coords.longitude;
latlon = new google.maps.LatLng(lat, lon)
mapholder = document.getElementById('mapholder')
var myOptions = {
center: latlon,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.SMALL
}
}
var map = new google.maps.Map(document.getElementById("mapholder"), myOptions);
Any help would be very much appreciated as I am quite new to this.
Thanks!
This has been adapted from the Google Maps API, and reworked to be independent of the library.
Example - calculate the distance from the center of New York City to the center of Philadelphia.
Fiddle for miles: http://jsfiddle.net/DXNzu/
Fiddle for kilometers: http://jsfiddle.net/DXNzu/1/
JS
function distanceFrom(points) {
var lat1 = points.lat1;
var radianLat1 = lat1 * (Math.PI / 180);
var lng1 = points.lng1;
var radianLng1 = lng1 * (Math.PI / 180);
var lat2 = points.lat2;
var radianLat2 = lat2 * (Math.PI / 180);
var lng2 = points.lng2;
var radianLng2 = lng2 * (Math.PI / 180);
var earth_radius = 3959; // or 6371 for kilometers
var diffLat = (radianLat1 - radianLat2);
var diffLng = (radianLng1 - radianLng2);
var sinLat = Math.sin(diffLat / 2);
var sinLng = Math.sin(diffLng / 2);
var a = Math.pow(sinLat, 2.0) + Math.cos(radianLat1) * Math.cos(radianLat2) * Math.pow(sinLng, 2.0);
var distance = earth_radius * 2 * Math.asin(Math.min(1, Math.sqrt(a)));
return distance.toFixed(3);
}
var distance = distanceFrom({
// NYC
'lat1': 40.713955826286046,
'lng1': -74.00665283203125,
// Philly
'lat2': 39.952335,
'lng2': -75.163789
});
The result is 80.524 miles or 129.583 kilometers.
you can use Haversine formula
rad = function(x) {return x*Math.PI/180;}
distHaversine = function(p1, p2) { // Points are Geolocation.coords objects
var R = 6371; // earth's mean radius in km
var dLat = rad(p2.latitude - p1.latitude);
var dLong = rad(p2.longitude - p1.longitude);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d.toFixed(3);
}
Two tips
typeof is not a function. Use it like this: typeof something
Do not put polyfills in listeners. you are repeating the polyfill action in every time listener fires.