Mods to elevation and async service #11

Closed
wants to merge 32 commits into
from
Commits
+305 −124
Split
View
@@ -0,0 +1,33 @@
+lib-cov
+*.seed
+*.log
+*.node
+*.o
+*.o.d
+*.mk
+*.gypi
+*.cache.py
+*.wafpickle-7
+*.lock-wscript
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+*.swp
+.DS_Store
+dump.rdb
+.jshintrc
+
+pids
+logs
+results
+
+/public/js/app.js
+/public/css/style.css
+npm-debug.log
+/client/config.js
+.build
+/docs
+
+/node_modules
View
244 geolib.js 100644 → 100755
@@ -13,8 +13,14 @@
var radius = 6378137; // Earth radius
var sexagesimalPattern = /^([0-9]{1,3}\s*([0-9]{1,3})'\s*(([0-9]{1,3}(\.([0-9]{1,2}))?)"\s*)?([NEOSW]?)$/;
+ var googleClientId;
+ var googlePrivateKey;
+ if (typeof window.navigator === 'undefined') {
+ var gm = require('googlemaps');
+ }
var geolib = {
+ distanceFormula: 'haversine',
decimal: {},
@@ -48,6 +54,37 @@
};
},
+ setDistanceFormula: function(formula) {
+ formula = formula ? formula.toLowerCase() : 'vincenty';
+ geolib.distanceFormula = formula;
+ },
+
+ /**
+ * Calculates geodetic distance between two points specified by latitude/longitude using
+ * haversine by default, but can be changed in config
+ *
+ * @param object Start position {latitude: 123, longitude: 123}
+ * @param object End position {latitude: 123, longitude: 123}
+ * @param integer Accuracy (in meters)
+ * @return float Distance (in meters)
+ */
+
+ getDistance: function(start, end, accuracy) {
+ switch (geolib.distanceFormula) {
+ case 'haversine':
+ return geolib.getDistanceHaversine(start, end, accuracy);
+ break;
+ case 'simple':
+ return geolib.getDistanceSimple(start, end, accuracy);
+ break;
+ case 'vincenty':
+ default:
+ return geolib.getDistanceVincenty(start, end, accuracy);
+ break;
+ }
+ },
+
+
/**
* Calculates geodetic distance between two points specified by latitude/longitude using
* Vincenty inverse formula for ellipsoids
@@ -60,7 +97,7 @@
* @return integer Distance (in meters)
*/
- getDistance: function(start, end, accuracy) {
+ getDistanceVincenty: function(start, end, accuracy) {
var keys = geolib.getKeys(start);
var latitude = keys.latitude;
@@ -204,6 +241,41 @@
},
+ /**
+ * Calculates geodetic distance between two points specified by latitude/longitude using
+ * haversine equation
+ *
+ * @param object Start position {latitude: 123, longitude: 123}
+ * @param object End position {latitude: 123, longitude: 123}
+ * @return float Distance (in meters)
+ */
+
+ getDistanceHaversine: function(start, end, accuracy) {
+ var keys = geolib.getKeys(start);
+ var latitude = keys.latitude;
+ var longitude = keys.longitude;
+ var elevation = keys.elevation;
+
+ var coord1 = {}, coord2 = {};
+ coord1[latitude] = geolib.useDecimal(start[latitude]);
+ coord1[longitude] = geolib.useDecimal(start[longitude]);
+
+ coord2[latitude] = geolib.useDecimal(end[latitude]);
+ coord2[longitude] = geolib.useDecimal(end[longitude]);
+
+ accuracy = accuracy || 0.00000001;
+
+ var R = 6378137 // Radius of earth in meters
+ var dLat = (coord2[latitude] - coord1[latitude]).toRad()
+ var dLng = (coord2[longitude] - coord1[longitude]).toRad()
+ var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
+ Math.cos((coord1[latitude]).toRad()) * Math.cos((coord2[latitude].toRad())) *
+ Math.sin(dLng/2) * Math.sin(dLng/2);
+ var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+ var d = R * c; // Distance in meters
+ return geolib.distance = Math.round(d/accuracy)*accuracy;
+ },
+
/**
* Calculates the distance between two spots.
@@ -323,14 +395,14 @@
var useElevation = coords[0].hasOwnProperty(elevation);
var stats = {
- maxLat: 0,
+ maxLat: Infinity * -1,
minLat: Infinity,
- maxLng: 0,
- minLng: Infinity
+ maxLng: Infinity * -1,
+ minLng: Infinity,
};
if (useElevation) {
- stats.maxElev = 0;
+ stats.maxElev = Infinity * -1;
stats.minElev = Infinity;
}
@@ -627,10 +699,20 @@
/*global google:true require:true module:true elevationResult*/
/**
- * @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},....]}
- */
+ * @params client_id and private_key for Google Enterprise Accounts
+ *
+ * @return Array [{lat:#lat, lng:#lng, elev:#elev},....]}
+ */
+ setBusinessSpecificParameters: function(clientId, privateKey){
+ gm.config('google-client-id', clientId);
+ gm.config('google-private-key', privateKey);
+ },
+
+ /**
+ * @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 window.navigator !== 'undefined') {
geolib.getElevationClient.apply(this, arguments);
@@ -640,65 +722,63 @@
},
getElevationClient: function(coords, cb) {
-
- if (!window.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 = [];
- var keys = geolib.getKeys(coords[0]);
- var latitude = keys.latitude;
- var longitude = keys.longitude;
-
- for(var i = 0; i < coords.length; i++) {
- path.push(new google.maps.LatLng(
- geolib.useDecimal(coords[i][latitude]),
- geolib.useDecimal(coords[i][longitude])
- ));
+ try {
+ if (!window.google) {
+ return cb(new Error("Geolib: Google maps api not loaded"));
+ }
+ if (coords.length == 0) {
+ return cb(null, null);
+ }
+ if (coords.length == 1) {
+ return cb(new Error("Geolib: getElevation requires at least 2 points."));
+ }
+ var path = [];
+ var keys = geolib.getKeys(coords[0]);
+ var latitude = keys.latitude;
+ var longitude = keys.longitude;
+
+ for(var i = 0; i < coords.length; i++) {
+ path.push(new google.maps.LatLng(
+ geolib.useDecimal(coords[i][latitude]),
+ geolib.useDecimal(coords[i][longitude])
+ ));
+ }
+ var positionalRequest = {
+ 'path': path,
+ 'samples': path.length
+ };
+ var elevationService = new google.maps.ElevationService();
+ elevationService.getElevationAlongPath(positionalRequest,function (results, status){
+ geolib.elevationHandler(results, status, coords, keys, cb);
+ });
+ } catch (e) {
+ return cb(e);
}
-
- var positionalRequest = {
- 'path': path,
- 'samples': path.length
- };
- var elevationService = new google.maps.ElevationService();
- elevationService.getElevationAlongPath(positionalRequest,function (results, status){
- geolib.elevationHandler(results, status, coords, keys, 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 = [];
- var keys = geolib.getKeys(coords[0]);
- //coords[0]
- var latitude = keys.latitude;
- var longitude = keys.longitude;
- for(var i = 0; i < coords.length; i++) {
- path.push(geolib.useDecimal(coords[i][latitude]) + ',' +
- geolib.useDecimal(coords[i][longitude]));
+ try {
+ if (coords.length == 0) {
+ return cb(null, null);
+ }
+ if (coords.length == 1) {
+ return cb(new Error("Geolib: getElevation requires at least 2 points."));
+ }
+ var path = [];
+ var keys = geolib.getKeys(coords[0]);
+ coords[0]
+ var latitude = keys.latitude;
+ var longitude = keys.longitude;
+ for (var i = 0; i < coords.length; i++) {
+ path.push(geolib.useDecimal(coords[i][latitude]) + ',' +
+ geolib.useDecimal(coords[i][longitude]));
+ }
+ gm.elevationFromPath(path.join('|'), path.length, function(err, results) {
+ geolib.elevationHandler(results.results, results.status, coords, keys, cb)
+ });
+ } catch (e) {
+ return cb(e);
}
- gm.elevationFromPath(path.join('|'), path.length, function(err, results) {
- geolib.elevationHandler(results.results, results.status, coords, keys, cb);
- });
},
elevationHandler: function(results, status, coords, keys, cb){
@@ -715,29 +795,36 @@
}
cb(null, latsLngsElevs);
} else {
- cb(new Error("Could not get elevation using Google's API"), elevationResult.status);
+ console.log('RESULTS FROM WONKY GOOGLE REQUEST' + results);
+ cb(new Error("Geolib: Could not get elevation using Google's API: Status: " + status));
}
},
/**
- * @param Array [{lat:#lat, lng:#lng, elev:#elev},....]}
- *
- * @return Number % grade
- */
- getGrade: function(coords){
+ * @param Array [{lat:#lat, lng:#lng, elev:#elev},....]}
+ * @param integer digits Decimal places to round to
+ *
+ * @return Number % grade
+ */
+ getGrade: function(coords, digits) {
var keys = geolib.getKeys(coords[0]);
var elevation = keys.elevation;
- var rise = Math.abs(coords[coords.length-1][elevation] - coords[0][elevation]);
+ var rise = coords[coords.length-1][elevation] - coords[0][elevation];
var run = geolib.getPathLength(coords);
- return Math.floor((rise/run)*100);
+ var grade = (rise/run)*100;
+ if (typeof digits === "number") {
+ var d = Math.pow(10,digits);
+ grade = Math.floor(grade * d) / d;
+ }
+ return grade;
},
/**
- * @param Array [{lat:#lat, lng:#lng, elev:#elev},....]}
- *
- * @return Object {gain:#gain, loss:#loss}
- */
- getTotalElevationGainAndLoss: function(coords){
+ * @param Array [{lat:#lat, lng:#lng, elev:#elev},....]}
+ *
+ * @return Object {gain:#gain, loss:#loss}
+ */
+ getTotalElevationGainAndLoss: function(coords) {
var keys = geolib.getKeys(coords[0]);
var elevation = keys.elevation;
var gain = 0;
@@ -768,8 +855,7 @@
if(distance === 0 || typeof distance == 'undefined') {
- if(geolib.distance === 0) {
- // throw 'No distance given.';
+ if(geolib.distance == 0) {
return 0;
} else {
distance = geolib.distance;
@@ -825,7 +911,7 @@
} else if(geolib.isSexagesimal(value) === true) {
return parseFloat(geolib.sexagesimal2decimal(value));
} else {
- throw 'Unknown format.';
+ throw new Error('Geolib: Unknown format.');
}
},
Oops, something went wrong.