🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

standstill

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

standstill - npm Package Compare versions

Comparing version
1.0.0
to
1.0.1
+92
result.json
[
[
"2014-11-28 09:48:38",
"Recording starts",
0
],
[
"2014-11-28 09:48:38",
"Route #0 starts.",
0
],
[
"2014-11-28 10:00:05",
"Route #0 ends.",
687000
],
[
"2014-11-28 10:00:28",
"Stop #0 start.",
23000
],
[
"2014-11-28 10:41:19",
"Stop #0 ends.",
2451000
],
[
"2014-11-28 10:41:51",
"Route #1 starts.",
32000
],
[
"2014-11-28 11:40:54",
"Route #1 ends.",
3543000
],
[
"2014-11-28 11:42:14",
"Stop #1 start.",
80000
],
[
"2014-11-28 13:25:15",
"Stop #1 ends.",
6181000
],
[
"2014-11-28 13:25:41",
"Route #2 starts.",
26000
],
[
"2014-11-28 14:58:32",
"Route #2 ends.",
5571000
],
[
"2014-11-28 14:58:41",
"Stop #2 start.",
9000
],
[
"2014-11-28 15:46:38",
"Stop #2 ends.",
2877000
],
[
"2014-11-28 15:50:13",
"Route #3 starts.",
215000
],
[
"2014-11-28 15:50:54",
"Route #3 ends.",
41000
],
[
"2014-11-28 15:50:57",
"Stop #3 start.",
3000
],
[
"2014-11-28 15:57:11",
"Recording ends",
374000
],
[
"2014-11-28 15:57:11",
"Stop #3 ends.",
0
]
]
+31
-30

@@ -21,11 +21,19 @@ var distance = require('turf-distance'),

