@wemap/osm 4.0.15 → 5.0.2
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/itinerary-grenoble-otp-1.json +1536 -0
- package/assets/itinerary-grenoble-otp-2.json +1092 -0
- package/assets/itinerary-montpellier-outdoor-without-steps.json +110 -1
- package/assets/itinerary-montpellier-outdoor.json +513 -1
- package/index.js +21 -2
- package/package.json +6 -5
- package/src/routers/Itinerary.js +185 -0
- package/src/routers/Itinerary.type.spec.js +104 -0
- package/src/routers/Leg.js +101 -0
- package/src/routers/LevelChange.js +65 -0
- package/src/routers/RouterResponse.js +19 -0
- package/src/routers/RouterResponse.type.spec.js +24 -0
- package/src/routers/Step.js +113 -0
- package/src/routers/Utils.js +22 -0
- package/src/routers/custom/OsmNetworkUtils.js +194 -0
- package/src/{network → routers/custom}/OsmNetworkUtils.spec.js +13 -34
- package/src/routers/custom/OsmRouter.js +27 -0
- package/src/routers/custom/OsmRouter.spec.js +222 -0
- package/src/routers/custom/OsmRouterOptions.js +33 -0
- package/src/routers/custom/OsmRouterUtils.js +46 -0
- package/src/routers/custom/StepsGeneration.js +104 -0
- package/src/routers/info/ItineraryInfo.js +34 -0
- package/src/routers/info/ItineraryInfoManager.js +142 -0
- package/src/routers/info/ItineraryInfoManager.spec.js +54 -0
- package/src/routers/osrm/OsrmUtils.js +273 -0
- package/src/routers/osrm/OsrmUtils.spec.js +431 -0
- package/src/routers/otp/OtpUtils.js +172 -0
- package/src/routers/otp/OtpUtils.spec.js +97 -0
- package/src/network/OsmNetworkUtils.js +0 -168
- package/src/network/OsmRouter.spec.js +0 -174
- package/src/osrm/OsrmUtils.js +0 -284
- package/src/osrm/OsrmUtils.spec.js +0 -384
package/src/osrm/OsrmUtils.js
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import {
|
|
3
|
-
Level, Coordinates, Edge, Node, Itinerary, Step, Network
|
|
4
|
-
} from '@wemap/geo';
|
|
5
|
-
import {
|
|
6
|
-
rad2deg, positiveMod, diffAngle, deg2rad
|
|
7
|
-
} from '@wemap/maths';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export function coordinatesToJson(coordinates) {
|
|
11
|
-
const output = [coordinates.lng, coordinates.lat];
|
|
12
|
-
if (coordinates.level) {
|
|
13
|
-
output.push(coordinates.level.toString());
|
|
14
|
-
}
|
|
15
|
-
return output;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function jsonToCoordinates(json) {
|
|
19
|
-
const output = new Coordinates(json[1], json[0]);
|
|
20
|
-
if (json.length > 2) {
|
|
21
|
-
output.level = Level.fromString(json[2]);
|
|
22
|
-
}
|
|
23
|
-
return output;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function nodesToJsonCoords(nodes) {
|
|
27
|
-
return nodes.map(node => coordinatesToJson(node.coords));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export function getModifierFromAngle(_angle) {
|
|
32
|
-
|
|
33
|
-
const angle = positiveMod(rad2deg(_angle), 360);
|
|
34
|
-
|
|
35
|
-
if (angle > 0 && angle < 60) {
|
|
36
|
-
return 'sharp right';
|
|
37
|
-
}
|
|
38
|
-
if (angle >= 60 && angle < 140) {
|
|
39
|
-
return 'right';
|
|
40
|
-
}
|
|
41
|
-
if (angle >= 140 && angle < 160) {
|
|
42
|
-
return 'slight right';
|
|
43
|
-
}
|
|
44
|
-
if (angle >= 160 && angle <= 200) {
|
|
45
|
-
return 'straight';
|
|
46
|
-
}
|
|
47
|
-
if (angle > 200 && angle <= 220) {
|
|
48
|
-
return 'slight left';
|
|
49
|
-
}
|
|
50
|
-
if (angle > 220 && angle <= 300) {
|
|
51
|
-
return 'left';
|
|
52
|
-
}
|
|
53
|
-
if (angle > 300 && angle < 360) {
|
|
54
|
-
return 'sharp left';
|
|
55
|
-
}
|
|
56
|
-
return 'u turn';
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
export function noRouteFoundJson(message) {
|
|
61
|
-
return {
|
|
62
|
-
'code': 'NoRoute',
|
|
63
|
-
message
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @param {Itinerary} itinerary
|
|
69
|
-
* @returns {object}
|
|
70
|
-
*/
|
|
71
|
-
export function itineraryToOsrmJson(itinerary) {
|
|
72
|
-
|
|
73
|
-
const itinerarySteps = itinerary.steps;
|
|
74
|
-
const osrmSteps = [];
|
|
75
|
-
|
|
76
|
-
const lastStepId = itinerarySteps.length - 1;
|
|
77
|
-
for (let i = 0; i <= lastStepId; i++) {
|
|
78
|
-
|
|
79
|
-
const {
|
|
80
|
-
nodes, length, nextEdge, nextBearing, previousBearing, angle, node,
|
|
81
|
-
duration, levelChange, subwayEntrance, subwayEntranceRef
|
|
82
|
-
} = itinerarySteps[i];
|
|
83
|
-
|
|
84
|
-
const name = (i === lastStepId ? node.name : nextEdge.name) || '';
|
|
85
|
-
|
|
86
|
-
let type = i === 0 ? 'depart' : 'turn';
|
|
87
|
-
type = i === lastStepId ? 'arrive' : type;
|
|
88
|
-
|
|
89
|
-
const bearingBefore = positiveMod(i === 0 ? 0 : previousBearing, 2 * Math.PI);
|
|
90
|
-
const bearingAfter = positiveMod(i === lastStepId ? 0 : nextBearing, 2 * Math.PI);
|
|
91
|
-
|
|
92
|
-
const osrmStep = {
|
|
93
|
-
geometry: {
|
|
94
|
-
type: 'LineString',
|
|
95
|
-
coordinates: nodesToJsonCoords(nodes)
|
|
96
|
-
},
|
|
97
|
-
distance: length,
|
|
98
|
-
duration,
|
|
99
|
-
name,
|
|
100
|
-
maneuver: {
|
|
101
|
-
bearing_before: rad2deg(bearingBefore),
|
|
102
|
-
bearing_after: rad2deg(bearingAfter),
|
|
103
|
-
location: coordinatesToJson(node.coords),
|
|
104
|
-
type
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
if (levelChange !== null) {
|
|
109
|
-
osrmStep.levelChange = levelChange;
|
|
110
|
-
}
|
|
111
|
-
if (subwayEntrance) {
|
|
112
|
-
osrmStep.name = node.name;
|
|
113
|
-
osrmStep.subwayEntrance = true;
|
|
114
|
-
if (subwayEntranceRef) {
|
|
115
|
-
osrmStep.subwayEntranceRef = subwayEntranceRef;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// The first modifier is not mandatory by OSRM.
|
|
120
|
-
// if (i !== 0) {
|
|
121
|
-
osrmStep.maneuver.modifier = getModifierFromAngle(angle);
|
|
122
|
-
// }
|
|
123
|
-
|
|
124
|
-
osrmSteps.push(osrmStep);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
'code': 'Ok',
|
|
129
|
-
'routes': [
|
|
130
|
-
{
|
|
131
|
-
'geometry': {
|
|
132
|
-
'type': 'LineString',
|
|
133
|
-
'coordinates': nodesToJsonCoords(itinerary.nodes)
|
|
134
|
-
},
|
|
135
|
-
'legs': [
|
|
136
|
-
{
|
|
137
|
-
'duration': itinerary.duration,
|
|
138
|
-
'distance': itinerary.length,
|
|
139
|
-
'steps': osrmSteps
|
|
140
|
-
}
|
|
141
|
-
],
|
|
142
|
-
'distance': itinerary.length,
|
|
143
|
-
'duration': itinerary.duration,
|
|
144
|
-
'weight_name': 'routability',
|
|
145
|
-
'weight': 0
|
|
146
|
-
}
|
|
147
|
-
],
|
|
148
|
-
'waypoints': []
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* @param {Itinerary} itinerary
|
|
154
|
-
* @param {object} jsonSteps
|
|
155
|
-
*/
|
|
156
|
-
function _parseSteps(itinerary, jsonSteps) {
|
|
157
|
-
|
|
158
|
-
itinerary._steps = [];
|
|
159
|
-
itinerary._nextStepsIndexes = [];
|
|
160
|
-
|
|
161
|
-
let currentNodeIndex = 0;
|
|
162
|
-
|
|
163
|
-
for (let i = 0; i < jsonSteps.length; i++) {
|
|
164
|
-
const jsonStep = jsonSteps[i];
|
|
165
|
-
|
|
166
|
-
const step = new Step();
|
|
167
|
-
step.number = i + 1;
|
|
168
|
-
step.firstStep = i === 0;
|
|
169
|
-
step.lastStep = i === jsonSteps.length - 1;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Add nodes and edges to step
|
|
174
|
-
*/
|
|
175
|
-
step.nodes = [];
|
|
176
|
-
step.edges = [];
|
|
177
|
-
|
|
178
|
-
let previousNode;
|
|
179
|
-
let { coordinates } = jsonStep.geometry;
|
|
180
|
-
|
|
181
|
-
// The OSRM last step is twice the last node. So, remove the second.
|
|
182
|
-
if (step.lastStep) {
|
|
183
|
-
coordinates = [coordinates[0]];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
for (const coords of coordinates) {
|
|
187
|
-
|
|
188
|
-
const node = itinerary.nodes[currentNodeIndex];
|
|
189
|
-
step.nodes.push(node);
|
|
190
|
-
|
|
191
|
-
const isFirstNode = coordinates[0] === coords;
|
|
192
|
-
const isLastNode = coordinates[coordinates.length - 1] === coords;
|
|
193
|
-
if (isFirstNode) {
|
|
194
|
-
itinerary._nextStepsIndexes.push(i);
|
|
195
|
-
} else if (!isLastNode) {
|
|
196
|
-
itinerary._nextStepsIndexes.push(i + 1);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (previousNode) {
|
|
200
|
-
const edge = Network.getEdgeByNodes(previousNode.edges, previousNode, node);
|
|
201
|
-
step.edges.push(edge);
|
|
202
|
-
|
|
203
|
-
if (jsonStep.name) {
|
|
204
|
-
edge.name = jsonStep.name;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
previousNode = node;
|
|
209
|
-
currentNodeIndex++;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const firstStepNode = step.nodes[0];
|
|
214
|
-
if (jsonStep.subwayEntrance === true) {
|
|
215
|
-
firstStepNode.subwayEntrance = true;
|
|
216
|
-
step.subwayEntrance = true;
|
|
217
|
-
if (jsonStep.subwayEntranceRef) {
|
|
218
|
-
firstStepNode.subwayEntranceRef = jsonStep.subwayEntranceRef;
|
|
219
|
-
step.subwayEntranceRef = jsonStep.subwayEntranceRef;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Add common fields
|
|
225
|
-
*/
|
|
226
|
-
step.previousBearing = step.firstStep
|
|
227
|
-
? itinerary.start.bearingTo(itinerary.nodes[0].coords)
|
|
228
|
-
: deg2rad(jsonStep.maneuver.bearing_before);
|
|
229
|
-
step.nextBearing = step.lastStep
|
|
230
|
-
? previousNode.coords.bearingTo(itinerary.end)
|
|
231
|
-
: deg2rad(jsonStep.maneuver.bearing_after);
|
|
232
|
-
step.angle = diffAngle(step.previousBearing, step.nextBearing + Math.PI);
|
|
233
|
-
step.name = jsonStep.name;
|
|
234
|
-
step.levelChange = jsonStep.levelChange ? jsonStep.levelChange : null;
|
|
235
|
-
|
|
236
|
-
itinerary._steps.push(step);
|
|
237
|
-
|
|
238
|
-
currentNodeIndex--;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Generate Itinerary from OSRM JSON, start and end.
|
|
244
|
-
* @param {object} json JSON file provided by OSRM.
|
|
245
|
-
* @param {Coordinates} start itinerary start
|
|
246
|
-
* @param {Coordinates} end itinerary end
|
|
247
|
-
*/
|
|
248
|
-
export function createItineraryFromJson(json, start, end) {
|
|
249
|
-
const itinerary = new Itinerary();
|
|
250
|
-
|
|
251
|
-
itinerary.start = start;
|
|
252
|
-
itinerary.end = end;
|
|
253
|
-
|
|
254
|
-
const {
|
|
255
|
-
legs, geometry
|
|
256
|
-
} = json.routes[0];
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Create nodes and edges from geometry
|
|
260
|
-
*/
|
|
261
|
-
let previousNode;
|
|
262
|
-
const { coordinates } = geometry;
|
|
263
|
-
for (let i = 0; i < coordinates.length; i++) {
|
|
264
|
-
const node = new Node(jsonToCoordinates(coordinates[i]));
|
|
265
|
-
itinerary.nodes.push(node);
|
|
266
|
-
|
|
267
|
-
if (previousNode) {
|
|
268
|
-
const edge = new Edge(previousNode, node);
|
|
269
|
-
edge.level = Level.union(previousNode.coords.level, node.coords.level);
|
|
270
|
-
itinerary.edges.push(edge);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
previousNode = node;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (legs && legs[0]) {
|
|
277
|
-
const { steps } = legs[0];
|
|
278
|
-
_parseSteps(itinerary, steps);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
return itinerary;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import chai from 'chai';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
Level, Coordinates, Edge, GraphRouter
|
|
9
|
-
} from '@wemap/geo';
|
|
10
|
-
import { verifyCoherence } from '@wemap/geo/tests/CommonTest.js';
|
|
11
|
-
|
|
12
|
-
import OsmParser from '../model/OsmParser.js';
|
|
13
|
-
import OsmNetworkUtils from '../network/OsmNetworkUtils.js';
|
|
14
|
-
import {
|
|
15
|
-
itineraryToOsrmJson,
|
|
16
|
-
jsonToCoordinates,
|
|
17
|
-
createItineraryFromJson,
|
|
18
|
-
getModifierFromAngle,
|
|
19
|
-
noRouteFoundJson
|
|
20
|
-
} from './OsrmUtils.js';
|
|
21
|
-
|
|
22
|
-
const { expect } = chai;
|
|
23
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const load = fileName => {
|
|
27
|
-
const filePath = path.resolve(__dirname, '../../assets/' + fileName);
|
|
28
|
-
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
29
|
-
const model = OsmParser.parseOsmXmlString(osmXmlString);
|
|
30
|
-
const network = OsmNetworkUtils.createNetworkFromOsmModel(model);
|
|
31
|
-
const router = new GraphRouter(network);
|
|
32
|
-
return {
|
|
33
|
-
network,
|
|
34
|
-
router
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
let wemapIndoorItinerary, wemapIndoorJsonItinerary, wemapIndoorStart, wemapIndoorEnd;
|
|
39
|
-
let wemapOutdoorItinerary, wemapOutdoorJsonItinerary, wemapOutdoorStart, wemapOutdoorEnd;
|
|
40
|
-
|
|
41
|
-
describe('OsrmUtils - itineraryToOsrmJson', () => {
|
|
42
|
-
|
|
43
|
-
it('With levels (Bureaux Wemap)', () => {
|
|
44
|
-
|
|
45
|
-
const {
|
|
46
|
-
network, router
|
|
47
|
-
} = load('bureaux-wemap-montpellier-network.osm');
|
|
48
|
-
|
|
49
|
-
wemapIndoorStart = new Coordinates(43.6092754, 3.8842306, null, new Level(2));
|
|
50
|
-
wemapIndoorEnd = new Coordinates(43.6092602, 3.8842669, null, new Level(1));
|
|
51
|
-
const itinerary = router.getShortestPath(wemapIndoorStart, wemapIndoorEnd);
|
|
52
|
-
wemapIndoorItinerary = itinerary;
|
|
53
|
-
|
|
54
|
-
const osrmJson = itineraryToOsrmJson(itinerary);
|
|
55
|
-
wemapIndoorJsonItinerary = osrmJson;
|
|
56
|
-
const itinerarySteps = itinerary.steps;
|
|
57
|
-
|
|
58
|
-
const {
|
|
59
|
-
geometry, legs
|
|
60
|
-
} = osrmJson.routes[0];
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Verify if JSON geometry corresponds to Itinerary points
|
|
64
|
-
*/
|
|
65
|
-
const { coordinates } = geometry;
|
|
66
|
-
expect(coordinates.length).equal(11);
|
|
67
|
-
for (let i = 1; i < 11; i++) {
|
|
68
|
-
expect(
|
|
69
|
-
network.getNodeByName('p' + (i + 6)).coords.equalsTo(
|
|
70
|
-
jsonToCoordinates(coordinates[i]))
|
|
71
|
-
).true;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Verify location, type and modifier of each step
|
|
76
|
-
*/
|
|
77
|
-
const { steps } = legs[0];
|
|
78
|
-
for (let i = 0; i < steps.length; i++) {
|
|
79
|
-
const {
|
|
80
|
-
location, type
|
|
81
|
-
} = steps[i].maneuver;
|
|
82
|
-
expect(itinerarySteps[i].node.coords.equalsTo(jsonToCoordinates(location))).true;
|
|
83
|
-
|
|
84
|
-
let expectedType;
|
|
85
|
-
switch (i) {
|
|
86
|
-
case 0:
|
|
87
|
-
expectedType = 'depart';
|
|
88
|
-
break;
|
|
89
|
-
case steps.length - 1:
|
|
90
|
-
expectedType = 'arrive';
|
|
91
|
-
break;
|
|
92
|
-
default:
|
|
93
|
-
expectedType = 'turn';
|
|
94
|
-
}
|
|
95
|
-
expect(type).equals(expectedType);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// The first modifier is not mandatory by OSRM.
|
|
99
|
-
expect(steps[0].maneuver.modifier).equals('left');
|
|
100
|
-
expect(steps[0].distance).be.closeTo(2.33, 0.01);
|
|
101
|
-
expect(steps[0].maneuver.bearing_after).be.closeTo(11.90, 0.01);
|
|
102
|
-
|
|
103
|
-
expect(steps[1].maneuver.modifier).equals('right');
|
|
104
|
-
expect(steps[1].distance).be.closeTo(1.76, 0.01);
|
|
105
|
-
expect(steps[1].maneuver.bearing_after).be.closeTo(56.90, 0.01);
|
|
106
|
-
|
|
107
|
-
expect(steps[2].maneuver.modifier).equals('left');
|
|
108
|
-
expect(steps[2].distance).be.closeTo(1.15, 0.01);
|
|
109
|
-
expect(steps[2].maneuver.bearing_after).be.closeTo(11.90, 0.01);
|
|
110
|
-
|
|
111
|
-
expect(steps[3].maneuver.modifier).equals('left');
|
|
112
|
-
expect(steps[3].distance).be.closeTo(5.95, 0.01);
|
|
113
|
-
expect(steps[3].maneuver.bearing_after).be.closeTo(281.93, 0.01);
|
|
114
|
-
|
|
115
|
-
expect(steps[4].maneuver.modifier).equals('right');
|
|
116
|
-
expect(steps[4].distance).be.closeTo(10.71, 0.01);
|
|
117
|
-
expect(steps[4].maneuver.bearing_after).be.closeTo(12.22, 0.01);
|
|
118
|
-
expect(steps[4].levelChange).is.not.null;
|
|
119
|
-
expect(steps[4].levelChange.direction).equals('down');
|
|
120
|
-
expect(steps[4].levelChange.difference).equals(-1);
|
|
121
|
-
expect(steps[4].levelChange.type).equals('stairs');
|
|
122
|
-
|
|
123
|
-
expect(steps[5].maneuver.modifier).equals('left');
|
|
124
|
-
expect(steps[5].distance).be.closeTo(4.23, 0.01);
|
|
125
|
-
expect(steps[5].maneuver.bearing_after).be.closeTo(102.00, 0.01);
|
|
126
|
-
|
|
127
|
-
expect(steps[6].maneuver.modifier).equals('right');
|
|
128
|
-
expect(steps[6].distance).be.closeTo(5.03, 0.01);
|
|
129
|
-
expect(steps[6].maneuver.bearing_after).be.closeTo(191.75, 0.01);
|
|
130
|
-
|
|
131
|
-
expect(steps[7].maneuver.modifier).equals('left');
|
|
132
|
-
expect(steps[7].distance).be.closeTo(0, 0.01);
|
|
133
|
-
expect(steps[7].maneuver.bearing_after).be.closeTo(0, 0.01);
|
|
134
|
-
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('Without levels', () => {
|
|
138
|
-
|
|
139
|
-
const {
|
|
140
|
-
network, router
|
|
141
|
-
} = load('network-simple.osm');
|
|
142
|
-
|
|
143
|
-
const start = network.getNodeByName('p1');
|
|
144
|
-
const end = network.getNodeByName('p3');
|
|
145
|
-
|
|
146
|
-
const itinerary = router.getShortestPath(start, end);
|
|
147
|
-
|
|
148
|
-
wemapOutdoorJsonItinerary = itineraryToOsrmJson(itinerary);
|
|
149
|
-
|
|
150
|
-
wemapOutdoorStart = start.coords;
|
|
151
|
-
wemapOutdoorEnd = end.coords;
|
|
152
|
-
wemapOutdoorItinerary = itinerary;
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('Itinerary with modifiers', () => {
|
|
156
|
-
|
|
157
|
-
const {
|
|
158
|
-
network, router
|
|
159
|
-
} = load('network-with-modifiers.osm');
|
|
160
|
-
|
|
161
|
-
const start = network.getNodeByName('start');
|
|
162
|
-
const end = network.getNodeByName('end');
|
|
163
|
-
|
|
164
|
-
const itinerary = router.getShortestPath(start, end);
|
|
165
|
-
expect(() => itineraryToOsrmJson(itinerary)).not.throw(Error);
|
|
166
|
-
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
describe('OsrmUtils - createItineraryFromJson', () => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
it('Without levels (Montpellier outdoor)', () => {
|
|
176
|
-
|
|
177
|
-
const filePath = path.resolve(__dirname, '../../assets/itinerary-montpellier-outdoor.json');
|
|
178
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
179
|
-
|
|
180
|
-
const json = JSON.parse(fileString);
|
|
181
|
-
|
|
182
|
-
const start = new Coordinates(43.6007871, 3.8757218000000004);
|
|
183
|
-
const end = new Coordinates(43.598877, 3.873866);
|
|
184
|
-
|
|
185
|
-
const itinerary = createItineraryFromJson(json, start, end);
|
|
186
|
-
|
|
187
|
-
expect(json.routes[0].geometry.coordinates.length).equal(itinerary.nodes.length);
|
|
188
|
-
expect(itinerary.nodes.length).equal(itinerary.edges.length + 1);
|
|
189
|
-
expect(itinerary.nodes.length).equal(19);
|
|
190
|
-
|
|
191
|
-
const { steps } = itinerary;
|
|
192
|
-
expect(steps.length).equal(5);
|
|
193
|
-
|
|
194
|
-
let step;
|
|
195
|
-
step = steps[0];
|
|
196
|
-
expect(Coordinates.equalsTo(step.location, new Coordinates(43.600777, 3.875607))).true;
|
|
197
|
-
expect(getModifierFromAngle(step.angle)).equals('left');
|
|
198
|
-
expect(step.nodes.length).equals(6);
|
|
199
|
-
expect(step.edges.length).equals(5);
|
|
200
|
-
expect(step.firstStep).true;
|
|
201
|
-
expect(step.lastStep).false;
|
|
202
|
-
expect(step.name).equals('');
|
|
203
|
-
|
|
204
|
-
step = steps[1];
|
|
205
|
-
expect(Coordinates.equalsTo(step.location, new Coordinates(43.599881, 3.876396))).true;
|
|
206
|
-
expect(getModifierFromAngle(step.angle)).equals('right');
|
|
207
|
-
expect(step.nodes.length).equals(12);
|
|
208
|
-
expect(step.edges.length).equals(11);
|
|
209
|
-
expect(step.firstStep).false;
|
|
210
|
-
expect(step.lastStep).false;
|
|
211
|
-
expect(step.name).equals('Boulevard Vieussens');
|
|
212
|
-
|
|
213
|
-
step = steps[2];
|
|
214
|
-
expect(Coordinates.equalsTo(step.location, new Coordinates(43.599577, 3.874655))).true;
|
|
215
|
-
expect(getModifierFromAngle(step.angle)).equals('left');
|
|
216
|
-
expect(step.nodes.length).equals(2);
|
|
217
|
-
expect(step.edges.length).equals(1);
|
|
218
|
-
expect(step.firstStep).false;
|
|
219
|
-
expect(step.lastStep).false;
|
|
220
|
-
expect(step.name).equals('Impasse Bizeray');
|
|
221
|
-
|
|
222
|
-
step = steps[3];
|
|
223
|
-
expect(Coordinates.equalsTo(step.location, new Coordinates(43.599063, 3.874623))).true;
|
|
224
|
-
expect(getModifierFromAngle(step.angle)).equals('right');
|
|
225
|
-
expect(step.nodes.length).equals(2);
|
|
226
|
-
expect(step.edges.length).equals(1);
|
|
227
|
-
expect(step.firstStep).false;
|
|
228
|
-
expect(step.lastStep).false;
|
|
229
|
-
expect(step.name).equals('Rue du Docteur Louis Perrier');
|
|
230
|
-
|
|
231
|
-
step = steps[4];
|
|
232
|
-
expect(Coordinates.equalsTo(step.location, new Coordinates(43.59906, 3.873865))).true;
|
|
233
|
-
expect(getModifierFromAngle(step.angle)).equals('left');
|
|
234
|
-
expect(step.nodes.length).equals(1);
|
|
235
|
-
expect(step.edges.length).equals(0);
|
|
236
|
-
expect(step.firstStep).false;
|
|
237
|
-
expect(step.lastStep).true;
|
|
238
|
-
expect(step.name).equals('Rue du Docteur Louis Perrier');
|
|
239
|
-
|
|
240
|
-
expect(itinerary._nextStepsIndexes.length).equals(itinerary.nodes.length);
|
|
241
|
-
expect(itinerary._nextStepsIndexes[0]).equals(0);
|
|
242
|
-
for (let i = 1; i <= 5; i++) {
|
|
243
|
-
expect(itinerary._nextStepsIndexes[i]).equals(1);
|
|
244
|
-
}
|
|
245
|
-
for (let i = 6; i <= 16; i++) {
|
|
246
|
-
expect(itinerary._nextStepsIndexes[i]).equals(2);
|
|
247
|
-
}
|
|
248
|
-
expect(itinerary._nextStepsIndexes[17]).equals(3);
|
|
249
|
-
expect(itinerary._nextStepsIndexes[18]).equals(4);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
it('Without levels (from itineraryToOsrmJson)', () => {
|
|
254
|
-
|
|
255
|
-
const itinerary = createItineraryFromJson(wemapOutdoorJsonItinerary,
|
|
256
|
-
wemapOutdoorStart, wemapOutdoorEnd);
|
|
257
|
-
|
|
258
|
-
expect(itinerary.nodes.length).equal(wemapOutdoorItinerary.nodes.length);
|
|
259
|
-
for (let i = 0; i < itinerary.nodes.length; i++) {
|
|
260
|
-
const itineraryNode = itinerary.nodes[i];
|
|
261
|
-
const wemapItineraryNode = wemapOutdoorItinerary.nodes[i];
|
|
262
|
-
expect(itineraryNode.coords.equalsTo(wemapItineraryNode.coords)).true;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
expect(itinerary.edges.length).equal(wemapOutdoorItinerary.edges.length);
|
|
266
|
-
for (let i = 0; i < itinerary.edges.length; i++) {
|
|
267
|
-
const itineraryEdge = itinerary.edges[i];
|
|
268
|
-
const wemapItineraryEdge = wemapOutdoorItinerary.edges[i];
|
|
269
|
-
const firstNode = wemapItineraryEdge[wemapOutdoorItinerary._edgesDirectionReversed[i] ? 'node2' : 'node1'];
|
|
270
|
-
const secondNode = wemapItineraryEdge[wemapOutdoorItinerary._edgesDirectionReversed[i] ? 'node1' : 'node2'];
|
|
271
|
-
expect(itineraryEdge.node1.coords.equalsTo(firstNode.coords)).true;
|
|
272
|
-
expect(itineraryEdge.node2.coords.equalsTo(secondNode.coords)).true;
|
|
273
|
-
expect(Level.equalsTo(itineraryEdge.level, wemapItineraryEdge.level)).true;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('Without steps (Montpellier outdoor)', () => {
|
|
279
|
-
|
|
280
|
-
const filePath = path.resolve(__dirname,
|
|
281
|
-
'../../assets/itinerary-montpellier-outdoor-without-steps.json');
|
|
282
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
283
|
-
|
|
284
|
-
const json = JSON.parse(fileString);
|
|
285
|
-
|
|
286
|
-
const start = new Coordinates(43.6007871, 3.8757218000000004);
|
|
287
|
-
const end = new Coordinates(43.598877, 3.873866);
|
|
288
|
-
|
|
289
|
-
const itinerary = createItineraryFromJson(json, start, end);
|
|
290
|
-
|
|
291
|
-
expect(json.routes[0].geometry.coordinates.length).equal(itinerary.nodes.length);
|
|
292
|
-
expect(itinerary.nodes.length).equal(itinerary.edges.length + 1);
|
|
293
|
-
expect(itinerary.nodes.length).equal(19);
|
|
294
|
-
|
|
295
|
-
const { steps } = itinerary;
|
|
296
|
-
expect(steps.length).equal(7);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
it('With levels (from itineraryToOsrmJson)', () => {
|
|
301
|
-
|
|
302
|
-
const itinerary = createItineraryFromJson(wemapIndoorJsonItinerary,
|
|
303
|
-
wemapIndoorStart, wemapIndoorEnd);
|
|
304
|
-
|
|
305
|
-
expect(itinerary.nodes.length).equal(wemapIndoorItinerary.nodes.length);
|
|
306
|
-
for (let i = 0; i < itinerary.nodes.length; i++) {
|
|
307
|
-
const itineraryNode = itinerary.nodes[i];
|
|
308
|
-
const wemapItineraryNode = wemapIndoorItinerary.nodes[i];
|
|
309
|
-
expect(itineraryNode.coords.equalsTo(wemapItineraryNode.coords)).true;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
expect(itinerary.edges.length).equal(wemapIndoorItinerary.edges.length);
|
|
313
|
-
for (let i = 0; i < itinerary.edges.length; i++) {
|
|
314
|
-
const itineraryEdge = itinerary.edges[i];
|
|
315
|
-
const wemapItineraryEdge = wemapIndoorItinerary.edges[i];
|
|
316
|
-
const firstNode = wemapItineraryEdge[wemapIndoorItinerary._edgesDirectionReversed[i] ? 'node2' : 'node1'];
|
|
317
|
-
const secondNode = wemapItineraryEdge[wemapIndoorItinerary._edgesDirectionReversed[i] ? 'node1' : 'node2'];
|
|
318
|
-
expect(itineraryEdge.node1.coords.equalsTo(firstNode.coords)).true;
|
|
319
|
-
expect(itineraryEdge.node2.coords.equalsTo(secondNode.coords)).true;
|
|
320
|
-
expect(Level.equalsTo(itineraryEdge.level, wemapItineraryEdge.level)).true;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
it('Errored (Montpellier outdoor)', () => {
|
|
326
|
-
|
|
327
|
-
const filePath = path.resolve(__dirname,
|
|
328
|
-
'../../assets/itinerary-with-duplicate-nodes.json');
|
|
329
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
330
|
-
|
|
331
|
-
const json = JSON.parse(fileString);
|
|
332
|
-
|
|
333
|
-
const start = new Coordinates(44.810569099999995, 4.9503924999999995);
|
|
334
|
-
const end = new Coordinates(44.302673, 4.556377);
|
|
335
|
-
|
|
336
|
-
const itinerary = createItineraryFromJson(json, start, end);
|
|
337
|
-
itinerary.edges.forEach(edge => {
|
|
338
|
-
expect(edge).instanceOf(Edge);
|
|
339
|
-
});
|
|
340
|
-
itinerary.steps.forEach(step => {
|
|
341
|
-
step.edges.forEach(edge => {
|
|
342
|
-
expect(edge).instanceOf(Edge);
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
describe('OsrmUtils - itineraryToOsrmJson - createItineraryFromJson - way/node', () => {
|
|
350
|
-
|
|
351
|
-
it('With levels (Bureaux Wemap)', () => {
|
|
352
|
-
|
|
353
|
-
const { router } = load('bureaux-wemap-montpellier-network.osm');
|
|
354
|
-
|
|
355
|
-
const start = new Coordinates(43.6092754, 3.8842306, null, new Level(2));
|
|
356
|
-
const end = new Coordinates(43.60949854, 3.88452048, null, new Level(0));
|
|
357
|
-
const itinerary = router.getShortestPath(start, end);
|
|
358
|
-
|
|
359
|
-
const osrmJson = itineraryToOsrmJson(itinerary);
|
|
360
|
-
const jsonSteps = osrmJson.routes[0].legs[0].steps;
|
|
361
|
-
|
|
362
|
-
expect(jsonSteps[0].name).equals('w2');
|
|
363
|
-
expect(jsonSteps[4].name).equals('p19');
|
|
364
|
-
expect(jsonSteps[6].name).equals('p21');
|
|
365
|
-
|
|
366
|
-
const itineraryBis = createItineraryFromJson(osrmJson, start, end);
|
|
367
|
-
verifyCoherence(itineraryBis);
|
|
368
|
-
|
|
369
|
-
expect(itineraryBis.nodes.length).equals(itinerary.nodes.length);
|
|
370
|
-
expect(itineraryBis.edges.length).equals(itinerary.edges.length);
|
|
371
|
-
expect(itineraryBis.steps.length).equals(itinerary.steps.length);
|
|
372
|
-
});
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
describe('OsrmUtils - Output JSON', () => {
|
|
376
|
-
|
|
377
|
-
it('noRouteFoundJson', () => {
|
|
378
|
-
expect(noRouteFoundJson('foo')).deep.equals({
|
|
379
|
-
'code': 'NoRoute',
|
|
380
|
-
'message': 'foo'
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
});
|