compute-distance
Advanced tools
+23
-49
@@ -1,26 +0,8 @@ | ||
| // Get the Google API object, if it exists | ||
| var getGoogleAPI = function (options) { | ||
| if (options && options.google) { | ||
| return options.google; | ||
| } | ||
| else if (global && global.google) { | ||
| return global.google; | ||
| } | ||
| else if (window && window.google) { | ||
| return window.google; | ||
| } | ||
| else { | ||
| console.log("Google API object does not exist"); | ||
| console.trace(); | ||
| } | ||
| var sgeo = require('sgeo'); | ||
| return undefined; | ||
| }; | ||
| // Smooth the run (e.g. ignore bouncing GPS tracks) | ||
| var defaultFilter = function (data, options) { | ||
| var defaultFilter = function (data) { | ||
| var accurate = [], | ||
| filtered = [], | ||
| maxDistance = 20, // Meters | ||
| google = getGoogleAPI(options); | ||
| maxDistance = 20; // Meters | ||
@@ -36,22 +18,16 @@ // Filter out inaccurate points | ||
| for (var i = 1; i < accurate.length - 1; ++i) { | ||
| var pt1 = new google.maps.LatLng( | ||
| { | ||
| lat: parseFloat(accurate[i-1].latitude), | ||
| lng: parseFloat(accurate[i-1].longitude) | ||
| } | ||
| var pt1 = new sgeo.latlon( | ||
| parseFloat(accurate[i-1].latitude), | ||
| parseFloat(accurate[i-1].longitude) | ||
| ); | ||
| var pt2 = new google.maps.LatLng( | ||
| { | ||
| lat: parseFloat(accurate[i].latitude), | ||
| lng: parseFloat(accurate[i].longitude) | ||
| } | ||
| var pt2 = new sgeo.latlon( | ||
| parseFloat(accurate[i].latitude), | ||
| parseFloat(accurate[i].longitude) | ||
| ); | ||
| var pt3 = new google.maps.LatLng( | ||
| { | ||
| lat: parseFloat(accurate[i+1].latitude), | ||
| lng: parseFloat(accurate[i+1].longitude) | ||
| } | ||
| var pt3 = new sgeo.latlon( | ||
| parseFloat(accurate[i+1].latitude), | ||
| parseFloat(accurate[i+1].longitude) | ||
| ); | ||
| var d1 = google.maps.geometry.spherical.computeDistanceBetween(pt1, pt2); | ||
| var d2 = google.maps.geometry.spherical.computeDistanceBetween(pt2, pt3); | ||
| var d1 = pt1.distanceTo(pt2); | ||
| var d2 = pt2.distanceTo(pt3); | ||
| if (d1 <= maxDistance && d2 <= maxDistance) { | ||
@@ -66,11 +42,10 @@ filtered.push(accurate[i]); | ||
| // Get an array of coordinates | ||
| var getCoordinates = function (data, options) { | ||
| var coords = [], | ||
| google = getGoogleAPI(options); | ||
| var getCoordinates = function (data) { | ||
| var coords = []; | ||
| for (var i in data) { | ||
| coords.push(new google.maps.LatLng({ | ||
| lat: parseFloat(data[i].latitude), | ||
| lng: parseFloat(data[i].longitude) | ||
| })); | ||
| coords.push(new sgeo.latlon( | ||
| parseFloat(data[i].latitude), | ||
| parseFloat(data[i].longitude) | ||
| )); | ||
| } | ||
@@ -82,10 +57,9 @@ | ||
| // Get the distance represented by a set of coordinates (meters) | ||
| var computeDistance = function (coords, options) { | ||
| var google = getGoogleAPI(options); | ||
| var computeDistance = function (coords) { | ||
| var distance = 0; | ||
| for (var i = 0; i < coords.length - 1; ++i) { | ||
| distance += google.maps.geometry.spherical.computeDistanceBetween(coords[i], coords[i+1]); | ||
| distance += parseFloat(coords[i].distanceTo(coords[i + 1])); | ||
| } | ||
| return distance; | ||
| return distance * 1000; | ||
| }; | ||
@@ -92,0 +66,0 @@ |
+2
-2
| { | ||
| "name": "compute-distance", | ||
| "version": "0.0.2", | ||
| "version": "0.0.3", | ||
| "author": "Daniel Sauble", | ||
@@ -25,4 +25,4 @@ "description": "Find the distance represented by a set of points, filter if necessary", | ||
| "dependencies": { | ||
| "google-maps": "^3.2.1" | ||
| "sgeo": "^0.0.5" | ||
| } | ||
| } |
+634
-219
| (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
| (function (global){ | ||
| // Get the Google API object, if it exists | ||
| var getGoogleAPI = function (options) { | ||
| if (options && options.google) { | ||
| return options.google; | ||
| } | ||
| else if (global && global.google) { | ||
| return global.google; | ||
| } | ||
| else if (window && window.google) { | ||
| return window.google; | ||
| } | ||
| else { | ||
| console.log("Google API object does not exist"); | ||
| console.trace(); | ||
| } | ||
| var sgeo = require('sgeo'); | ||
| return undefined; | ||
| }; | ||
| // Smooth the run (e.g. ignore bouncing GPS tracks) | ||
| var defaultFilter = function (data, options) { | ||
| var defaultFilter = function (data) { | ||
| var accurate = [], | ||
| filtered = [], | ||
| maxDistance = 20, // Meters | ||
| google = getGoogleAPI(options); | ||
| maxDistance = 20; // Meters | ||
@@ -38,22 +19,16 @@ // Filter out inaccurate points | ||
| for (var i = 1; i < accurate.length - 1; ++i) { | ||
| var pt1 = new google.maps.LatLng( | ||
| { | ||
| lat: parseFloat(accurate[i-1].latitude), | ||
| lng: parseFloat(accurate[i-1].longitude) | ||
| } | ||
| var pt1 = new sgeo.latlon( | ||
| parseFloat(accurate[i-1].latitude), | ||
| parseFloat(accurate[i-1].longitude) | ||
| ); | ||
| var pt2 = new google.maps.LatLng( | ||
| { | ||
| lat: parseFloat(accurate[i].latitude), | ||
| lng: parseFloat(accurate[i].longitude) | ||
| } | ||
| var pt2 = new sgeo.latlon( | ||
| parseFloat(accurate[i].latitude), | ||
| parseFloat(accurate[i].longitude) | ||
| ); | ||
| var pt3 = new google.maps.LatLng( | ||
| { | ||
| lat: parseFloat(accurate[i+1].latitude), | ||
| lng: parseFloat(accurate[i+1].longitude) | ||
| } | ||
| var pt3 = new sgeo.latlon( | ||
| parseFloat(accurate[i+1].latitude), | ||
| parseFloat(accurate[i+1].longitude) | ||
| ); | ||
| var d1 = google.maps.geometry.spherical.computeDistanceBetween(pt1, pt2); | ||
| var d2 = google.maps.geometry.spherical.computeDistanceBetween(pt2, pt3); | ||
| var d1 = pt1.distanceTo(pt2); | ||
| var d2 = pt2.distanceTo(pt3); | ||
| if (d1 <= maxDistance && d2 <= maxDistance) { | ||
@@ -68,11 +43,10 @@ filtered.push(accurate[i]); | ||
| // Get an array of coordinates | ||
| var getCoordinates = function (data, options) { | ||
| var coords = [], | ||
| google = getGoogleAPI(options); | ||
| var getCoordinates = function (data) { | ||
| var coords = []; | ||
| for (var i in data) { | ||
| coords.push(new google.maps.LatLng({ | ||
| lat: parseFloat(data[i].latitude), | ||
| lng: parseFloat(data[i].longitude) | ||
| })); | ||
| coords.push(new sgeo.latlon( | ||
| parseFloat(data[i].latitude), | ||
| parseFloat(data[i].longitude) | ||
| )); | ||
| } | ||
@@ -84,10 +58,9 @@ | ||
| // Get the distance represented by a set of coordinates (meters) | ||
| var computeDistance = function (coords, options) { | ||
| var google = getGoogleAPI(options); | ||
| var computeDistance = function (coords) { | ||
| var distance = 0; | ||
| for (var i = 0; i < coords.length - 1; ++i) { | ||
| distance += google.maps.geometry.spherical.computeDistanceBetween(coords[i], coords[i+1]); | ||
| distance += parseFloat(coords[i].distanceTo(coords[i + 1])); | ||
| } | ||
| return distance; | ||
| return distance * 1000; | ||
| }; | ||
@@ -101,249 +74,691 @@ | ||
| }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | ||
| },{}],2:[function(require,module,exports){ | ||
| (function(root, factory) { | ||
| },{"sgeo":2}],2:[function(require,module,exports){ | ||
| if (root === null) { | ||
| throw new Error('Google-maps package can be used only in browser'); | ||
| } | ||
| //Original version of this module came from following website by Chris Veness | ||
| //http://www.movable-type.co.uk/scripts/latlong.html | ||
| if (typeof define === 'function' && define.amd) { | ||
| define(factory); | ||
| } else if (typeof exports === 'object') { | ||
| module.exports = factory(); | ||
| } else { | ||
| root.GoogleMapsLoader = factory(); | ||
| } | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| /* Geodesy representation conversion functions (c) Chris Veness 2002-2012 */ | ||
| /* - www.movable-type.co.uk/scripts/latlong.html */ | ||
| /* */ | ||
| /* Sample usage: */ | ||
| /* var lat = Geo.parseDMS('51 28 40.12 N'); */ | ||
| /* var lon = Geo.parseDMS('000 00 05.31 W'); */ | ||
| /* var p1 = new latlon(lat, lon); */ | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| })(typeof window !== 'undefined' ? window : null, function() { | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| /* Latitude/longitude spherical geodesy formulae & scripts (c) Chris Veness 2002-2012 */ | ||
| /* - www.movable-type.co.uk/scripts/latlong.html */ | ||
| /* */ | ||
| /* Sample usage: */ | ||
| /* var p1 = new latlon(51.5136, -0.0983); */ | ||
| /* var p2 = new latlon(51.4778, -0.0015); */ | ||
| /* var dist = p1.distanceTo(p2); // in km */ | ||
| /* var brng = p1.bearingTo(p2); // in degrees clockwise from north */ | ||
| /* ... etc */ | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| /* Note that minimal error checking is performed in this example code! */ | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| 'use strict'; | ||
| /** | ||
| * Parses string representing degrees/minutes/seconds into numeric degrees | ||
| * | ||
| * This is very flexible on formats, allowing signed decimal degrees, or deg-min-sec optionally | ||
| * suffixed by compass direction (NSEW). A variety of separators are accepted (eg 3º 37' 09"W) | ||
| * or fixed-width format without separators (eg 0033709W). Seconds and minutes may be omitted. | ||
| * (Note minimal validation is done). | ||
| * | ||
| * @param {String|Number} dmsStr: Degrees or deg/min/sec in variety of formats | ||
| * @returns {Number} Degrees as decimal number | ||
| * @throws {TypeError} dmsStr is an object, perhaps DOM object without .value? | ||
| */ | ||
| exports.parseDMS = function(dmsStr) { | ||
| if (typeof deg == 'object') throw new TypeError('geo.parseDMS - dmsStr is [DOM?] object'); | ||
| var googleVersion = '3.18'; | ||
| // check for signed decimal degrees without NSEW, if so return it directly | ||
| if (typeof dmsStr === 'number' && isFinite(dmsStr)) return Number(dmsStr); | ||
| var script = null; | ||
| // strip off any sign or compass dir'n & split out separate d/m/s | ||
| var dms = String(dmsStr).trim().replace(/^-/,'').replace(/[NSEW]$/i,'').split(/[^0-9.,]+/); | ||
| if (dms[dms.length-1]=='') dms.splice(dms.length-1); // from trailing symbol | ||
| var google = null; | ||
| if (dms == '') return NaN; | ||
| var loading = false; | ||
| // and convert to decimal degrees... | ||
| switch (dms.length) { | ||
| case 3: // interpret 3-part result as d/m/s | ||
| var deg = dms[0]/1 + dms[1]/60 + dms[2]/3600; | ||
| break; | ||
| case 2: // interpret 2-part result as d/m | ||
| var deg = dms[0]/1 + dms[1]/60; | ||
| break; | ||
| case 1: // just d (possibly decimal) or non-separated dddmmss | ||
| var deg = dms[0]; | ||
| // check for fixed-width unseparated format eg 0033709W | ||
| //if (/[NS]/i.test(dmsStr)) deg = '0' + deg; // - normalise N/S to 3-digit degrees | ||
| //if (/[0-9]{7}/.test(deg)) deg = deg.slice(0,3)/1 + deg.slice(3,5)/60 + deg.slice(5)/3600; | ||
| break; | ||
| default: | ||
| return NaN; | ||
| } | ||
| if (/^-|[WS]$/i.test(dmsStr.trim())) deg = -deg; // take '-', west and south as -ve | ||
| return Number(deg); | ||
| } | ||
| var callbacks = []; | ||
| var onLoadEvents = []; | ||
| /** | ||
| * Convert decimal degrees to deg/min/sec format | ||
| * - degree, prime, double-prime symbols are added, but sign is discarded, though no compass | ||
| * direction is added | ||
| * | ||
| * @private | ||
| * @param {Number} deg: Degrees | ||
| * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d | ||
| * @returns {String} deg formatted as deg/min/secs according to specified format | ||
| * @throws {TypeError} deg is an object, perhaps DOM object without .value? | ||
| */ | ||
| exports.toDMS = function(deg, format, dp) { | ||
| if (typeof deg == 'object') throw new TypeError('geo.toDMS - deg is [DOM?] object'); | ||
| if (isNaN(deg)) return null; // give up here if we can't make a number from deg | ||
| var originalCreateLoaderMethod = null; | ||
| // default values | ||
| if (typeof format == 'undefined') format = 'dms'; | ||
| if (typeof dp == 'undefined') { | ||
| switch (format) { | ||
| case 'd': dp = 4; break; | ||
| case 'dm': dp = 2; break; | ||
| case 'dms': dp = 0; break; | ||
| default: format = 'dms'; dp = 0; // be forgiving on invalid format | ||
| } | ||
| } | ||
| deg = Math.abs(deg); // (unsigned result ready for appending compass dir'n) | ||
| var GoogleMapsLoader = {}; | ||
| switch (format) { | ||
| case 'd': | ||
| d = deg.toFixed(dp); // round degrees | ||
| if (d<100) d = '0' + d; // pad with leading zeros | ||
| if (d<10) d = '0' + d; | ||
| dms = d + '\u00B0'; // add º symbol | ||
| break; | ||
| case 'dm': | ||
| var min = (deg*60).toFixed(dp); // convert degrees to minutes & round | ||
| var d = Math.floor(min / 60); // get component deg/min | ||
| var m = (min % 60).toFixed(dp); // pad with trailing zeros | ||
| if (d<100) d = '0' + d; // pad with leading zeros | ||
| if (d<10) d = '0' + d; | ||
| if (m<10) m = '0' + m; | ||
| dms = d + '\u00B0' + m + '\u2032'; // add º, ' symbols | ||
| break; | ||
| case 'dms': | ||
| var sec = (deg*3600).toFixed(dp); // convert degrees to seconds & round | ||
| var d = Math.floor(sec / 3600); // get component deg/min/sec | ||
| var m = Math.floor(sec/60) % 60; | ||
| var s = (sec % 60).toFixed(dp); // pad with trailing zeros | ||
| if (d<100) d = '0' + d; // pad with leading zeros | ||
| if (d<10) d = '0' + d; | ||
| if (m<10) m = '0' + m; | ||
| if (s<10) s = '0' + s; | ||
| dms = d + '\u00B0' + m + '\u2032' + s + '\u2033'; // add º, ', " symbols | ||
| break; | ||
| } | ||
| return dms; | ||
| } | ||
| GoogleMapsLoader.URL = 'https://maps.googleapis.com/maps/api/js'; | ||
| GoogleMapsLoader.KEY = null; | ||
| /** | ||
| * Convert numeric degrees to deg/min/sec latitude (suffixed with N/S) | ||
| * | ||
| * @param {Number} deg: Degrees | ||
| * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d | ||
| * @returns {String} Deg/min/seconds | ||
| */ | ||
| exports.toLat = function(deg, format, dp) { | ||
| var lat = exports.toDMS(deg, format, dp); | ||
| return lat==null ? '.' : lat.slice(1) + (deg<0 ? 'S' : 'N'); // knock off initial '0' for lat! | ||
| } | ||
| GoogleMapsLoader.LIBRARIES = []; | ||
| /** | ||
| * Convert numeric degrees to deg/min/sec longitude (suffixed with E/W) | ||
| * | ||
| * @param {Number} deg: Degrees | ||
| * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d | ||
| * @returns {String} Deg/min/seconds | ||
| */ | ||
| exports.toLon = function(deg, format, dp) { | ||
| var lon = exports.toDMS(deg, format, dp); | ||
| return lon==null ? '.' : lon + (deg<0 ? 'W' : 'E'); | ||
| } | ||
| GoogleMapsLoader.CLIENT = null; | ||
| GoogleMapsLoader.CHANNEL = null; | ||
| /** | ||
| * Convert numeric degrees to deg/min/sec as a bearing (0º..360º) | ||
| * | ||
| * @param {Number} deg: Degrees | ||
| * @param {String} [format=dms]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to use - default 0 for dms, 2 for dm, 4 for d | ||
| * @returns {String} Deg/min/seconds | ||
| */ | ||
| exports.toBrng = function(deg, format, dp) { | ||
| deg = (Number(deg)+360) % 360; // normalise -ve values to 180º..360º | ||
| var brng = exports.toDMS(deg, format, dp); | ||
| return brng==null ? '.' : brng.replace('360', '0'); // just in case rounding took us up to 360º! | ||
| } | ||
| GoogleMapsLoader.LANGUAGE = null; | ||
| /** | ||
| * Creates a point on the earth's surface at the supplied latitude / longitude | ||
| * | ||
| * @constructor | ||
| * @param {Number} lat: latitude in numeric degrees | ||
| * @param {Number} lon: longitude in numeric degrees | ||
| */ | ||
| GoogleMapsLoader.REGION = null; | ||
| //radius of earth | ||
| var radius = 6371; | ||
| GoogleMapsLoader.VERSION = googleVersion; | ||
| var latlon = exports.latlon = function(lat, lon) { | ||
| // only accept numbers or valid numeric strings | ||
| this.lat = typeof(lat)=='number' ? lat : typeof(lat)=='string' && lat.trim()!='' ? +lat : NaN; | ||
| this.lng = typeof(lon)=='number' ? lon : typeof(lon)=='string' && lon.trim()!='' ? +lon : NaN; | ||
| //this._radius = typeof(rad)=='number' ? rad : typeof(rad)=='string' && trim(lon)!='' ? +rad : NaN; | ||
| } | ||
| GoogleMapsLoader.WINDOW_CALLBACK_NAME = '__google_maps_api_provider_initializator__'; | ||
| /** | ||
| * Returns the distance from this point to the supplied point, in km | ||
| * (using Haversine formula) | ||
| * | ||
| * from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine", | ||
| * Sky and Telescope, vol 68, no 2, 1984 | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @param {Number} [precision=4]: no of significant digits to use for returned value | ||
| * @returns {Number} Distance in km between this point and destination point | ||
| */ | ||
| exports.latlon.prototype.distanceTo = function(point, precision) { | ||
| // default 4 sig figs reflects typical 0.3% accuracy of spherical model | ||
| if (typeof precision == 'undefined') precision = 4; | ||
| var c = this.distanceRadTo(point); | ||
| var d = radius * c; | ||
| return d.toPrecisionFixed(precision); | ||
| } | ||
| GoogleMapsLoader._googleMockApiObject = {}; | ||
| exports.latlon.prototype.distanceRadTo = function(point) { | ||
| var lat1 = this.lat.toRad(), lon1 = this.lng.toRad(); | ||
| var lat2 = point.lat.toRad(), lon2 = point.lng.toRad(); | ||
| var dLat = lat2 - lat1; | ||
| var dLon = lon2 - lon1; | ||
| var a = Math.sin(dLat/2) * Math.sin(dLat/2) + | ||
| Math.cos(lat1) * Math.cos(lat2) * | ||
| Math.sin(dLon/2) * Math.sin(dLon/2); | ||
| var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); | ||
| return c; | ||
| } | ||
| GoogleMapsLoader.load = function(fn) { | ||
| if (google === null) { | ||
| if (loading === true) { | ||
| if (fn) { | ||
| callbacks.push(fn); | ||
| } | ||
| } else { | ||
| loading = true; | ||
| window[GoogleMapsLoader.WINDOW_CALLBACK_NAME] = function() { | ||
| ready(fn); | ||
| }; | ||
| /** | ||
| * Returns the (initial) bearing from this point to the supplied point, in degrees | ||
| * see http://williams.best.vwh.net/avform.htm#Crs | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @returns {Number} Initial bearing in degrees from North | ||
| */ | ||
| exports.latlon.prototype.bearingTo = function(point) { | ||
| var brng = this.bearingRadTo(point); | ||
| return (brng.toDeg()+360) % 360; | ||
| } | ||
| exports.latlon.prototype.bearingRadTo = function(point) { | ||
| var lat1 = this.lat.toRad() | ||
| var lat2 = point.lat.toRad(); | ||
| var dLon = (point.lng-this.lng).toRad(); | ||
| GoogleMapsLoader.createLoader(); | ||
| } | ||
| } else if (fn) { | ||
| fn(google); | ||
| } | ||
| }; | ||
| var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2)*Math.cos(dLon); | ||
| var y = Math.cos(lat2) * Math.sin(dLon); | ||
| var brng = Math.atan2(y, x); | ||
| return brng; | ||
| } | ||
| GoogleMapsLoader.createLoader = function() { | ||
| script = document.createElement('script'); | ||
| script.type = 'text/javascript'; | ||
| script.src = GoogleMapsLoader.createUrl(); | ||
| /** | ||
| * Returns final bearing arriving at supplied destination point from this point; the final bearing | ||
| * will differ from the initial bearing by varying degrees according to distance and latitude | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @returns {Number} Final bearing in degrees from North | ||
| */ | ||
| exports.latlon.prototype.finalBearingTo = function(point) { | ||
| // get initial bearing from supplied point back to this point... | ||
| var lat1 = point.lat.toRad(), lat2 = this.lat.toRad(); | ||
| var dLon = (this.lng-point.lng).toRad(); | ||
| document.body.appendChild(script); | ||
| }; | ||
| var y = Math.sin(dLon) * Math.cos(lat2); | ||
| var x = Math.cos(lat1)*Math.sin(lat2) - | ||
| Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon); | ||
| var brng = Math.atan2(y, x); | ||
| // ... & reverse it by adding 180° | ||
| return (brng.toDeg()+180) % 360; | ||
| } | ||
| GoogleMapsLoader.isLoaded = function() { | ||
| return google !== null; | ||
| }; | ||
| /** | ||
| * Returns the midpoint between this point and the supplied point. | ||
| * see http://mathforum.org/library/drmath/view/51822.html for derivation | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @returns {latlon} Midpoint between this point and the supplied point | ||
| */ | ||
| exports.latlon.prototype.midpointTo = function(point) { | ||
| var lat1 = this.lat.toRad(); | ||
| var lat2 = point.lat.toRad(); | ||
| var dLon = (point.lng-this.lng).toRad(); | ||
| GoogleMapsLoader.createUrl = function() { | ||
| var url = GoogleMapsLoader.URL; | ||
| var Bx = Math.cos(lat2) * Math.cos(dLon); | ||
| var By = Math.cos(lat2) * Math.sin(dLon); | ||
| url += '?callback=' + GoogleMapsLoader.WINDOW_CALLBACK_NAME; | ||
| var lon1 = this.lng.toRad(); | ||
| if (GoogleMapsLoader.KEY) { | ||
| url += '&key=' + GoogleMapsLoader.KEY; | ||
| } | ||
| lat3 = Math.atan2(Math.sin(lat1)+Math.sin(lat2), Math.sqrt( (Math.cos(lat1)+Bx)*(Math.cos(lat1)+Bx) + By*By) ); | ||
| lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx); | ||
| lon3 = (lon3+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180º | ||
| if (GoogleMapsLoader.LIBRARIES.length > 0) { | ||
| url += '&libraries=' + GoogleMapsLoader.LIBRARIES.join(','); | ||
| } | ||
| return new exports.latlon(lat3.toDeg(), lon3.toDeg()); | ||
| } | ||
| if (GoogleMapsLoader.CLIENT) { | ||
| url += '&client=' + GoogleMapsLoader.CLIENT + '&v=' + GoogleMapsLoader.VERSION; | ||
| } | ||
| exports.midpoint = function(points) { | ||
| var X = 0; | ||
| var Y = 0; | ||
| var Z = 0; | ||
| if (GoogleMapsLoader.CHANNEL) { | ||
| url += '&channel=' + GoogleMapsLoader.CHANNEL; | ||
| } | ||
| for(var i in points) { | ||
| var point = points[i]; | ||
| //console.log(i); | ||
| //console.dir(point); | ||
| if (GoogleMapsLoader.LANGUAGE) { | ||
| url += '&language=' + GoogleMapsLoader.LANGUAGE; | ||
| } | ||
| var lat = point.lat * Math.PI / 180; | ||
| var lon = point.lng * Math.PI / 180; | ||
| //console.log("lat:"+lat); | ||
| //console.log("lon:"+lon); | ||
| if (GoogleMapsLoader.REGION) { | ||
| url += '®ion=' + GoogleMapsLoader.REGION; | ||
| } | ||
| var x = Math.cos(lat) * Math.cos(lon); | ||
| var y = Math.cos(lat) * Math.sin(lon); | ||
| var z = Math.sin(lat); | ||
| //console.log("x:"+x); | ||
| return url; | ||
| }; | ||
| X += x; | ||
| Y += y; | ||
| Z += z; | ||
| } | ||
| X = X / points.length; | ||
| Y = Y / points.length; | ||
| Z = Z / points.length; | ||
| GoogleMapsLoader.release = function(fn) { | ||
| var release = function() { | ||
| GoogleMapsLoader.KEY = null; | ||
| GoogleMapsLoader.LIBRARIES = []; | ||
| GoogleMapsLoader.CLIENT = null; | ||
| GoogleMapsLoader.CHANNEL = null; | ||
| GoogleMapsLoader.LANGUAGE = null; | ||
| GoogleMapsLoader.REGION = null; | ||
| GoogleMapsLoader.VERSION = googleVersion; | ||
| var Lon = Math.atan2(Y, X); | ||
| var Hyp = Math.sqrt(X * X + Y * Y); | ||
| var Lat = Math.atan2(Z, Hyp); | ||
| google = null; | ||
| loading = false; | ||
| callbacks = []; | ||
| onLoadEvents = []; | ||
| return new exports.latlon(Lat * 180 / Math.PI, Lon * 180 / Math.PI); | ||
| } | ||
| if (typeof window.google !== 'undefined') { | ||
| delete window.google; | ||
| } | ||
| /* | ||
| Returns list of latlon between this point and the supplied endpoint | ||
| */ | ||
| exports.latlon.prototype.interpolate = function(point, num) { | ||
| if (typeof window[GoogleMapsLoader.WINDOW_CALLBACK_NAME] !== 'undefined') { | ||
| delete window[GoogleMapsLoader.WINDOW_CALLBACK_NAME]; | ||
| } | ||
| var distance = this.distanceRadTo(point); | ||
| var bearing = this.bearingRadTo(point); | ||
| if (originalCreateLoaderMethod !== null) { | ||
| GoogleMapsLoader.createLoader = originalCreateLoaderMethod; | ||
| originalCreateLoaderMethod = null; | ||
| } | ||
| var lat1 = this.lat.toRad(); | ||
| var lon1 = this.lng.toRad(); | ||
| var lat2 = point.lat.toRad(); | ||
| var lon2 = point.lng.toRad(); | ||
| if (script !== null) { | ||
| script.parentElement.removeChild(script); | ||
| script = null; | ||
| } | ||
| var alatRadSin = Math.sin(lat1); | ||
| var blatRadSin = Math.sin(lat2); | ||
| var alatRadCos = Math.cos(lat1); | ||
| var blatRadCos = Math.cos(lat2); | ||
| if (fn) { | ||
| fn(); | ||
| } | ||
| }; | ||
| var points = []; | ||
| if (loading) { | ||
| GoogleMapsLoader.load(function() { | ||
| release(); | ||
| }); | ||
| } else { | ||
| release(); | ||
| } | ||
| }; | ||
| for(var i = 0;i < num;i++) { | ||
| var t = 1/(num-1) * i; | ||
| // Find new point | ||
| var angularDistance=distance*t; | ||
| var angDistSin=Math.sin(angularDistance); | ||
| var angDistCos=Math.cos(angularDistance); | ||
| var xlatRad = Math.asin( alatRadSin*angDistCos + alatRadCos*angDistSin*Math.cos(bearing) ); | ||
| var xlonRad = lon1 + Math.atan2( Math.sin(bearing)*angDistSin*alatRadCos, angDistCos-alatRadSin*Math.sin(xlatRad)); | ||
| // Convert radians to deg | ||
| var xlat=xlatRad.toDeg(); | ||
| var xlon=xlonRad.toDeg(); | ||
| GoogleMapsLoader.onLoad = function(fn) { | ||
| onLoadEvents.push(fn); | ||
| }; | ||
| //normalize | ||
| if(xlat>90)xlat=90; | ||
| if(xlat<-90)xlat=-90; | ||
| while(xlon>180)xlon-=360; | ||
| while(xlon<=-180)xlon+=360; | ||
| points.push(new exports.latlon(xlat, xlon)); | ||
| } | ||
| return points; | ||
| } | ||
| GoogleMapsLoader.makeMock = function() { | ||
| originalCreateLoaderMethod = GoogleMapsLoader.createLoader; | ||
| /** | ||
| * Returns the destination point from this point having travelled the given distance (in km) on the | ||
| * given initial bearing (bearing may vary before destination is reached) | ||
| * | ||
| * see http://williams.best.vwh.net/avform.htm#LL | ||
| * | ||
| * @param {Number} brng: Initial bearing in degrees | ||
| * @param {Number} dist: Distance in km | ||
| * @returns {latlon} Destination point | ||
| */ | ||
| exports.latlon.prototype.destinationPoint = function(brng, dist) { | ||
| dist = typeof(dist)=='number' ? dist : typeof(dist)=='string' && dist.trim()!='' ? +dist : NaN; | ||
| dist = dist/radius; // convert dist to angular distance in radians | ||
| brng = brng.toRad(); // | ||
| var lat1 = this.lat.toRad(), lon1 = this.lng.toRad(); | ||
| GoogleMapsLoader.createLoader = function() { | ||
| window.google = GoogleMapsLoader._googleMockApiObject; | ||
| window[GoogleMapsLoader.WINDOW_CALLBACK_NAME](); | ||
| }; | ||
| }; | ||
| var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) + | ||
| Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) ); | ||
| var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1), | ||
| Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2)); | ||
| lon2 = (lon2+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180º | ||
| return new exports.latlon(lat2.toDeg(), lon2.toDeg()); | ||
| } | ||
| var ready = function(fn) { | ||
| var i; | ||
| loading = false; | ||
| /** | ||
| * Returns the point of intersection of two paths defined by point and bearing | ||
| * | ||
| * see http://williams.best.vwh.net/avform.htm#Intersection | ||
| * | ||
| * @param {latlon} p1: First point | ||
| * @param {Number} brng1: Initial bearing from first point | ||
| * @param {latlon} p2: Second point | ||
| * @param {Number} brng2: Initial bearing from second point | ||
| * @returns {latlon} Destination point (null if no unique intersection defined) | ||
| */ | ||
| exports.latlon.intersection = function(p1, brng1, p2, brng2) { | ||
| brng1 = typeof brng1 == 'number' ? brng1 : typeof brng1 == 'string' && trim(brng1)!='' ? +brng1 : NaN; | ||
| brng2 = typeof brng2 == 'number' ? brng2 : typeof brng2 == 'string' && trim(brng2)!='' ? +brng2 : NaN; | ||
| lat1 = p1.lat.toRad(), lon1 = p1.lng.toRad(); | ||
| lat2 = p2.lat.toRad(), lon2 = p2.lng.toRad(); | ||
| brng13 = brng1.toRad(), brng23 = brng2.toRad(); | ||
| dLat = lat2-lat1, dLon = lon2-lon1; | ||
| if (google === null) { | ||
| google = window.google; | ||
| } | ||
| dist12 = 2*Math.asin( Math.sqrt( Math.sin(dLat/2)*Math.sin(dLat/2) + | ||
| Math.cos(lat1)*Math.cos(lat2)*Math.sin(dLon/2)*Math.sin(dLon/2) ) ); | ||
| if (dist12 == 0) return null; | ||
| for (i = 0; i < onLoadEvents.length; i++) { | ||
| onLoadEvents[i](google); | ||
| } | ||
| // initial/final bearings between points | ||
| brngA = Math.acos( ( Math.sin(lat2) - Math.sin(lat1)*Math.cos(dist12) ) / | ||
| ( Math.sin(dist12)*Math.cos(lat1) ) ); | ||
| if (isNaN(brngA)) brngA = 0; // protect against rounding | ||
| brngB = Math.acos( ( Math.sin(lat1) - Math.sin(lat2)*Math.cos(dist12) ) / | ||
| ( Math.sin(dist12)*Math.cos(lat2) ) ); | ||
| if (fn) { | ||
| fn(google); | ||
| } | ||
| if (Math.sin(lon2-lon1) > 0) { | ||
| brng12 = brngA; | ||
| brng21 = 2*Math.PI - brngB; | ||
| } else { | ||
| brng12 = 2*Math.PI - brngA; | ||
| brng21 = brngB; | ||
| } | ||
| for (i = 0; i < callbacks.length; i++) { | ||
| callbacks[i](google); | ||
| } | ||
| alpha1 = (brng13 - brng12 + Math.PI) % (2*Math.PI) - Math.PI; // angle 2-1-3 | ||
| alpha2 = (brng21 - brng23 + Math.PI) % (2*Math.PI) - Math.PI; // angle 1-2-3 | ||
| callbacks = []; | ||
| }; | ||
| if (Math.sin(alpha1)==0 && Math.sin(alpha2)==0) return null; // infinite intersections | ||
| if (Math.sin(alpha1)*Math.sin(alpha2) < 0) return null; // ambiguous intersection | ||
| //alpha1 = Math.abs(alpha1); | ||
| //alpha2 = Math.abs(alpha2); | ||
| // ... Ed Williams takes abs of alpha1/alpha2, but seems to break calculation? | ||
| return GoogleMapsLoader; | ||
| alpha3 = Math.acos( -Math.cos(alpha1)*Math.cos(alpha2) + | ||
| Math.sin(alpha1)*Math.sin(alpha2)*Math.cos(dist12) ); | ||
| dist13 = Math.atan2( Math.sin(dist12)*Math.sin(alpha1)*Math.sin(alpha2), | ||
| Math.cos(alpha2)+Math.cos(alpha1)*Math.cos(alpha3) ) | ||
| lat3 = Math.asin( Math.sin(lat1)*Math.cos(dist13) + | ||
| Math.cos(lat1)*Math.sin(dist13)*Math.cos(brng13) ); | ||
| dLon13 = Math.atan2( Math.sin(brng13)*Math.sin(dist13)*Math.cos(lat1), | ||
| Math.cos(dist13)-Math.sin(lat1)*Math.sin(lat3) ); | ||
| lon3 = lon1+dLon13; | ||
| lon3 = (lon3+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180º | ||
| }); | ||
| return new exports.latlon(lat3.toDeg(), lon3.toDeg()); | ||
| } | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| /** | ||
| * Returns the distance from this point to the supplied point, in km, travelling along a rhumb line | ||
| * | ||
| * see http://williams.best.vwh.net/avform.htm#Rhumb | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @returns {Number} Distance in km between this point and destination point | ||
| */ | ||
| exports.latlon.prototype.rhumbDistanceTo = function(point) { | ||
| var R = radius; | ||
| var lat1 = this.lat.toRad(), lat2 = point.lat.toRad(); | ||
| var dLat = (point.lat-this.lat).toRad(); | ||
| var dLon = Math.abs(point.lng-this.lng).toRad(); | ||
| var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4)); | ||
| var q = (isFinite(dLat/dPhi)) ? dLat/dPhi : Math.cos(lat1); // E-W line gives dPhi=0 | ||
| // if dLon over 180° take shorter rhumb across anti-meridian: | ||
| if (Math.abs(dLon) > Math.PI) { | ||
| dLon = dLon>0 ? -(2*Math.PI-dLon) : (2*Math.PI+dLon); | ||
| } | ||
| var dist = Math.sqrt(dLat*dLat + q*q*dLon*dLon) * R; | ||
| return dist.toPrecisionFixed(4); // 4 sig figs reflects typical 0.3% accuracy of spherical model | ||
| } | ||
| /** | ||
| * Returns the bearing from this point to the supplied point along a rhumb line, in degrees | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @returns {Number} Bearing in degrees from North | ||
| */ | ||
| exports.latlon.prototype.rhumbBearingTo = function(point) { | ||
| var lat1 = this.lat.toRad(), lat2 = point.lat.toRad(); | ||
| var dLon = (point.lng-this.lng).toRad(); | ||
| var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4)); | ||
| if (Math.abs(dLon) > Math.PI) dLon = dLon>0 ? -(2*Math.PI-dLon) : (2*Math.PI+dLon); | ||
| var brng = Math.atan2(dLon, dPhi); | ||
| return (brng.toDeg()+360) % 360; | ||
| } | ||
| /** | ||
| * Returns the destination point from this point having travelled the given distance (in km) on the | ||
| * given bearing along a rhumb line | ||
| * | ||
| * @param {Number} brng: Bearing in degrees from North | ||
| * @param {Number} dist: Distance in km | ||
| * @returns {latlon} Destination point | ||
| */ | ||
| exports.latlon.prototype.rhumbDestinationPoint = function(brng, dist) { | ||
| var R = radius; | ||
| var d = parseFloat(dist)/R; // d = angular distance covered on earth.s surface | ||
| var lat1 = this.lat.toRad(), lon1 = this.lng.toRad(); | ||
| brng = brng.toRad(); | ||
| var dLat = d*Math.cos(brng); | ||
| // nasty kludge to overcome ill-conditioned results around parallels of latitude: | ||
| if (Math.abs(dLat) < 1e-10) dLat = 0; // dLat < 1 mm | ||
| var lat2 = lat1 + dLat; | ||
| var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4)); | ||
| var q = (isFinite(dLat/dPhi)) ? dLat/dPhi : Math.cos(lat1); // E-W line gives dPhi=0 | ||
| var dLon = d*Math.sin(brng)/q; | ||
| // check for some daft bugger going past the pole, normalise latitude if so | ||
| if (Math.abs(lat2) > Math.PI/2) lat2 = lat2>0 ? Math.PI-lat2 : -Math.PI-lat2; | ||
| lon2 = (lon1+dLon+3*Math.PI)%(2*Math.PI) - Math.PI; | ||
| return new exports.latlon(lat2.toDeg(), lon2.toDeg()); | ||
| } | ||
| /** | ||
| * Returns the loxodromic midpoint (along a rhumb line) between this point and the supplied point. | ||
| * see http://mathforum.org/kb/message.jspa?messageID=148837 | ||
| * | ||
| * @param {latlon} point: Latitude/longitude of destination point | ||
| * @returns {latlon} Midpoint between this point and the supplied point | ||
| */ | ||
| exports.latlon.prototype.rhumbMidpointTo = function(point) { | ||
| lat1 = this.lat.toRad(), lon1 = this.lng.toRad(); | ||
| lat2 = point.lat.toRad(), lon2 = point.lng.toRad(); | ||
| if (Math.abs(lon2-lon1) > Math.PI) lon1 += 2*Math.PI; // crossing anti-meridian | ||
| var lat3 = (lat1+lat2)/2; | ||
| var f1 = Math.tan(Math.PI/4 + lat1/2); | ||
| var f2 = Math.tan(Math.PI/4 + lat2/2); | ||
| var f3 = Math.tan(Math.PI/4 + lat3/2); | ||
| var lon3 = ( (lon2-lon1)*Math.log(f3) + lon1*Math.log(f2) - lon2*Math.log(f1) ) / Math.log(f2/f1); | ||
| if (!isFinite(lon3)) lon3 = (lon1+lon2)/2; // parallel of latitude | ||
| lon3 = (lon3+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180º | ||
| return new exports.latlon(lat3.toDeg(), lon3.toDeg()); | ||
| } | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| /** | ||
| * Returns the latitude of this point; signed numeric degrees if no format, otherwise format & dp | ||
| * as per toLat() | ||
| * | ||
| * @param {String} [format]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to display | ||
| * @returns {Number|String} Numeric degrees if no format specified, otherwise deg/min/sec | ||
| */ | ||
| exports.latlon.prototype.lat = function(format, dp) { | ||
| if (typeof format == 'undefined') return this.lat; | ||
| return exports.toLat(this.lat, format, dp); | ||
| } | ||
| /** | ||
| * Returns the longitude of this point; signed numeric degrees if no format, otherwise format & dp | ||
| * as per toLon() | ||
| * | ||
| * @param {String} [format]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to display | ||
| * @returns {Number|String} Numeric degrees if no format specified, otherwise deg/min/sec | ||
| */ | ||
| exports.latlon.prototype.lon = function(format, dp) { | ||
| if (typeof format == 'undefined') return this.lng; | ||
| return exports.toLon(this.lng, format, dp); | ||
| } | ||
| /** | ||
| * Returns a string representation of this point; format and dp as per lat()/lon() | ||
| * | ||
| * @param {String} [format]: Return value as 'd', 'dm', 'dms' | ||
| * @param {Number} [dp=0|2|4]: No of decimal places to display | ||
| * @returns {String} Comma-separated latitude/longitude | ||
| */ | ||
| exports.latlon.prototype.toString = function(format, dp) { | ||
| if (typeof format == 'undefined') format = 'dms'; | ||
| return exports.toLat(this.lat, format, dp) + ', ' + exports.toLon(this.lng, format, dp); | ||
| } | ||
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
| // ---- extend Number object with methods for converting degrees/radians | ||
| /** Converts numeric degrees to radians */ | ||
| if (typeof Number.prototype.toRad == 'undefined') { | ||
| Number.prototype.toRad = function() { | ||
| return this * Math.PI / 180; | ||
| } | ||
| } | ||
| /** Converts radians to numeric (signed) degrees */ | ||
| if (typeof Number.prototype.toDeg == 'undefined') { | ||
| Number.prototype.toDeg = function() { | ||
| return this * 180 / Math.PI; | ||
| } | ||
| } | ||
| /** | ||
| * Formats the significant digits of a number, using only fixed-point notation (no exponential) | ||
| * | ||
| * @param {Number} precision: Number of significant digits to appear in the returned string | ||
| * @returns {String} A string representation of number which contains precision significant digits | ||
| */ | ||
| if (typeof Number.prototype.toPrecisionFixed == 'undefined') { | ||
| Number.prototype.toPrecisionFixed = function(precision) { | ||
| // use standard toPrecision method | ||
| var n = this.toPrecision(precision); | ||
| // ... but replace +ve exponential format with trailing zeros | ||
| n = n.replace(/(.+)e\+(.+)/, function(n, sig, exp) { | ||
| sig = sig.replace(/\./, ''); // remove decimal from significand | ||
| l = sig.length - 1; | ||
| while (exp-- > l) sig = sig + '0'; // append zeros from exponent | ||
| return sig; | ||
| }); | ||
| // ... and replace -ve exponential format with leading zeros | ||
| n = n.replace(/(.+)e-(.+)/, function(n, sig, exp) { | ||
| sig = sig.replace(/\./, ''); // remove decimal from significand | ||
| while (exp-- > 1) sig = '0' + sig; // prepend zeros from exponent | ||
| return '0.' + sig; | ||
| }); | ||
| return n; | ||
| } | ||
| } | ||
| /** Trims whitespace from string (q.v. blog.stevenlevithan.com/archives/faster-trim-javascript) */ | ||
| if (typeof String.prototype.trim == 'undefined') { | ||
| String.prototype.trim = function() { | ||
| return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); | ||
| } | ||
| } | ||
| },{}],3:[function(require,module,exports){ | ||
| var Distance = require('../index'); | ||
| var GoogleMapsLoader = require('google-maps'); | ||
| GoogleMapsLoader.KEY = 'AIzaSyDrMrHDCL33b4PkB0p5SZlCR7mwc7Yp7SA'; | ||
| GoogleMapsLoader.LIBRARIES = ['geometry']; | ||
| QUnit.test( 'Filter a GPS track to ensure the filter works', function(assert) { | ||
| var done = assert.async(); | ||
| var filtered = Distance.filter(data); | ||
| GoogleMapsLoader.load(function(google) { | ||
| var options = { google: google }; | ||
| var raw = Distance.mapToGoogle(data); | ||
| var civilized = Distance.mapToGoogle(filtered); | ||
| var filtered = Distance.filter(data, options); | ||
| var rawDistance = Distance.computeDistance(raw); | ||
| var filteredDistance = Distance.computeDistance(civilized); | ||
| var raw = Distance.mapToGoogle(data, options); | ||
| var civilized = Distance.mapToGoogle(filtered, options); | ||
| var rawDistance = Distance.computeDistance(raw, options); | ||
| var filteredDistance = Distance.computeDistance(civilized, options); | ||
| assert.equal(104.01168761662434, rawDistance, 'Passed!'); | ||
| assert.equal(97.55330283703395, filteredDistance, 'Passed!'); | ||
| done(); | ||
| }); | ||
| assert.equal(rawDistance, 103.89499999999998, 'Passed!'); | ||
| assert.equal(filteredDistance, 97.44399999999999, 'Passed!'); | ||
| }); | ||
@@ -578,2 +993,2 @@ | ||
| },{"../index":1,"google-maps":2}]},{},[3]); | ||
| },{"../index":1}]},{},[3]); |
+7
-18
| var Distance = require('../index'); | ||
| var GoogleMapsLoader = require('google-maps'); | ||
| GoogleMapsLoader.KEY = 'AIzaSyDrMrHDCL33b4PkB0p5SZlCR7mwc7Yp7SA'; | ||
| GoogleMapsLoader.LIBRARIES = ['geometry']; | ||
| QUnit.test( 'Filter a GPS track to ensure the filter works', function(assert) { | ||
| var done = assert.async(); | ||
| var filtered = Distance.filter(data); | ||
| GoogleMapsLoader.load(function(google) { | ||
| var options = { google: google }; | ||
| var raw = Distance.mapToGoogle(data); | ||
| var civilized = Distance.mapToGoogle(filtered); | ||
| var filtered = Distance.filter(data, options); | ||
| var rawDistance = Distance.computeDistance(raw); | ||
| var filteredDistance = Distance.computeDistance(civilized); | ||
| var raw = Distance.mapToGoogle(data, options); | ||
| var civilized = Distance.mapToGoogle(filtered, options); | ||
| var rawDistance = Distance.computeDistance(raw, options); | ||
| var filteredDistance = Distance.computeDistance(civilized, options); | ||
| assert.equal(104.01168761662434, rawDistance, 'Passed!'); | ||
| assert.equal(97.55330283703395, filteredDistance, 'Passed!'); | ||
| done(); | ||
| }); | ||
| assert.equal(rawDistance, 103.89499999999998, 'Passed!'); | ||
| assert.equal(filteredDistance, 97.44399999999999, 'Passed!'); | ||
| }); | ||
@@ -26,0 +15,0 @@ |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
47749
70.39%1183
41.17%4
100%+ Added
+ Added
- Removed
- Removed