-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
113 lines (100 loc) · 3.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
var distance = require('turf-distance'),
point = require('turf-point'),
linestring = require('turf-linestring'),
featurecollection = require('turf-featurecollection');
module.exports = function(geojson, options) {
if (!geojson) {
throw 'Must supply GeoJSON';
}
if (geojson.type !== 'Feature' || !geojson.geometry || geojson.geometry.type !== 'LineString') {
throw 'GeoJSON must be a LineString feature';
}
options = options || {};
var filter = {
maxTimeGap: options.maxTimeGap || 5 * 60 * 1000,
stopTolerance: options.stopTolerance || 0.1,
stopMinTime: options.stopMinTime || 5 * 60 * 1000
},
getCenter = function(coords) {
var coordSum = coords.reduce(function(center, c) {
center[0] += c[0];
center[1] += c[1];
return center;
}, [0, 0]);
return [coordSum[0] / coords.length, coordSum[1] / coords.length];
},
handleRoute = function(result) {
if (result.currentRoute.length > 0) {
result.routes.features.push(linestring(result.currentRoute, {coordTimes: result.currentRouteTimes}));
}
result.currentRoute = [];
result.currentRouteTimes = [];
},
handleCandidate = function(result) {
var c = result.stopCandidate;
if (c) {
delete result.stopCandidate;
if (result.lastTimestamp - c.startTimeStamp >= filter.stopMinTime) {
result.stops.features.push(point(getCenter(c.coords), {
startTime: c.times[0],
endTime: c.times[c.times.length - 1]
}));
if (result.currentRoute.length > 0) {
result.currentRoute.push(c.coords[0]);
result.currentRouteTimes.push(c.times[0]);
handleRoute(result);
}
return true;
}
result.currentRoute = result.currentRoute.concat(c.coords);
result.currentRouteTimes = result.currentRouteTimes.concat(c.times);
}
return false;
},
r = geojson.geometry.coordinates.reduce(function(result, c, i) {
var t = geojson.properties.coordTimes[i],
timestamp = new Date(t).getTime(),
p = point(c),
candidate = result.stopCandidate,
d;
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);
candidate = result.stopCandidate = {
startTimeStamp: timestamp,
coords: [c],
times: [t]
};
result.lastPoint = p;
//candidate.coords.push(c);
//candidate.times.push(t);
} else {
result.lastPoint = point(getCenter(candidate.coords));
}
} else {
result.lastPoint = p;
}
result.lastTimestamp = timestamp;
return result;
}, {
stops: featurecollection([]),
routes: featurecollection([]),
currentRoute: [],
currentRouteTimes: [],
candidateRouteCoords: [],
candidateRouteTimes: []
});
handleCandidate(r);
handleRoute(r);
return {stops: r.stops, routes: r.routes};
};