I tried to calculate the distance between two coordinates in javascript.
More specifically the distance between one set of static coordinates and my current position taken from the geolocation cordova plugin.
Here's my code:
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
var onSuccess = function(position) {
document.getElementById("content").innerHTML = 'Success, attempting calculation...';
var lla = position.coords.latitude;
var llo = position.coords.longitude;
document.getElementById("content").innerHTML =
'GPS Position: ' + calcTheDistance(lla, llo).d + 'Metres';
};
var onError = function(error) {
document.getElementById("content").innerHTML =
'code: ' + error.code + '\n' +
'message: ' + error.message + '\n';
};
function refrGps() {
document.getElementById("content").innerHTML = 'Loading...';
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
function calcTheDistance(lati1, long1) {
var r = 6371000; //Meters
var joschLat = 50.1109221;
var joschLon = 8.6821267;
var la1 = lati1;
var la2 = joschLat;
var lat1 = lati1.toRadians();
var lat2 = joschLat.toRadians();
var lo1 = long1;
var lo2 = joschLon;
var la2minla1 = (la2-la1).toRadians();
var lo2minlo1 = (lo2-lo1).toRadians();
var cal = Math.sin(la2minla1 / 2) * Math.sin(la2minla1 / 2) +
Math.cos(lat1) * Math.cos(lat2) *
Math.sin(lo2minlo1/2) * Math.sin(lo2minlo1/2);
var c = 2* Math.atan2(Math.sqrt(cal), Math.sqrt(1-cal));
d = r * c;
};
I tried to rewrite it several times with no luck.
For the calculation I referred to this: http://www.movable-type.co.uk/scripts/latlong.html
The page you referenced contains a library of functions already implemented in Javascript. If you include these in your app, the calculation becomes trivial:
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
var onSuccess = function(position) {
document.getElementById("content").innerHTML = 'Success, attempting calculation...';
var sourceLl = new LatLon(position.coords.latitude, position.coords.longitude);
document.getElementById("content").innerHTML =
'GPS Position: ' + calcTheDistance(sourceLl) + 'Metres';
};
var onError = function(error) {
document.getElementById("content").innerHTML =
'code: ' + error.code + '\n' +
'message: ' + error.message + '\n';
};
function refrGps() {
document.getElementById("content").innerHTML = 'Loading...';
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
function calcTheDistance(sourceLl) {
var joschLat = 50.1109221;
var joschLon = 8.6821267;
var joschLl = new LatLon(joschLat, joschLon);
return joschLl.distanceTo(sourceLl);
};
So I figured it out after reading #DaveAlden 's Answer, thanks by the way!
toRadians(); is not a standard Javascript function, so after I added this and rewrote my code a bit, it worked fine.
Here's the working code
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
var onSuccess = function(position) {
document.getElementById("content").innerHTML = 'Success, attempting calculation...';
var lla = position.coords.latitude;
var llo = position.coords.longitude;
var dst = 'Distance: ' + calcTheDistance(lla, llo) + ' Metres';
document.getElementById("content").innerHTML = dst;
};
var onError = function(error) {
document.getElementById("content").innerHTML =
'code: ' + error.code + '\n' +
'message: ' + error.message + '\n';
};
function refrGps() {
document.getElementById("content").innerHTML = 'Loading...';
navigator.geolocation.getCurrentPosition(onSuccess, onError);
};
function toRadians(num) {
return num * Math.PI / 180;
};
function calcTheDistance(lati1, long1) {
var r = 6371000; //metres
var joschLat = 50.1109221;
var joschLon = 8.6821267;
var la1 = lati1;
var la2 = joschLat;
var lat1 = toRadians(lati1);
var lat2 = toRadians(joschLat);
var lo1 = long1;
var lo2 = joschLon;
var la2minla1 = toRadians(la2-la1);
var lo2minlo1 = toRadians(lo2-lo1);
var cal = Math.sin(la2minla1 / 2) * Math.sin(la2minla1 / 2) +
Math.cos(lat1) * Math.cos(lat2) *
Math.sin(lo2minlo1/2) * Math.sin(lo2minlo1/2);
var c = 2* Math.atan2(Math.sqrt(cal), Math.sqrt(1-cal));
var d = r * c;
return Math.round(d);
};
Related
I'm trying to get multiple elevations using Google API, but it usually it does not work.
Here is my code:
var axios = require('axios');
var fs = require('fs');
const util = require('util');
var config = {
method: 'get',
url: 'https://maps.googleapis.com/maps/api/elevation/json?key=<MY_API_KEY>&locations=',
headers: { }
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getElevationsWithAPI(config) {
console.log('in getElevationsWithAPI()');
console.log(config);
console.log('method = ' + config.method);
let queryResult = [];
let res = await axios(config); // comment 1
console.log('status = ' + res.status);
console.log('location = ' + res.data.results[0].location.lat + ', ' + res.data.results[0].location.lng);
console.log('elevation = ' + res.data.results[0].elevation);
let results = res.data.results;
for (i = 0; i < results.length; i++) {
let entry = results[i];
queryResult.push({[entry.location.lat + ',' + entry.location.lng]: entry.elevation});
}
const json = JSON.stringify(queryResult);
//console.log('json = ' + json);
return queryResult;
}
function getDistance(lat1, lng1, lat2, lng2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lng2-lng1);
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);
}
async function getElevationsExported(fileName, lat1, lng1, lat2, lng2) {
console.log('in getElevationsExported(), fileName = ' + fileName);
console.log(`lat1 = ${lat1}, lat2 = ${lat2}, lng1 = ${lng1}, lng2 = ${lng2}`);
console.log('lat distance: ' + getDistance(lat1, lng1, lat2, lng1));
console.log('lng distance: ' + getDistance(lat1, lng1, lat1, lng2));
console.log('point distance: ' + getDistance(lat1, lng1, lat2, lng2));
var url = config.url;
var res = [];
let counter = 0;
console.log('before for');
try {
// Calculate number of rows
for (i = lat1; i <= lat2 + 0.00026; i += 0.00026) {
counter++;
}
console.log('counter = ' + counter);
// Send the location data to google elevation API
let k = 1;
for (i = lat1; i <= lat2 + 0.00026; i += 0.00026) {
console.log(`${k++}: i = ${i}`);
var locations = '';
let jArr = [];
for (j = lng1; j <= lng2; j += 0.00032) {
jArr.push(j);
locations += i.toFixed(5) + '%2C' + j.toFixed(5) + '%7C';
}
locations = locations.slice(0, -3); // remove the last %7C character
config.url = url + locations;
//console.log('config.url = ' + config.url);
try {
await sleep(10); // comment 2
var elevationRes = getElevationsWithAPI(config);
elevationRes.then(function(result) {
//console.log(result);
counter--;
res.push(...result);
console.log('after --, counter = ' + counter);
if (counter === 0) { // comment 3
console.log('finished getting data');
// Write the new elevations file
fs.writeFile(consts.ElevationDirFullPath + fileName, JSON.stringify(res), (err) => {
if (err) {
console.log(err);
throw err;
}
console.log('The file has been saved');
});
}
});
} catch(error) {
console.log(error);
throw error;
}
}
console.log('exited for loop');
} catch (error2) {
console.log('error2 = ' + error2);
}
}
module.exports.getDistance = getDistance;
module.exports.getElevationsExported = getElevationsExported;
The problem is when I call Google API through axios (see comment 1). Sometimes it succeeds and sometimes it fails. I also tried to add timeout between calls (see comment 2), but then not all calls to getElevationsWithAPI() are called.
Also I usually don't reach the end condition (comment 3).
How can I fix all these problems?
I am writing a REST client to remote api. And I am using xmlHTTPRequest to get information about images.I need to refresh my images in every 30 seconds. My implementation of setTimeout function doesn't work. Anyone can help me? Thank you in advance.
Here is my code: Image.js
function Camera(id, name, ip, port) {
var button = document.createElement("button");
button.classList.add("camera");
button.innerHTML += "<h3>" + name + "</h3><br>";
var ismin = true;
this.id = id;
this.name = name;
this.ip = ip;
this.port = port;
this.getURL = function getURL(min) {
var url = 'http://' + ip + ":8080/api";
return min ? url + '/miniature/' + id + '?t=' + new Date().getTime() : url + '/image/' + id + '?t=' + new Date().getTime();
};
this.appendImg = function appendImg(url) {
button.innerHTML = "<h3>" + name + '</h3><br><img src="' + url + '"/>';
setTimeout(appendImg(url),30000);
};
this.showElement = function showElement(url) {
this.appendImg(url);
var that = this;
document.querySelector('#camera-section').appendChild(button);
button.addEventListener('click', function () {
ismin = !ismin;
that.appendImg(that.getURL(ismin), false);
});
};}
And a part of main.js:
function showImage(response) {
response = JSON.parse(sessionStorage.getItem('camera'));
console.log(response);
for (var i = 0; i < response.length; i++) {
var a = response[i];
var camera = new Camera(a.cameraId, a.name, ip, port, true);
var curl = camera.getURL(true);
camera.showElement(curl);
}
}
xml.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
sessionStorage.setItem('camera',JSON.stringify(response));
//console.log(sessionStorage.getItem('camera'));
showImage(sessionStorage.getItem('camera'));
}
};
xml.open('GET', mainUrl);
xml.send(null);
Regarding the comment of Pranay Kumar, first part of your code could be like this::
function Camera(id, name, ip, port) {
var button = document.createElement("button");
button.classList.add("camera");
button.innerHTML += "<h3>" + name + "</h3><br>";
var ismin = true;
this.id = id;
this.name = name;
this.ip = ip;
this.port = port;
this.getURL = function getURL(min) {
var url = 'http://' + ip + ":8080/api";
return min ? url + '/miniature/' + id + '?t=' + new Date().getTime() : url + '/image/' + id + '?t=' + new Date().getTime();
};
this._appendImg = function(url) {
return function() {
button.innerHTML = "<h3>" + name + '</h3><br><img src="' + url + '"/>';
}
};
this._timerHandle = 0;
this.appendImg = function(url) {
if (this._timerHandle) {
clearInterval(this._timerHandle);
}
this._timerHandle = setInterval(this._appendImg(url),30000);
}
this.showElement = function showElement(url) {
this.appendImg(url);
var that = this;
document.querySelector('#camera-section').appendChild(button);
button.addEventListener('click', function () {
ismin = !ismin;
that.appendImg(that.getURL(ismin), false);
});
}
}
You want refresh image every 30 seconds.
So use setInterval instead of setTimeout
I'm trying to create a weather app, sending Ajax requests to OpenWeatherMap. I've got an error in w.getWeatherFunc, when I'm giving the function sendRequest the parameter of w.weather and then giving the same parameter to the function displayFunc, which I'm calling next.
Here is what I've got in the console:
Uncaught TypeError: Cannot read property 'weather' of undefined
at displayFunc (weather.js:46)
at weather.js:78
How can I fix this and make it work?
function Weather () {
var w = this;
var weatherUrl = 'http://api.openweathermap.org/data/2.5/weather?';
var appid = '&appid=c0a7816b2acba9dbfb70977a1e537369';
var googleUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=';
var googleKey = '&key=AIzaSyBHBjF5lDpw2tSXVJ6A1ra-RKT90ek5bvQ';
w.demo = document.getElementById('demo');
w.place = document.getElementById('place');
w.description = document.getElementById('description');
w.temp = document.getElementById('temp');
w.humidity = document.getElementById('humidity');
w.getWeather = document.getElementById('getWeather');
w.addCityBtn = document.getElementById('addCity');
w.rmCityBtn = document.getElementById('rmCity');
w.icon = document.getElementById('icon');
w.wind = document.getElementById('wind');
w.time = document.getElementById('time');
w.lat = null;
w.lon = null;
w.cityArray = [];
w.weather = null;
function sendRequest (url, data) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.send();
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
data = JSON.parse(request.responseText);
console.log(data);
return data;
} else {
console.log(request.status + ': ' + request.statusText);
}
}
}
function displayFunc (obj) {
console.log('obj ' + obj);
w.icon.src = 'http://openweathermap.org/img/w/' + obj.weather[0].icon + '.png';
var timeNow = new Date();
var hours = timeNow.getHours();
var minutes = timeNow.getMinutes() < 10 ? '0' + timeNow.getMinutes() : timeNow.getMinutes();
w.time.innerHTML = hours + ':' + minutes;
w.place.innerHTML = 'Place: ' + obj.name;
w.description.innerHTML = "Weather: " + obj.weather[0].description;
w.temp.innerHTML = "Temperature: " + w.convertToCels(obj.main.temp) + "°C";
w.humidity.innerHTML = "Humidity: " + obj.main.humidity + '%';
w.wind.innerHTML = 'Wind: ' + obj.wind.speed + ' meter/sec';
}
w.convertToCels = function(temp) {
var tempC = Math.round(temp - 273.15);
return tempC;
}
w.getWeatherFunc = function() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(location){
w.lat = location.coords.latitude;
w.lon = location.coords.longitude;
var url = weatherUrl + 'lat=' + w.lat + '&lon=' + w.lon + appid;
var result = sendRequest(url, w.weather);
console.log(result);
displayFunc(result);
});
} else {
alert('Browser could not find your current location');
}
}
w.addCityBtn.onclick = function() {
var newCity = prompt('Please insert city', 'Kiev');
var gUrl = googleUrl + newCity + googleKey;
var newCityWeather = null;
sendRequest(url, newCityWeather);
var location = newCityWeather.results[0].geometry.location;
var newUrl = weatherUrl + 'lat=' + location.lat + '&lon=' + location.lng + appid;
sendRequest(newUrl, w.weather);
displayFunc(newCity);
w.cityArray.push(newCity);
}
window.onload = w.getWeatherFunc;
setInterval(function() {
w.getWeatherFunc();
}, 900000);
}
Your ajax return returns into the browsers engine. As its async you need to create a callback:
function sendRequest(url,data,callback){
//if the data was received
callback(data);
}
Use like this
sendRequest("yoururl",data,function(data){
displayFunc(data);
});
The first time you pass the obj to the function it will save it one scope higher. after that, if you don;t pass the object the one you saved earlier will be used.
var objBkp;
function displayFunc (obj) {
if(undefined === obj) obj = objBkp;
else objBkp = obj;
// rest of code here
}
In your sendRequest you are passing only the value of w.weather, not its reference. JavaScript doesn't pass variables by value or by reference, but by sharing. So if you want to give the value to your variable you should do this inside your function sendRequest:
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
w.weather = JSON.parse(request.responseText);
console.log(data);
return data;
} else {
console.log(request.status + ': ' + request.statusText);
}
}
Also, if you are using the attributes, you don't have to pass them in the function as arguments. Besides that fact, it would be good if you also create get() and set()
What does the console.log(result); in getWeatherFunc gives you?
The problem as I see it is that in the displayFunc the parameter passed is undefined.
I keep getting this Uncaught TypeError: Cannot read property '0' of undefined
The code works perfectly fine with no errors in the console or anything, but everything now and then this error pops up then just disappears. Does anyone know why?
var temp, loc, icon, hum, wind, dir;
var APPID = "56a4fe4f1240df2a9fe267b687a5d191";
function update (weather) {
temp.innerHTML += weather.temp;
loc.innerHTML += weather.loc;
hum.innerHTML += weather.hum;
wind.innerHTML += weather.wind;
dir.innerHTML += weather.dir;
sUp.innerHTML += weather.sUp;
sDown.innerHTML += weather.sDown
icon.src = "//openweathermap.org/img/w/" + weather.icon + ".png";
}
window.onload = function () {
temp = document.getElementById ("t");
loc = document.getElementById ("l");
icon = document.getElementById ("i");
hum = document.getElementById ("h");
wind = document.getElementById ("w");
dir = document.getElementById ("d");
sUp = document.getElementById ("sU");
sDown = document.getElementById ("sD");
if (navigator.geolocation) {
var showPos = function (pos) {
updateLoc (pos.coords.latitude, pos.coords.longitude);
}
navigator.geolocation.getCurrentPosition (showPos);
} else {
var zip = window.prompt("Your location could not be found, please enter your post/zip code.");
updateByZip(zip);
}
}
function updateLoc (lat, long) {
var url = "http://api.openweathermap.org/data/2.5/weather?" +
"lat=" + lat +
"&lon=" + long +
"&APPID=" + APPID;
sendRequest (url);
}
function updateByZip(zip){
var url = "http://api.openweathermap.org/data/2.5/weather?" +
"zip=" + zip +
"&APPID=" + APPID;
sendRequest(url);
}
function sendRequest (url) {
var xmlhttp = new XMLHttpRequest ();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var data = JSON.parse (xmlhttp.responseText);
var weather = {};
weather.icon = data.weather[0].icon;
weather.dir = direction (data.wind.deg);
weather.wind = mph (data.wind.speed) + "mph";
weather.temp = K2C (data.main.temp) + "°C";
weather.loc = data.name;
weather.hum = data.main.humidity + "%";
weather.sUp = formatDate (data.sys.sunrise);
weather.sDown = formatDate (data.sys.sunset);
update (weather);
}
};
xmlhttp.open ("GET", url, true);
xmlhttp.send ();
}
function K2F (k) {
return Math.round(k * (9 / 5) - 459.67);
}
function K2C (k) {
return Math.round (k - 273.15);
}
function mph (ms) {
return Math.round (ms / 0.44704);
}
function kmph (ms) {
return Math.round (ms * 3.6);
}
function formatDate (t) {
var date = new Date (t * 1000);
var h = date.getHours ();
var m = "0" + date.getMinutes ();
var s = "0" + date.getSeconds ();
return h + ":" + m.substr(-2) + ":" + s.substr(-2);
}
function direction (deg) {
var range = 360 / 16;
var low = 360 - (range / 2);
var high = (low + range) % 360;
var angles = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"];
for (var i in angles) {
if (deg >= low && deg < high) {
return angles[i]
}
low = (low + range) % 360;
high = (high + range) % 360;
}
return "N";
}
I've been trying to convert a v2 to v3 map application that calculates the distance between and address entered and a stored lat/Lon. Not having any luck with getting this up and running. Would really appreciate some help.
<script type="text/javascript" src="js/addHTMLControls2.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#order").validate();
addInput();
});
</script>
<script type="text/javascript">
var geocoder, location1, location2;
function initialize() {
geocoder = new google.maps.Geocoder();
}
function showLocation() {
document.getElementById('address').value= document.getElementById('address2').value;
/*coordinate system*/
geocoder.geocode(document.forms[0].address1.value,
function (response) {
if (!response || response.Status.code != 200)
{alert("Sorry, we were unable to geocode the first address");}
else
{location1 =
{lat: response.Placemark[0].Point.coordinates[1],
lon: response.Placemark[0].Point.coordinates[0],
address: response.Placemark[0].address
};
geocoder.geocode(document.forms[0].address2.value, function (response) {
if (!response || response.Status.code != 200)
{
alert("Sorry, we were unable to geocode the second address");
}
else
{
location2 = {lat: response.Placemark[0].Point.coordinates[1], lon: response.Placemark[0].Point.coordinates[0], address: response.Placemark[0].address};
calculateDistance();
}
});
}
});
}
function calculateDistance()
{
try
{
var map;
var directionsPanel;
var directions;
var glatlng1 = new google.maps.LatLng(location1.lat, location1.lon);
var glatlng2 = new google.maps.LatLng(location2.lat, location2.lon);
var miledistance = glatlng1.distanceFrom(glatlng2, 3959).toFixed(1);
var kmdistance = (miledistance * 1.609344).toFixed(1);
map = new google.maps.Map(document.getElementById("map_canvas"));
map.setCenter(new google.maps.LatLng(location1.lat, location1.lon), 15);
directionsPanel = document.getElementById("route");
directions = new GDirections(map, directionsPanel);
document.getElementById('route').innerHTML='';
document.getElementById('map_canvas').innerHTML='';
/* location1.address+ */
//alert(document.getElementById('hdnLat').value);
document.getElementById('distance').value = directions.load("from:"+ document.getElementById('hdnLat').value +"," + document.getElementById('hdnLan').value + " to: "+location2.address, {travelMode:G_TRAVEL_MODE_DRIVING});
/* document.getElementById('results').innerHTML = '<strong>Address 1: </strong>' + location1.address + ' (' + location1.lat + ':' + location1.lon + ')<br /><strong>Address 2: </strong>' + location2.address + ' (' + location2.lat + ':' + location2.lon + ')<br /><strong>Distance: </strong>' + miledistance + ' miles (or ' + kmdistance + ' kilometers)';*/
setTimeout('adjustdistance(document.getElementById("route").innerHTML)', 8000);
;
document.getElementById('distance').value= 'calculating...';
}
catch (error)
{
alert(error);
}
}
function adjustdistance(htmlcode)
{
var ht1;
ht1 = htmlcode;
var tyu;
tyu= parseReturnedXML(ht1,'$Route.summaryHtml','table jstcache');
document.getElementById('distance').value=tyu;
}
function parseReturnedXML(strToParse, strStart, strFinish)
{
var str;
str=strToParse;
var str1;
var str2;
str = str.replace(strStart,'~');
str = str.replace(strFinish,'~');
str=str.replace(/(<([^>]+)>)/ig,"");
str = str.replace(',','');
str = str.replace(' ','');
str1= str.indexOf('km (');
str2=" km(s)";
if(str1=='-1')
{
str1=str.indexOf('mi (');
str2=" miles";
}
var str4;
var str5;
str4 = parseInt(str1) - 8;
str5 = parseInt(str1) + 2;
str = str.substring(str4,str5);
str = str.replace(/[a-zA-Z]/g,"");
str = str.replace(/^\s+/,"");
str = str+str2;
return str;
}
</script>
I've updated the various v3 changes but its simply not returning a distance for me.
Thanks
Alan
Please refer the link. http://jsfiddle.net/xJ26V/1/
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;
}