@wemap/routers 11.4.0 → 11.7.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/dist/index.js CHANGED
@@ -5,7 +5,7 @@ var __publicField = (obj, key, value) => {
5
5
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
6
  return value;
7
7
  };
8
- Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
8
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
9
9
  const geo = require("@wemap/geo");
10
10
  const maths = require("@wemap/maths");
11
11
  const salesman = require("@wemap/salesman.js");
@@ -14,12 +14,6 @@ const Logger = require("@wemap/logger");
14
14
  const Polyline = require("@mapbox/polyline");
15
15
  const pointInPolygon = require("@turf/boolean-point-in-polygon");
16
16
  const convexHullFn = require("@turf/convex");
17
- const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
18
- const salesman__default = /* @__PURE__ */ _interopDefaultLegacy(salesman);
19
- const Logger__default = /* @__PURE__ */ _interopDefaultLegacy(Logger);
20
- const Polyline__default = /* @__PURE__ */ _interopDefaultLegacy(Polyline);
21
- const pointInPolygon__default = /* @__PURE__ */ _interopDefaultLegacy(pointInPolygon);
22
- const convexHullFn__default = /* @__PURE__ */ _interopDefaultLegacy(convexHullFn);
23
17
  function getDurationFromLength(length, speed = 5) {
24
18
  return length / (speed * 1e3 / 3600);
25
19
  }
@@ -245,6 +239,8 @@ class Leg {
245
239
  stepsGenerationRules
246
240
  });
247
241
  }
242
+ // TODO: Remove when possible...
243
+ // Livemap specific
248
244
  multiplyLevel(levelFactor) {
249
245
  this.from.coords.level = geo.Level.multiplyBy(this.from.coords.level, levelFactor);
250
246
  this.to.coords.level = geo.Level.multiplyBy(this.to.coords.level, levelFactor);
@@ -285,6 +281,7 @@ class Leg {
285
281
  firstStep: stepId === 0,
286
282
  lastStep: stepId === stepsInfo.length - 1,
287
283
  distance,
284
+ // stepInfo.distance is overwritten
288
285
  duration: stepInfo.duration || getDurationFromLength(distance),
289
286
  levelChange: stepInfo.levelChange || null,
290
287
  extras: stepInfo.extras || null
@@ -384,6 +381,9 @@ class Itinerary {
384
381
  legs
385
382
  });
386
383
  }
384
+ /**
385
+ * Convert lat/lng/level? points to Itinerary
386
+ */
387
387
  static fromOrderedPointsArray(points, start, end) {
388
388
  const pointToCoordinates = (point) => new geo.Coordinates(point[0], point[1], null, point[2]);
389
389
  return this.fromOrderedCoordinates(
@@ -392,6 +392,9 @@ class Itinerary {
392
392
  pointToCoordinates(end)
393
393
  );
394
394
  }
395
+ /**
396
+ * Convert ordered Coordinates to Itinerary
397
+ */
395
398
  static fromOrderedCoordinates(coords, from, to, mode = "WALK") {
396
399
  const leg = new Leg({
397
400
  from: { coords: from },
@@ -446,11 +449,15 @@ class Itinerary {
446
449
  legs: [leg]
447
450
  });
448
451
  }
452
+ // TODO: Remove when possible...
453
+ // Livemap specific
449
454
  multiplyLevel(levelFactor) {
450
455
  this.from.level = geo.Level.multiplyBy(this.from.level, levelFactor);
451
456
  this.to.level = geo.Level.multiplyBy(this.to.level, levelFactor);
452
457
  this.legs.forEach((leg) => leg.multiplyLevel(levelFactor));
453
458
  }
459
+ // TODO: Remove when possible...
460
+ // Livemap specific
454
461
  forceUnknownLevelTo0() {
455
462
  this.from.level = this.from.level || 0;
456
463
  this.to.level = this.to.level || 0;
@@ -482,6 +489,14 @@ class Itinerary {
482
489
  }
483
490
  };
484
491
  }
492
+ /**
493
+ * Update steps info thanks to the coordinates of the whole itinerary.
494
+ * This method will update:
495
+ * - all steps number
496
+ * - first/last steps
497
+ * - previousBearing/nextBearing/angle of first and last step of each leg
498
+ * - distance/duration of first and last step of each leg
499
+ */
485
500
  updateStepsFromLegs() {
486
501
  const itineraryCoords = this.coords.filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
487
502
  const steps = this.legs.map((leg) => leg.steps).flat();
@@ -566,6 +581,8 @@ class RouterResponse {
566
581
  error: json.error
567
582
  });
568
583
  }
