Javascript function order - javascript

I want to execute functions in order but i constantly get 1,3,4,2 in console.Because of that ltt and lott remains 0 in function getDistanceFromLatLonInKm.Any ideas?Thanks in advance.
var ltt=0;
var lott=0;
if (navigator.geolocation){
navigator.geolocation.getCurrentPosition(ajmo);
console.log('1');
}
function ajmo(position){
console.log('2');
window.ltt=position.coords.latitude;
window.lott=position.coords.longitude;
document.write(window.ltt);
}
console.log('3');
document.write(window.ltt);
document.write("kurac:" + getDistanceFromLatLonInKm(45.332497,14.436384));
function getDistanceFromLatLonInKm(lat1,lon1){
console.log('4');
//second
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(ltt-lat1); // deg2rad below
var dLon = deg2rad(lott-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(ltt)) *
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)
}

The following changes will ensure that all console messages are in order 1,2,3,4
var ltt=0;
var lott=0;
if (navigator.geolocation){
console.log('1');
navigator.geolocation.getCurrentPosition(ajmo);
}
function ajmo(position){
console.log('2');
window.ltt=position.coords.latitude;
window.lott=position.coords.longitude;
document.write(window.ltt);
console.log('3');
document.write(window.ltt);
document.write("kurac:" + getDistanceFromLatLonInKm(45.332497,14.436384));
}
function getDistanceFromLatLonInKm(lat1,lon1){
console.log('4');
//second
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(ltt-lat1); // deg2rad below
var dLon = deg2rad(lott-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(ltt)) *
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)
}

The reason why they are being called out of order is because the method "geolocation.getCurrentPosition(success, error, options)" is asynchronous.
https://developer.mozilla.org/en-US/docs/WebAPI/Using_geolocation
The (function)object AJMO that you are giving to it is actually used to describe the callback method. The script hits the line and sends an asynchronous request to the function, BUT it isn't going to wait for a response. The execution proceeds forward even though it hasn't heard back yet. The remaining lines are pretty simple with very low overhead so they resolve much, much quicker than the getCurrentPosition method. '2' is executed at the end, but this is only because the method finally "called back" to the success function you created, "AJMO".
If you want to make sure that the code is executed in order you could try this instead.
var ltt=0;
var lott=0;
function getDistanceFromLatLonInKm(lat1,lon1){
console.log('4');
//second
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(ltt-lat1); // deg2rad below
var dLon = deg2rad(lott-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(ltt)) *
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 ajmo(position){
console.log('2');
window.ltt=position.coords.latitude;
window.lott=position.coords.longitude;
document.write(window.ltt);
console.log('3');
document.write("kurac:" + getDistanceFromLatLonInKm(45.332497,14.436384));
}
if (navigator.geolocation){
navigator.geolocation.getCurrentPosition(ajmo);
console.log('1');
}
This puts the calls to '2', '3', and '4' within the successful callback method while still exposing "getDistanceFromLatLonInKm" as a separate function if you need it for some other purpose.

You don't need to use global variables here. Simply include the call to getDistanceFromLatLonInKm within ajmo, and this will ensure that your code does things in the right order.
// call getLocation
getLocation();
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(ajmo);
}
}
function ajmo(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
// don't use document.write - it's considered bad practice
// this will get access to an element with id="out"
var out = document.getElementById('out');
// now pass lat and lng as new parameters into getDistanceFromLatLonInKm
out.innerHTML = 'kurac:' + getDistanceFromLatLonInKm(45.332497, 14.436384, lat, lng);
}
// now use the lat/lng arguments instead of the global variables
function getDistanceFromLatLonInKm(lat_origin, lon_origin, lat_pos, lng_pos) {
var R = 6371;
var dLat = deg2rad(lat_pos - lat_origin);
var dLon = deg2rad(lng_pos - lng_origin);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat_origin)) * Math.cos(deg2rad(lat_pos)) *
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;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}

Related

I am trying to get markers near user location by calculating distance using haversine formula

