@wemap/routers 11.0.0-alpha.16 → 11.0.0-alpha.19

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.
Files changed (36) hide show
  1. package/dist/index.js +428 -273
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +431 -277
  4. package/dist/index.mjs.map +1 -1
  5. package/index.ts +6 -8
  6. package/package.json +6 -5
  7. package/src/ItineraryInfoManager.spec.ts +14 -14
  8. package/src/ItineraryInfoManager.ts +13 -13
  9. package/src/model/Itinerary.spec.ts +12 -6
  10. package/src/model/Itinerary.ts +67 -66
  11. package/src/model/Leg.spec.ts +4 -4
  12. package/src/model/Leg.ts +76 -31
  13. package/src/model/Step.spec.ts +99 -0
  14. package/src/model/Step.ts +78 -11
  15. package/src/model/generateSteps.ts +8 -8
  16. package/src/remote/RemoteRouterManager.ts +17 -15
  17. package/src/remote/cityway/CitywayRemoteRouter.ts +9 -11
  18. package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.ts +1 -3
  19. package/src/remote/idfm/IdfmRemoteRouter.ts +31 -31
  20. package/src/remote/osrm/OsrmRemoteRouter.ts +5 -8
  21. package/src/remote/otp/OtpRemoteRouter.ts +9 -12
  22. package/src/remote/wemap-multi/WemapMultiRemoteRouter.ts +1 -3
  23. package/src/wemap-multi/CustomNetworkMap.ts +51 -32
  24. package/src/wemap-multi/WemapMultiRouter.ts +3 -4
  25. package/src/wemap-multi/WemapMultiRouterOptions.ts +3 -1
  26. package/src/wemap-osm/OsmGraph.spec.ts +99 -0
  27. package/src/wemap-osm/OsmGraph.ts +169 -0
  28. package/src/wemap-osm/{WemapOsmRouter.spec.ts → OsmRouter.spec.ts} +61 -40
  29. package/src/wemap-osm/OsmRouter.ts +201 -0
  30. package/vite.config.ts +1 -1
  31. package/src/model/ItineraryInfo.ts +0 -19
  32. package/src/model/StepInfo.spec.ts +0 -78
  33. package/src/model/StepInfo.ts +0 -78
  34. package/src/wemap-osm/WemapOsmRouter.ts +0 -109
  35. package/src/wemap-osm/WemapOsmRouterOptions.ts +0 -23
  36. package/src/wemap-osm/WemapOsmRouterUtils.ts +0 -21
package/dist/index.js CHANGED
@@ -8,13 +8,14 @@ var __publicField = (obj, key, value) => {
8
8
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
9
9
  const geo = require("@wemap/geo");
10
10
  const maths = require("@wemap/maths");
11
+ const salesman = require("@wemap/salesman.js");
11
12
  const osm = require("@wemap/osm");
12
13
  const Logger = require("@wemap/logger");
13
14
  const Polyline = require("@mapbox/polyline");
14
15
  const pointInPolygon = require("@turf/boolean-point-in-polygon");
15
16
  const convexHullFn = require("@turf/convex");
16
- const helpers = require("@turf/helpers");
17
17
  const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
18
+ const salesman__default = /* @__PURE__ */ _interopDefaultLegacy(salesman);
18
19
  const Logger__default = /* @__PURE__ */ _interopDefaultLegacy(Logger);
19
20
  const Polyline__default = /* @__PURE__ */ _interopDefaultLegacy(Polyline);
20
21
  const pointInPolygon__default = /* @__PURE__ */ _interopDefaultLegacy(pointInPolygon);
@@ -22,53 +23,6 @@ const convexHullFn__default = /* @__PURE__ */ _interopDefaultLegacy(convexHullFn
22
23
  function getDurationFromLength(length, speed = 5) {
23
24
  return length / (speed * 1e3 / 3600);
24
25
  }
25
- function areLevelChangeEquals(l1, l2) {
26
- return l1 === l2 || l1.difference === l2.difference && l1.direction === l2.direction && l1.type === l2.type;
27
- }
28
- class StepInfo {
29
- constructor({
30
- coords,
31
- distance,
32
- name,
33
- levelChange,
34
- extras,
35
- duration
36
- }) {
37
- __publicField(this, "coords");
38
- __publicField(this, "name");
39
- __publicField(this, "distance");
40
- __publicField(this, "duration");
41
- __publicField(this, "levelChange");
42
- __publicField(this, "extras");
43
- this.coords = coords;
44
- this.name = name || null;
45
- this.distance = typeof distance === "number" ? distance : null;
46
- this.duration = typeof duration === "number" ? duration : null;
47
- this.levelChange = levelChange || null;
48
- this.extras = extras || null;
49
- }
50
- static equals(obj1, obj2) {
51
- return obj1.coords.equals(obj2.coords) && obj1.distance === obj2.distance && obj1.duration === obj2.duration && obj1.name === obj2.name && (obj1.levelChange === obj2.levelChange || obj1.levelChange && obj2.levelChange && areLevelChangeEquals(obj1.levelChange, obj2.levelChange));
52
- }
53
- equals(obj) {
54
- return StepInfo.equals(this, obj);
55
- }
56
- toJson() {
57
- return {
58
- coords: this.coords.toCompressedJson(),
59
- ...this.distance !== null && { distance: this.distance },
60
- ...this.duration !== null && { duration: this.duration },
61
- ...this.name !== null && { name: this.name },
62
- ...this.levelChange !== null && { levelChange: this.levelChange },
63
- ...this.extras && Object.keys(this.extras).length !== 0 && { extras: this.extras }
64
- };
65
- }
66
- static fromJson(json) {
67
- return new StepInfo(Object.assign({}, json, {
68
- coords: geo.Coordinates.fromCompressedJson(json.coords)
69
- }));
70
- }
71
- }
72
26
  const SKIP_STEP_ANGLE_MAX = maths.deg2rad(20);
73
27
  function generateSteps(leg, rules) {
74
28
  const steps = [];
@@ -99,16 +53,16 @@ function generateSteps(leg, rules) {
99
53
  levelChange = { difference, direction, type: customRules == null ? void 0 : customRules.levelChangeType };
100
54
  }
101
55
  if (currentStep && currentStep.duration === 0) {
102
- currentStep.duration = null;
56
+ delete currentStep.duration;
103
57
  }
104
- currentStep = new StepInfo({
58
+ currentStep = {
105
59
  coords: currentCoords,
106
60
  name: customRules == null ? void 0 : customRules.stepName,
107
61
  extras: customRules == null ? void 0 : customRules.stepExtras,
108
62
  levelChange,
109
63
  distance: 0,
110
64
  duration: 0
111
- });
65
+ };
112
66
  steps.push(currentStep);
113
67
  }
114
68
  currentStep.distance += currentCoords.distanceTo(nextCoords);
@@ -119,7 +73,7 @@ function generateSteps(leg, rules) {
119
73
  }
120
74
  const lastCoords = coordsArray[coordsArray.length - 1];
121
75
  if (!geo.Coordinates.equals(lastCoords, to.coords)) {
122
- steps.push(new StepInfo({ coords: lastCoords }));
76
+ steps.push({ coords: lastCoords });
123
77
  }
124
78
  return steps;
125
79
  }
@@ -135,6 +89,36 @@ function isRoutingModePublicTransport(routingMode) {
135
89
  "TRAM"
136
90
  ].includes(routingMode);
137
91
  }