584
+ // TODO: Remove when possible...
585
+ // Livemap specific
569
586
  multiplyLevel(levelFactor) {
570
587
  this.from.level = geo.Level.multiplyBy(this.from.level, levelFactor);
571
588
  this.to.level = geo.Level.multiplyBy(this.to.level, levelFactor);
@@ -579,7 +596,7 @@ const DEFAULT_WAY_SELECTOR = (way) => {
579
596
  const isElevatorArea = way.tags.highway === "elevator" && way.isArea;
580
597
  return HIGHWAYS_PEDESTRIANS.includes(way.tags.highway) && !isElevatorArea && !["no", "private"].includes(way.tags.access) || way.tags.footway === "sidewalk" || way.tags.public_transport === "platform" || way.tags.railway === "platform";
581
598
  };
582
- const _OsmGraph = class extends geo.GeoGraph {
599
+ const _OsmGraph = class _OsmGraph extends geo.GeoGraph {
583
600
  getVertexByCoords(coords) {
584
601
  return geo.GeoGraph.getVertexByCoords(this.vertices, coords);
585
602
  }
@@ -590,53 +607,98 @@ const _OsmGraph = class extends geo.GeoGraph {
590
607
  return super.getEdgeByName(name);
591
608
  }
592
609
  static fromOsmModel(osmModel, waySelectionFilter = DEFAULT_WAY_SELECTOR) {
593
- const nodes = [];
610
+ const vertices = [];
594
611
  const edges = [];
595
- const nodesCreated = {};
596
- const elevatorNodes = [];
597
- const getOrCreateNode = (osmNode) => {
598
- let node = nodesCreated[osmNode.id];
599
- if (!node) {
600
- node = new geo.GeoGraphVertex(osmNode.coords, { data: osmNode, name: osmNode.tags.name });
601
- nodesCreated[osmNode.id] = node;
602
- nodes.push(node);
603
- if (osmNode.tags.highway === "elevator") {
604
- elevatorNodes.push(node);
612
+ const elevatorVertices = [];
613
+ const getOrCreateVertex = (osmNode, forceLevel = null) => {
614
+ let vertex = vertices.find(
615
+ (vertex2) => vertex2.data.id === osmNode.id && (forceLevel !== null ? geo.Level.intersect(vertex2.coords.level, forceLevel) : true)
616
+ ) || null;
617
+ if (vertex) {
618
+ return vertex;
619
+ }
620
+ const otherVertex = vertices.find((v) => v.data.id === osmNode.id);
621
+ if (otherVertex) {
622
+ if (otherVertex && otherVertex.coords.level !== null) {
623
+ throw new Error(`An error occured because repeat_on as not been set on node ${osmNode.coords} for level ${forceLevel}`);
624
+ }
625
+ otherVertex.coords.level = forceLevel;
626
+ }
627
+ let levelsToGenerate = [null];
628
+ if ("level" in osmNode.tags) {
629
+ levelsToGenerate = [osmNode.coords.level];
630
+ if ("repeat_on" in osmNode.tags) {
631
+ levelsToGenerate.push(...osmNode.tags.repeat_on.split(";").map(geo.Level.fromString));
605
632
  }
633
+ } else if (forceLevel !== null) {
634
+ levelsToGenerate = [forceLevel];
606
635
  }
607
- return node;
636
+ levelsToGenerate.forEach((level) => {
637
+ const newVertex = new geo.GeoGraphVertex(osmNode.coords.clone(), { data: osmNode, name: osmNode.tags.name });
638
+ newVertex.coords.level = level;
639
+ vertices.push(newVertex);
640
+ if (geo.Level.intersect(newVertex.coords.level, forceLevel) || forceLevel === null && "level" in osmNode.tags) {
641
+ vertex = newVertex;
642
+ }
643
+ });
644
+ if (!vertex) {
645
+ throw new Error(`Unable to parse vertex {id: ${osmNode.id}, coords: ${osmNode.coords.lat}, ${osmNode.coords.lng}}. Please check "level" tag.`);
646
+ }
647
+ if (osmNode.tags.highway === "elevator" && vertex) {
648
+ elevatorVertices.push(vertex);
649
+ }
650
+ return vertex;
608
651
  };
609
652
  osmModel.ways.forEach((way) => {
610
653
  if (!waySelectionFilter(way)) {
611
654
  return;
612
655
  }
613
- let firstNode = getOrCreateNode(way.nodes[0]);
614
- for (let i = 1; i < way.nodes.length; i++) {
615
- const secondNode = getOrCreateNode(way.nodes[i]);
616
- const edge = new geo.GeoGraphEdge(
617
- firstNode,
618
- secondNode,
619
- { data: way, name: way.tags.name, level: way.level }
620
- );
621
- _OsmGraph.manageOneWay(edge, way);
622
- edges.push(edge);
623
- firstNode = secondNode;
656
+ let levelsToGenerate = [null];
657
+ if ("level" in way.tags) {
658
+ levelsToGenerate = [way.level];
659
+ if ("repeat_on" in way.tags) {
660
+ levelsToGenerate.push(...way.tags.repeat_on.split(";").map(geo.Level.fromString));
661
+ }
624
662
  }
663
+ levelsToGenerate.forEach((level) => {
664
+ let firstVertex = getOrCreateVertex(way.nodes[0], level);
665
+ for (let i = 1; i < way.nodes.length; i++) {
666
+ const secondVertex = getOrCreateVertex(way.nodes[i], level);
667
+ const edge = new geo.GeoGraphEdge(
668
+ firstVertex,
669
+ secondVertex,
670
+ { data: way, name: way.tags.name, level }
671
+ );
672
+ _OsmGraph.manageOneWay(edge, way);
673
+ edges.push(edge);
674
+ firstVertex = secondVertex;
675
+ }
676
+ });
625
677
  });
626
678
  osmModel.ways.filter((way) => way.isElevator).forEach((way) => {
627
- way.nodes.forEach((node) => {
628
- const connectedWays = node.ways.filter((otherWay) => otherWay != way);
629
- if (connectedWays.length) {
630
- const graphVertex = getOrCreateNode(node);
631
- graphVertex.data.tags.highway = "elevator";
632
- elevatorNodes.push(graphVertex);
633
- }
679
+ const entryVertices = way.nodes.map((node) => vertices.filter((v) => v.data.id === node.id)).flat();
680
+ const elevatorLevel = entryVertices.reduce((acc, v) => geo.Level.union(acc, v.coords.level), null);
681
+ const elevatorCenter = way.nodes.reduce((acc, node) => [acc[0] + node.coords.lat, acc[1] + node.coords.lng], [0, 0]).map((val) => val / way.nodes.length);
682
+ const elevatorCenterCoords = new geo.Coordinates(elevatorCenter[0], elevatorCenter[1], null, elevatorLevel);
683
+ const elevatorCenterVertex = new geo.GeoGraphVertex(elevatorCenterCoords, { data: way, name: way.tags.name });
684
+ vertices.push(elevatorCenterVertex);
685
+ entryVertices.forEach((entryVertex) => {
686
+ const newEdge = new geo.GeoGraphEdge(
687
+ elevatorCenterVertex,
688
+ entryVertex,
689
+ {
690
+ level: geo.Level.intersection(elevatorCenterVertex.coords.level, entryVertex.coords.level),
691
+ data: way
692
+ }
693
+ );
694
+ edges.push(newEdge);
634
695
  });
696
+ elevatorVertices.push(elevatorCenterVertex);
635
697
  });
636
- elevatorNodes.forEach((node) => {
637
- _OsmGraph.createNodesAndEdgesFromElevator(nodes, edges, node);
698
+ elevatorVertices.forEach((node) => {
699
+ _OsmGraph.createNodesAndEdgesFromElevator(vertices, edges, node);
638
700
  });
639
- return new _OsmGraph(nodes, edges, true);
701
+ return new _OsmGraph(vertices, edges, true);
640
702
  }
641
703
  static manageOneWay(edge, way) {
642
704
  const { highway, oneway, conveying } = way.tags;
@@ -647,59 +709,58 @@ const _OsmGraph = class extends geo.GeoGraph {
647
709
  edge.vertex2 = tmpNode;
648
710
  }
649
711
  }
650
- static createNodesAndEdgesFromElevator(nodes, edges, elevatorNode) {
651
- const createdNodes = [];
712
+ static createNodesAndEdgesFromElevator(vertices, edges, elevatorVertex) {
713
+ const createdVertices = [];
652
714
  const getOrCreateLevelVertex = (level) => {
653
- let levelVertex = createdNodes.find(({ coords }) => geo.Level.equals(level, coords.level));
715
+ let levelVertex = createdVertices.find(({ coords }) => geo.Level.equals(level, coords.level));
654
716
  if (!levelVertex) {
655
- levelVertex = new geo.GeoGraphVertex(elevatorNode.coords.clone(), {
656
- data: elevatorNode.data,
657
- name: `${elevatorNode.name} (elevator lvl: ${level})`
717
+ levelVertex = new geo.GeoGraphVertex(elevatorVertex.coords.clone(), {
718
+ data: elevatorVertex.data,
719
+ name: `${elevatorVertex.name} (elevator lvl: ${level})`
658
720
  });
659
721
  levelVertex.coords.level = level;
660
- createdNodes.push(levelVertex);
661
- nodes.push(levelVertex);
722
+ createdVertices.push(levelVertex);
723
+ vertices.push(levelVertex);
662
724
  }
663
725
  return levelVertex;
664
726
  };
665
- elevatorNode.edges.forEach((edge) => {
727
+ elevatorVertex.edges.forEach((edge) => {
666
728
  if (geo.Level.isRange(edge.level)) {
667
- throw new Error("Cannot handle this elevator edge due to ambiguity");
729
+ throw new Error(`Cannot handle this elevator edge due to ambiguity (vertex: ${edge.vertex1.coords})`);
668
730
  }
669
731
  const levelVertex = getOrCreateLevelVertex(edge.level);
670
- if (edge.vertex1 === elevatorNode) {
732
+ if (edge.vertex1 === elevatorVertex) {
671
733
  edge.vertex1 = levelVertex;
672
734
  } else {
673
735
  edge.vertex2 = levelVertex;
674
736
  }
675
- levelVertex.edges.push(edge);
676
737
  });
677
- for (let i = 0; i < createdNodes.length; i++) {
678
- for (let j = i + 1; j < createdNodes.length; j++) {
679
- const createdNode1 = createdNodes[i];
680
- const createdNode2 = createdNodes[j];
681
- if (createdNode1.coords.level === null || createdNode2.coords.level === null) {
738
+ for (let i = 0; i < createdVertices.length; i++) {
739
+ for (let j = i + 1; j < createdVertices.length; j++) {
740
+ const createdVertex1 = createdVertices[i];
741
+ const createdVertex2 = createdVertices[j];
742
+ if (createdVertex1.coords.level === null || createdVertex2.coords.level === null) {
682
743
  continue;
683
744
  }
684
- const minLevel = Math.min(createdNode1.coords.level, createdNode2.coords.level);
685
- const maxLevel = Math.max(createdNode1.coords.level, createdNode2.coords.level);
745
+ const minLevel = Math.min(createdVertex1.coords.level, createdVertex2.coords.level);
746
+ const maxLevel = Math.max(createdVertex1.coords.level, createdVertex2.coords.level);
686
747
  const newEdge = new geo.GeoGraphEdge(
687
- createdNode1,
688
- createdNode2,
689
- { data: elevatorNode.data, name: elevatorNode.name, level: [minLevel, maxLevel] }
748
+ createdVertex1,
749
+ createdVertex2,
750
+ { data: elevatorVertex.data, name: elevatorVertex.name, level: [minLevel, maxLevel] }
690
751
  );
691
752
  edges.push(newEdge);
692
753
  }
693
754
  }
694
- const elevatorNodeIndex = nodes.indexOf(elevatorNode);
755
+ const elevatorNodeIndex = vertices.indexOf(elevatorVertex);
695
756
  if (elevatorNodeIndex > -1) {
696
- nodes.splice(elevatorNodeIndex, 1);
757
+ vertices.splice(elevatorNodeIndex, 1);
697
758
  }
698
759
  }
699
760
  };
761
+ __publicField(_OsmGraph, "HIGHWAYS_PEDESTRIANS", HIGHWAYS_PEDESTRIANS);
762
+ __publicField(_OsmGraph, "DEFAULT_WAY_SELECTOR", DEFAULT_WAY_SELECTOR);
700
763
  let OsmGraph = _OsmGraph;
701
- __publicField(OsmGraph, "HIGHWAYS_PEDESTRIANS", HIGHWAYS_PEDESTRIANS);
702
- __publicField(OsmGraph, "DEFAULT_WAY_SELECTOR", DEFAULT_WAY_SELECTOR);
703
764
  const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previousStep) => {
704
765
  var _a, _b, _c, _d, _e;
705
766
  const edges = graphItinerary.edges;
@@ -764,7 +825,7 @@ const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previous
764
825
  ...forceEndOfLevelChange && { forceEndOfLevelChange }
765
826
  };
766
827
  };
767
- const _WemapOsmRouter = class extends geo.GeoGraphRouter {
828
+ const _WemapOsmRouter = class _WemapOsmRouter extends geo.GeoGraphRouter {
768
829
  constructor(graph) {
769
830
  super(graph);
770
831
  }
@@ -796,12 +857,12 @@ const _WemapOsmRouter = class extends geo.GeoGraphRouter {
796
857
  }
797
858
  getShortestTrip(waypoints, options = _WemapOsmRouter.DEFAULT_TRIP_OPTIONS) {
798
859
  const points = waypoints.map((waypoint) => {
799
- const point = new salesman__default.default.Point(0, 0);
860
+ const point = new salesman.Point(0, 0);
800
861
  point.coords = waypoint;
801
862
  return point;
802
863
  });
803
864
  const cache = [];
804
- const solution = salesman__default.default.solve(points, options.tspTempCoeff, void 0, (p, q) => {
865
+ const solution = salesman.solve(points, options.tspTempCoeff, void 0, (p, q) => {
805
866
  const osmItinerary = this.getShortestPath(
806
867
  p.coords,
807
868
  q.coords,
@@ -875,10 +936,10 @@ const _WemapOsmRouter = class extends geo.GeoGraphRouter {
875
936
  );
876
937
  }
877
938
  };
939
+ __publicField(_WemapOsmRouter, "DEFAULT_OPTIONS", _WemapOsmRouter.buildOptions());
940
+ __publicField(_WemapOsmRouter, "WITHOUT_STAIRS_OPTIONS", _WemapOsmRouter.buildOptions({ useStairs: false }));
941
+ __publicField(_WemapOsmRouter, "DEFAULT_TRIP_OPTIONS", _WemapOsmRouter.buildTripOptions());
878
942
  let WemapOsmRouter = _WemapOsmRouter;
879
- __publicField(WemapOsmRouter, "DEFAULT_OPTIONS", _WemapOsmRouter.buildOptions());
880
- __publicField(WemapOsmRouter, "WITHOUT_STAIRS_OPTIONS", _WemapOsmRouter.buildOptions({ useStairs: false }));
881
- __publicField(WemapOsmRouter, "DEFAULT_TRIP_OPTIONS", _WemapOsmRouter.buildTripOptions());
882
943
  class RemoteRouter {
883
944
  }
884
945
  class RemoteRouterServerUnreachable extends Error {
@@ -978,9 +1039,17 @@ function parseWKTGeometry(wktGeometry) {
978
1039
  });
979
1040
  }
980
1041
  class CitywayRemoteRouter extends RemoteRouter {
1042
+ /**
1043
+ * @override
1044
+ */
981
1045
  get rname() {
982
1046
  return "cityway";
983
1047
  }
1048
+ /**
1049
+ * @override
1050
+ * @throws {RoutingModeCorrespondanceNotFound}
1051
+ * @throws {RemoteRouterServerUnreachable}
1052
+ */
984
1053
  async getItineraries(endpointUrl, mode, waypoints) {
985
1054
  const url = this.getURL(endpointUrl, mode, waypoints);
986
1055
  const res = await fetch(url).catch(() => {
@@ -991,13 +1060,16 @@ class CitywayRemoteRouter extends RemoteRouter {
991
1060
  });
992
1061
  return this.createRouterResponseFromJson(jsonResponse, waypoints[0], waypoints[1]);
993
1062
  }
1063
+ /**
1064
+ * @throws {RoutingModeCorrespondanceNotFound}
1065
+ */
994
1066
  getURL(endpointUrl, mode, waypoints) {
995
1067
  const citywayMode = inputModeCorrespondance$2.get(mode);
996
1068
  if (!citywayMode) {
997
1069
  throw new RoutingModeCorrespondanceNotFound(this.rname, mode);
998
1070
  }
999
1071
  if (waypoints.length > 2) {
1000
- Logger__default.default.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1072
+ Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1001
1073
  }
1002
1074
  const fromPlace = `DepartureLatitude=${waypoints[0].latitude}&DepartureLongitude=${waypoints[0].longitude}`;
1003
1075
  const toPlace = `ArrivalLatitude=${waypoints[1].latitude}&ArrivalLongitude=${waypoints[1].longitude}`;
@@ -1007,6 +1079,11 @@ class CitywayRemoteRouter extends RemoteRouter {
1007
1079
  search = (search ? `${search}&` : "?") + `${fromPlace}&${toPlace}&${queryMode}`;
1008
1080
  return `${url.origin}${url.pathname}${search}`;
1009
1081
  }
1082
+ /**
1083
+ * Generate multi itineraries from Cityway JSON
1084
+ * @returns {!RouterResponse}
1085
+ * @example https://preprod.api.lia2.cityway.fr/journeyplanner/api/opt/PlanTrips/json?DepartureLatitude=49.51509388236216&DepartureLongitude=0.09341749619366316&ArrivalLatitude=49.5067090188444&ArrivalLongitude=0.1694842115417831&DepartureType=COORDINATES&ArrivalType=COORDINATES
1086
+ */
1010
1087
  createRouterResponseFromJson(json, from, to) {
1011
1088
  const routerResponse = new RouterResponse({ routerName: this.rname, from, to });
1012
1089
  if (json.StatusCode !== 200 || !json.Data || !json.Data.length) {
@@ -1100,7 +1177,7 @@ class CitywayRemoteRouter extends RemoteRouter {
1100
1177
  distance: jsonLeg.Distance
1101
1178
  }];
1102
1179
  } else {
1103
- Logger__default.default.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
1180
+ Logger.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
1104
1181
  continue;
1105
1182
  }
1106
1183
  const leg = new Leg({
@@ -1128,6 +1205,10 @@ class CitywayRemoteRouter extends RemoteRouter {
1128
1205
  }
1129
1206
  return routerResponse;
1130
1207
  }
1208
+ /**
1209
+ * @param {string} iso8601Duration
1210
+ * @see https://stackoverflow.com/a/29153059/2239938
1211
+ */
1131
1212
  parseDuration(iso8601Duration) {
1132
1213
  const iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
1133
1214
  const matches = iso8601Duration.match(iso8601DurationRegex);
@@ -1143,9 +1224,16 @@ class CitywayRemoteRouter extends RemoteRouter {
1143
1224
  }
1144
1225
  const CitywayRemoteRouter$1 = new CitywayRemoteRouter();
1145
1226
  class DeutscheBahnRemoteRouter extends RemoteRouter {
1227
+ /**
1228
+ * @override
1229
+ */
1146
1230
  get rname() {
1147
1231
  return "deutsche-bahn";
1148
1232
  }
1233
+ /**
1234
+ * @override
1235
+ * @throws {RemoteRouterServerUnreachable}
1236
+ */
1149
1237
  async getItineraries(endpointUrl, mode, waypoints) {
1150
1238
  const url = this.getURL(endpointUrl, mode, waypoints);
1151
1239
  const res = await fetch(url).catch(() => {
@@ -1201,7 +1289,7 @@ routingModeCorrespondance.set("Funicular", "FUNICULAR");
1201
1289
  routingModeCorrespondance.set("LocalTrain", "TRAIN");
1202
1290
  routingModeCorrespondance.set("LongDistanceTrain", "TRAIN");
1203
1291
  routingModeCorrespondance.set("Metro", "METRO");
1204
- routingModeCorrespondance.set("M\xE9tro", "METRO");
1292
+ routingModeCorrespondance.set("Métro", "METRO");
1205
1293
  routingModeCorrespondance.set("RailShuttle", "TRAIN");
1206
1294
  routingModeCorrespondance.set("RapidTransit", "BUS");
1207
1295
  routingModeCorrespondance.set("Shuttle", "BUS");
@@ -1256,9 +1344,16 @@ function dateStringToTimestamp(stringDate, timeZone) {
1256
1344
  ).getTime();
1257
1345
  }
1258
1346
  class IdfmRemoteRouter extends RemoteRouter {
1347
+ /**
1348
+ * @override
1349
+ */
1259
1350
  get rname() {
1260
1351
  return "idfm";
1261
1352
  }
1353
+ /**
1354
+ * @throws {IdfmRemoteRouterTokenError}
1355
+ * @throws {RemoteRouterServerUnreachable}
1356
+ */
1262
1357
  async getItineraries(endpointUrl, mode, waypoints, options = {}) {
1263
1358
  const url = this.getURL(endpointUrl, mode, waypoints, options);
1264
1359
  const res = await fetch(url, {
@@ -1282,7 +1377,7 @@ class IdfmRemoteRouter extends RemoteRouter {
1282
1377
  }
1283
1378
  getURL(endpointUrl, mode, waypoints, options) {
1284
1379
  if (waypoints.length > 2) {
1285
- Logger__default.default.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1380
+ Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1286
1381
  }
1287
1382
  const url = new URL(endpointUrl);
1288
1383
  const coreParams = new URLSearchParams();
@@ -1347,6 +1442,11 @@ class IdfmRemoteRouter extends RemoteRouter {
1347
1442
  to
1348
1443
  };
1349
1444
  }
1445
+ /**
1446
+ * Since the IDFM API does not provide coords for each step, we need to compute them
1447
+ * We trim the coordinates of the leg with the distance of each step and keep the last result as the coords of the step
1448
+ * @param {Leg} leg
1449
+ */
1350
1450
  findStepsCoord(legCoords, steps) {
1351
1451
  const coords = legCoords;
1352
1452
  const duplicatedCoords = [...coords];
@@ -1472,9 +1572,16 @@ inputModeCorrespondance$1.set("BIKE", "bike");
1472
1572
  inputModeCorrespondance$1.set("BUS", "bus");
1473
1573
  inputModeCorrespondance$1.set("MULTI", "walking");
1474
1574
  class OsrmRemoteRouter extends RemoteRouter {
1575
+ /**
1576
+ * @override
1577
+ */
1475
1578
  get rname() {
1476
1579
  return "osrm";
1477
1580
  }
1581
+ /**
1582
+ * @throws {RemoteRouterServerUnreachable}
1583
+ * @throws {RoutingModeCorrespondanceNotFound}
1584
+ */
1478
1585
  async getItineraries(endpointUrl, mode, waypoints, options = {}) {
1479
1586
  const url = this.getURL(endpointUrl, mode, waypoints, options);
1480
1587
  const res = await fetch(url).catch(() => {
@@ -1488,6 +1595,9 @@ class OsrmRemoteRouter extends RemoteRouter {
1488
1595
  const osrmMode = inputModeCorrespondance$1.get(mode);
1489
1596
  return this.createRouterResponseFromJson(jsonResponse, from, to, osrmMode);
1490
1597
  }
1598
+ /**
1599
+ * @throws {RoutingModeCorrespondanceNotFound}
1600
+ */
1491
1601
  getURL(endpointUrl, mode, waypoints, options = {}) {
1492
1602
  let osrmMode = inputModeCorrespondance$1.get(mode);
1493
1603
  if (!osrmMode) {
@@ -1510,6 +1620,10 @@ class OsrmRemoteRouter extends RemoteRouter {
1510
1620
  }
1511
1621
  return [lng, lat, level];
1512
1622
  }
1623
+ /**
1624
+ * @param {object} json
1625
+ * @returns {Coordinates}
1626
+ */
1513
1627
  jsonToCoordinates(json) {
1514
1628
  const coords = new geo.Coordinates(json[1], json[0]);
1515
1629
  if (json.length > 2) {
@@ -1548,6 +1662,9 @@ class OsrmRemoteRouter extends RemoteRouter {
1548
1662
  message
1549
1663
  };
1550
1664
  }
1665
+ /**
1666
+ * @deprecated
1667
+ */
1551
1668
  itineraryToOsrmJson(itinerary) {
1552
1669
  const lastLegId = itinerary.legs.length - 1;
1553
1670
  const itinerarySteps = itinerary.steps;
@@ -1671,6 +1788,10 @@ class OtpRemoteRouter extends RemoteRouter {
1671
1788
  get rname() {
1672
1789
  return "otp";
1673
1790
  }
1791
+ /**
1792
+ * @throws {RemoteRouterServerUnreachable}
1793
+ * @throws {RoutingModeCorrespondanceNotFound}
1794
+ */
1674
1795
  async getItineraries(endpointUrl, mode, waypoints) {
1675
1796
  const url = this.getURL(endpointUrl, mode, waypoints);
1676
1797
  const res = await fetch(url).catch(() => {
@@ -1681,13 +1802,16 @@ class OtpRemoteRouter extends RemoteRouter {
1681
1802
  });
1682
1803
  return this.createRouterResponseFromJson(jsonResponse, waypoints[0], waypoints[1]);
1683
1804
  }
1805
+ /**
1806
+ * @throws {RoutingModeCorrespondanceNotFound}
1807
+ */
1684
1808
  getURL(endpointUrl, mode, waypoints) {
1685
1809
  const otpMode = inputModeCorrespondance.get(mode);
1686
1810
  if (!otpMode) {
1687
1811
  throw new RoutingModeCorrespondanceNotFound(this.rname, mode);
1688
1812
  }
1689
1813
  if (waypoints.length > 2) {
1690
- Logger__default.default.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1814
+ Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1691
1815
  }
1692
1816
  const fromPlace = `fromPlace=${waypoints[0].latitude},${waypoints[0].longitude}`;
1693
1817
  const toPlace = `toPlace=${waypoints[1].latitude},${waypoints[1].longitude}`;
@@ -1697,6 +1821,9 @@ class OtpRemoteRouter extends RemoteRouter {
1697
1821
  search = (search ? `${search}&` : "?") + `${fromPlace}&${toPlace}&${queryMode}`;
1698
1822
  return `${url.origin}${url.pathname}${search}`;
1699
1823
  }
1824
+ /**
1825
+ * Generate multi itineraries from OTP JSON
1826
+ */
1700
1827
  createRouterResponseFromJson(json, from, to) {
1701
1828
  const routerResponse = new RouterResponse({ routerName: this.rname, from, to });
1702
1829
  const { plan: jsonPlan } = json;
@@ -1708,7 +1835,7 @@ class OtpRemoteRouter extends RemoteRouter {
1708
1835
  for (const jsonItinerary of jsonPlan.itineraries) {
1709
1836
  const legs = [];
1710
1837
  for (const jsonLeg of jsonItinerary.legs) {
1711
- const legCoords = Polyline__default.default.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new geo.Coordinates(lat, lon));
1838
+ const legCoords = Polyline.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new geo.Coordinates(lat, lon));
1712
1839
  let transportInfo;
1713
1840
  let minStepsInfo;
1714
1841
  if (isLegPT(jsonLeg)) {
@@ -1828,6 +1955,11 @@ class RemoteRouterManager {
1828
1955
  getRouterByName(name) {
1829
1956
  return remoteRouters.find((remoteRouter) => remoteRouter.rname === name);
1830
1957
  }
1958
+ /**
1959
+ * @throws {RemoteRouterServerUnreachable}
1960
+ * @throws {RoutingModeCorrespondanceNotFound}
1961
+ * @throws {IdfmRemoteRouterTokenError}
1962
+ */
1831
1963
  async getItineraries(name, endpointUrl, mode, waypoints, options) {
1832
1964
  const router = this.getRouterByName(name);
1833
1965
  if (!router) {
@@ -1835,6 +1967,11 @@ class RemoteRouterManager {
1835
1967
  }
1836
1968
  return router.getItineraries(endpointUrl, mode, waypoints, options);
1837
1969
  }
1970
+ /**
1971
+ * @throws {RemoteRouterServerUnreachable}
1972
+ * @throws {RoutingModeCorrespondanceNotFound}
1973
+ * @throws {IdfmRemoteRouterTokenError}
1974
+ */
1838
1975
  async getItinerariesWithFallback(remoteRouters2, mode, waypoints, options) {
1839
1976
  let routerResponse;
1840
1977
  for (const { name, endpointUrl } of remoteRouters2) {
@@ -1876,7 +2013,7 @@ class WemapMultiRouter {
1876
2013
  if (ioMapsToTest.length !== targetMaps.length) {
1877
2014
  ioMapsToTest.forEach((map) => {
1878
2015
  if (map.name && !targetMaps.includes(map.name)) {
1879
- Logger__default.default.warn(`CustomNetworkMap "${map.name}" not found in WemapMultiRouter`);
2016
+ Logger.warn(`CustomNetworkMap "${map.name}" not found in WemapMultiRouter`);
1880
2017
  }
1881
2018
  });
1882
2019
  }
@@ -1920,7 +2057,7 @@ class WemapMultiRouter {
1920
2057
  async getItineraries(mode, waypoints, options = null) {
1921
2058
  var _a;
1922
2059
  if (waypoints.length > 2) {
1923
- Logger__default.default.warn(`WemapMultiRouter uses only the first 2 waypoints (asked ${waypoints.length})`);
2060
+ Logger.warn(`WemapMultiRouter uses only the first 2 waypoints (asked ${waypoints.length})`);
1924
2061
  }
1925
2062
  const start = waypoints[0];
1926
2063
  const end = waypoints[1];
@@ -2099,7 +2236,7 @@ class CustomNetworkMap {
2099
2236
  this.bounds = bounds;
2100
2237
  } else {
2101
2238
  const polygon = [graph.vertices.map((vertex) => [vertex.coords.lng, vertex.coords.lat])];
2102
- const convexHull = convexHullFn__default.default({ type: "polygon", coordinates: polygon });
2239
+ const convexHull = convexHullFn({ type: "polygon", coordinates: polygon });
2103
2240
  if (!convexHull) {
2104
2241
  throw new Error(`Cannot calculate convexHull of network "${name}"`);
2105
2242
  }
@@ -2138,8 +2275,14 @@ class CustomNetworkMap {
2138
2275
  return new CustomNetworkMap(graph, entryPoints, bounds, name);
2139
2276
  }
2140
2277
  isPointInside(coordinates) {
2141
- return pointInPolygon__default.default([coordinates.lng, coordinates.lat], this.bounds);
2142
- }
2278
+ return pointInPolygon([coordinates.lng, coordinates.lat], this.bounds);
2279
+ }
2280
+ /**
2281
+ * Get the list of entry points sorted by the lowest distance between:
2282
+ * start -> entry point -> end
2283
+ * (as the crow flies)
2284
+ *
2285
+ */
2143
2286
  getOrderedEntryPointsSortedByDistance(start, end) {
2144
2287
  const entryPointsCopy = [...this.entryPoints];
2145
2288
  const levelDiffFactor = 50;
@@ -2153,6 +2296,17 @@ class CustomNetworkMap {
2153
2296
  return distance2D + levelDiff * levelDiffFactor;
2154
2297
  });
2155
2298
  }
2299
+ /**
2300
+ * Get the best itinerary from any entry point to an end coordinates.
2301
+ *
2302
+ * The algorithm works as following:
2303
+ * 1 - Entry points are sorted using distance (as the crow flies) between start - entry point - end
2304
+ * 2 - Try to calculate an itinerary from the first entry point to the end coordinates.
2305
+ * 3 - If an itinerary is found, it is returned. Otherwise it tries from the next entry point.
2306
+ *
2307
+ * /!\ start is only used to sort the entry points (step 1).
2308
+ *
2309
+ */
2156
2310
  getBestItineraryFromEntryPointsToEnd(start, end, options) {
2157
2311
  const sortedEntryPoints = this.getOrderedEntryPointsSortedByDistance(start, end);
2158
2312
  for (const entryPoint of sortedEntryPoints) {
@@ -2167,6 +2321,17 @@ class CustomNetworkMap {
2167
2321
  `No route found from entry points to ${end.toString()} in map: ${this.name}`
2168
2322
  );
2169
2323
  }
2324
+ /**
2325
+ * Get the best itinerary from start coordinates to any entry point.
2326
+ *
2327
+ * The algorithm works as following:
2328
+ * 1 - Entry points are sorted using distance (as the crow flies) between start - entry point - end
2329
+ * 2 - Try to calculate an itinerary from the start coordinates to the first entry point.
2330
+ * 3 - If an itinerary is found, it is returned. Otherwise it tries to the next entry point.
2331
+ *
2332
+ * /!\ end is only used to sort the entry points (step 1).
2333
+ *
2334
+ */
2170
2335
  getBestItineraryFromStartToEntryPoints(start, end, options) {
2171
2336
  const sortedEntryPoints = this.getOrderedEntryPointsSortedByDistance(start, end);
2172
2337
  for (const entryPoint of sortedEntryPoints) {