Hey guys can anybody help me why i am getting an error in this code
Here is the code.
getWithinDistance: function(){
var selectedMarker = [];
var lat1 = this.state.region.latitude;
var lon1 = this.state.region.longitude;
for(var i = 0 ; i <= 3 ; i++)
{
var lat2 = this.state.a[i].latitude;
var lon2 = this.state.a[i].longitude;
var R = 6371;
var dLat = (lat2-lat1) * (Math.PI/180);
var dLon = (lon2-lon1) * (Math.PI/180);
var 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);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
if(d <= 2.00){
var latlng = {
latitude: lat2,
longitude: lon2
}
selectedMarker.push(latlng);
}
}
console.log(selectedMarker);
var at = selectedMarker.map(marker => {
return(
<MapView.Marker coordinate={marker.latlng} />
);
})
},
I am getting Warning: Failed prop type: Required prop coordinate was not specified. but when i log it i can see two markers in the array selectedMarker[]
here is the snap of log which i get
Thanks in advance.
You have placed the return statement inside your for loop. So the the loop will exit after the first iteration.
Take these lines out of the for loop.
return (
<MapView.Marker coordinate={this.state.a[i]} />
);
Edit your for loop to store all the markers that are within the required distance in an array and then after the for loop return that array
You can use Array.prototype.map() to iterate and get the values.
Like this:
(ES6 Style)
getWithinDistance: function(){
const lat1 = this.state.region.latitude;
const lon1 = this.state.region.longitude;
const R = 6371
this.state.a.map(coordinate => {
const dLat = (coordinate.latitude - lat1) * (Math.PI/180)
const dLon = (coordinate.longitude - lon1) * (Math.PI/180)
const 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);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const d = R * c
console.log(coordinate, d)
}
}
This will show the coordinates with their distance to your location.
The return statement has to be outside the map() function. And return whatever you want to achieve.

Using the Haversine Formula in Javascript

