190 lines
3.8 KiB
JavaScript
190 lines
3.8 KiB
JavaScript
|
/*! geolib.elevation $version$ by Manuel Bieh
|
||
|
*
|
||
|
* Elevation Addon for Geolib.js
|
||
|
*
|
||
|
* @author Manuel Bieh
|
||
|
* @url http://www.manuelbieh.com/
|
||
|
* @version $version$
|
||
|
* @license MIT
|
||
|
*/
|
||
|
;(function(global, geolib, undefined) {
|
||
|
|
||
|
var elevation = {
|
||
|
|
||
|
/*global google:true geolib:true require:true module:true elevationResult:true */
|
||
|
|
||
|
/**
|
||
|
* @param Array Collection of coords [{latitude: 51.510, longitude: 7.1321}, {latitude: 49.1238, longitude: "8° 30' W"}, ...]
|
||
|
* @return Array [{lat:#lat, lng:#lng, elev:#elev},....]}
|
||
|
*/
|
||
|
getElevation: function() {
|
||
|
if (typeof global.navigator !== 'undefined') {
|
||
|
this.getElevationClient.apply(this, arguments);
|
||
|
} else {
|
||
|
this.getElevationServer.apply(this, arguments);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
/* Optional elevation addon requires Googlemaps API JS */
|
||
|
getElevationClient: function(coords, cb) {
|
||
|
|
||
|
if (!global.google) {
|
||
|
throw new Error("Google maps api not loaded");
|
||
|
}
|
||
|
|
||
|
if (coords.length === 0) {
|
||
|
return cb(null, null);
|
||
|
}
|
||
|
|
||
|
if (coords.length === 1) {
|
||
|
return cb(new Error("getElevation requires at least 2 points."));
|
||
|
}
|
||
|
|
||
|
var path = [];
|
||
|
|
||
|
for(var i = 0; i < coords.length; i++) {
|
||
|
path.push(new google.maps.LatLng(
|
||
|
this.latitude(coords[i]),
|
||
|
this.longitude(coords[i])
|
||
|
));
|
||
|
}
|
||
|
|
||
|
var positionalRequest = {
|
||
|
'path': path,
|
||
|
'samples': path.length
|
||
|
};
|
||
|
|
||
|
var elevationService = new google.maps.ElevationService();
|
||
|
var geolib = this;
|
||
|
|
||
|
elevationService.getElevationAlongPath(positionalRequest, function (results, status) {
|
||
|
geolib.elevationHandler(results, status, coords, cb);
|
||
|
});
|
||
|
|
||
|
},
|
||
|
|
||
|
|
||
|
getElevationServer: function(coords, cb) {
|
||
|
|
||
|
if (coords.length === 0) {
|
||
|
return cb(null, null);
|
||
|
}
|
||
|
|
||
|
if (coords.length === 1) {
|
||
|
return cb(new Error("getElevation requires at least 2 points."));
|
||
|
}
|
||
|
|
||
|
var gm = require('googlemaps');
|
||
|
var path = [];
|
||
|
|
||
|
for(var i = 0; i < coords.length; i++) {
|
||
|
path.push(
|
||
|
this.latitude(coords[i]) + ',' + this.longitude(coords[i])
|
||
|
);
|
||
|
}
|
||
|
|
||
|
var geolib = this;
|
||
|
|
||
|
gm.elevationFromPath(path.join('|'), path.length, function(err, results) {
|
||
|
geolib.elevationHandler(results.results, results.status, coords, cb);
|
||
|
});
|
||
|
|
||
|
},
|
||
|
|
||
|
|
||
|
elevationHandler: function(results, status, coords, cb) {
|
||
|
|
||
|
var latsLngsElevs = [];
|
||
|
|
||
|
if (status == "OK" ) {
|
||
|
|
||
|
for (var i = 0; i < results.length; i++) {
|
||
|
latsLngsElevs.push({
|
||
|
"lat": this.latitude(coords[i]),
|
||
|
"lng": this.longitude(coords[i]),
|
||
|
"elev":results[i].elevation
|
||
|
});
|
||
|
}
|
||
|
|
||
|
cb(null, latsLngsElevs);
|
||
|
|
||
|
} else {
|
||
|
|
||
|
cb(new Error("Could not get elevation using Google's API"), elevationResult.status);
|
||
|
|
||
|
}
|
||
|
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @param Array [{lat:#lat, lng:#lng, elev:#elev},....]}
|
||
|
* @return Number % grade
|
||
|
*/
|
||
|
getGrade: function(coords) {
|
||
|
|
||
|
var rise = Math.abs(
|
||
|
this.elevation(coords[coords.length-1]) - this.elevation(coords[0])
|
||
|
);
|
||
|
|
||
|
var run = this.getPathLength(coords);
|
||
|
|
||
|
return Math.floor((rise/run)*100);
|
||
|
|
||
|
},
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @param Array [{lat:#lat, lng:#lng, elev:#elev},....]}
|
||
|
* @return Object {gain:#gain, loss:#loss}
|
||
|
*/
|
||
|
getTotalElevationGainAndLoss: function(coords) {
|
||
|
|
||
|
var gain = 0;
|
||
|
var loss = 0;
|
||
|
|
||
|
for(var i = 0; i < coords.length - 1; i++) {
|
||
|
|
||
|
var deltaElev = this.elevation(coords[i]) - this.elevation(coords[i + 1]);
|
||
|
|
||
|
if (deltaElev > 0) {
|
||
|
loss += deltaElev;
|
||
|
} else {
|
||
|
gain += Math.abs(deltaElev);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
"gain": gain,
|
||
|
"loss": loss
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// Node module
|
||
|
if (typeof module !== 'undefined' &&
|
||
|
typeof module.exports !== 'undefined') {
|
||
|
|
||
|
geolib = require('geolib');
|
||
|
geolib.extend(elevation);
|
||
|
|
||
|
// AMD module
|
||
|
} else if (typeof define === "function" && define.amd) {
|
||
|
|
||
|
define(["geolib"], function (geolib) {
|
||
|
geolib.extend(elevation);
|
||
|
return geolib;
|
||
|
});
|
||
|
|
||
|
// we're in a browser
|
||
|
} else {
|
||
|
|
||
|
geolib.extend(elevation);
|
||
|
|
||
|
}
|
||
|
|
||
|
}(this, this.geolib));
|