handleCandidate = function(result) {
var c = result.stopCandidate;
var c = result.stopCandidate,
coordSum;
if (c) {
if (result.lastTimestamp - c.startTime >= filter.stopMinTime) {
result.stops.features.push(point([c.lngSum / c.numCoords, c.latSum / c.numCoords], {
startTime: c.startTime,
endTime: result.lastTimestamp
if (result.lastTimestamp - c.startTimeStamp >= filter.stopMinTime) {
coordSum = c.coords.reduce(function(center, c) {
center[0] += c[0];
center[1] += c[1];
return center;
}, [0, 0]);
result.stops.features.push(point([coordSum[0] / c.coords.length, coordSum[1] / c.coords.length], {
startTime: c.times[0],
endTime: c.times[c.times.length - 1]
}));
result.routes.features.push(linestring(result.currentRoute, {coordTimes: result.currentRouteTimes}));
result.currentRoute = [];
result.currentRouteTimes = [];

@@ -45,30 +53,23 @@ return true;

if (result.lastPoint) {
if (!candidate) {
candidate = result.stopCandidate = {
startTimeStamp: timestamp,
coords: [],
times: []
};
}
candidate.coords.push(c);
candidate.times.push(t);
if (result.lastPoint && candidate) {
d = distance(p, result.lastPoint);
if (d > filter.stopTolerance || timestamp - result.lastTimestamp > filter.maxTimeGap) {
handleCandidate(result);
if (!handleCandidate(result)) {
result.currentRoute = result.currentRoute.concat(candidate.coords);
result.currentRouteTimes = result.currentRouteTimes.concat(candidate.times);
}
delete result.stopCandidate;
if (result.candidateRouteCoords.length) {
result.currentRoute = result.currentRoute.concat(result.candidateRouteCoords);
result.currentRouteTimes = result.currentRouteTimes.concat(result.candidateRouteTimes);
result.candidateRouteCoords = [];
result.candidateRouteTimes = [];
}
result.candidateRouteCoords.push(c);
result.candidateRouteTimes.push(t);
} else {
if (!candidate) {
candidate = result.stopCandidate = {
startTime: result.lastTimestamp,
lngSum: 0,
latSum: 0,
numCoords: 0
};
}
candidate.lngSum += c[0];
candidate.latSum += c[1];
candidate.numCoords++;
result.candidateRouteCoords.push(c);
result.candidateRouteTimes.push(t);
result.currentRoute.push(c);
result.currentRouteTimes.push(t);
}

@@ -75,0 +76,0 @@ }

{
"name": "standstill",
"version": "1.0.0",
"version": "1.0.1",
"description": "Find locations where there has been no movement, a stop, within a GeoJSON track, typically recorded from a GPS",

@@ -5,0 +5,0 @@ "main": "index.js",

+25
-3

@@ -1,4 +0,26 @@

var findstops = require('./');
track = require('./test/sample-geojson.json');
var findstops = require('./'),
track = require('./test/sample-geojson.json'),
d = findstops(track, {maxTimeGap: 24 * 60 * 60 * 1000}),
stopStarts = d.stops.features.map(function(s, i) {
return [s.properties.startTime, 'Stop #' + i + ' start.'];
}),
stopEnds = d.stops.features.map(function(s, i) {
return [s.properties.endTime, 'Stop #' + i + ' ends.'];
}),
routeStarts = d.routes.features.map(function(s, i) {
return [s.properties.coordTimes[0], 'Route #' + i + ' starts.'];
}),
routeEnds = d.routes.features.map(function(s, i) {
return [s.properties.coordTimes[s.properties.coordTimes.length - 1], 'Route #' + i + ' ends.'];
}),
events = [
[track.properties.coordTimes[0], 'Recording starts'],
[track.properties.coordTimes[track.properties.coordTimes.length - 1], 'Recording ends']
].concat(stopStarts).concat(stopEnds).concat(routeStarts).concat(routeEnds);
console.log(JSON.stringify(findstops(track, {maxTimeGap: 24 * 60 * 60 * 1000}), null, ' '));
events.sort(function(a, b) { return a[0] < b[0] ? -1 : b[0] < a[0] ? 1 : 0; });
events.forEach(function(e, i) {
e[2] = i > 0 ? new Date(e[0]).getTime() - new Date(events[i - 1][0]).getTime() : 0;
});
console.log(JSON.stringify(events, null, ' '));

@@ -58,1 +58,53 @@ var test = require('tape'),

});
test('routes have one timestamp per coordinate', function(t) {
var routes = findstops(geojsonTrack, {maxTimeGap: 24 * 60 * 60 * 1000}).routes,
r,
i;
t.ok(routes.features.length > 0, 'contains at least one route (' + routes.length + ')');
for (i = 0; i < routes.features.length; i++) {
r = routes.features[i];
t.ok(r.geometry.coordinates.length, r.properties.coordTimes.length,
'route ' + i + ' does not have one coordinate per timestamp');
}
t.end();
});
test('routes do not overlap', function(t) {
var routes = findstops(geojsonTrack, {maxTimeGap: 24 * 60 * 60 * 1000}).routes,
r1,
r2,
i;
t.ok(routes.features.length > 1, 'contains at least two routes (' + routes.length + ')');
for (i = 1; i < routes.features.length; i++) {
r1 = routes.features[i - 1];
r2 = routes.features[i];
t.ok(r2.properties.coordTimes[0] > r1.properties.coordTimes[r1.properties.coordTimes.length - 1],
'route ' + i + ' does not overlap route ' + (i - 1));
}
t.end();
});
test('routes and stops together are as long as original geojson', function(t) {
var ts = function(d) { return new Date(d).getTime(); },
d = findstops(geojsonTrack, {maxTimeGap: 24 * 60 * 60 * 1000}),
indataTime = ts(geojsonTrack.properties.coordTimes[geojsonTrack.properties.coordTimes.length - 1]) -
ts(geojsonTrack.properties.coordTimes[0]),
stopTime = d.stops.features.reduce(function(t, s) {
return t + ts(s.properties.endTime) - ts(s.properties.startTime);
}, 0),
routeTime = d.routes.features.reduce(function(t, r) {
return t + ts(r.properties.coordTimes[r.properties.coordTimes.length - 1]) - ts(r.properties.coordTimes[0]);
}, 0),
aggregatedTime = stopTime + routeTime;
t.ok(almostEqual(aggregatedTime, indataTime, 5 * 60 * 1000), aggregatedTime + ' should be similar to ' + indataTime +
' (diff is ' + Math.round((aggregatedTime - indataTime) / (60 * 1000)) + ' minutes)');
t.end();
});