92
+ function stepToJson(step) {
93
+ return {
94
+ ...step.firstStep && { firstStep: true },
95
+ ...step.lastStep && { lastStep: true },
96
+ number: step.number,
97
+ coords: step.coords.toCompressedJson(),
98
+ ...step.name !== null && { name: step.name },
99
+ angle: step.angle,
100
+ previousBearing: step.previousBearing,
101
+ nextBearing: step.nextBearing,
102
+ distance: step.distance,
103
+ duration: step.duration,
104
+ ...step.levelChange !== null && { levelChange: step.levelChange },
105
+ ...step.extras && Object.keys(step.extras).length !== 0 && { extras: step.extras }
106
+ };
107
+ }
108
+ function jsonToStep(json) {
109
+ return Object.assign({}, json, {
110
+ coords: geo.Coordinates.fromCompressedJson(json.coords),
111
+ firstStep: Boolean(json.firstStep),
112
+ lastStep: Boolean(json.lastStep),
113
+ name: json.name || null,
114
+ levelChange: json.levelChange || null,
115
+ extras: json.extras || null
116
+ });
117
+ }
118
+ function stepEquals(step1, step2) {
119
+ var _a, _b, _c, _d, _e, _f;
120
+ return step1.coords.equals(step2.coords) && step1.angle === step2.angle && step1.distance === step2.distance && step1.duration === step2.duration && step1.firstStep === step2.firstStep && step1.lastStep === step2.lastStep && ((_a = step1.levelChange) == null ? void 0 : _a.difference) === ((_b = step2.levelChange) == null ? void 0 : _b.difference) && ((_c = step1.levelChange) == null ? void 0 : _c.direction) === ((_d = step2.levelChange) == null ? void 0 : _d.direction) && ((_e = step1.levelChange) == null ? void 0 : _e.type) === ((_f = step2.levelChange) == null ? void 0 : _f.type) && step1.name === step2.name && step1.nextBearing === step2.nextBearing && step1.number === step2.number && step1.previousBearing === step2.previousBearing;
121
+ }
138
122
  class Leg {
139
123
  constructor({
140
124
  from,
@@ -155,7 +139,7 @@ class Leg {
155
139
  __publicField(this, "duration");
156
140
  __publicField(this, "startTime");
157
141
  __publicField(this, "endTime");
158
- __publicField(this, "stepsInfo");
142
+ __publicField(this, "steps");
159
143
  __publicField(this, "transportInfo");
160
144
  this.from = {
161
145
  name: from.name || null,
@@ -172,17 +156,22 @@ class Leg {
172
156
  this.startTime = typeof startTime === "number" ? startTime : null;
173
157
  this.endTime = typeof endTime === "number" ? endTime : null;
174
158
  this.transportInfo = transportInfo || null;
175
- this.stepsInfo = "stepsInfo" in otherParams ? otherParams.stepsInfo : generateSteps(this, otherParams.stepsGenerationRules);
159
+ if ("steps" in otherParams) {
160
+ this.steps = otherParams.steps;
161
+ return;
162
+ }
163
+ const minStepsInfo = "minStepsInfo" in otherParams ? otherParams.minStepsInfo : generateSteps(this, otherParams.stepsGenerationRules);
164
+ this.steps = Leg.generateStepsFromMinStepInfo(from.coords, to.coords, coords, minStepsInfo);
176
165
  }
177
166
  isPublicTransport() {
178
167
  return isRoutingModePublicTransport(this.mode);
179
168
  }
180
- toNetwork() {
181
- return geo.Network.fromCoordinates([this.coords]);
169
+ toGraph() {
170
+ return geo.GeoGraph.fromCoordinates([this.coords]);
182
171
  }
183
172
  static equals(obj1, obj2) {
184
173
  var _a, _b;
185
- const intermediate = obj1.mode === obj2.mode && obj1.duration === obj2.duration && obj1.startTime === obj2.startTime && obj1.endTime === obj2.endTime && obj1.from.name === obj2.from.name && obj1.from.coords.equals(obj2.from.coords) && obj1.to.name === obj2.to.name && obj1.to.coords.equals(obj2.to.coords) && obj1.coords.length === obj2.coords.length && (obj1.stepsInfo === obj2.stepsInfo || ((_a = obj1.stepsInfo) == null ? void 0 : _a.length) === ((_b = obj2.stepsInfo) == null ? void 0 : _b.length));
174
+ const intermediate = obj1.mode === obj2.mode && obj1.duration === obj2.duration && obj1.startTime === obj2.startTime && obj1.endTime === obj2.endTime && obj1.from.name === obj2.from.name && obj1.from.coords.equals(obj2.from.coords) && obj1.to.name === obj2.to.name && obj1.to.coords.equals(obj2.to.coords) && obj1.coords.length === obj2.coords.length && (obj1.steps === obj2.steps || ((_a = obj1.steps) == null ? void 0 : _a.length) === ((_b = obj2.steps) == null ? void 0 : _b.length));
186
175
  if (!intermediate) {
187
176
  return false;
188
177
  }
@@ -192,11 +181,9 @@ class Leg {
192
181
  return false;
193
182
  }
194
183
  }
195
- if (obj1.stepsInfo && obj2.stepsInfo) {
196
- for (i = 0; i < obj1.stepsInfo.length; i++) {
197
- if (!obj1.stepsInfo[i].equals(obj2.stepsInfo[i])) {
198
- return false;
199
- }
184
+ for (i = 0; i < obj1.steps.length; i++) {
185
+ if (!stepEquals(obj1.steps[i], obj2.steps[i])) {
186
+ return false;
200
187
  }
201
188
  }
202
189
  if (obj1.transportInfo !== obj2.transportInfo) {
@@ -225,7 +212,7 @@ class Leg {
225
212
  },
226
213
  duration: this.duration,
227
214
  coords: this.coords.map((coords) => coords.toCompressedJson()),
228
- steps: this.stepsInfo.map((stepInfo) => stepInfo.toJson()),
215
+ steps: this.steps.map(stepToJson),
229
216
  ...this.startTime !== null && { startTime: this.startTime },
230
217
  ...this.endTime !== null && { endTime: this.endTime },
231
218
  ...this.transportInfo !== null && { transportInfo: this.transportInfo }
@@ -243,8 +230,7 @@ class Leg {
243
230
  name: json.to.name || null
244
231
  },
245
232
  coords: json.coords.map(geo.Coordinates.fromCompressedJson),
246
- stepsInfo: ((_a = json.steps) == null ? void 0 : _a.map(StepInfo.fromJson)) || null,
247
- stepsGenerationRules: void 0
233
+ steps: ((_a = json.steps) == null ? void 0 : _a.map(jsonToStep)) || null
248
234
  }));
249
235
  return leg;
250
236
  }
@@ -252,7 +238,7 @@ class Leg {
252
238
  return new Leg({
253
239
  from: { coords: graphItinerary.start },
254
240
  to: { coords: graphItinerary.end },
255
- coords: graphItinerary.nodes.map((node) => node.coords),
241
+ coords: graphItinerary.vertices.map((vertex) => vertex.coords),
256
242
  duration: graphItinerary.edgesWeights.reduce((acc, weight) => acc + weight, 0),
257
243
  mode,
258
244
  stepsGenerationRules
@@ -264,12 +250,45 @@ class Leg {
264
250
  for (const coords of this.coords) {
265
251
  coords.level = geo.Level.multiplyBy(coords.level, levelFactor);
266
252
  }
267
- this.stepsInfo.forEach((step) => {
253
+ this.steps.forEach((step) => {
268
254
  step.coords.level = geo.Level.multiplyBy(step.coords.level, levelFactor);
269
255
  });
270
256
  }
271
- getSteps(itinerarySteps) {
272
- return this.stepsInfo.map((stepInfo) => itinerarySteps.find((_step) => _step.coords.equals(stepInfo.coords)));
257
+ static generateStepsFromMinStepInfo(from, to, legCoords, stepsInfo) {
258
+ return stepsInfo.map((stepInfo, stepId) => {
259
+ const coordsId = legCoords.findIndex((coords) => coords.equals(stepInfo.coords));
260
+ if (coordsId === -1) {
261
+ throw new Error("Cannot find step coordinates in itinerary coordinates.");
262
+ }
263
+ const coordsBeforeStep = coordsId === 0 ? from : legCoords[coordsId - 1];
264
+ const coordsAfterStep = coordsId === legCoords.length - 1 ? to : legCoords[coordsId + 1];
265
+ const previousBearing = coordsBeforeStep.bearingTo(stepInfo.coords);
266
+ const nextBearing = stepInfo.coords.bearingTo(coordsAfterStep);
267
+ let distance = 0;
268
+ const coordsToStopCalculation = stepId !== stepsInfo.length - 1 ? stepsInfo[stepId + 1].coords : legCoords[legCoords.length - 1];
269
+ let currentCoordsId = coordsId;
270
+ while (!legCoords[currentCoordsId].equals(coordsToStopCalculation)) {
271
+ distance += legCoords[currentCoordsId].distanceTo(legCoords[currentCoordsId + 1]);
272
+ currentCoordsId++;
273
+ }
274
+ if (currentCoordsId === legCoords.length - 1) {
275
+ distance += legCoords[currentCoordsId].distanceTo(to);
276
+ }
277
+ return {
278
+ coords: stepInfo.coords,
279
+ name: stepInfo.name || null,
280
+ number: stepId + 1,
281
+ previousBearing,
282
+ nextBearing,
283
+ angle: maths.diffAngle(previousBearing, nextBearing + Math.PI),
284
+ firstStep: stepId === 0,
285
+ lastStep: stepId === stepsInfo.length - 1,
286
+ distance,
287
+ duration: stepInfo.duration || getDurationFromLength(distance),
288
+ levelChange: stepInfo.levelChange || null,
289
+ extras: stepInfo.extras || null
290
+ };
291
+ });
273
292
  }
274
293
  }
275
294
  class Itinerary {
@@ -289,7 +308,6 @@ class Itinerary {
289
308
  __publicField(this, "startTime");
290
309
  __publicField(this, "endTime");
291
310
  __publicField(this, "_coords", null);
292
- __publicField(this, "_steps", null);
293
311
  __publicField(this, "_distance", null);
294
312
  this.from = from;
295
313
  this.to = to;
@@ -297,6 +315,7 @@ class Itinerary {
297
315
  this.duration = typeof duration === "number" ? duration : this.legs.reduce((dur, leg) => dur + leg.duration, 0);
298
316
  this.startTime = typeof startTime === "number" ? startTime : null;
299
317
  this.endTime = typeof endTime === "number" ? endTime : null;
318
+ this.updateStepsFromLegs();
300
319
  }
301
320
  set coords(_) {
302
321
  throw new Error("Itinerary.coords cannot be set. They are calculated from Itinerary.legs.");
@@ -311,45 +330,7 @@ class Itinerary {
311
330
  throw new Error("Itinerary.step cannot be set. They are calculated from Itinerary.legs.");
312
331
  }
313
332
  get steps() {
314
- if (this._steps) {
315
- return this._steps;
316
- }
317
- const itineraryCoords = this.coords.filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
318
- const stepsInfo = this.legs.map((leg) => leg.stepsInfo).flat();
319
- const steps = stepsInfo.map((stepInfo, stepId) => {
320
- const coordsId = itineraryCoords.findIndex((coords) => coords.equals(stepInfo.coords));
321
- if (coordsId === -1) {
322
- throw new Error("Cannot find step coordinates in itinerary coordinates.");
323
- }
324
- const coordsBeforeStep = coordsId === 0 ? this.from : itineraryCoords[coordsId - 1];
325
- const coordsAfterStep = coordsId === itineraryCoords.length - 1 ? this.to : itineraryCoords[coordsId + 1];
326
- const previousBearing = coordsBeforeStep.bearingTo(stepInfo.coords);
327
- const nextBearing = stepInfo.coords.bearingTo(coordsAfterStep);
328
- let distance = 0;
329
- const coordsToStopCalculation = stepId !== stepsInfo.length - 1 ? stepsInfo[stepId + 1].coords : itineraryCoords[itineraryCoords.length - 1];
330
- let currentCoordsId = coordsId;
331
- while (!itineraryCoords[currentCoordsId].equals(coordsToStopCalculation)) {
332
- distance += itineraryCoords[currentCoordsId].distanceTo(itineraryCoords[currentCoordsId + 1]);
333
- currentCoordsId++;
334
- }
335
- if (currentCoordsId === itineraryCoords.length - 1) {
336
- distance += itineraryCoords[currentCoordsId].distanceTo(this.to);
337
- }
338
- return {
339
- ...stepInfo,
340
- number: stepId + 1,
341
- previousBearing,
342
- nextBearing,
343
- angle: maths.diffAngle(previousBearing, nextBearing + Math.PI),
344
- firstStep: stepId === 0,
345
- lastStep: stepId === stepsInfo.length - 1,
346
- distance,
347
- duration: stepInfo.duration || getDurationFromLength(distance),
348
- previousStep: null,
349
- nextStep: null
350
- };
351
- });
352
- return steps;
333
+ return this.legs.map((leg) => leg.steps).flat();
353
334
  }
354
335
  set mode(_) {
355
336
  throw new Error("Itinerary.mode cannot be set. They are calculated from Itinerary.legs.");
@@ -385,8 +366,8 @@ class Itinerary {
385
366
  }
386
367
  return this._distance;
387
368
  }
388
- toNetwork() {
389
- return geo.Network.fromCoordinates([this.coords]);
369
+ toGraph() {
370
+ return geo.GeoGraph.fromCoordinates([this.coords]);
390
371
  }
391
372
  static fromItineraries(...itineraries) {
392
373
  let duration = 0;
@@ -478,8 +459,8 @@ class Itinerary {
478
459
  for (const coords of leg.coords) {
479
460
  coords.level = coords.level || 0;
480
461
  }
481
- if (leg.stepsInfo) {
482
- for (const step of leg.stepsInfo) {
462
+ if (leg.steps) {
463
+ for (const step of leg.steps) {
483
464
  step.coords.level = step.coords.level || 0;
484
465
  }
485
466
  }
@@ -500,6 +481,36 @@ class Itinerary {
500
481
  }
501
482
  };
502
483
  }
484
+ updateStepsFromLegs() {
485
+ const itineraryCoords = this.coords.filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
486
+ const steps = this.legs.map((leg) => leg.steps).flat();
487
+ steps.map((step, stepId) => {
488
+ const coordsId = itineraryCoords.findIndex((coords) => coords.equals(step.coords));
489
+ if (coordsId === -1) {
490
+ throw new Error("Cannot find step coordinates in itinerary coordinates.");
491
+ }
492
+ const coordsBeforeStep = coordsId === 0 ? this.from : itineraryCoords[coordsId - 1];
493
+ const coordsAfterStep = coordsId === itineraryCoords.length - 1 ? this.to : itineraryCoords[coordsId + 1];
494
+ step.previousBearing = coordsBeforeStep.bearingTo(step.coords);
495
+ step.nextBearing = step.coords.bearingTo(coordsAfterStep);
496
+ step.angle = maths.diffAngle(step.previousBearing, step.nextBearing + Math.PI);
497
+ const stepDistanceBefore = step.distance;
498
+ step.distance = 0;
499
+ const coordsToStopCalculation = stepId !== steps.length - 1 ? steps[stepId + 1].coords : itineraryCoords[itineraryCoords.length - 1];
500
+ let currentCoordsId = coordsId;
501
+ while (!itineraryCoords[currentCoordsId].equals(coordsToStopCalculation)) {
502
+ step.distance += itineraryCoords[currentCoordsId].distanceTo(itineraryCoords[currentCoordsId + 1]);
503
+ currentCoordsId++;
504
+ }
505
+ if (currentCoordsId === itineraryCoords.length - 1) {
506
+ step.distance += itineraryCoords[currentCoordsId].distanceTo(this.to);
507
+ }
508
+ step.number = stepId + 1;
509
+ step.firstStep = stepId === 0;
510
+ step.lastStep = stepId === steps.length - 1;
511
+ step.duration += getDurationFromLength(step.distance - stepDistanceBefore);
512
+ });
513
+ }
503
514
  }
504
515
  class RouterResponse {
505
516
  constructor({
@@ -562,56 +573,158 @@ class RouterResponse {
562
573
  }
563
574
  }
564
575
  }
565
- const _WemapOsmRouterOptions = class extends osm.OsmGraphRouterOptions {
566
- constructor() {
567
- super(...arguments);
568
- __publicField(this, "weightEdgeFn", (edge) => edge.builtFrom instanceof osm.OsmNode && edge.builtFrom.isElevator ? 30 : getDurationFromLength(edge.length));
569
- }
570
- static get WITHOUT_STAIRS() {
571
- const options = new _WemapOsmRouterOptions();
572
- options.acceptEdgeFn = (edge) => {
573
- var _a;
574
- return ((_a = edge.builtFrom) == null ? void 0 : _a.tags.highway) !== "steps";
576
+ const HIGHWAYS_PEDESTRIANS = ["footway", "steps", "pedestrian", "living_street", "path", "track", "sidewalk", "elevator"];
577
+ const DEFAULT_WAY_SELECTOR = (way) => {
578
+ return HIGHWAYS_PEDESTRIANS.includes(way.tags.highway) || way.tags.footway === "sidewalk" || way.tags.public_transport === "platform" || way.tags.railway === "platform";
579
+ };
580
+ class OsmGraph extends geo.GeoGraph {
581
+ getVertexByCoords(coords) {
582
+ return geo.GeoGraph.getVertexByCoords(this.vertices, coords);
583
+ }
584
+ getVertexByName(name) {
585
+ return super.getVertexByName(name);
586
+ }
587
+ getEdgeByName(name) {
588
+ return super.getEdgeByName(name);
589
+ }
590
+ static fromOsmModel(osmModel, waySelectionFilter = DEFAULT_WAY_SELECTOR) {
591
+ const nodes = [];
592
+ const edges = [];
593
+ const nodesCreated = {};
594
+ const elevatorNodes = [];
595
+ const getOrCreateNode = (osmNode) => {
596
+ let node = nodesCreated[osmNode.id];
597
+ if (!node) {
598
+ node = new geo.GeoGraphVertex(osmNode.coords, { data: osmNode, name: osmNode.tags.name });
599
+ nodesCreated[osmNode.id] = node;
600
+ nodes.push(node);
601
+ if (osmNode.tags.highway === "elevator") {
602
+ elevatorNodes.push(node);
603
+ }
604
+ }
605
+ return node;
606
+ };
607
+ osmModel.ways.forEach((way) => {
608
+ if (!waySelectionFilter(way)) {
609
+ return;
610
+ }
611
+ let firstNode = getOrCreateNode(way.nodes[0]);
612
+ for (let i = 1; i < way.nodes.length; i++) {
613
+ const secondNode = getOrCreateNode(way.nodes[i]);
614
+ const edge = new geo.GeoGraphEdge(
615
+ firstNode,
616
+ secondNode,
617
+ { data: way, name: way.tags.name, level: way.level }
618
+ );
619
+ OsmGraph.manageOneWay(edge, way);
620
+ edges.push(edge);
621
+ firstNode = secondNode;
622
+ }
623
+ });
624
+ elevatorNodes.forEach((node) => {
625
+ OsmGraph.createNodesAndEdgesFromElevator(nodes, edges, node);
626
+ });
627
+ return new OsmGraph(nodes, edges, true);
628
+ }
629
+ static manageOneWay(edge, way) {
630
+ const { highway, oneway, conveying } = way.tags;
631
+ edge.isOneway = Boolean(oneway === "yes" || oneway === "true" || oneway === "1" || conveying && highway && ["forward", "backward"].includes(conveying));
632
+ if (edge.isOneway && conveying === "backward") {
633
+ const tmpNode = edge.vertex1;
634
+ edge.vertex1 = edge.vertex2;
635
+ edge.vertex2 = tmpNode;
636
+ }
637
+ }
638
+ static createNodesAndEdgesFromElevator(nodes, edges, elevatorNode) {
639
+ const createdNodes = [];
640
+ const getOrCreateLevelVertex = (level) => {
641
+ let levelVertex = createdNodes.find(({ coords }) => geo.Level.equals(level, coords.level));
642
+ if (!levelVertex) {
643
+ levelVertex = new geo.GeoGraphVertex(elevatorNode.coords.clone(), {
644
+ data: elevatorNode.data,
645
+ name: `${elevatorNode.name} (elevator lvl: ${level})`
646
+ });
647
+ levelVertex.coords.level = level;
648
+ createdNodes.push(levelVertex);
649
+ nodes.push(levelVertex);
650
+ }
651
+ return levelVertex;
575
652
  };
576
- return options;
653
+ elevatorNode.edges.forEach((edge) => {
654
+ if (geo.Level.isRange(edge.level)) {
655
+ throw new Error("Cannot handle this elevator edge due to ambiguity");
656
+ }
657
+ const levelVertex = getOrCreateLevelVertex(edge.level);
658
+ if (edge.vertex1 === elevatorNode) {
659
+ edge.vertex1 = levelVertex;
660
+ } else {
661
+ edge.vertex2 = levelVertex;
662
+ }
663
+ levelVertex.edges.push(edge);
664
+ });
665
+ for (let i = 0; i < createdNodes.length; i++) {
666
+ for (let j = i + 1; j < createdNodes.length; j++) {
667
+ const createdNode1 = createdNodes[i];
668
+ const createdNode2 = createdNodes[j];
669
+ if (createdNode1.coords.level === null || createdNode2.coords.level === null) {
670
+ continue;
671
+ }
672
+ const minLevel = Math.min(createdNode1.coords.level, createdNode2.coords.level);
673
+ const maxLevel = Math.max(createdNode1.coords.level, createdNode2.coords.level);
674
+ const newEdge = new geo.GeoGraphEdge(
675
+ createdNode1,
676
+ createdNode2,
677
+ { data: elevatorNode.data, name: elevatorNode.name, level: [minLevel, maxLevel] }
678
+ );
679
+ edges.push(newEdge);
680
+ }
681
+ }
682
+ const elevatorNodeIndex = nodes.indexOf(elevatorNode);
683
+ if (elevatorNodeIndex > -1) {
684
+ nodes.splice(elevatorNodeIndex, 1);
685
+ }
577
686
  }
578
- };
579
- let WemapOsmRouterOptions = _WemapOsmRouterOptions;
580
- __publicField(WemapOsmRouterOptions, "DEFAULT", new _WemapOsmRouterOptions());
687
+ }
688
+ const DEFAULT_OPTIONS = Object.assign({}, geo.GeoGraphRouter.DEFAULT_OPTIONS, {
689
+ weightEdgeFn: (edge) => edge.data instanceof osm.OsmNode && edge.data.isElevator ? 30 : getDurationFromLength(edge.length)
690
+ });
691
+ const WITHOUT_STAIRS_OPTIONS = Object.assign({}, DEFAULT_OPTIONS, {
692
+ acceptEdgeFn: (edge) => edge.data.tags.highway !== "steps"
693
+ });
581
694
  const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previousStep) => {
582
- var _a, _b, _c, _d, _e, _f, _g;
695
+ var _a, _b, _c, _d, _e;
583
696
  const edges = graphItinerary.edges;
584
- const nodes = graphItinerary.nodes;
585
- const node = geo.GraphUtils.getNodeByCoords(nodes, currentCoords);
586
- const nextNode = geo.GraphUtils.getNodeByCoords(nodes, nextCoords);
587
- if (!node || !nextNode)
697
+ const vertices = graphItinerary.vertices;
698
+ const vertex = geo.GeoGraph.getVertexByCoords(vertices, currentCoords);
699
+ const nextVertex = geo.GeoGraph.getVertexByCoords(vertices, nextCoords);
700
+ if (!vertex || !nextVertex)
588
701
  return {};
589
- const edge = geo.GraphUtils.getEdgeByNodes(edges, node, nextNode);
702
+ const edge = geo.GeoGraphEdge.getEdgeByVertices(edges, vertex, nextVertex);
590
703
  if (!edge)
591
704
  return {};
592
705
  const edgeId = edges.findIndex((_edge) => _edge === edge);
593
- const isSubwayEntrance = node ? ((_a = node.builtFrom) == null ? void 0 : _a.tags.railway) === "subway_entrance" : false;
594
- const isGate = node ? ((_b = node.builtFrom) == null ? void 0 : _b.tags.barrier) === "gate" || ((_c = node.builtFrom) == null ? void 0 : _c.tags.aeroway) === "gate" : false;
706
+ const isSubwayEntrance = vertex ? ((_a = vertex.data) == null ? void 0 : _a.tags.railway) === "subway_entrance" : false;
707
+ const isGate = vertex ? ((_b = vertex.data) == null ? void 0 : _b.tags.barrier) === "gate" || ((_c = vertex.data) == null ? void 0 : _c.tags.aeroway) === "gate" : false;
595
708
  let levelChangeType = null;
596
- if ((_d = edge.builtFrom) == null ? void 0 : _d.isElevator) {
709
+ if (edge.data.isElevator) {
597
710
  levelChangeType = "elevator";
598
- } else if ((edge.builtFrom instanceof osm.OsmNode || edge.builtFrom instanceof osm.OsmWay) && edge.builtFrom.isConveying) {
711
+ } else if (edge.data.isConveying) {
599
712
  levelChangeType = "conveyor";
600
- } else if (edge.builtFrom instanceof osm.OsmWay && edge.builtFrom.areStairs) {
713
+ } else if (edge.data instanceof osm.OsmWay && edge.data.areStairs) {
601
714
  levelChangeType = "stairs";
602
715
  }
603
- const edgeTags = ((_e = edge.builtFrom) == null ? void 0 : _e.tags) || {};
716
+ const edgeTags = edge.data.tags || {};
604
717
  let levelChangeDirection = null;
605
- if (edge.builtFrom instanceof osm.OsmWay && edge.builtFrom.areStairs && ["up", "down"].includes(edgeTags.incline) && !(previousStep == null ? void 0 : previousStep.levelChange)) {
718
+ if (edge.data instanceof osm.OsmWay && edge.data.areStairs && ["up", "down"].includes(edgeTags.incline) && !(previousStep == null ? void 0 : previousStep.levelChange)) {
606
719
  levelChangeDirection = edgeTags.incline;
607
- for (const n of edge.builtFrom.nodes) {
608
- if (n !== node.builtFrom)
720
+ for (const n of edge.data.nodes) {
721
+ if (n !== vertex.data)
609
722
  continue;
610
723
  }
611
- const isReversed = edge.builtFrom.nodes.reduce((acc, n, idx, arr) => {
612
- if (n !== node.builtFrom)
724
+ const isReversed = edge.data.nodes.reduce((acc, n, idx, arr) => {
725
+ if (n !== vertex.data)
613
726
  return acc;
614
- acc = !(idx + 1 < arr.length && arr[idx + 1] === nextNode.builtFrom);
727
+ acc = !(idx + 1 < arr.length && arr[idx + 1] === nextVertex.data);
615
728
  return acc;
616
729
  }, null);
617
730
  if (isReversed) {
@@ -621,32 +734,85 @@ const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previous
621
734
  const createNewStep = isSubwayEntrance || levelChangeDirection;
622
735
  return {
623
736
  createNewStep,
624
- stepName: (_f = edge.builtFrom) == null ? void 0 : _f.tags.name,
737
+ stepName: (_d = edge.data) == null ? void 0 : _d.tags.name,
625
738
  duration: graphItinerary.edgesWeights[edgeId],
626
739
  stepExtras: {
627
740
  ...isSubwayEntrance && { isSubwayEntrance: true },
628
- ...isSubwayEntrance && ((_g = node.builtFrom) == null ? void 0 : _g.tags.ref) && { subwayEntranceRef: node.builtFrom.tags.ref },
741
+ ...isSubwayEntrance && ((_e = vertex.data) == null ? void 0 : _e.tags.ref) && { subwayEntranceRef: vertex.data.tags.ref },
629
742
  ...isGate && { isGate: true }
630
743
  },
631
744
  ...levelChangeType && { levelChangeType },
632
745
  ...levelChangeDirection && { levelChangeDirection }
633
746
  };
634
747
  };
635
- class WemapOsmRouter extends osm.OsmGraphRouter {
636
- constructor(network) {
637
- super(network);
748
+ class WemapOsmRouter extends geo.GeoGraphRouter {
749
+ constructor(graph) {
750
+ super(graph);
638
751
  }
639
752
  static get rname() {
640
- return "wemap";
753
+ return "wemap-osm";
641
754
  }
642
- getShortestPath(start, end, options = new WemapOsmRouterOptions()) {
755
+ getShortestPath(start, end, options = DEFAULT_OPTIONS) {
643
756
  return super.getShortestPath(start, end, options);
644
757
  }
645
- getItinerary(start, end, options = new WemapOsmRouterOptions()) {
758
+ getItinerary(start, end, options = DEFAULT_OPTIONS) {
646
759
  const graphItinerary = this.getShortestPath(start, end, options);
647
760
  return Itinerary.fromGraphItinerary(graphItinerary, "WALK", buildStepsRules(graphItinerary));
648
761
  }
762
+ static getTurnInfoFromAngle(_angle) {
763
+ let direction, directionExtra;
764
+ const directionAngle = maths.rad2deg(maths.diffAngle(_angle, Math.PI));
765
+ const directionAngleAbs = Math.abs(directionAngle);
766
+ if (directionAngleAbs <= 20) {
767
+ direction = "straight";
768
+ } else {
769
+ direction = directionAngle > 0 ? "left" : "right";
770
+ if (directionAngleAbs < 55) {
771
+ directionExtra = "slight";
772
+ } else if (directionAngleAbs > 120) {
773
+ directionExtra = "sharp";
774
+ }
775
+ }
776
+ return { direction, directionExtra };
777
+ }
778
+ getShortestTrip(waypoints, options = DEFAULT_OPTIONS) {
779
+ const points = waypoints.map((waypoint) => {
780
+ const point = new salesman__default.default.Point(0, 0);
781
+ point.coords = waypoint;
782
+ return point;
783
+ });
784
+ const cache = [];
785
+ const solution = salesman__default.default.solve(points, 0.9, void 0, (p, q) => {
786
+ const osmItinerary = this.getShortestPath(
787
+ p.coords,
788
+ q.coords,
789
+ options
790
+ );
791
+ cache.push(osmItinerary);
792
+ return osmItinerary.edgesWeights.reduce((acc, weight) => acc + weight, 0);
793
+ });
794
+ const orderedPoints = solution.map((i) => points[i]);
795
+ const orderedItineraries = [];
796
+ for (let i = 0; i < orderedPoints.length - 1; i++) {
797
+ const p = orderedPoints[i];
798
+ const q = orderedPoints[i + 1];
799
+ orderedItineraries.push(
800
+ cache.find((itinerary) => itinerary.start === p.coords && itinerary.end === q.coords || itinerary.end === p.coords && itinerary.start === q.coords)
801
+ );
802
+ }
803
+ return orderedItineraries;
804
+ }
805
+ getTripItinerary(waypoints, options = DEFAULT_OPTIONS) {
806
+ const shortestTrip = this.getShortestTrip(waypoints, options);
807
+ return new Itinerary({
808
+ from: shortestTrip[0].start,
809
+ to: shortestTrip[shortestTrip.length - 1].end,
810
+ legs: shortestTrip.map((graphItinerary) => Leg.fromGraphItinerary(graphItinerary))
811
+ });
812
+ }
649
813
  }
814
+ __publicField(WemapOsmRouter, "DEFAULT_OPTIONS", DEFAULT_OPTIONS);
815
+ __publicField(WemapOsmRouter, "WITHOUT_STAIRS_OPTIONS", WITHOUT_STAIRS_OPTIONS);
650
816
  class RemoteRouter {
651
817
  }
652
818
  class RemoteRouterServerUnreachable extends Error {
@@ -798,7 +964,7 @@ class CitywayRemoteRouter extends RemoteRouter {
798
964
  const legCoords = [];
799
965
  let legFrom, legTo;
800
966
  let transportInfo;
801
- let stepsInfo;
967
+ let minStepsInfo;
802
968
  if (legMode === "UNKNOWN") {
803
969
  continue itineraryLoop;
804
970
  }
@@ -811,7 +977,7 @@ class CitywayRemoteRouter extends RemoteRouter {
811
977
  name: jsonLeg.Arrival.Site.Name,
812
978
  coords: jsonToCoordinates$2(jsonLeg.Arrival.Site.Position)
813
979
  };
814
- stepsInfo = [];
980
+ minStepsInfo = [];
815
981
  for (const jsonPathLink of jsonLeg.pathLinks.PathLink) {
816
982
  let stepCoords;
817
983
  if (jsonPathLink.Geometry && jsonPathLink.Geometry !== "Null") {
@@ -824,11 +990,11 @@ class CitywayRemoteRouter extends RemoteRouter {
824
990
  legCoords.push(coords);
825
991
  }
826
992
  });
827
- stepsInfo.push(new StepInfo({
993
+ minStepsInfo.push({
828
994
  coords: stepCoords[0],
829
995
  distance: jsonPathLink.Distance,
830
996
  name: jsonPathLink.Departure.Site.Name
831
- }));
997
+ });
832
998
  }
833
999
  } else if (isRoutingModePublicTransport(legMode)) {
834
1000
  legFrom = {
@@ -857,11 +1023,11 @@ class CitywayRemoteRouter extends RemoteRouter {
857
1023
  }
858
1024
  });
859
1025
  }
860
- stepsInfo = [new StepInfo({
1026
+ minStepsInfo = [{
861
1027
  coords: legCoords[0],
862
1028
  name: jsonLeg.Line.Name,
863
1029
  distance: jsonLeg.Distance
864
- })];
1030
+ }];
865
1031
  } else {
866
1032
  Logger__default.default.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
867
1033
  continue;
@@ -875,7 +1041,7 @@ class CitywayRemoteRouter extends RemoteRouter {
875
1041
  from: legFrom,
876
1042
  to: legTo,
877
1043
  transportInfo,
878
- stepsInfo
1044
+ minStepsInfo
879
1045
  });
880
1046
  legs.push(leg);
881
1047
  }
@@ -1117,16 +1283,15 @@ class IdfmRemoteRouter extends RemoteRouter {
1117
1283
  newCoords = last(result);
1118
1284
  coords[_idCoordsInLeg] = newCoords;
1119
1285
  }
1120
- outputSteps.push(new StepInfo({
1286
+ outputSteps.push({
1121
1287
  ...step,
1122
1288
  coords: newCoords
1123
- }));
1289
+ });
1124
1290
  previousStep = step;
1125
1291
  }
1126
1292
  return outputSteps;
1127
1293
  }
1128
1294
  createRouterResponseFromJson(json, from, to) {
1129
- var _a;
1130
1295
  const routerResponse = new RouterResponse({ routerName: this.rname, from, to });
1131
1296
  if (!json || !json.journeys) {
1132
1297
  return routerResponse;
@@ -1147,7 +1312,9 @@ class IdfmRemoteRouter extends RemoteRouter {
1147
1312
  }
1148
1313
  return acc;
1149
1314
  }, []);
1150
- let stepsInfo;
1315
+ let minStepsInfo;
1316
+ let transportInfo;
1317
+ let mode = routingModeCorrespondance.get(jsonSection.mode);
1151
1318
  if (jsonSection.path) {
1152
1319
  const idfmIntermediateSteps = [];
1153
1320
  for (const jsonPathLink of jsonSection.path) {
@@ -1156,10 +1323,25 @@ class IdfmRemoteRouter extends RemoteRouter {
1156
1323
  distance: jsonPathLink.length
1157
1324
  });
1158
1325
  }
1159
- stepsInfo = this.findStepsCoord(legCoords, idfmIntermediateSteps);
1326
+ minStepsInfo = this.findStepsCoord(legCoords, idfmIntermediateSteps);
1327
+ }
1328
+ if (jsonSection.type === "public_transport") {
1329
+ transportInfo = {
1330
+ name: jsonSection.display_informations.code,
1331
+ routeColor: jsonSection.display_informations.color,
1332
+ routeTextColor: jsonSection.display_informations.text_color,
1333
+ directionName: jsonSection.display_informations.direction
1334
+ };
1335
+ mode = routingModeCorrespondance.get(jsonSection.display_informations.physical_mode);
1336
+ const legStep = {
1337
+ coords: legCoords[0],
1338
+ name: transportInfo.directionName,
1339
+ distance: jsonSection.geojson.properties[0].length
1340
+ };
1341
+ minStepsInfo = [legStep];
1160
1342
  }
1161
1343
  const leg = new Leg({
1162
- mode: routingModeCorrespondance.get(jsonSection.mode),
1344
+ mode,
1163
1345
  duration: jsonSection.duration,
1164
1346
  startTime: dateStringToTimestamp(jsonSection.departure_date_time, timeZone),
1165
1347
  endTime: dateStringToTimestamp(jsonSection.arrival_date_time, timeZone),
@@ -1172,23 +1354,9 @@ class IdfmRemoteRouter extends RemoteRouter {
1172
1354
  coords: toSection
1173
1355
  },
1174
1356
  coords: legCoords,
1175
- stepsInfo
1357
+ transportInfo,
1358
+ minStepsInfo
1176
1359
  });
1177
- if (jsonSection.type === "public_transport") {
1178
- leg.transportInfo = {
1179
- name: jsonSection.display_informations.code,
1180
- routeColor: jsonSection.display_informations.color,
1181
- routeTextColor: jsonSection.display_informations.text_color,
1182
- directionName: jsonSection.display_informations.direction
1183
- };
1184
- leg.mode = routingModeCorrespondance.get(jsonSection.display_informations.physical_mode);
1185
- const legStep = new StepInfo({
1186
- coords: leg.coords[0],
1187
- name: (_a = leg.transportInfo) == null ? void 0 : _a.directionName,
1188
- distance: jsonSection.geojson.properties[0].length
1189
- });
1190
- leg.stepsInfo = [legStep];
1191
- }
1192
1360
  legs.push(leg);
1193
1361
  }
1194
1362
  const itinerary = new Itinerary({
@@ -1353,19 +1521,19 @@ class OsrmRemoteRouter extends RemoteRouter {
1353
1521
  const legs = jsonItinerary.legs.map((jsonLeg) => {
1354
1522
  var _a;
1355
1523
  const legCoords = jsonLeg.steps.map((step) => step.geometry.coordinates.map(this.jsonToCoordinates)).flat().filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
1356
- const stepsInfo = (_a = jsonLeg.steps) == null ? void 0 : _a.map(({ maneuver, name, distance, duration }) => {
1524
+ const minStepsInfo = (_a = jsonLeg.steps) == null ? void 0 : _a.map(({ maneuver, name, distance, duration }) => {
1357
1525
  const stepCoords = this.jsonToCoordinates(maneuver.location);
1358
1526
  const distances = legCoords.map((coords) => coords.distanceTo(stepCoords));
1359
1527
  const idStepCoordsInLeg = distances.indexOf(Math.min(...distances));
1360
1528
  if (idStepCoordsInLeg < 0) {
1361
1529
  throw new Error("Osrm Parser: Cannot find step coords in leg coordinates");
1362
1530
  }
1363
- return new StepInfo({
1531
+ return {
1364
1532
  coords: stepCoords,
1365
1533
  name,
1366
1534
  distance,
1367
1535
  duration
1368
- });
1536
+ };
1369
1537
  });
1370
1538
  return new Leg({
1371
1539
  mode,
@@ -1377,7 +1545,7 @@ class OsrmRemoteRouter extends RemoteRouter {
1377
1545
  to: {
1378
1546
  coords: legCoords[legCoords.length - 1]
1379
1547
  },
1380
- stepsInfo
1548
+ minStepsInfo
1381
1549
  });
1382
1550
  });
1383
1551
  return new Itinerary({
@@ -1446,7 +1614,7 @@ class OtpRemoteRouter extends RemoteRouter {
1446
1614
  for (const jsonLeg of jsonItinerary.legs) {
1447
1615
  const legCoords = Polyline__default.default.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new geo.Coordinates(lat, lon));
1448
1616
  let transportInfo;
1449
- let stepsInfo;
1617
+ let minStepsInfo;
1450
1618
  if (isLegPT(jsonLeg)) {
1451
1619
  transportInfo = {
1452
1620
  name: jsonLeg.routeShortName,
@@ -1454,21 +1622,21 @@ class OtpRemoteRouter extends RemoteRouter {
1454
1622
  routeTextColor: jsonLeg.routeTextColor,
1455
1623
  directionName: jsonLeg.headsign
1456
1624
  };
1457
- stepsInfo = [new StepInfo({
1625
+ minStepsInfo = [{
1458
1626
  coords: legCoords[0],
1459
1627
  name: jsonLeg.headsign
1460
- })];
1628
+ }];
1461
1629
  } else {
1462
- stepsInfo = jsonLeg.steps.map((jsonStep) => {
1630
+ minStepsInfo = jsonLeg.steps.map((jsonStep) => {
1463
1631
  const distances = legCoords.map((coords) => coords.distanceTo(jsonToCoordinates(jsonStep)));
1464
1632
  const idStepCoordsInLeg = distances.indexOf(Math.min(...distances));
1465
1633
  if (idStepCoordsInLeg < 0) {
1466
1634
  throw new Error("OTP Parser: Cannot find closest step");
1467
1635
  }
1468
- return new StepInfo({
1636
+ return {
1469
1637
  coords: legCoords[idStepCoordsInLeg],
1470
1638
  name: jsonStep.streetName
1471
- });
1639
+ };
1472
1640
  });
1473
1641
  }
1474
1642
  const leg = new Leg({
@@ -1486,7 +1654,7 @@ class OtpRemoteRouter extends RemoteRouter {
1486
1654
  },
1487
1655
  coords: legCoords,
1488
1656
  transportInfo,
1489
- stepsInfo
1657
+ minStepsInfo
1490
1658
  });
1491
1659
  legs.push(leg);
1492
1660
  }
@@ -1552,19 +1720,17 @@ class WemapMultiRemoteRouter extends RemoteRouter {
1552
1720
  }
1553
1721
  }
1554
1722
  const WemapMultiRemoteRouter$1 = new WemapMultiRemoteRouter();
1723
+ const remoteRouters = [
1724
+ CitywayRemoteRouter$1,
1725
+ DeutscheBahnRemoteRouter$1,
1726
+ IdfmRemoteRouter$1,
1727
+ OsrmRemoteRouter$1,
1728
+ OtpRemoteRouter$1,
1729
+ WemapMultiRemoteRouter$1
1730
+ ];
1555
1731
  class RemoteRouterManager {
1556
- constructor() {
1557
- __publicField(this, "remoteRouters", [
1558
- CitywayRemoteRouter$1,
1559
- DeutscheBahnRemoteRouter$1,
1560
- IdfmRemoteRouter$1,
1561
- OsrmRemoteRouter$1,
1562
- OtpRemoteRouter$1,
1563
- WemapMultiRemoteRouter$1
1564
- ]);
1565
- }
1566
1732
  getRouterByName(name) {
1567
- return this.remoteRouters.find((remoteRouter) => remoteRouter.rname === name);
1733
+ return remoteRouters.find((remoteRouter) => remoteRouter.rname === name);
1568
1734
  }
1569
1735
  async getItineraries(name, endpointUrl, mode, waypoints, options) {
1570
1736
  const router = this.getRouterByName(name);
@@ -1573,9 +1739,9 @@ class RemoteRouterManager {
1573
1739
  }
1574
1740
  return router.getItineraries(endpointUrl, mode, waypoints, options);
1575
1741
  }
1576
- async getItinerariesWithFallback(remoteRouters, mode, waypoints, options) {
1742
+ async getItinerariesWithFallback(remoteRouters2, mode, waypoints, options) {
1577
1743
  let routerResponse;
1578
- for (const { name, endpointUrl } of remoteRouters) {
1744
+ for (const { name, endpointUrl } of remoteRouters2) {
1579
1745
  routerResponse = await this.getItineraries(name, endpointUrl, mode, waypoints, options);
1580
1746
  if (routerResponse.itineraries.length) {
1581
1747
  return routerResponse;
@@ -1583,7 +1749,7 @@ class RemoteRouterManager {
1583
1749
  }
1584
1750
  if (!routerResponse) {
1585
1751
  routerResponse = new RouterResponse({
1586
- routerName: remoteRouters.map((rr) => rr.name),
1752
+ routerName: remoteRouters2.map((rr) => rr.name),
1587
1753
  from: waypoints[0],
1588
1754
  to: waypoints[waypoints.length]
1589
1755
  });
@@ -1618,7 +1784,7 @@ class WemapMultiRouter {
1618
1784
  from: start,
1619
1785
  to: end
1620
1786
  });
1621
- const remoteRouters = ((_a = options == null ? void 0 : options.remoteRouters) == null ? void 0 : _a.filter(({ name }) => name !== WemapMultiRemoteRouter$1.rname)) || [];
1787
+ const remoteRouters2 = ((_a = options == null ? void 0 : options.remoteRouters) == null ? void 0 : _a.filter(({ name }) => name !== WemapMultiRemoteRouter$1.rname)) || [];
1622
1788
  let ioMapsToTest = this.maps;
1623
1789
  const targetMaps = options == null ? void 0 : options.targetMaps;
1624
1790
  if (targetMaps) {
@@ -1633,7 +1799,7 @@ class WemapMultiRouter {
1633
1799
  }
1634
1800
  if (!ioMapsToTest.length) {
1635
1801
  try {
1636
- return await RemoteRouterManager$1.getItinerariesWithFallback(remoteRouters, mode, waypoints);
1802
+ return await RemoteRouterManager$1.getItinerariesWithFallback(remoteRouters2, mode, waypoints);
1637
1803
  } catch (e) {
1638
1804
  if (!isRoutingError(e)) {
1639
1805
  throw e;
@@ -1644,7 +1810,7 @@ class WemapMultiRouter {
1644
1810
  }
1645
1811
  let ioMapItinerary;
1646
1812
  const mapWithStart = ioMapsToTest.find((map) => map.isPointInside(start));
1647
- const wemapOsmRouterOptions = !options || !("useStairs" in options) || options.useStairs ? WemapOsmRouterOptions.DEFAULT : WemapOsmRouterOptions.WITHOUT_STAIRS;
1813
+ const wemapOsmRouterOptions = !options || !("useStairs" in options) || options.useStairs ? WemapOsmRouter.DEFAULT_OPTIONS : WemapOsmRouter.WITHOUT_STAIRS_OPTIONS;
1648
1814
  if (mapWithStart && mapWithStart.isPointInside(end)) {
1649
1815
  try {
1650
1816
  ioMapItinerary = mapWithStart.getItineraryInsideMap(start, end, wemapOsmRouterOptions);
@@ -1663,7 +1829,7 @@ class WemapMultiRouter {
1663
1829
  let remoteRouterResponse;
1664
1830
  if (!mapWithStart && !mapWithEnd) {
1665
1831
  try {
1666
- return await RemoteRouterManager$1.getItinerariesWithFallback(remoteRouters, mode, waypoints);
1832
+ return await RemoteRouterManager$1.getItinerariesWithFallback(remoteRouters2, mode, waypoints);
1667
1833
  } catch (e) {
1668
1834
  if (!isRoutingError(e)) {
1669
1835
  throw e;
@@ -1681,7 +1847,7 @@ class WemapMultiRouter {
1681
1847
  try {
1682
1848
  ioMapItinerary = mapWithStart.getBestItineraryFromStartToEntryPoints(start, end, wemapOsmRouterOptions);
1683
1849
  remoteRouterResponse = await RemoteRouterManager$1.getItinerariesWithFallback(
1684
- remoteRouters,
1850
+ remoteRouters2,
1685
1851
  mode,
1686
1852
  [ioMapItinerary.to, end]
1687
1853
  );
@@ -1692,7 +1858,7 @@ class WemapMultiRouter {
1692
1858
  if (!isRoutingError(e)) {
1693
1859
  throw e;
1694
1860
  }
1695
- routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using wemap router on local map "${mapWithStart.name}" and an itinerary from "entrypoints" to "end" using remote routers (${remoteRouters.map((r) => r.name).join(", ")}), but failed. Details: ${e.message}.`;
1861
+ routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using wemap router on local map "${mapWithStart.name}" and an itinerary from "entrypoints" to "end" using remote routers (${remoteRouters2.map((r) => r.name).join(", ")}), but failed. Details: ${e.message}.`;
1696
1862
  return routerResponse;
1697
1863
  }
1698
1864
  routerResponse.itineraries = remoteRouterResponse.itineraries.map(
@@ -1710,7 +1876,7 @@ class WemapMultiRouter {
1710
1876
  try {
1711
1877
  ioMapItinerary = mapWithEnd.getBestItineraryFromEntryPointsToEnd(start, end, wemapOsmRouterOptions);
1712
1878
  remoteRouterResponse = await RemoteRouterManager$1.getItinerariesWithFallback(
1713
- remoteRouters,
1879
+ remoteRouters2,
1714
1880
  mode,
1715
1881
  [start, ioMapItinerary.from]
1716
1882
  );
@@ -1721,7 +1887,7 @@ class WemapMultiRouter {
1721
1887
  if (!isRoutingError(e)) {
1722
1888
  throw e;
1723
1889
  }
1724
- routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using remote routers (${remoteRouters.map((r) => r.name).join(", ")}) and an itinerary from "entrypoints" to "end" using wemap router on local map "${mapWithEnd.name}", but failed. Details: ${e.message}.`;
1890
+ routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using remote routers (${remoteRouters2.map((r) => r.name).join(", ")}) and an itinerary from "entrypoints" to "end" using wemap router on local map "${mapWithEnd.name}", but failed. Details: ${e.message}.`;
1725
1891
  return routerResponse;
1726
1892
  }
1727
1893
  routerResponse.itineraries = remoteRouterResponse.itineraries.map(
@@ -1748,7 +1914,7 @@ class WemapMultiRouter {
1748
1914
  ioMapItinerary1 = mapWithStart.getBestItineraryFromStartToEntryPoints(start, end, wemapOsmRouterOptions);
1749
1915
  ioMapItinerary2 = mapWithEnd.getBestItineraryFromEntryPointsToEnd(start, end, wemapOsmRouterOptions);
1750
1916
  remoteRouterResponse = await RemoteRouterManager$1.getItinerariesWithFallback(
1751
- remoteRouters,
1917
+ remoteRouters2,
1752
1918
  mode,
1753
1919
  [ioMapItinerary1.to, ioMapItinerary2.from]
1754
1920
  );
@@ -1759,7 +1925,7 @@ class WemapMultiRouter {
1759
1925
  if (!isRoutingError(e)) {
1760
1926
  throw e;
1761
1927
  }
1762
- routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints1" using wemap router on local map "${mapWithStart.name}", an itinerary from "entrypoints1" to "entrypoints2" using remote routers (${remoteRouters.map((r) => r.name).join(", ")}) and an itinerary from "entrypoints2" to "end" using wemap router on local map "${mapWithEnd.name}", but failed. Details: ${e.message}.`;
1928
+ routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints1" using wemap router on local map "${mapWithStart.name}", an itinerary from "entrypoints1" to "entrypoints2" using remote routers (${remoteRouters2.map((r) => r.name).join(", ")}) and an itinerary from "entrypoints2" to "end" using wemap router on local map "${mapWithEnd.name}", but failed. Details: ${e.message}.`;
1763
1929
  return routerResponse;
1764
1930
  }
1765
1931
  routerResponse.itineraries = remoteRouterResponse.itineraries.map(
@@ -1776,46 +1942,63 @@ class WemapMultiRouter {
1776
1942
  }
1777
1943
  }
1778
1944
  class CustomNetworkMap {
1779
- constructor(network, entryPoints, bounds = null, name = null) {
1945
+ constructor(graph, entryPoints, bounds = null, name = null) {
1780
1946
  __publicField(this, "name");
1781
- __publicField(this, "network");
1947
+ __publicField(this, "graph");
1782
1948
  __publicField(this, "router");
1783
1949
  __publicField(this, "bounds");
1784
1950
  __publicField(this, "entryPoints");
1785
1951
  __publicField(this, "disabledWays", /* @__PURE__ */ new Set());
1786
1952
  this.name = name;
1787
- this.network = network;
1788
- this.router = new WemapOsmRouter(network);
1953
+ this.graph = graph;
1954
+ this.router = new WemapOsmRouter(graph);
1789
1955
  entryPoints.forEach((entryPoint) => {
1790
- if (!network.nodes.includes(entryPoint)) {
1956
+ if (!graph.vertices.includes(entryPoint)) {
1791
1957
  throw new Error(`Cannot find entry point ${entryPoint.coords.toString()} in network "${name}"`);
1792
1958
  }
1793
1959
  });
1794
1960
  this.entryPoints = entryPoints;
1795
1961
  if (bounds) {
1796
- this.bounds = helpers.polygon([bounds.map((coords) => [coords.lng, coords.lat])]);
1962
+ this.bounds = bounds;
1797
1963
  } else {
1798
- const polygon = [network.nodes.map((node) => [node.coords.lng, node.coords.lat])];
1964
+ const polygon = [graph.vertices.map((vertex) => [vertex.coords.lng, vertex.coords.lat])];
1799
1965
  const convexHull = convexHullFn__default.default({ type: "polygon", coordinates: polygon });
1800
1966
  if (!convexHull) {
1801
1967
  throw new Error(`Cannot calculate convexHull of network "${name}"`);
1802
1968
  }
1803
- this.bounds = convexHull;
1969
+ this.bounds = {
1970
+ type: "MultiPolygon",
1971
+ coordinates: [convexHull.geometry.coordinates]
1972
+ };
1804
1973
  }
1805
1974
  }
1806
1975
  static fromOsmXml(osmXmlString, name = null) {
1807
1976
  const osmModel = osm.OsmParser.parseOsmXmlString(osmXmlString);
1808
- const network = osm.OsmNetworkUtils.createNetworkFromOsmModel(osmModel);
1809
- const entryPoints = osmModel.nodes.filter(({ tags }) => tags && tags["wemap:routing-io"]).map((osmNode) => network.getNodeByCoords(osmNode.coords));
1977
+ const graph = OsmGraph.fromOsmModel(osmModel);
1978
+ const entryPoints = graph.vertices.filter(({ data: { tags } }) => tags && tags["wemap:routing-io"]);
1810
1979
  if (entryPoints.some((el) => el === null) || new Set(entryPoints).size !== entryPoints.length) {
1811
1980
  throw new Error("Cannot parse wemap:routing-io correctly");
1812
1981
  }
1813
- const wayBounds = osmModel.ways.find(({ tags }) => tags["wemap:routing-bounds"]);
1814
- if (!wayBounds) {
1982
+ const bounds = {
1983
+ type: "MultiPolygon",
1984
+ coordinates: []
1985
+ };
1986
+ osmModel.ways.filter(({ tags }) => tags["wemap:routing-bounds"]).forEach((way) => {
1987
+ bounds.coordinates.push([
1988
+ way.nodes.reduce((acc, node) => {
1989
+ acc.push([node.coords.lng, node.coords.lat]);
1990
+ return acc;
1991
+ }, [])
1992
+ ]);
1993
+ });
1994
+ osmModel.relations.filter((rel) => rel.tags["wemap:routing-bounds"] && rel.isMultipolygon()).forEach((rel) => {
1995
+ const polygon = rel.getGeoJsonPolygon();
1996
+ polygon && bounds.coordinates.push(polygon.coordinates);
1997
+ });
1998
+ if (!bounds.coordinates.length) {
1815
1999
  throw new Error('Search bounds is undefined. Please use OSM tag : "wemap:routing-bounds=yes"');
1816
2000
  }
1817
- const bounds = wayBounds.nodes.map((node) => node.coords);
1818
- return new CustomNetworkMap(network, entryPoints, bounds, name);
2001
+ return new CustomNetworkMap(graph, entryPoints, bounds, name);
1819
2002
  }
1820
2003
  isPointInside(coordinates) {
1821
2004
  return pointInPolygon__default.default([coordinates.lng, coordinates.lat], this.bounds);
@@ -1858,44 +2041,18 @@ class CustomNetworkMap {
1858
2041
  return this.router.getItinerary(start, end, options);
1859
2042
  }
1860
2043
  enableWay(osmId) {
1861
- this.network.edges.filter((edge) => {
1862
- var _a;
1863
- return ((_a = edge.builtFrom) == null ? void 0 : _a.id) === osmId;
1864
- }).forEach((e) => this.router.disabledEdges.delete(e));
2044
+ this.graph.edges.filter((edge) => edge.data.id === osmId).forEach((e) => this.router.disabledEdges.delete(e));
1865
2045
  this.disabledWays.delete(osmId);
1866
2046
  }
1867
2047
  disableWay(osmId) {
1868
- this.network.edges.filter((edge) => {
1869
- var _a;
1870
- return ((_a = edge.builtFrom) == null ? void 0 : _a.id) === osmId;
1871
- }).forEach((e) => this.router.disabledEdges.add(e));
2048
+ this.graph.edges.filter((edge) => edge.data.id === osmId).forEach((e) => this.router.disabledEdges.add(e));
1872
2049
  this.disabledWays.add(osmId);
1873
2050
  }
1874
2051
  }
1875
- function getTurnInfoFromAngle(_angle) {
1876
- let direction, directionExtra;
1877
- const directionAngle = maths.rad2deg(maths.diffAngle(_angle, Math.PI));
1878
- const directionAngleAbs = Math.abs(directionAngle);
1879
- if (directionAngleAbs <= 20) {
1880
- direction = "straight";
1881
- } else {
1882
- direction = directionAngle > 0 ? "left" : "right";
1883
- if (directionAngleAbs < 55) {
1884
- directionExtra = "slight";
1885
- } else if (directionAngleAbs > 120) {
1886
- directionExtra = "sharp";
1887
- }
1888
- }
1889
- return { direction, directionExtra };
1890
- }
1891
- const WemapOsmRouterUtils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1892
- __proto__: null,
1893
- getTurnInfoFromAngle
1894
- }, Symbol.toStringTag, { value: "Module" }));
1895
2052
  class ItineraryInfoManager {
1896
2053
  constructor(itinerary = null) {
1897
2054
  __publicField(this, "_itinerary", null);
1898
- __publicField(this, "_mapMatching", null);
2055
+ __publicField(this, "_geoGraphProjectionHandler", null);
1899
2056
  __publicField(this, "_steps", []);
1900
2057
  __publicField(this, "_coordsNextStep", []);
1901
2058
  __publicField(this, "_coordsPreviousStep", []);
@@ -1913,8 +2070,8 @@ class ItineraryInfoManager {
1913
2070
  }
1914
2071
  this._itinerary = itinerary;
1915
2072
  this._steps = itinerary.steps;
1916
- const network = itinerary.toNetwork();
1917
- this._mapMatching = new geo.MapMatching(network);
2073
+ const graph = itinerary.toGraph();
2074
+ this._geoGraphProjectionHandler = new geo.GeoGraphProjectionHandler(graph);
1918
2075
  this._coordsNextStep = new Array(itinerary.coords.length);
1919
2076
  this._coordsPreviousStep = new Array(itinerary.coords.length);
1920
2077
  this._coordsDistanceTraveled = new Array(itinerary.coords.length);
@@ -1939,15 +2096,15 @@ class ItineraryInfoManager {
1939
2096
  });
1940
2097
  }
1941
2098
  getInfo(position) {
1942
- if (!this._itinerary || !this._mapMatching) {
2099
+ if (!this._itinerary || !this._geoGraphProjectionHandler) {
1943
2100
  return null;
1944
2101
  }
1945
- const projection = this._mapMatching.getProjection(position);
2102
+ const projection = this._geoGraphProjectionHandler.getProjection(position);
1946
2103
  if (!projection) {
1947
2104
  return null;
1948
2105
  }
1949
2106
  let itineraryInfo = null;
1950
- if (projection.nearestElement instanceof geo.GraphNode) {
2107
+ if (projection.nearestElement instanceof geo.GeoGraphVertex) {
1951
2108
  const idx = this._itinerary.coords.findIndex(
1952
2109
  (coords) => projection.nearestElement.coords === coords
1953
2110
  );
@@ -1966,14 +2123,14 @@ class ItineraryInfoManager {
1966
2123
  traveledPercentage: traveledDistance / this._itinerary.distance,
1967
2124
  remainingPercentage: remainingDistance / this._itinerary.distance
1968
2125
  };
1969
- } else if (projection.nearestElement instanceof geo.GraphEdge) {
1970
- let firstNode = projection.nearestElement.node1.coords;
2126
+ } else if (projection.nearestElement instanceof geo.GeoGraphEdge) {
2127
+ let firstNode = projection.nearestElement.vertex1.coords;
1971
2128
  let idx = this._itinerary.coords.findIndex((coords) => firstNode === coords);
1972
2129
  if (idx === -1) {
1973
2130
  throw new Error("ItineraryInfoManager: could not find projection in itinerary (Edge)");
1974
2131
  }
1975
- if (idx === this._itinerary.coords.length - 1 || this._itinerary.coords[idx + 1] !== projection.nearestElement.node2.coords) {
1976
- firstNode = projection.nearestElement.node2.coords;
2132
+ if (idx === this._itinerary.coords.length - 1 || this._itinerary.coords[idx + 1] !== projection.nearestElement.vertex2.coords) {
2133
+ firstNode = projection.nearestElement.vertex2.coords;
1977
2134
  idx--;
1978
2135
  }
1979
2136
  const traveledDistance = this._coordsDistanceTraveled[idx] + projection.coords.distanceTo(firstNode);
@@ -1999,17 +2156,15 @@ exports.IdfmRemoteRouter = IdfmRemoteRouter$1;
1999
2156
  exports.Itinerary = Itinerary;
2000
2157
  exports.ItineraryInfoManager = ItineraryInfoManager;
2001
2158
  exports.Leg = Leg;
2159
+ exports.OsmGraph = OsmGraph;
2160
+ exports.OsmRouter = WemapOsmRouter;
2002
2161
  exports.OsrmRemoteRouter = OsrmRemoteRouter$1;
2003
2162
  exports.OtpRemoteRouter = OtpRemoteRouter$1;
2004
2163
  exports.RemoteRouterManager = RemoteRouterManager$1;
2005
2164
  exports.RemoteRouterServerUnreachable = RemoteRouterServerUnreachable;
2006
2165
  exports.RouterResponse = RouterResponse;
2007
- exports.StepInfo = StepInfo;
2008
2166
  exports.WemapMultiRemoteRouter = WemapMultiRemoteRouter$1;
2009
2167
  exports.WemapMultiRemoteRouterPayload = WemapMultiRemoteRouterPayload;
2010
2168
  exports.WemapMultiRouter = WemapMultiRouter;
2011
- exports.WemapOsmRouter = WemapOsmRouter;
2012
- exports.WemapOsmRouterOptions = WemapOsmRouterOptions;
2013
- exports.WemapOsmRouterUtils = WemapOsmRouterUtils;
2014
2169
  exports.getDurationFromLength = getDurationFromLength;
2015
2170
  //# sourceMappingURL=index.js.map