Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

compute-distance

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

compute-distance - npm Package Compare versions

Comparing version
0.0.2
to
0.0.3
+23
-49
index.js

@@ -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 @@

{
"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"
}
}
(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 += '&region=' + 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]);
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 @@