@wemap/routers 11.5.0 → 11.8.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
  }
@@ -741,9 +758,9 @@ const _OsmGraph = class extends geo.GeoGraph {
741
758
  }
742
759
  }
743
760
  };
761
+ __publicField(_OsmGraph, "HIGHWAYS_PEDESTRIANS", HIGHWAYS_PEDESTRIANS);
762
+ __publicField(_OsmGraph, "DEFAULT_WAY_SELECTOR", DEFAULT_WAY_SELECTOR);
744
763
  let OsmGraph = _OsmGraph;
745
- __publicField(OsmGraph, "HIGHWAYS_PEDESTRIANS", HIGHWAYS_PEDESTRIANS);
746
- __publicField(OsmGraph, "DEFAULT_WAY_SELECTOR", DEFAULT_WAY_SELECTOR);
747
764
  const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previousStep) => {
748
765
  var _a, _b, _c, _d, _e;
749
766
  const edges = graphItinerary.edges;
@@ -808,7 +825,7 @@ const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previous
808
825
  ...forceEndOfLevelChange && { forceEndOfLevelChange }
809
826
  };
810
827
  };
811
- const _WemapOsmRouter = class extends geo.GeoGraphRouter {
828
+ const _WemapOsmRouter = class _WemapOsmRouter extends geo.GeoGraphRouter {
812
829
  constructor(graph) {
813
830
  super(graph);
814
831
  }
@@ -822,6 +839,21 @@ const _WemapOsmRouter = class extends geo.GeoGraphRouter {
822
839
  const graphItinerary = this.getShortestPath(start, end, options);
823
840
  return Itinerary.fromGraphItinerary(graphItinerary, "WALK", buildStepsRules(graphItinerary));
824
841
  }
842
+ getShortestPaths(start, ends, options = _WemapOsmRouter.DEFAULT_OPTIONS) {
843
+ return super.getShortestPaths(start, ends, options);
844
+ }
845
+ getItineraries(start, ends, options = _WemapOsmRouter.DEFAULT_OPTIONS) {
846
+ const graphItineraries = this.getShortestPaths(start, ends, options);
847
+ return graphItineraries.map((graphItinerary, idx) => {
848
+ if (graphItinerary === null || !graphItinerary.edges.length) {
849
+ const startCoords = start instanceof geo.GeoGraphVertex ? start.coords : start;
850
+ const end = ends[idx];
851
+ const endCoords = end instanceof geo.GeoGraphVertex ? end.coords : end;
852
+ return new Itinerary({ from: startCoords, to: endCoords, legs: [] });
853
+ }
854
+ return Itinerary.fromGraphItinerary(graphItinerary, "WALK", buildStepsRules(graphItinerary));
855
+ });
856
+ }
825
857
  static getTurnInfoFromAngle(_angle) {
826
858
  let direction, directionExtra;
827
859
  const directionAngle = maths.rad2deg(maths.diffAngle(_angle, Math.PI));
@@ -840,12 +872,12 @@ const _WemapOsmRouter = class extends geo.GeoGraphRouter {
840
872
  }
841
873
  getShortestTrip(waypoints, options = _WemapOsmRouter.DEFAULT_TRIP_OPTIONS) {
842
874
  const points = waypoints.map((waypoint) => {
843
- const point = new salesman__default.default.Point(0, 0);
875
+ const point = new salesman.Point(0, 0);
844
876
  point.coords = waypoint;
845
877
  return point;
846
878
  });
847
879
  const cache = [];
848
- const solution = salesman__default.default.solve(points, options.tspTempCoeff, void 0, (p, q) => {
880
+ const solution = salesman.solve(points, options.tspTempCoeff, void 0, (p, q) => {
849
881
  const osmItinerary = this.getShortestPath(
850
882
  p.coords,
851
883
  q.coords,
@@ -919,10 +951,10 @@ const _WemapOsmRouter = class extends geo.GeoGraphRouter {
919
951
  );
920
952
  }
921
953
  };
954
+ __publicField(_WemapOsmRouter, "DEFAULT_OPTIONS", _WemapOsmRouter.buildOptions());
955
+ __publicField(_WemapOsmRouter, "WITHOUT_STAIRS_OPTIONS", _WemapOsmRouter.buildOptions({ useStairs: false }));
956
+ __publicField(_WemapOsmRouter, "DEFAULT_TRIP_OPTIONS", _WemapOsmRouter.buildTripOptions());
922
957
  let WemapOsmRouter = _WemapOsmRouter;
923
- __publicField(WemapOsmRouter, "DEFAULT_OPTIONS", _WemapOsmRouter.buildOptions());
924
- __publicField(WemapOsmRouter, "WITHOUT_STAIRS_OPTIONS", _WemapOsmRouter.buildOptions({ useStairs: false }));
925
- __publicField(WemapOsmRouter, "DEFAULT_TRIP_OPTIONS", _WemapOsmRouter.buildTripOptions());
926
958
  class RemoteRouter {
927
959
  }
928
960
  class RemoteRouterServerUnreachable extends Error {
@@ -1022,9 +1054,17 @@ function parseWKTGeometry(wktGeometry) {
1022
1054
  });
1023
1055
  }
1024
1056
  class CitywayRemoteRouter extends RemoteRouter {
1057
+ /**
1058
+ * @override
1059
+ */
1025
1060
  get rname() {
1026
1061
  return "cityway";
1027
1062
  }
1063
+ /**
1064
+ * @override
1065
+ * @throws {RoutingModeCorrespondanceNotFound}
1066
+ * @throws {RemoteRouterServerUnreachable}
1067
+ */
1028
1068
  async getItineraries(endpointUrl, mode, waypoints) {
1029
1069
  const url = this.getURL(endpointUrl, mode, waypoints);
1030
1070
  const res = await fetch(url).catch(() => {
@@ -1035,13 +1075,16 @@ class CitywayRemoteRouter extends RemoteRouter {
1035
1075
  });
1036
1076
  return this.createRouterResponseFromJson(jsonResponse, waypoints[0], waypoints[1]);
1037
1077
  }
1078
+ /**
1079
+ * @throws {RoutingModeCorrespondanceNotFound}
1080
+ */
1038
1081
  getURL(endpointUrl, mode, waypoints) {
1039
1082
  const citywayMode = inputModeCorrespondance$2.get(mode);
1040
1083
  if (!citywayMode) {
1041
1084
  throw new RoutingModeCorrespondanceNotFound(this.rname, mode);
1042
1085
  }
1043
1086
  if (waypoints.length > 2) {
1044
- Logger__default.default.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1087
+ Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1045
1088
  }
1046
1089
  const fromPlace = `DepartureLatitude=${waypoints[0].latitude}&DepartureLongitude=${waypoints[0].longitude}`;
1047
1090
  const toPlace = `ArrivalLatitude=${waypoints[1].latitude}&ArrivalLongitude=${waypoints[1].longitude}`;
@@ -1051,6 +1094,11 @@ class CitywayRemoteRouter extends RemoteRouter {
1051
1094
  search = (search ? `${search}&` : "?") + `${fromPlace}&${toPlace}&${queryMode}`;
1052
1095
  return `${url.origin}${url.pathname}${search}`;
1053
1096
  }
1097
+ /**
1098
+ * Generate multi itineraries from Cityway JSON
1099
+ * @returns {!RouterResponse}
1100
+ * @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
1101
+ */
1054
1102
  createRouterResponseFromJson(json, from, to) {
1055
1103
  const routerResponse = new RouterResponse({ routerName: this.rname, from, to });
1056
1104
  if (json.StatusCode !== 200 || !json.Data || !json.Data.length) {
@@ -1144,7 +1192,7 @@ class CitywayRemoteRouter extends RemoteRouter {
1144
1192
  distance: jsonLeg.Distance
1145
1193
  }];
1146
1194
  } else {
1147
- Logger__default.default.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
1195
+ Logger.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
1148
1196
  continue;
1149
1197
  }
1150
1198
  const leg = new Leg({
@@ -1172,6 +1220,10 @@ class CitywayRemoteRouter extends RemoteRouter {
1172
1220
  }
1173
1221
  return routerResponse;
1174
1222
  }
1223
+ /**
1224
+ * @param {string} iso8601Duration
1225
+ * @see https://stackoverflow.com/a/29153059/2239938
1226
+ */
1175
1227
  parseDuration(iso8601Duration) {
1176
1228
  const iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
1177
1229
  const matches = iso8601Duration.match(iso8601DurationRegex);
@@ -1187,9 +1239,16 @@ class CitywayRemoteRouter extends RemoteRouter {
1187
1239
  }
1188
1240
  const CitywayRemoteRouter$1 = new CitywayRemoteRouter();
1189
1241
  class DeutscheBahnRemoteRouter extends RemoteRouter {
1242
+ /**
1243
+ * @override
1244
+ */
1190
1245
  get rname() {
1191
1246
  return "deutsche-bahn";
1192
1247
  }
1248
+ /**
1249
+ * @override
1250
+ * @throws {RemoteRouterServerUnreachable}
1251
+ */
1193
1252
  async getItineraries(endpointUrl, mode, waypoints) {
1194
1253
  const url = this.getURL(endpointUrl, mode, waypoints);
1195
1254
  const res = await fetch(url).catch(() => {
@@ -1245,7 +1304,7 @@ routingModeCorrespondance.set("Funicular", "FUNICULAR");
1245
1304
  routingModeCorrespondance.set("LocalTrain", "TRAIN");
1246
1305
  routingModeCorrespondance.set("LongDistanceTrain", "TRAIN");
1247
1306
  routingModeCorrespondance.set("Metro", "METRO");
1248
- routingModeCorrespondance.set("M\xE9tro", "METRO");
1307
+ routingModeCorrespondance.set("Métro", "METRO");
1249
1308
  routingModeCorrespondance.set("RailShuttle", "TRAIN");
1250
1309
  routingModeCorrespondance.set("RapidTransit", "BUS");
1251
1310
  routingModeCorrespondance.set("Shuttle", "BUS");
@@ -1300,9 +1359,16 @@ function dateStringToTimestamp(stringDate, timeZone) {
1300
1359
  ).getTime();
1301
1360
  }
1302
1361
  class IdfmRemoteRouter extends RemoteRouter {
1362
+ /**
1363
+ * @override
1364
+ */
1303
1365
  get rname() {
1304
1366
  return "idfm";
1305
1367
  }
1368
+ /**
1369
+ * @throws {IdfmRemoteRouterTokenError}
1370
+ * @throws {RemoteRouterServerUnreachable}
1371
+ */
1306
1372
  async getItineraries(endpointUrl, mode, waypoints, options = {}) {
1307
1373
  const url = this.getURL(endpointUrl, mode, waypoints, options);
1308
1374
  const res = await fetch(url, {
@@ -1326,7 +1392,7 @@ class IdfmRemoteRouter extends RemoteRouter {
1326
1392
  }
1327
1393
  getURL(endpointUrl, mode, waypoints, options) {
1328
1394
  if (waypoints.length > 2) {
1329
- Logger__default.default.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1395
+ Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1330
1396
  }
1331
1397
  const url = new URL(endpointUrl);
1332
1398
  const coreParams = new URLSearchParams();
@@ -1391,6 +1457,11 @@ class IdfmRemoteRouter extends RemoteRouter {
1391
1457
  to
1392
1458
  };
1393
1459
  }
1460
+ /**
1461
+ * Since the IDFM API does not provide coords for each step, we need to compute them
1462
+ * We trim the coordinates of the leg with the distance of each step and keep the last result as the coords of the step
1463
+ * @param {Leg} leg
1464
+ */
1394
1465
  findStepsCoord(legCoords, steps) {
1395
1466
  const coords = legCoords;
1396
1467
  const duplicatedCoords = [...coords];
@@ -1516,9 +1587,16 @@ inputModeCorrespondance$1.set("BIKE", "bike");
1516
1587
  inputModeCorrespondance$1.set("BUS", "bus");
1517
1588
  inputModeCorrespondance$1.set("MULTI", "walking");
1518
1589
  class OsrmRemoteRouter extends RemoteRouter {
1590
+ /**
1591
+ * @override
1592
+ */
1519
1593
  get rname() {
1520
1594
  return "osrm";
1521
1595
  }
1596
+ /**
1597
+ * @throws {RemoteRouterServerUnreachable}
1598
+ * @throws {RoutingModeCorrespondanceNotFound}
1599
+ */
1522
1600
  async getItineraries(endpointUrl, mode, waypoints, options = {}) {
1523
1601
  const url = this.getURL(endpointUrl, mode, waypoints, options);
1524
1602
  const res = await fetch(url).catch(() => {
@@ -1532,6 +1610,9 @@ class OsrmRemoteRouter extends RemoteRouter {
1532
1610
  const osrmMode = inputModeCorrespondance$1.get(mode);
1533
1611
  return this.createRouterResponseFromJson(jsonResponse, from, to, osrmMode);
1534
1612
  }
1613
+ /**
1614
+ * @throws {RoutingModeCorrespondanceNotFound}
1615
+ */
1535
1616
  getURL(endpointUrl, mode, waypoints, options = {}) {
1536
1617
  let osrmMode = inputModeCorrespondance$1.get(mode);
1537
1618
  if (!osrmMode) {
@@ -1554,6 +1635,10 @@ class OsrmRemoteRouter extends RemoteRouter {
1554
1635
  }
1555
1636
  return [lng, lat, level];
1556
1637
  }
1638
+ /**
1639
+ * @param {object} json
1640
+ * @returns {Coordinates}
1641
+ */
1557
1642
  jsonToCoordinates(json) {
1558
1643
  const coords = new geo.Coordinates(json[1], json[0]);
1559
1644
  if (json.length > 2) {
@@ -1592,6 +1677,9 @@ class OsrmRemoteRouter extends RemoteRouter {
1592
1677
  message
1593
1678
  };
1594
1679
  }
1680
+ /**
1681
+ * @deprecated
1682
+ */
1595
1683
  itineraryToOsrmJson(itinerary) {
1596
1684
  const lastLegId = itinerary.legs.length - 1;
1597
1685
  const itinerarySteps = itinerary.steps;
@@ -1715,6 +1803,10 @@ class OtpRemoteRouter extends RemoteRouter {
1715
1803
  get rname() {
1716
1804
  return "otp";
1717
1805
  }
1806
+ /**
1807
+ * @throws {RemoteRouterServerUnreachable}
1808
+ * @throws {RoutingModeCorrespondanceNotFound}
1809
+ */
1718
1810
  async getItineraries(endpointUrl, mode, waypoints) {
1719
1811
  const url = this.getURL(endpointUrl, mode, waypoints);
1720
1812
  const res = await fetch(url).catch(() => {
@@ -1725,13 +1817,16 @@ class OtpRemoteRouter extends RemoteRouter {
1725
1817
  });
1726
1818
  return this.createRouterResponseFromJson(jsonResponse, waypoints[0], waypoints[1]);
1727
1819
  }
1820
+ /**
1821
+ * @throws {RoutingModeCorrespondanceNotFound}
1822
+ */
1728
1823
  getURL(endpointUrl, mode, waypoints) {
1729
1824
  const otpMode = inputModeCorrespondance.get(mode);
1730
1825
  if (!otpMode) {
1731
1826
  throw new RoutingModeCorrespondanceNotFound(this.rname, mode);
1732
1827
  }
1733
1828
  if (waypoints.length > 2) {
1734
- Logger__default.default.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1829
+ Logger.warn(`${this.rname} router uses only the first 2 waypoints (asked ${waypoints.length})`);
1735
1830
  }
1736
1831
  const fromPlace = `fromPlace=${waypoints[0].latitude},${waypoints[0].longitude}`;
1737
1832
  const toPlace = `toPlace=${waypoints[1].latitude},${waypoints[1].longitude}`;
@@ -1741,6 +1836,9 @@ class OtpRemoteRouter extends RemoteRouter {
1741
1836
  search = (search ? `${search}&` : "?") + `${fromPlace}&${toPlace}&${queryMode}`;
1742
1837
  return `${url.origin}${url.pathname}${search}`;
1743
1838
  }
1839
+ /**
1840
+ * Generate multi itineraries from OTP JSON
1841
+ */
1744
1842
  createRouterResponseFromJson(json, from, to) {
1745
1843
  const routerResponse = new RouterResponse({ routerName: this.rname, from, to });
1746
1844
  const { plan: jsonPlan } = json;
@@ -1752,7 +1850,7 @@ class OtpRemoteRouter extends RemoteRouter {
1752
1850
  for (const jsonItinerary of jsonPlan.itineraries) {
1753
1851
  const legs = [];
1754
1852
  for (const jsonLeg of jsonItinerary.legs) {
1755
- const legCoords = Polyline__default.default.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new geo.Coordinates(lat, lon));
1853
+ const legCoords = Polyline.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new geo.Coordinates(lat, lon));
1756
1854
  let transportInfo;
1757
1855
  let minStepsInfo;
1758
1856
  if (isLegPT(jsonLeg)) {
@@ -1872,6 +1970,11 @@ class RemoteRouterManager {
1872
1970
  getRouterByName(name) {
1873
1971
  return remoteRouters.find((remoteRouter) => remoteRouter.rname === name);
1874
1972
  }
1973
+ /**
1974
+ * @throws {RemoteRouterServerUnreachable}
1975
+ * @throws {RoutingModeCorrespondanceNotFound}
1976
+ * @throws {IdfmRemoteRouterTokenError}
1977
+ */
1875
1978
  async getItineraries(name, endpointUrl, mode, waypoints, options) {
1876
1979
  const router = this.getRouterByName(name);
1877
1980
  if (!router) {
@@ -1879,6 +1982,11 @@ class RemoteRouterManager {
1879
1982
  }
1880
1983
  return router.getItineraries(endpointUrl, mode, waypoints, options);
1881
1984
  }
1985
+ /**
1986
+ * @throws {RemoteRouterServerUnreachable}
1987
+ * @throws {RoutingModeCorrespondanceNotFound}
1988
+ * @throws {IdfmRemoteRouterTokenError}
1989
+ */
1882
1990
  async getItinerariesWithFallback(remoteRouters2, mode, waypoints, options) {
1883
1991
  let routerResponse;
1884
1992
  for (const { name, endpointUrl } of remoteRouters2) {
@@ -1920,7 +2028,7 @@ class WemapMultiRouter {
1920
2028
  if (ioMapsToTest.length !== targetMaps.length) {
1921
2029
  ioMapsToTest.forEach((map) => {
1922
2030
  if (map.name && !targetMaps.includes(map.name)) {
1923
- Logger__default.default.warn(`CustomNetworkMap "${map.name}" not found in WemapMultiRouter`);
2031
+ Logger.warn(`CustomNetworkMap "${map.name}" not found in WemapMultiRouter`);
1924
2032
  }
1925
2033
  });
1926
2034
  }
@@ -1961,10 +2069,26 @@ class WemapMultiRouter {
1961
2069
  itineraries: [tripItinerary]
1962
2070
  });
1963
2071
  }
2072
+ async getItinerariesMultipleDestinations(start, ends, options = null) {
2073
+ const ioMapsToTest = this.getIoMapsFromOptions(options);
2074
+ const mapOfWaypoints = [start, ...ends].reduce((map, waypoint) => {
2075
+ const mapOfThisWaypoint = ioMapsToTest.find((map2) => map2.isPointInside(waypoint)) || null;
2076
+ if (mapOfThisWaypoint && map && mapOfThisWaypoint !== map) {
2077
+ throw Error(`Cannot handle this itineraries, because two points are on different maps (${mapOfThisWaypoint} and ${mapOfWaypoints}). Multi-map multiple destinations are not implemented.`);
2078
+ }
2079
+ return mapOfThisWaypoint;
2080
+ }, null);
2081
+ const wemapOsmRouterOptions = this.convertOptionsToWemapOsmOptions(options);
2082
+ const itineraries = mapOfWaypoints.getItinerariesMultipleDestinationsInsideMap(start, ends, wemapOsmRouterOptions);
2083
+ return {
2084
+ routerName: this.rname,
2085
+ itineraries
2086
+ };
2087
+ }
1964
2088
  async getItineraries(mode, waypoints, options = null) {
1965
2089
  var _a;
1966
2090
  if (waypoints.length > 2) {
1967
- Logger__default.default.warn(`WemapMultiRouter uses only the first 2 waypoints (asked ${waypoints.length})`);
2091
+ Logger.warn(`WemapMultiRouter uses only the first 2 waypoints (asked ${waypoints.length})`);
1968
2092
  }
1969
2093
  const start = waypoints[0];
1970
2094
  const end = waypoints[1];
@@ -2143,7 +2267,7 @@ class CustomNetworkMap {
2143
2267
  this.bounds = bounds;
2144
2268
  } else {
2145
2269
  const polygon = [graph.vertices.map((vertex) => [vertex.coords.lng, vertex.coords.lat])];
2146
- const convexHull = convexHullFn__default.default({ type: "polygon", coordinates: polygon });
2270
+ const convexHull = convexHullFn({ type: "polygon", coordinates: polygon });
2147
2271
  if (!convexHull) {
2148
2272
  throw new Error(`Cannot calculate convexHull of network "${name}"`);
2149
2273
  }
@@ -2182,8 +2306,14 @@ class CustomNetworkMap {
2182
2306
  return new CustomNetworkMap(graph, entryPoints, bounds, name);
2183
2307
  }
2184
2308
  isPointInside(coordinates) {
2185
- return pointInPolygon__default.default([coordinates.lng, coordinates.lat], this.bounds);
2186
- }
2309
+ return pointInPolygon([coordinates.lng, coordinates.lat], this.bounds);
2310
+ }
2311
+ /**
2312
+ * Get the list of entry points sorted by the lowest distance between:
2313
+ * start -> entry point -> end
2314
+ * (as the crow flies)
2315
+ *
2316
+ */
2187
2317
  getOrderedEntryPointsSortedByDistance(start, end) {
2188
2318
  const entryPointsCopy = [...this.entryPoints];
2189
2319
  const levelDiffFactor = 50;
@@ -2197,6 +2327,17 @@ class CustomNetworkMap {
2197
2327
  return distance2D + levelDiff * levelDiffFactor;
2198
2328
  });
2199
2329
  }
2330
+ /**
2331
+ * Get the best itinerary from any entry point to an end coordinates.
2332
+ *
2333
+ * The algorithm works as following:
2334
+ * 1 - Entry points are sorted using distance (as the crow flies) between start - entry point - end
2335
+ * 2 - Try to calculate an itinerary from the first entry point to the end coordinates.
2336
+ * 3 - If an itinerary is found, it is returned. Otherwise it tries from the next entry point.
2337
+ *
2338
+ * /!\ start is only used to sort the entry points (step 1).
2339
+ *
2340
+ */
2200
2341
  getBestItineraryFromEntryPointsToEnd(start, end, options) {
2201
2342
  const sortedEntryPoints = this.getOrderedEntryPointsSortedByDistance(start, end);
2202
2343
  for (const entryPoint of sortedEntryPoints) {
@@ -2211,6 +2352,17 @@ class CustomNetworkMap {
2211
2352
  `No route found from entry points to ${end.toString()} in map: ${this.name}`
2212
2353
  );
2213
2354
  }
2355
+ /**
2356
+ * Get the best itinerary from start coordinates to any entry point.
2357
+ *
2358
+ * The algorithm works as following:
2359
+ * 1 - Entry points are sorted using distance (as the crow flies) between start - entry point - end
2360
+ * 2 - Try to calculate an itinerary from the start coordinates to the first entry point.
2361
+ * 3 - If an itinerary is found, it is returned. Otherwise it tries to the next entry point.
2362
+ *
2363
+ * /!\ end is only used to sort the entry points (step 1).
2364
+ *
2365
+ */
2214
2366
  getBestItineraryFromStartToEntryPoints(start, end, options) {
2215
2367
  const sortedEntryPoints = this.getOrderedEntryPointsSortedByDistance(start, end);
2216
2368
  for (const entryPoint of sortedEntryPoints) {
@@ -2231,6 +2383,9 @@ class CustomNetworkMap {
2231
2383
  getTripInsideMap(waypoints, options) {
2232
2384
  return this.router.getTripItinerary(waypoints, options);
2233
2385
  }
2386
+ getItinerariesMultipleDestinationsInsideMap(start, ends, options) {
2387
+ return this.router.getItineraries(start, ends, options);
2388
+ }
2234
2389
  enableWay(osmId) {
2235
2390
  this.graph.edges.filter((edge) => edge.data.id === osmId).forEach((e) => this.router.disabledEdges.delete(e));
2236
2391
  this.disabledWays.delete(osmId);