@wemap/geo 4.0.13 → 5.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/index.js +18 -11
- package/package.json +4 -4
- package/src/Utils.spec.js +38 -0
- package/src/graph/{Edge.js → GraphEdge.js} +33 -94
- package/src/graph/GraphEdge.spec.js +91 -0
- package/src/graph/{Node.js → GraphNode.js} +29 -67
- package/src/graph/GraphNode.spec.js +203 -0
- package/src/graph/{Projection.js → GraphProjection.js} +4 -4
- package/src/graph/GraphUtils.js +17 -0
- package/src/graph/MapMatching.js +7 -5
- package/src/graph/MapMatching.spec.js +26 -26
- package/src/graph/Network.js +85 -48
- package/src/graph/Network.spec.js +66 -15
- package/src/router/GraphItinerary.js +70 -0
- package/src/router/GraphItinerary.spec.js +18 -0
- package/src/{graph → router}/GraphRouter.js +52 -52
- package/src/{graph → router}/GraphRouter.spec.js +54 -96
- package/src/router/GraphRouterOptions.js +19 -0
- package/src/{graph → router}/NoRouteFoundError.js +1 -1
- package/tests/CommonTest.js +6 -6
- package/src/graph/Edge.spec.js +0 -131
- package/src/graph/Itinerary.js +0 -529
- package/src/graph/Itinerary.spec.js +0 -811
- package/src/graph/ItineraryInfo.js +0 -29
- package/src/graph/LevelChange.js +0 -43
- package/src/graph/Node.spec.js +0 -227
- package/src/graph/Step.js +0 -99
- package/src/graph/StepsGeneration.js +0 -119
- package/src/graph/Utils.js +0 -7
package/src/graph/Itinerary.js
DELETED
|
@@ -1,529 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import Coordinates from '../coordinates/Coordinates.js';
|
|
3
|
-
import Level from '../coordinates/Level.js';
|
|
4
|
-
|
|
5
|
-
import Edge from './Edge.js';
|
|
6
|
-
import ItineraryInfo from './ItineraryInfo.js';
|
|
7
|
-
import MapMatching from './MapMatching.js';
|
|
8
|
-
import Network from './Network.js';
|
|
9
|
-
import Node from './Node.js';
|
|
10
|
-
import Step from './Step.js';
|
|
11
|
-
import StepsGeneration from './StepsGeneration.js';
|
|
12
|
-
import { getDurationFromLength } from './Utils.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Main attributes are:
|
|
16
|
-
* nodes: the ordered list of Node
|
|
17
|
-
* edges: the ordered list of Edge
|
|
18
|
-
* start: the start point (Coordinates)
|
|
19
|
-
* end: the end point (Coordinates)
|
|
20
|
-
* length: the route length
|
|
21
|
-
*/
|
|
22
|
-
class Itinerary extends Network {
|
|
23
|
-
|
|
24
|
-
/** @type {?Coordinates} */
|
|
25
|
-
start;
|
|
26
|
-
|
|
27
|
-
/** @type {?Coordinates} */
|
|
28
|
-
end;
|
|
29
|
-
|
|
30
|
-
/** @type {?Step[]} */
|
|
31
|
-
_steps;
|
|
32
|
-
|
|
33
|
-
/** @type {number} */
|
|
34
|
-
_length;
|
|
35
|
-
|
|
36
|
-
/** @type {boolean[]} */
|
|
37
|
-
_edgesDirectionReversed;
|
|
38
|
-
|
|
39
|
-
/** @type {number[]} */
|
|
40
|
-
_nextStepsIndexes;
|
|
41
|
-
|
|
42
|
-
/** @type {MapMatching} */
|
|
43
|
-
_mapMatching;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @param {Node[]} nodes
|
|
47
|
-
* @param {Edge[]} edges
|
|
48
|
-
*/
|
|
49
|
-
constructor(nodes, edges) {
|
|
50
|
-
super(nodes, edges);
|
|
51
|
-
this.start = null;
|
|
52
|
-
this.end = null;
|
|
53
|
-
this._steps = null;
|
|
54
|
-
this._length = 0;
|
|
55
|
-
|
|
56
|
-
// This array is for computational time gain only
|
|
57
|
-
// It helps to know if this.edges is in the same direction than the current itinerary
|
|
58
|
-
// true = opposite direction
|
|
59
|
-
// false = same direction
|
|
60
|
-
// if this.edgeDirectionReversed[i] is true, this.edges[i].node2 is before
|
|
61
|
-
// this.edges[i].node1 following the current itinerary
|
|
62
|
-
this._edgesDirectionReversed = new Array(edges ? edges.length : 0);
|
|
63
|
-
|
|
64
|
-
// This array is for computational time gain only
|
|
65
|
-
// It helps to find next and previous steps by storing next steps indexes for each node
|
|
66
|
-
// The size of this array is the same than this.nodes
|
|
67
|
-
this._nextStepsIndexes = null;
|
|
68
|
-
|
|
69
|
-
this._mapMatching = new MapMatching(this);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Get route length
|
|
74
|
-
* @type {number}
|
|
75
|
-
*/
|
|
76
|
-
get length() {
|
|
77
|
-
if (!this._length) {
|
|
78
|
-
this._length = this.edges.reduce((acc, edge) => acc + edge.length, 0);
|
|
79
|
-
}
|
|
80
|
-
return this._length;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get route duration with default speed
|
|
85
|
-
* @type {number}
|
|
86
|
-
*/
|
|
87
|
-
get duration() {
|
|
88
|
-
return this.getDuration();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Get route duration
|
|
93
|
-
* @param {number} speed in km/h
|
|
94
|
-
*/
|
|
95
|
-
getDuration(speed) {
|
|
96
|
-
return getDurationFromLength(this.length, speed);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** @type {Step[]} */
|
|
100
|
-
get steps() {
|
|
101
|
-
if (!this._steps) {
|
|
102
|
-
const {
|
|
103
|
-
steps, nextStepsIndexes
|
|
104
|
-
} = StepsGeneration.fromItinerary(this);
|
|
105
|
-
this._steps = steps;
|
|
106
|
-
this._nextStepsIndexes = nextStepsIndexes;
|
|
107
|
-
}
|
|
108
|
-
return this._steps;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Get edge at given distance
|
|
113
|
-
* @param {number} distance
|
|
114
|
-
* @returns {Edge} the edge or null if not exists
|
|
115
|
-
*/
|
|
116
|
-
getEdgeAt(distance) {
|
|
117
|
-
|
|
118
|
-
if (distance === 0 && this.edges.length > 0) {
|
|
119
|
-
return this.edges[0];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
let sum = 0;
|
|
123
|
-
for (let i = 0; i < this.edges.length; i++) {
|
|
124
|
-
sum += this.edges[i].length;
|
|
125
|
-
if (distance <= sum) {
|
|
126
|
-
return this.edges[i];
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* @param {Edge|Node} graphElement
|
|
134
|
-
* @returns {Node}
|
|
135
|
-
*/
|
|
136
|
-
getNextNode(graphElement) {
|
|
137
|
-
if (graphElement instanceof Edge) {
|
|
138
|
-
const indexOfEdge = this.edges.indexOf(graphElement);
|
|
139
|
-
if (indexOfEdge !== -1) {
|
|
140
|
-
return this.nodes[indexOfEdge + 1];
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (graphElement instanceof Node) {
|
|
145
|
-
const indexOfNode = this.nodes.indexOf(graphElement);
|
|
146
|
-
if (indexOfNode !== -1 && indexOfNode !== this.nodes.length - 1) {
|
|
147
|
-
return this.nodes[indexOfNode + 1];
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* @param {Edge|Node} graphElement
|
|
155
|
-
* @returns {Edge}
|
|
156
|
-
*/
|
|
157
|
-
getNextEdge(graphElement) {
|
|
158
|
-
if (graphElement instanceof Edge) {
|
|
159
|
-
const indexOfEdge = this.edges.indexOf(graphElement);
|
|
160
|
-
if (indexOfEdge !== -1 && indexOfEdge !== this.edges.length - 1) {
|
|
161
|
-
return this.edges[indexOfEdge + 1];
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (graphElement instanceof Node) {
|
|
166
|
-
const indexOfNode = this.nodes.indexOf(graphElement);
|
|
167
|
-
if (indexOfNode !== -1 && indexOfNode !== this.edges.length) {
|
|
168
|
-
return this.edges[indexOfNode];
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @param {Edge|Node} graphElement
|
|
176
|
-
* @returns {Step}
|
|
177
|
-
*/
|
|
178
|
-
getNextStep(graphElement) {
|
|
179
|
-
|
|
180
|
-
if (graphElement instanceof Edge) {
|
|
181
|
-
const indexOfEdge = this.edges.indexOf(graphElement);
|
|
182
|
-
if (indexOfEdge !== -1) {
|
|
183
|
-
return this._getNextStepFromEdgeId(indexOfEdge);
|
|
184
|
-
}
|
|
185
|
-
} else if (graphElement instanceof Node) {
|
|
186
|
-
const indexOfNode = this.nodes.indexOf(graphElement);
|
|
187
|
-
if (indexOfNode !== -1) {
|
|
188
|
-
return this._getNextStepFromNodeId(indexOfNode);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* @param {number} edgeId
|
|
196
|
-
* @returns {Step}
|
|
197
|
-
*/
|
|
198
|
-
_getNextStepFromEdgeId(edgeId) {
|
|
199
|
-
return this.steps[this._nextStepsIndexes[edgeId + 1]];
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* @param {number} nodeId
|
|
204
|
-
* @returns {Step}
|
|
205
|
-
*/
|
|
206
|
-
_getNextStepFromNodeId(nodeId) {
|
|
207
|
-
return this.steps[this._nextStepsIndexes[nodeId]];
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* @param {Edge|Node} graphElement
|
|
212
|
-
* @returns {Step}
|
|
213
|
-
*/
|
|
214
|
-
getPreviousStep(graphElement) {
|
|
215
|
-
|
|
216
|
-
if (graphElement instanceof Edge) {
|
|
217
|
-
const indexOfEdge = this.edges.indexOf(graphElement);
|
|
218
|
-
if (indexOfEdge !== -1) {
|
|
219
|
-
return this._getPreviousStepFromEdgeId(indexOfEdge);
|
|
220
|
-
}
|
|
221
|
-
} else if (graphElement instanceof Node) {
|
|
222
|
-
const indexOfNode = this.nodes.indexOf(graphElement);
|
|
223
|
-
if (indexOfNode !== -1) {
|
|
224
|
-
return this._getPreviousStepFromNodeId(indexOfNode);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return null;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* @param {number} edgeId
|
|
232
|
-
* @returns {Step}
|
|
233
|
-
*/
|
|
234
|
-
_getPreviousStepFromEdgeId(edgeId) {
|
|
235
|
-
const previousStepId = this._nextStepsIndexes[edgeId + 1] - 1;
|
|
236
|
-
return this.steps[previousStepId];
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* @param {number} nodeId
|
|
241
|
-
* @returns {Step}
|
|
242
|
-
*/
|
|
243
|
-
_getPreviousStepFromNodeId(nodeId) {
|
|
244
|
-
const previousStepId = this._nextStepsIndexes[nodeId] - 1;
|
|
245
|
-
if (previousStepId !== -1) {
|
|
246
|
-
return this.steps[previousStepId];
|
|
247
|
-
}
|
|
248
|
-
return null;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* @param {Coordinates} position
|
|
253
|
-
* @returns {ItineraryInfo}
|
|
254
|
-
*/
|
|
255
|
-
getInfo(position) {
|
|
256
|
-
|
|
257
|
-
if (!(position instanceof Coordinates)) {
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const projection = this._mapMatching.getProjection(position);
|
|
262
|
-
if (!projection) {
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const totalDistance = this.length;
|
|
267
|
-
let traveledDistance = 0;
|
|
268
|
-
let nextStep, previousStep;
|
|
269
|
-
|
|
270
|
-
if (projection.nearestElement instanceof Node) {
|
|
271
|
-
|
|
272
|
-
let currentNodeIndex = 0;
|
|
273
|
-
while (this.nodes[currentNodeIndex] !== projection.nearestElement) {
|
|
274
|
-
traveledDistance += this.edges[currentNodeIndex].length;
|
|
275
|
-
currentNodeIndex++;
|
|
276
|
-
}
|
|
277
|
-
nextStep = this._getNextStepFromNodeId(currentNodeIndex);
|
|
278
|
-
previousStep = this._getPreviousStepFromNodeId(currentNodeIndex);
|
|
279
|
-
|
|
280
|
-
} else {
|
|
281
|
-
// if (projection.nearestElement instanceof Edge)
|
|
282
|
-
let currentEdgeIndex = 0;
|
|
283
|
-
while (this.edges[currentEdgeIndex] !== projection.nearestElement) {
|
|
284
|
-
traveledDistance += this.edges[currentEdgeIndex].length;
|
|
285
|
-
currentEdgeIndex++;
|
|
286
|
-
}
|
|
287
|
-
traveledDistance += this.nodes[currentEdgeIndex].coords
|
|
288
|
-
.distanceTo(projection.projection);
|
|
289
|
-
nextStep = this._getNextStepFromEdgeId(currentEdgeIndex);
|
|
290
|
-
previousStep = this._getPreviousStepFromEdgeId(currentEdgeIndex);
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const itineraryInfo = new ItineraryInfo();
|
|
295
|
-
return Object.assign(itineraryInfo, {
|
|
296
|
-
nextStep,
|
|
297
|
-
previousStep,
|
|
298
|
-
projection,
|
|
299
|
-
traveledDistance,
|
|
300
|
-
traveledPercentage: traveledDistance / totalDistance,
|
|
301
|
-
remainingDistance: totalDistance - traveledDistance,
|
|
302
|
-
remainingPercentage: 1 - traveledDistance / totalDistance
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
static fromNetworkNodes(nodes, start, end) {
|
|
307
|
-
|
|
308
|
-
/**
|
|
309
|
-
* Itinerary part of network is cloned and ordered
|
|
310
|
-
*/
|
|
311
|
-
|
|
312
|
-
const itinerary = new Itinerary();
|
|
313
|
-
itinerary._length = 0;
|
|
314
|
-
itinerary.start = start;
|
|
315
|
-
itinerary.end = end;
|
|
316
|
-
|
|
317
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
318
|
-
|
|
319
|
-
const networkNode = nodes[i];
|
|
320
|
-
|
|
321
|
-
itinerary.nodes.push(networkNode);
|
|
322
|
-
|
|
323
|
-
if (i === nodes.length - 1) {
|
|
324
|
-
break;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const nextNetworkNode = nodes[i + 1];
|
|
328
|
-
const networkEdge = Network.getEdgeByNodes(networkNode.edges, networkNode, nextNetworkNode);
|
|
329
|
-
itinerary._edgesDirectionReversed.push(networkNode !== networkEdge.node1);
|
|
330
|
-
|
|
331
|
-
itinerary.edges.push(networkEdge);
|
|
332
|
-
itinerary._length += networkEdge.length;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return itinerary;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Convert lat/lng/level points to Itinerary
|
|
340
|
-
* @param {2DArray} points 2D points array of lat/lng/level (level is optional)
|
|
341
|
-
*/
|
|
342
|
-
static fromOrderedPointsArray(points, start, end) {
|
|
343
|
-
|
|
344
|
-
const pointToCoordinates = point => new Coordinates(point[0], point[1], null, point[2]);
|
|
345
|
-
|
|
346
|
-
return this.fromOrderedCoordinates(
|
|
347
|
-
points.map(pointToCoordinates),
|
|
348
|
-
pointToCoordinates(start),
|
|
349
|
-
pointToCoordinates(end)
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Convert lat/lng/level points to Itinerary
|
|
355
|
-
* @param {2DArray} points 2D points array of lat/lng/level (level is optional)
|
|
356
|
-
*/
|
|
357
|
-
static fromOrderedCoordinates(points, start, end) {
|
|
358
|
-
|
|
359
|
-
const route = new Itinerary();
|
|
360
|
-
route._length = 0;
|
|
361
|
-
route.start = start;
|
|
362
|
-
route.end = end;
|
|
363
|
-
|
|
364
|
-
let lastPoint = null;
|
|
365
|
-
|
|
366
|
-
points.forEach(point => {
|
|
367
|
-
const currentPoint = new Node(point);
|
|
368
|
-
if (lastPoint) {
|
|
369
|
-
const edge = new Edge(
|
|
370
|
-
lastPoint,
|
|
371
|
-
currentPoint,
|
|
372
|
-
Level.union(lastPoint.coords.level, currentPoint.coords.level)
|
|
373
|
-
);
|
|
374
|
-
route._edgesDirectionReversed.push(false);
|
|
375
|
-
route.edges.push(edge);
|
|
376
|
-
route._length += edge.length;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
route.nodes.push(currentPoint);
|
|
380
|
-
lastPoint = currentPoint;
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
return route;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Create edges From MultiLevel Itinerary for a given level
|
|
388
|
-
* @param {Level} targetLevel level for selection.
|
|
389
|
-
* @param {Boolean} useMultiLevelEdges use segments which intersect both levels (stairs, elevators...)
|
|
390
|
-
* @returns {Array[Edge]} Ordered edges
|
|
391
|
-
*/
|
|
392
|
-
getEdgesAtLevel(targetLevel, useMultiLevelEdges = true) {
|
|
393
|
-
return this.edges.filter(
|
|
394
|
-
({ level }) => useMultiLevelEdges
|
|
395
|
-
? Level.intersect(targetLevel, level) !== null
|
|
396
|
-
: Level.contains(targetLevel, level)
|
|
397
|
-
);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Append another itinerary
|
|
402
|
-
* @param {Itinerary} other
|
|
403
|
-
* @returns {Itinerary} this
|
|
404
|
-
*/
|
|
405
|
-
append(other) {
|
|
406
|
-
|
|
407
|
-
if (!this.end.equalsTo(other.start)) {
|
|
408
|
-
throw new Error('end of the first itinerary does not equal to the start of the second one');
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
this._steps = null;
|
|
412
|
-
this._nextStepsIndexes = null;
|
|
413
|
-
this._length = this.length + other.length;
|
|
414
|
-
|
|
415
|
-
const lastNodeOfThis = this.nodes[this.nodes.length - 1];
|
|
416
|
-
const firstNodeOfOther = other.nodes[0];
|
|
417
|
-
const firstEdgeOfOther = other.edges[0];
|
|
418
|
-
|
|
419
|
-
if (this.end.equalsTo(lastNodeOfThis.coords)
|
|
420
|
-
&& other.start.equalsTo(firstNodeOfOther.coords)) {
|
|
421
|
-
// first itinerary end node equals to the second itinerary first node
|
|
422
|
-
|
|
423
|
-
// Add to nodes other.nodes[1..end]
|
|
424
|
-
this.nodes = this.nodes.concat(other.nodes.slice(1));
|
|
425
|
-
|
|
426
|
-
// Add to edges other.edges[0..end]
|
|
427
|
-
this.edges = this.edges.concat(other.edges);
|
|
428
|
-
this._edgesDirectionReversed = this._edgesDirectionReversed.concat(other._edgesDirectionReversed);
|
|
429
|
-
firstEdgeOfOther.node1 = lastNodeOfThis;
|
|
430
|
-
|
|
431
|
-
} else if (this.end.equalsTo(lastNodeOfThis.coords)
|
|
432
|
-
|| other.start.equalsTo(firstNodeOfOther.coords)) {
|
|
433
|
-
// last node and end of the first itinerary are merged
|
|
434
|
-
// or
|
|
435
|
-
// first node and start of the second itinerary are merged
|
|
436
|
-
|
|
437
|
-
// Add to nodes other.nodes[0..end]
|
|
438
|
-
this.nodes = this.nodes.concat(other.nodes);
|
|
439
|
-
|
|
440
|
-
// Add to edges [newEdge].concat(other.edges[0..end])
|
|
441
|
-
const newEdge = new Edge(lastNodeOfThis, firstNodeOfOther,
|
|
442
|
-
Level.union(lastNodeOfThis.coords.level, firstNodeOfOther.coords.level)
|
|
443
|
-
);
|
|
444
|
-
this.edges.push(newEdge);
|
|
445
|
-
this.edges = this.edges.concat(other.edges);
|
|
446
|
-
this._edgesDirectionReversed.push(false);
|
|
447
|
-
this._edgesDirectionReversed = this._edgesDirectionReversed.concat(other._edgesDirectionReversed);
|
|
448
|
-
|
|
449
|
-
this._length += newEdge.length;
|
|
450
|
-
|
|
451
|
-
} else {
|
|
452
|
-
// normal case
|
|
453
|
-
|
|
454
|
-
// Add to nodes [newNode].concat(other.nodes[0..end])
|
|
455
|
-
const coords = this.end.clone();
|
|
456
|
-
coords.level = Level.intersect(this.end.level, other.start.level);
|
|
457
|
-
const newNode = new Node(this.end);
|
|
458
|
-
this.nodes.push(newNode);
|
|
459
|
-
this.nodes = this.nodes.concat(other.nodes);
|
|
460
|
-
|
|
461
|
-
// Add to edges [newEdge1, newEdge2].concat(other.edges[0..end])
|
|
462
|
-
const newEdge1 = new Edge(lastNodeOfThis, newNode,
|
|
463
|
-
Level.union(lastNodeOfThis.coords.level, coords.level)
|
|
464
|
-
);
|
|
465
|
-
const newEdge2 = new Edge(newNode, firstNodeOfOther,
|
|
466
|
-
Level.union(coords.level, firstNodeOfOther.coords.level)
|
|
467
|
-
);
|
|
468
|
-
this.edges.push(newEdge1);
|
|
469
|
-
this.edges.push(newEdge2);
|
|
470
|
-
this.edges = this.edges.concat(other.edges);
|
|
471
|
-
this._edgesDirectionReversed.push(false);
|
|
472
|
-
this._edgesDirectionReversed.push(false);
|
|
473
|
-
this._edgesDirectionReversed = this._edgesDirectionReversed.concat(other._edgesDirectionReversed);
|
|
474
|
-
|
|
475
|
-
this._length += newEdge1.length + newEdge2.length;
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
this.end = other.end;
|
|
480
|
-
|
|
481
|
-
return this;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
toCompressedJson() {
|
|
485
|
-
return {
|
|
486
|
-
start: this.start.toCompressedJson(),
|
|
487
|
-
end: this.end.toCompressedJson(),
|
|
488
|
-
coords: this.nodes.map(node => node.coords.toCompressedJson()),
|
|
489
|
-
nodeProperties: this.nodes.reduce((acc, node, idx) => {
|
|
490
|
-
const properties = node.extractProperties();
|
|
491
|
-
if (Object.keys(properties).length !== 0) {
|
|
492
|
-
acc[idx] = properties;
|
|
493
|
-
}
|
|
494
|
-
return acc;
|
|
495
|
-
}, {}),
|
|
496
|
-
edgeProperties: this.edges.reduce((acc, edge, idx) => {
|
|
497
|
-
const properties = edge.extractProperties();
|
|
498
|
-
if (Object.keys(properties).length !== 0) {
|
|
499
|
-
acc[idx] = properties;
|
|
500
|
-
}
|
|
501
|
-
return acc;
|
|
502
|
-
}, {})
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
static fromCompressedJson(json) {
|
|
507
|
-
const itinerary = Itinerary.fromOrderedCoordinates(
|
|
508
|
-
json.coords.map(coords => Coordinates.fromCompressedJson(coords)),
|
|
509
|
-
Coordinates.fromCompressedJson(json.start),
|
|
510
|
-
Coordinates.fromCompressedJson(json.end)
|
|
511
|
-
);
|
|
512
|
-
if ('nodeProperties' in json) {
|
|
513
|
-
for (const idx in json.nodeProperties) {
|
|
514
|
-
if (json.nodeProperties.hasOwnProperty(idx)) {
|
|
515
|
-
itinerary.nodes[idx].applyProperties(json.nodeProperties[idx]);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
if ('edgeProperties' in json) {
|
|
520
|
-
for (const idx in json.edgeProperties) {
|
|
521
|
-
if (json.edgeProperties.hasOwnProperty(idx)) {
|
|
522
|
-
itinerary.edges[idx].applyProperties(json.edgeProperties[idx]);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
return itinerary;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
export default Itinerary;
|