@wemap/osm 3.2.16 → 4.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 +10 -0
- package/assets/network-elevator.osm +26 -26
- package/index.js +7 -19
- package/package.json +5 -6
- package/src/model/OsmModel.js +1 -0
- package/src/model/OsmWay.js +4 -2
- package/src/network/OsmNetworkUtils.js +159 -0
- package/src/network/OsmNetworkUtils.spec.js +130 -0
- package/src/network/OsmRouter.spec.js +29 -18
- package/src/osrm/OsrmUtils.js +224 -256
- package/src/osrm/OsrmUtils.spec.js +46 -31
- package/src/network/OsmNetwork.js +0 -156
- package/src/network/OsmNetwork.spec.js +0 -107
- package/src/network/OsmRouter.js +0 -75
package/src/osrm/OsrmUtils.js
CHANGED
|
@@ -1,318 +1,286 @@
|
|
|
1
1
|
/* eslint-disable max-statements */
|
|
2
2
|
import {
|
|
3
|
-
Level, Coordinates
|
|
3
|
+
Level, Coordinates, Edge, Node, Itinerary, Step, Network
|
|
4
4
|
} from '@wemap/geo';
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
} from '@wemap/graph';
|
|
8
|
-
import {
|
|
9
|
-
rad2deg, Utils as MathUtils, diffAngle, deg2rad
|
|
6
|
+
rad2deg, positiveMod, diffAngle, deg2rad
|
|
10
7
|
} from '@wemap/maths';
|
|
11
8
|
|
|
12
|
-
import OsmNode from '../model/OsmNode.js';
|
|
13
|
-
import OsmWay from '../model/OsmWay.js';
|
|
14
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
|
+
}
|
|
15
17
|
|
|
16
|
-
|
|
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
|
+
}
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
static itineraryToOsrmJson(itinerary) {
|
|
26
|
+
export function nodesToJsonCoords(nodes) {
|
|
27
|
+
return nodes.map(node => coordinatesToJson(node.coords));
|
|
28
|
+
}
|
|
23
29
|
|
|
24
|
-
const itinerarySteps = itinerary.steps;
|
|
25
|
-
const osrmSteps = [];
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
for (let i = 0; i <= lastStepId; i++) {
|
|
31
|
+
export function getModifierFromAngle(_angle) {
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
nodes, length, nextEdgeData, nextBearing, previousBearing, angle, node,
|
|
32
|
-
duration, levelChange, edges
|
|
33
|
-
} = itinerarySteps[i];
|
|
33
|
+
const angle = positiveMod(rad2deg(_angle), 360);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
}
|
|
37
58
|
|
|
38
|
-
let type = i === 0 ? 'depart' : 'turn';
|
|
39
|
-
type = i === lastStepId ? 'arrive' : type;
|
|
40
59
|
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
export function noRouteFoundJson(message) {
|
|
61
|
+
return {
|
|
62
|
+
'code': 'NoRoute',
|
|
63
|
+
message
|
|
64
|
+
};
|
|
65
|
+
}
|
|
43
66
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
distance: length,
|
|
50
|
-
duration,
|
|
51
|
-
name,
|
|
52
|
-
maneuver: {
|
|
53
|
-
bearing_before: rad2deg(bearingBefore),
|
|
54
|
-
bearing_after: rad2deg(bearingAfter),
|
|
55
|
-
location: OsrmUtils.coordinatesToJson(node.coords),
|
|
56
|
-
type
|
|
57
|
-
},
|
|
58
|
-
wemap: {}
|
|
59
|
-
};
|
|
67
|
+
/**
|
|
68
|
+
* @param {Itinerary} itinerary
|
|
69
|
+
* @returns {object}
|
|
70
|
+
*/
|
|
71
|
+
export function itineraryToOsrmJson(itinerary) {
|
|
60
72
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
73
|
+
const itinerarySteps = itinerary.steps;
|
|
74
|
+
const osrmSteps = [];
|
|
64
75
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
id: node.data.id,
|
|
68
|
-
tags: node.data.tags
|
|
69
|
-
};
|
|
70
|
-
}
|
|
76
|
+
const lastStepId = itinerarySteps.length - 1;
|
|
77
|
+
for (let i = 0; i <= lastStepId; i++) {
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
const {
|
|
80
|
+
nodes, length, nextEdge, nextBearing, previousBearing, angle, node,
|
|
81
|
+
duration, levelChange
|
|
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
|
+
wemap: {}
|
|
107
|
+
};
|
|
90
108
|
|
|
91
|
-
|
|
109
|
+
if (levelChange !== null) {
|
|
110
|
+
osrmStep.levelChange = levelChange;
|
|
92
111
|
}
|
|
93
112
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
'geometry': {
|
|
99
|
-
'type': 'LineString',
|
|
100
|
-
'coordinates': OsrmUtils.nodesToJsonCoords(itinerary.nodes)
|
|
101
|
-
},
|
|
102
|
-
'legs': [
|
|
103
|
-
{
|
|
104
|
-
'duration': itinerary.duration,
|
|
105
|
-
'distance': itinerary.length,
|
|
106
|
-
'steps': osrmSteps
|
|
107
|
-
}
|
|
108
|
-
],
|
|
109
|
-
'distance': itinerary.length,
|
|
110
|
-
'duration': itinerary.duration,
|
|
111
|
-
'weight_name': 'routability',
|
|
112
|
-
'weight': 0
|
|
113
|
-
}
|
|
114
|
-
],
|
|
115
|
-
'waypoints': []
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Generate Itinerary from OSRM JSON, start and end.
|
|
121
|
-
* @param {object} json JSON file provided by OSRM.
|
|
122
|
-
* @param {Coordinates} start itinerary start
|
|
123
|
-
* @param {Coordinates} end itinerary end
|
|
124
|
-
*/
|
|
125
|
-
static createItineraryFromJson(json, start, end) {
|
|
126
|
-
const itinerary = new Itinerary();
|
|
113
|
+
const nodeProperties = node.extractProperties();
|
|
114
|
+
if (Object.keys(nodeProperties).length !== 0) {
|
|
115
|
+
osrmStep.wemap.nodeProperties = nodeProperties;
|
|
116
|
+
}
|
|
127
117
|
|
|
128
|
-
|
|
129
|
-
|
|
118
|
+
if (i !== lastStepId && nextEdge) {
|
|
119
|
+
const nextEdgeProperties = nextEdge.extractProperties();
|
|
120
|
+
if (Object.keys(nextEdgeProperties).length !== 0) {
|
|
121
|
+
osrmStep.wemap.nextEdgeProperties = nextEdgeProperties;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
130
124
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
125
|
+
// The first modifier is not mandatory by OSRM.
|
|
126
|
+
// if (i !== 0) {
|
|
127
|
+
osrmStep.maneuver.modifier = getModifierFromAngle(angle);
|
|
128
|
+
// }
|
|
134
129
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
*/
|
|
138
|
-
let previousNode;
|
|
139
|
-
const { coordinates } = geometry;
|
|
140
|
-
for (let i = 0; i < coordinates.length; i++) {
|
|
141
|
-
const node = new Node(OsrmUtils.jsonToCoordinates(coordinates[i]));
|
|
142
|
-
itinerary.nodes.push(node);
|
|
130
|
+
osrmSteps.push(osrmStep);
|
|
131
|
+
}
|
|
143
132
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
133
|
+
return {
|
|
134
|
+
'code': 'Ok',
|
|
135
|
+
'routes': [
|
|
136
|
+
{
|
|
137
|
+
'geometry': {
|
|
138
|
+
'type': 'LineString',
|
|
139
|
+
'coordinates': nodesToJsonCoords(itinerary.nodes)
|
|
140
|
+
},
|
|
141
|
+
'legs': [
|
|
142
|
+
{
|
|
143
|
+
'duration': itinerary.duration,
|
|
144
|
+
'distance': itinerary.length,
|
|
145
|
+
'steps': osrmSteps
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
'distance': itinerary.length,
|
|
149
|
+
'duration': itinerary.duration,
|
|
150
|
+
'weight_name': 'routability',
|
|
151
|
+
'weight': 0
|
|
148
152
|
}
|
|
153
|
+
],
|
|
154
|
+
'waypoints': []
|
|
155
|
+
};
|
|
156
|
+
}
|
|
149
157
|
|
|
150
|
-
|
|
151
|
-
}
|
|
158
|
+
function _parseSteps(itinerary, jsonSteps) {
|
|
152
159
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
OsrmUtils._parseSteps(itinerary, steps);
|
|
156
|
-
}
|
|
160
|
+
itinerary._steps = [];
|
|
161
|
+
itinerary._nextStepsIndexes = [];
|
|
157
162
|
|
|
158
|
-
|
|
159
|
-
}
|
|
163
|
+
let currentNodeIndex = 0;
|
|
160
164
|
|
|
161
|
-
|
|
165
|
+
for (let i = 0; i < jsonSteps.length; i++) {
|
|
166
|
+
const jsonStep = jsonSteps[i];
|
|
162
167
|
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
const step = new Step();
|
|
169
|
+
step.number = i + 1;
|
|
170
|
+
step.firstStep = i === 0;
|
|
171
|
+
step.lastStep = i === jsonSteps.length - 1;
|
|
165
172
|
|
|
166
|
-
let currentNodeIndex = 0;
|
|
167
173
|
|
|
168
|
-
|
|
169
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Add nodes and edges to step
|
|
176
|
+
*/
|
|
177
|
+
step.nodes = [];
|
|
178
|
+
step.edges = [];
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
step.firstStep = i === 0;
|
|
174
|
-
step.lastStep = i === jsonSteps.length - 1;
|
|
180
|
+
let previousNode;
|
|
181
|
+
let { coordinates } = jsonStep.geometry;
|
|
175
182
|
|
|
183
|
+
// The OSRM last step is twice the last node. So, remove the second.
|
|
184
|
+
if (step.lastStep) {
|
|
185
|
+
coordinates = [coordinates[0]];
|
|
186
|
+
}
|
|
176
187
|
|
|
177
|
-
|
|
178
|
-
* Add nodes and edges to step
|
|
179
|
-
*/
|
|
180
|
-
step.nodes = [];
|
|
181
|
-
step.edges = [];
|
|
188
|
+
for (const coords of coordinates) {
|
|
182
189
|
|
|
183
|
-
|
|
184
|
-
|
|
190
|
+
const node = itinerary.nodes[currentNodeIndex];
|
|
191
|
+
step.nodes.push(node);
|
|
185
192
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
193
|
+
const isFirstNode = coordinates[0] === coords;
|
|
194
|
+
const isLastNode = coordinates[coordinates.length - 1] === coords;
|
|
195
|
+
if (isFirstNode) {
|
|
196
|
+
itinerary._nextStepsIndexes.push(i);
|
|
197
|
+
} else if (!isLastNode) {
|
|
198
|
+
itinerary._nextStepsIndexes.push(i + 1);
|
|
189
199
|
}
|
|
190
200
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
201
|
+
if (previousNode) {
|
|
202
|
+
const edge = Network.getEdgeByNodes(previousNode.edges, previousNode, node);
|
|
203
|
+
step.edges.push(edge);
|
|
204
|
+
}
|
|
195
205
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
itinerary._nextStepsIndexes.push(i);
|
|
200
|
-
} else if (!isLastNode) {
|
|
201
|
-
itinerary._nextStepsIndexes.push(i + 1);
|
|
202
|
-
}
|
|
206
|
+
previousNode = node;
|
|
207
|
+
currentNodeIndex++;
|
|
208
|
+
}
|
|
203
209
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Add common fields
|
|
212
|
+
*/
|
|
213
|
+
step.previousBearing = step.firstStep
|
|
214
|
+
? itinerary.start.bearingTo(itinerary.nodes[0].coords)
|
|
215
|
+
: deg2rad(jsonStep.maneuver.bearing_before);
|
|
216
|
+
step.nextBearing = step.lastStep
|
|
217
|
+
? previousNode.coords.bearingTo(itinerary.end)
|
|
218
|
+
: deg2rad(jsonStep.maneuver.bearing_after);
|
|
219
|
+
step.angle = diffAngle(step.previousBearing, step.nextBearing + Math.PI);
|
|
220
|
+
step.name = jsonStep.name;
|
|
221
|
+
step.levelChange = jsonStep.levelChange ? jsonStep.levelChange : null;
|
|
208
222
|
|
|
209
|
-
|
|
210
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Wemap fields
|
|
225
|
+
*/
|
|
226
|
+
if (jsonStep.wemap) {
|
|
227
|
+
const firstNode = step.nodes[0];
|
|
228
|
+
if (jsonStep.wemap.nodeProperties && firstNode) {
|
|
229
|
+
firstNode.applyProperties(jsonStep.wemap.nodeProperties);
|
|
211
230
|
}
|
|
212
231
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
step.previousBearing = step.firstStep
|
|
217
|
-
? itinerary.start.bearingTo(itinerary.nodes[0].coords)
|
|
218
|
-
: deg2rad(jsonStep.maneuver.bearing_before);
|
|
219
|
-
step.nextBearing = step.lastStep
|
|
220
|
-
? previousNode.coords.bearingTo(itinerary.end)
|
|
221
|
-
: deg2rad(jsonStep.maneuver.bearing_after);
|
|
222
|
-
step.angle = diffAngle(step.previousBearing, step.nextBearing + Math.PI);
|
|
223
|
-
step.name = jsonStep.name;
|
|
224
|
-
step.levelChange = jsonStep.levelChange ? jsonStep.levelChange : null;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Wemap fields
|
|
228
|
-
*/
|
|
229
|
-
if (jsonStep.wemap) {
|
|
230
|
-
const firstNode = step.nodes[0];
|
|
231
|
-
if (jsonStep.wemap.node && firstNode) {
|
|
232
|
-
const {
|
|
233
|
-
id, tags
|
|
234
|
-
} = jsonStep.wemap.node;
|
|
235
|
-
firstNode.data = new OsmNode(id, step.nodes[0].coords, tags);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const firstEdge = step.edges[0];
|
|
239
|
-
if (jsonStep.wemap.nextEdgeData && firstEdge) {
|
|
240
|
-
const {
|
|
241
|
-
coords, id, tags, type
|
|
242
|
-
} = jsonStep.wemap.nextEdgeData;
|
|
243
|
-
if (type === 'node') {
|
|
244
|
-
firstEdge.data = new OsmNode(id, OsrmUtils.jsonToCoordinates(coords), tags);
|
|
245
|
-
} else {
|
|
246
|
-
// if (type === 'way')
|
|
247
|
-
firstEdge.data = new OsmWay(id, tags);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
firstEdge.data.level = firstEdge.level;
|
|
251
|
-
}
|
|
232
|
+
const firstEdge = step.edges[0];
|
|
233
|
+
if (jsonStep.wemap.nextEdgeProperties && firstEdge) {
|
|
234
|
+
firstEdge.applyProperties(jsonStep.wemap.nextEdgeProperties);
|
|
252
235
|
}
|
|
236
|
+
}
|
|
253
237
|
|
|
254
|
-
|
|
238
|
+
itinerary._steps.push(step);
|
|
255
239
|
|
|
256
|
-
|
|
257
|
-
}
|
|
240
|
+
currentNodeIndex--;
|
|
258
241
|
}
|
|
242
|
+
}
|
|
259
243
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
244
|
+
/**
|
|
245
|
+
* Generate Itinerary from OSRM JSON, start and end.
|
|
246
|
+
* @param {object} json JSON file provided by OSRM.
|
|
247
|
+
* @param {Coordinates} start itinerary start
|
|
248
|
+
* @param {Coordinates} end itinerary end
|
|
249
|
+
*/
|
|
250
|
+
export function createItineraryFromJson(json, start, end) {
|
|
251
|
+
const itinerary = new Itinerary();
|
|
263
252
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
if (angle >= 60 && angle < 140) {
|
|
268
|
-
return 'right';
|
|
269
|
-
}
|
|
270
|
-
if (angle >= 140 && angle < 160) {
|
|
271
|
-
return 'slight right';
|
|
272
|
-
}
|
|
273
|
-
if (angle >= 160 && angle <= 200) {
|
|
274
|
-
return 'straight';
|
|
275
|
-
}
|
|
276
|
-
if (angle > 200 && angle <= 220) {
|
|
277
|
-
return 'slight left';
|
|
278
|
-
}
|
|
279
|
-
if (angle > 220 && angle <= 300) {
|
|
280
|
-
return 'left';
|
|
281
|
-
}
|
|
282
|
-
if (angle > 300 && angle < 360) {
|
|
283
|
-
return 'sharp left';
|
|
284
|
-
}
|
|
285
|
-
return 'u turn';
|
|
286
|
-
}
|
|
253
|
+
itinerary.start = start;
|
|
254
|
+
itinerary.end = end;
|
|
287
255
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
output.push(coordinates.level.toString());
|
|
292
|
-
}
|
|
293
|
-
return output;
|
|
294
|
-
}
|
|
256
|
+
const {
|
|
257
|
+
legs, geometry
|
|
258
|
+
} = json.routes[0];
|
|
295
259
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
260
|
+
/**
|
|
261
|
+
* Create nodes and edges from geometry
|
|
262
|
+
*/
|
|
263
|
+
let previousNode;
|
|
264
|
+
const { coordinates } = geometry;
|
|
265
|
+
for (let i = 0; i < coordinates.length; i++) {
|
|
266
|
+
const node = new Node(jsonToCoordinates(coordinates[i]));
|
|
267
|
+
itinerary.nodes.push(node);
|
|
268
|
+
|
|
269
|
+
if (previousNode) {
|
|
270
|
+
const edge = new Edge(previousNode, node);
|
|
271
|
+
edge.level = Level.union(previousNode.coords.level, node.coords.level);
|
|
272
|
+
itinerary.edges.push(edge);
|
|
300
273
|
}
|
|
301
|
-
return output;
|
|
302
|
-
}
|
|
303
274
|
|
|
304
|
-
|
|
305
|
-
return nodes.map(node => OsrmUtils.coordinatesToJson(node.coords));
|
|
275
|
+
previousNode = node;
|
|
306
276
|
}
|
|
307
277
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
'code': 'NoRoute',
|
|
312
|
-
message
|
|
313
|
-
};
|
|
278
|
+
if (legs && legs[0]) {
|
|
279
|
+
const { steps } = legs[0];
|
|
280
|
+
_parseSteps(itinerary, steps);
|
|
314
281
|
}
|
|
315
282
|
|
|
283
|
+
return itinerary;
|
|
316
284
|
}
|
|
317
285
|
|
|
318
|
-
|
|
286
|
+
|