@wemap/routers 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/bureaux-wemap-montpellier-network.osm +162 -0
- package/assets/gare-de-lyon-extract.osm +174 -0
- package/assets/itinerary-deutsche-bahn-1.json +368 -0
- package/assets/itinerary-grenoble-otp-1.json +1536 -0
- package/assets/itinerary-grenoble-otp-2.json +1092 -0
- package/assets/itinerary-lehavre-cityway-1.json +6799 -0
- package/assets/itinerary-lehavre-cityway-2.json +2133 -0
- package/assets/itinerary-lehavre-cityway-3.json +12577 -0
- package/assets/itinerary-lehavre-cityway-4.json +1451 -0
- package/assets/itinerary-lehavre-cityway-5.json +5925 -0
- package/assets/itinerary-montpellier-osrm-3.json +1 -0
- package/assets/itinerary-montpellier-outdoor-without-steps.json +110 -0
- package/assets/itinerary-montpellier-outdoor.json +513 -0
- package/assets/itinerary-with-duplicate-nodes.json +110 -0
- package/assets/network-conveying-backward.osm +74 -0
- package/assets/network-elevator.osm +48 -0
- package/assets/network-simple.osm +27 -0
- package/assets/network-with-modifiers.osm +39 -0
- package/assets/one-way.osm +46 -0
- package/dist/wemap-osm.es.js +2012 -0
- package/dist/wemap-osm.es.js.map +1 -0
- package/index.js +24 -0
- package/package.json +35 -0
- package/src/ItineraryInfoManager.js +148 -0
- package/src/ItineraryInfoManager.spec.js +54 -0
- package/src/Utils.js +64 -0
- package/src/cityway/CitywayUtils.js +240 -0
- package/src/cityway/CitywayUtils.spec.js +109 -0
- package/src/deutsche-bahn/DeutscheBahnRouterUtils.js +91 -0
- package/src/deutsche-bahn/DeutscheBahnRouterUtils.spec.js +54 -0
- package/src/model/Itinerary.js +197 -0
- package/src/model/Itinerary.type.spec.js +105 -0
- package/src/model/ItineraryInfo.js +34 -0
- package/src/model/Leg.js +113 -0
- package/src/model/LevelChange.js +65 -0
- package/src/model/RouterResponse.js +19 -0
- package/src/model/RouterResponse.type.spec.js +24 -0
- package/src/model/Step.js +118 -0
- package/src/osrm/OsrmUtils.js +269 -0
- package/src/osrm/OsrmUtils.spec.js +457 -0
- package/src/otp/OtpUtils.js +150 -0
- package/src/otp/OtpUtils.spec.js +97 -0
- package/src/wemap/WemapNetworkUtils.js +195 -0
- package/src/wemap/WemapNetworkUtils.spec.js +109 -0
- package/src/wemap/WemapRouter.js +27 -0
- package/src/wemap/WemapRouter.spec.js +221 -0
- package/src/wemap/WemapRouterOptions.js +32 -0
- package/src/wemap/WemapRouterUtils.js +46 -0
- package/src/wemap/WemapStepsGeneration.js +104 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
|
|
3
|
+
import { Level, Coordinates } from '@wemap/geo';
|
|
4
|
+
import { rad2deg, positiveMod } from '@wemap/maths';
|
|
5
|
+
|
|
6
|
+
import Itinerary from '../model/Itinerary.js';
|
|
7
|
+
import Leg from '../model/Leg.js';
|
|
8
|
+
import LevelChange from '../model/LevelChange.js';
|
|
9
|
+
import RouterResponse from '../model/RouterResponse.js';
|
|
10
|
+
import Step from '../model/Step.js';
|
|
11
|
+
import { generateStepsMetadata } from '../Utils.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Coordinates} coordinates
|
|
15
|
+
* @returns {object}
|
|
16
|
+
*/
|
|
17
|
+
export function coordinatesToJson(coordinates) {
|
|
18
|
+
const output = [coordinates.lng, coordinates.lat];
|
|
19
|
+
if (coordinates.level) {
|
|
20
|
+
output.push(coordinates.level.toString());
|
|
21
|
+
}
|
|
22
|
+
return output;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {object} json
|
|
27
|
+
* @returns {Coordinates}
|
|
28
|
+
*/
|
|
29
|
+
export function jsonToCoordinates(json) {
|
|
30
|
+
const output = new Coordinates(json[1], json[0]);
|
|
31
|
+
if (json.length > 2) {
|
|
32
|
+
output.level = Level.fromString(json[2]);
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function nodesToJsonCoords(nodes) {
|
|
38
|
+
return nodes.map(node => coordinatesToJson(node.coords));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
export function getModifierFromAngle(_angle) {
|
|
43
|
+
|
|
44
|
+
const angle = positiveMod(rad2deg(_angle), 360);
|
|
45
|
+
|
|
46
|
+
if (angle > 0 && angle < 60) {
|
|
47
|
+
return 'sharp right';
|
|
48
|
+
}
|
|
49
|
+
if (angle >= 60 && angle < 140) {
|
|
50
|
+
return 'right';
|
|
51
|
+
}
|
|
52
|
+
if (angle >= 140 && angle < 160) {
|
|
53
|
+
return 'slight right';
|
|
54
|
+
}
|
|
55
|
+
if (angle >= 160 && angle <= 200) {
|
|
56
|
+
return 'straight';
|
|
57
|
+
}
|
|
58
|
+
if (angle > 200 && angle <= 220) {
|
|
59
|
+
return 'slight left';
|
|
60
|
+
}
|
|
61
|
+
if (angle > 220 && angle <= 300) {
|
|
62
|
+
return 'left';
|
|
63
|
+
}
|
|
64
|
+
if (angle > 300 && angle < 360) {
|
|
65
|
+
return 'sharp left';
|
|
66
|
+
}
|
|
67
|
+
return 'u turn';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
export function noRouteFoundJson(message) {
|
|
72
|
+
return {
|
|
73
|
+
'code': 'NoRoute',
|
|
74
|
+
message
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {Itinerary} itinerary
|
|
80
|
+
* @returns {object}
|
|
81
|
+
*/
|
|
82
|
+
export function itineraryToOsrmJson(itinerary) {
|
|
83
|
+
|
|
84
|
+
const lastLegId = itinerary.legs.length - 1;
|
|
85
|
+
|
|
86
|
+
const jsonLegs = itinerary.legs.map(({ distance, duration, coords, steps }, idLeg) => {
|
|
87
|
+
|
|
88
|
+
const lastStepId = steps.length - 1;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
distance,
|
|
92
|
+
duration,
|
|
93
|
+
steps: steps.map((step, idStep, arr) => {
|
|
94
|
+
|
|
95
|
+
let type = idStep === 0 && idLeg === 0 ? 'depart' : 'turn';
|
|
96
|
+
type = idStep === lastStepId && idLeg === lastLegId ? 'arrive' : type;
|
|
97
|
+
|
|
98
|
+
const stepCoordsIdx = coords.findIndex(p => p.equalsTo(step.coords));
|
|
99
|
+
const nextStepCoordsIdx = idStep === lastStepId
|
|
100
|
+
? stepCoordsIdx
|
|
101
|
+
: coords.findIndex(p => p.equalsTo(arr[idStep + 1].coords));
|
|
102
|
+
|
|
103
|
+
const jsonStep = {
|
|
104
|
+
geometry: {
|
|
105
|
+
type: 'LineString',
|
|
106
|
+
coordinates: coords.slice(stepCoordsIdx, nextStepCoordsIdx + 1).map(coordinatesToJson)
|
|
107
|
+
},
|
|
108
|
+
distance: step.distance,
|
|
109
|
+
duration: step.duration,
|
|
110
|
+
name: step.name,
|
|
111
|
+
maneuver: {
|
|
112
|
+
bearing_before: rad2deg(step.previousBearing),
|
|
113
|
+
bearing_after: rad2deg(step.nextBearing),
|
|
114
|
+
location: coordinatesToJson(step.coords),
|
|
115
|
+
modifier: getModifierFromAngle(step.angle),
|
|
116
|
+
type
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
if (step.levelChange !== null) {
|
|
120
|
+
jsonStep.levelChange = step.levelChange.toJson();
|
|
121
|
+
}
|
|
122
|
+
if (typeof step.extras === 'object' && Object.keys(step.extras).length !== 0) {
|
|
123
|
+
jsonStep.extras = step.extras;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return jsonStep;
|
|
127
|
+
})
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
'code': 'Ok',
|
|
133
|
+
'routes': [
|
|
134
|
+
{
|
|
135
|
+
'geometry': {
|
|
136
|
+
'type': 'LineString',
|
|
137
|
+
'coordinates': itinerary.coords.map(coordinatesToJson)
|
|
138
|
+
},
|
|
139
|
+
'legs': jsonLegs,
|
|
140
|
+
'distance': itinerary.distance,
|
|
141
|
+
'duration': itinerary.duration,
|
|
142
|
+
'weight_name': 'routability',
|
|
143
|
+
'weight': 0
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
'waypoints': []
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @param {object} jsonSteps
|
|
153
|
+
* @param {Coordinates[]} legCoords
|
|
154
|
+
* @returns {Step[]}
|
|
155
|
+
*/
|
|
156
|
+
function parseJsonSteps(jsonSteps, legCoords) {
|
|
157
|
+
|
|
158
|
+
if (!jsonSteps) {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return jsonSteps.map(jsonStep => {
|
|
163
|
+
|
|
164
|
+
const step = new Step();
|
|
165
|
+
step.coords = jsonToCoordinates(jsonStep.maneuver.location);
|
|
166
|
+
|
|
167
|
+
// Sometimes, OSRM step does not have the same coordinates than a point in legCoords.
|
|
168
|
+
// ex: first step of https://routing.getwemap.com/route/v1/walking/2.33222164147,48.87084765712;2.3320734,48.8730212?geometries=geojson&overview=full&steps=true
|
|
169
|
+
// That is why we look for the closest point.
|
|
170
|
+
const distances = legCoords.map(coords => coords.distanceTo(step.coords));
|
|
171
|
+
const idStepCoordsInLeg = distances.indexOf(Math.min(...distances));
|
|
172
|
+
if (idStepCoordsInLeg < 0) {
|
|
173
|
+
throw new Error('Osrm Parser: Cannot find step coords in leg coordinates');
|
|
174
|
+
}
|
|
175
|
+
step._idCoordsInLeg = idStepCoordsInLeg;
|
|
176
|
+
|
|
177
|
+
step.name = jsonStep.name;
|
|
178
|
+
step.levelChange = jsonStep.levelChange ? LevelChange.fromJson(jsonStep.levelChange) : null;
|
|
179
|
+
|
|
180
|
+
step.distance = jsonStep.distance;
|
|
181
|
+
step.duration = jsonStep.duration;
|
|
182
|
+
|
|
183
|
+
if (jsonStep.extras && jsonStep.extras.subwayEntrance) {
|
|
184
|
+
step.extras.subwayEntrance = true;
|
|
185
|
+
if (jsonStep.extras.subwayEntranceRef) {
|
|
186
|
+
step.extras.subwayEntranceRef = jsonStep.extras.subwayEntranceRef;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return step;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Generate multi itineraries from OSRM JSON
|
|
197
|
+
* @param {object} json JSON file provided by OSRM.
|
|
198
|
+
* @param {Coordinates} from itinerary start
|
|
199
|
+
* @param {Coordinates} to itinerary end
|
|
200
|
+
* @param {?string} routingMode [walking|driving|bicycle]
|
|
201
|
+
* @returns {?RouterResponse}
|
|
202
|
+
*/
|
|
203
|
+
export function createRouterResponseFromJson(json, from, to, routingMode = 'walking') {
|
|
204
|
+
|
|
205
|
+
const { routes: jsonRoutes } = json;
|
|
206
|
+
|
|
207
|
+
if (!jsonRoutes) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const routingModeCorrespondance = new Map();
|
|
212
|
+
routingModeCorrespondance.set('walking', 'WALK');
|
|
213
|
+
routingModeCorrespondance.set('driving', 'CAR');
|
|
214
|
+
routingModeCorrespondance.set('bicycle', 'BIKE');
|
|
215
|
+
const mode = routingModeCorrespondance.get(routingMode) || null;
|
|
216
|
+
|
|
217
|
+
const routerResponse = new RouterResponse();
|
|
218
|
+
routerResponse.routerName = 'osrm';
|
|
219
|
+
|
|
220
|
+
routerResponse.from = from;
|
|
221
|
+
routerResponse.to = to;
|
|
222
|
+
|
|
223
|
+
for (const jsonItinerary of jsonRoutes) {
|
|
224
|
+
|
|
225
|
+
const itinerary = new Itinerary();
|
|
226
|
+
|
|
227
|
+
// itinerary.coords = jsonItinerary.geometry.coordinates.map(jsonToCoordinates);
|
|
228
|
+
itinerary.distance = jsonItinerary.distance;
|
|
229
|
+
itinerary.duration = jsonItinerary.duration;
|
|
230
|
+
itinerary.from = from;
|
|
231
|
+
itinerary.to = to;
|
|
232
|
+
|
|
233
|
+
routerResponse.itineraries.push(itinerary);
|
|
234
|
+
|
|
235
|
+
for (const jsonLeg of jsonItinerary.legs) {
|
|
236
|
+
|
|
237
|
+
const leg = new Leg();
|
|
238
|
+
|
|
239
|
+
leg.mode = mode;
|
|
240
|
+
leg.distance = jsonLeg.distance;
|
|
241
|
+
leg.duration = jsonLeg.duration;
|
|
242
|
+
|
|
243
|
+
leg.coords = jsonLeg.steps
|
|
244
|
+
.map(step => step.geometry.coordinates.map(jsonToCoordinates))
|
|
245
|
+
.flat()
|
|
246
|
+
// Remove duplicates
|
|
247
|
+
.filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equalsTo(coords));
|
|
248
|
+
|
|
249
|
+
leg.from = {
|
|
250
|
+
name: null,
|
|
251
|
+
coords: leg.coords[0]
|
|
252
|
+
};
|
|
253
|
+
leg.to = {
|
|
254
|
+
name: null,
|
|
255
|
+
coords: leg.coords[leg.coords.length - 1]
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
leg.steps = parseJsonSteps(jsonLeg.steps, leg.coords);
|
|
259
|
+
|
|
260
|
+
itinerary.legs.push(leg);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// All legs have to be parsed before computing steps metadata
|
|
264
|
+
generateStepsMetadata(itinerary);
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return routerResponse;
|
|
269
|
+
}
|