forked from mapbox/osrm-isochrone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
105 lines (100 loc) · 4.81 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
var isolines = require('turf-isolines'),
grid = require('turf-grid'),
destination = require('turf-destination'),
point = require('turf-point'),
distance = require('turf-distance'),
extent = require('turf-extent'),
featureCollection = require('turf-featurecollection'),
polylineDecode = require('polyline').decode,
OSRM = require('osrm');
module.exports = function (center, time, options, done) {
if (!options) throw 'options is mandatory';
if (!options.resolution) throw 'resolution is mandatory in options';
if (!options.network) throw 'network is mandatory in options';
if (!options.maxspeed) throw 'maxspeed is mandatory in options';
var unit = options.unit || 'miles';
if (options && options.draw) {
this.draw = options.draw;
} else {
this.draw = function(destinations) {
return isolines(destinations, 'eta', options.resolution, [time]);
};
}
this.getIsochrone = function() {
var osrm = options.network instanceof OSRM ? options.network : new OSRM(options.network);
// compute bbox
// bbox should go out 1.4 miles in each direction for each minute
// this will account for a driver going a bit above the max safe speed
var centerPt = point(center[0], center[1]);
var spokes = featureCollection([]);
var length = (time/3600) * options.maxspeed;
spokes.features.push(destination(centerPt, length, 180, unit));
spokes.features.push(destination(centerPt, length, 0, unit));
spokes.features.push(destination(centerPt, length, 90, unit));
spokes.features.push(destination(centerPt, length, -90, unit));
var bbox = this.bbox = extent(spokes);
var sizeCellGrid = this.sizeCellGrid = distance(point(bbox[0], bbox[1]), point(bbox[0], bbox[3]), unit) / options.resolution;
//compute destination grid
var targets = grid(bbox, options.resolution);
targets.features = targets.features.filter(function(feat) {
return distance(point(feat.geometry.coordinates[0], feat.geometry.coordinates[1]), centerPt, unit) <= length;
});
var destinations = featureCollection([]);
var coord = targets.features.map(function(feat) {
return [feat.geometry.coordinates[1], feat.geometry.coordinates[0]]
});
osrm.table({
destinations: coord,
sources: [[center[1], center[0]]]
}, function(err, res) {
if (err) {
console.log(err);
return done(err);
}
if (res.distance_table &&
res.distance_table[0] && res.destination_coordinates &&
res.distance_table[0].length == res.destination_coordinates.length) {
res.distance_table[0].forEach(function(time, idx) {
var distanceMapped = distance(
point(coord[idx][1], coord[idx][0]),
point(res.destination_coordinates[idx][1], res.destination_coordinates[idx][0]),
unit
);
if (distanceMapped < sizeCellGrid) {
destinations.features.push({
type: 'Feature',
properties: {
eta: time / 10
},
geometry: {
type: 'Point',
coordinates: [res.destination_coordinates[idx][1], res.destination_coordinates[idx][0]]
}
});
}
// specific for isoline algorithm: exclude some points from grid
else {
destinations.features.push({
type: 'Feature',
properties: {
// this point cannot be routed => a penality 2 is applied to maxspeed
eta: time + (distanceMapped - sizeCellGrid) / (options.maxspeed / 3600) * 2
},
geometry: {
type: 'Point',
coordinates: [coord[idx][1], coord[idx][0]]
}
});
}
});
}
var result = self.draw(destinations);
return done(null, result);
}
);
};
var self = this;
// in case module is called directly
if (this.process && this.process.title == 'node')
return getIsochrone();
}