I'm trying to use the Haversine Distance Formula (as found here: http://www.movable-type.co.uk/scripts/latlong.html) but I can't get it to work, please see the following code
function test() {
var lat2 = 42.741;
var lon2 = -71.3161;
var lat1 = 42.806911;
var lon1 = -71.290611;
var R = 6371; // km
//has a problem with the .toRad() method below.
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;
alert(d);
}
And the error is:
Uncaught TypeError: Object -0.06591099999999983 has no method 'toRad'
Which I understand to be because it needs to do the following:
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
But when I put this below the function, it still comes back with the same error message. How do I make it use the helper method? Or is there an alternative way to code this to get it to work? Thanks!
This code is working:
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
var lat2 = 42.741;
var lon2 = -71.3161;
var lat1 = 42.806911;
var lon1 = -71.290611;
var R = 6371; // km
//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));
var d = R * c;
alert(d);
Notice how I defined x1 and x2.
Play with it at: https://tinker.io/3f794
Here's a refactored function based on 3 of the other answers!
Please note that the coords arguments are [longitude, latitude].
function haversineDistance(coords1, coords2, isMiles) {
function toRad(x) {
return x * Math.PI / 180;
}
var lon1 = coords1[0];
var lat1 = coords1[1];
var lon2 = coords2[0];
var lat2 = coords2[1];
var R = 6371; // km
var x1 = lat2 - lat1;
var dLat = toRad(x1);
var x2 = lon2 - lon1;
var dLon = toRad(x2)
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(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;
if(isMiles) d /= 1.60934;
return d;
}
ES6 JavaScript/NodeJS refactored version:
/**
* Calculates the haversine distance between point A, and B.
* #param {number[]} latlngA [lat, lng] point A
* #param {number[]} latlngB [lat, lng] point B
* #param {boolean} isMiles If we are using miles, else km.
*/
const haversineDistance = ([lat1, lon1], [lat2, lon2], isMiles = false) => {
const toRadian = angle => (Math.PI / 180) * angle;
const distance = (a, b) => (Math.PI / 180) * (a - b);
const RADIUS_OF_EARTH_IN_KM = 6371;
const dLat = distance(lat2, lat1);
const dLon = distance(lon2, lon1);
lat1 = toRadian(lat1);
lat2 = toRadian(lat2);
// Haversine Formula
const a =
Math.pow(Math.sin(dLat / 2), 2) +
Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
const c = 2 * Math.asin(Math.sqrt(a));
let finalDistance = RADIUS_OF_EARTH_IN_KM * c;
if (isMiles) {
finalDistance /= 1.60934;
}
return finalDistance;
};
See codepen for tests against accepted answer: https://codepen.io/harrymt/pen/dyYvLpJ?editors=1011
Why not try the straight forward solution? Instead of extending Number prototype, just define toRad as a regular function:
function toRad(x) {
return x * Math.PI / 180;
}
and then call toRad everywhere:
var dLat = toRad(lat2-lat1);
Extending the Number prototype does not always work as expected. For example calling 123.toRad() does not work. I think that if you do var x1 = lat2 - lat1; x1.toRad(); works better than doing (lat2-lat1).toRad()
when I put this below the function
You only need to put it above the point where you call test(). Where the test function itself is declared does not matter.
You need to extend the Number prototype, before calling those extensions in a function.
So just ensure
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
is called before your function is called.
Another variant to reduce redundancy and also compatible with Google LatLng objects:
function haversine_distance(coords1, coords2) {
function toRad(x) {
return x * Math.PI / 180;
}
var dLat = toRad(coords2.latitude - coords1.latitude);
var dLon = toRad(coords2.longitude - coords1.longitude)
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRad(coords1.latitude)) *
Math.cos(toRad(coords2.latitude)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
return 12742 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
Here's another refactored answer in JavaScript:
getHaversineDistance = (firstLocation, secondLocation) => {
const earthRadius = 6371; // km
const diffLat = (secondLocation.lat-firstLocation.lat) * Math.PI / 180;
const diffLng = (secondLocation.lng-firstLocation.lng) * Math.PI / 180;
const arc = Math.cos(
firstLocation.lat * Math.PI / 180) * Math.cos(secondLocation.lat * Math.PI / 180)
* Math.sin(diffLng/2) * Math.sin(diffLng/2)
+ Math.sin(diffLat/2) * Math.sin(diffLat/2);
const line = 2 * Math.atan2(Math.sqrt(arc), Math.sqrt(1-arc));
const distance = earthRadius * line;
return distance;
}
const philly = { lat: 39.9526, lng: -75.1652 }
const nyc = { lat: 40.7128, lng: -74.0060 }
const losAngeles = { lat: 34.0522, lng: -118.2437 }
console.log(getHaversineDistance(philly, nyc)) //129.61277152662188
console.log(getHaversineDistance(philly, losAngeles)) //3843.4534005980404
This is a java implemetation of talkol's solution above. His or her solution worked very well for us. I'm not trying to answer the question, since the original question was for javascript. I'm just sharing our java implementation of the given javascript solution in case others find it of use.
// this was a pojo class we used internally...
public class GisPostalCode {
private String country;
private String postalCode;
private double latitude;
private double longitude;
// getters/setters, etc.
}
public static double distanceBetweenCoordinatesInMiles2(GisPostalCode c1, GisPostalCode c2) {
double lat2 = c2.getLatitude();
double lon2 = c2.getLongitude();
double lat1 = c1.getLatitude();
double lon1 = c1.getLongitude();
double R = 6371; // km
double x1 = lat2 - lat1;
double dLat = x1 * Math.PI / 180;
double x2 = lon2 - lon1;
double dLon = x2 * Math.PI / 180;
double 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);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
// convert to miles
return d / 1.60934;
}

use a variable outside the function

hello i have this function
locDistance(alat[i-1], alon[i-1], alat[i], alon[i]);
function locDistance(lat1, lon1, lat2, lon2) {
//Radius of the earth in: 1.609344 miles, 6371 km | var R = (6371 / 1.609344);
//var R = 3958.7558657440545;
var R = 3958.7558657440545;
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(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;
var dist = d;
};
function toRad(Value) {
/** Converts numeric degrees to radians */
return Value * Math.PI / 180;
}
i know i have to declare the variable outside the function to use it at another place
so i have defined at the top of the page
var dist = 0;
i want to use de variable 'dist' in another function like in here
$('.content').append(dist);
but the problem is i keep getting 0 as result of the dist variable.
i have checked but inside de locDistance function the dist variable has different values as it should be so the function is not the issue here
what am i doing wrong?
thank you in advance
The reason that the code above does not work is that the var keyword is being used in the locDistance method, thereby setting dist to a local variable every time the function is called and leaving the global dist set to 0.
That being said...
Perhaps you would rather have locDistance return the value and then call the function when you need it, like:
$('.content').append(locDistance(alat[i-1], alon[i-1], alat[i], alon[i]));
function locDistance(lat1, lon1, lat2, lon2) {
//Radius of the earth in: 1.609344 miles, 6371 km | var R = (6371 / 1.609344);
//var R = 3958.7558657440545;
var R = 3958.7558657440545;
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(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;
return d;
}
function toRad(Value) {
/** Converts numeric degrees to radians */
return Value * Math.PI / 180;
}

About calculate distances between coordinates

I found this post:
Google Maps - How to get the distance between two point in metre?
I have the same problem, my variable "a" has the NaN value. I prefer not using google api if I can do it.
I am using the code in this web page: http://www.movable-type.co.uk/scripts/latlong.html
But my variables still return NaN...
This is my code:
function actualizaLimpieza(jsonData){ //jsonData keeps all points (lat&lon)
var latJSON;
var lonJSON;
var R = 6371; // km
var dLat;
var dLon;
var lat1;
var lat2;
var a;
var c;
var d;
latGPS = 43.466827534582606; //this are supossed to be gotten by gps, but for try...
lonGPS = -3.863614797592163;
for(i = 0; i < jsonData.length; i ++){
latJSON = jsonData[i].lng;
lonJSON = jsonData[i].lat;
dlat = toRad(latJSON-latGPS);
dlon = toRad(lonJSON-lonGPS);
latGPS = toRad(latGPS);
latJSON = toRad(latJSON);
a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(latGPS) * Math.cos(latJSON);
alert("a vale: " + a); //returns NaN
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
alert("c vale: " + c);
d = R * c;
alert("d vale: " + d);
if(d < 0,010){
alert("less than 10 meters");
}
}
}
function toRad(degrees){
return degrees * Math.PI / 180;
}
Should I do any more changes to get it working? Any script I should add? I haven't add anyone for this work.
Ok, I fail writing variables: dlat != dLat... Now it works more or less

Google maps api v2 - find closest/nearest markers/points in the map ?

Hi i am trying do what seems to be almost impossible ... i am trying to get three nearest locations marker objects ... is this even possible ? .. it does not have to be 100% accurate ... but to do at least something ... what i found on the net and tried was this :
function find_closest_marker( lat1, lon1 ) {
for(var y = 1; y < 4; y++){
var pi = Math.PI;
var R = 6371; //equatorial radius
for(var i=0;i<markers.length; i++ ) {
//alert(markers.length);
var closest = -1;
var distances = [];
var lat2 = points[i].lat().toFixed(5);
var lon2 = points[i].lng().toFixed(5);
var chLat = lat2-lat1;
var chLon = lon2-lon1;
var dLat = chLat*(pi/180);
var dLon = chLon*(pi/180);
var rLat1 = lat1*(pi/180);
var rLat2 = lat2*(pi/180);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(rLat1) * Math.cos(rLat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
distances[i] = d;
if ( closest == -1 || d < distances[closest] ) {
closest = i;
}
}
var markerImg = "";
if(markers[closest].markerType == 1){
markerImg="/files/billeder/../Templates/Designs/Ideal2011/images/Map/dot_red.jpg"
} else if(markers[closest].markerType == 2){
markerImg="/files/billeder/../Templates/Designs/Ideal2011/images/Map/dot_lblue.jpg"
}else if(markers[closest].markerType == 3){
markerImg="/files/billeder/../Templates/Designs/Ideal2011/images/Map/dot_dblue.jpg"
}else if(markers[closest].markerType == 4){
markerImg="/files/billeder/../Templates/Designs/Ideal2011/images/Map/dot_green.jpg"
}
$('.nearestPlace'+y).html(
"<img src='"+markerImg+"' alt='"+markers[closest].address+"' />"+
"<div class='CompanyName'><strong>"+markers[closest].title+"</strong></div>"+
markers[closest].address+"<br/>"+
markers[closest].postby+"<br/>"+
"Tlf.: "+markers[closest].phone+"<br/>"+
markers[closest].fax+
markers[closest].web+
markers[closest].email
);
//markers.pop(markers[closest]);
//points.pop(points[closest]);
//markers[closest] = "";
//points[closest]= "";
//alert(closest);
//markers.slice(closest,closest+1);
//points.slice(closest,closest+1);
//alert(markers[closest].title)
delete markers[closest];
delete points[closest]
}
}
How you can see from some comments in the code i have tried many different things !! non of them seems to work for me ! It gives the first location (not even correct one) and then just breaks , does nothing for second and third ...
Can anyone see mistakes in this ? OR MAYBE EVEN BETTER KNOW OR CAN WRITE A CODE TO GET DESIRED FUNCTIONALITY ?
lat1, lon1 - of the current point !
i have 300 markers in not big area so there should not be difficult for script to find 3 nearest.
if you iterate through your markers you can call this method on each and then store the results in an array that you can sort the array. This is going to be a costly operation...
/**
* This will give you the distance in kilometers between 2 positions
*
* #param lat1 - The first positions latitude
* #param lng2 - The first positions longitude
* #param lat2 - The second positions latitide
* #param lng2 - The second positions longitude
*
* #return int- The distance in kilometers between the 2 places
*/
distanceFrom : function(lat1,lng1, lat2, lng2) {
var R = 6371; // km
var dLat = this._toRad((lat2-lat1));
var dLon = this._toRad((lng2-lng1));
var lat1 = this._toRad(lat1);
var lat2 = this._toRad(lat2);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}

Categories

Resources