mobility-toolbox-js 2.0.0-beta.30 → 2.0.0-beta.34

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 (225) hide show
  1. package/api/RealtimeAPI.d.ts +268 -0
  2. package/api/RealtimeAPI.d.ts.map +1 -0
  3. package/api/RealtimeAPI.js +626 -343
  4. package/api/RoutingAPI.d.ts +33 -0
  5. package/api/RoutingAPI.d.ts.map +1 -0
  6. package/api/RoutingAPI.js +65 -15
  7. package/api/StopsAPI.d.ts +36 -0
  8. package/api/StopsAPI.d.ts.map +1 -0
  9. package/api/StopsAPI.js +70 -12
  10. package/api/index.d.ts +5 -0
  11. package/api/index.d.ts.map +1 -0
  12. package/api/index.js +10 -3
  13. package/api/typedefs.d.ts +105 -0
  14. package/api/typedefs.d.ts.map +1 -0
  15. package/api/typedefs.js +72 -0
  16. package/common/api/HttpAPI.d.ts +31 -0
  17. package/common/api/HttpAPI.d.ts.map +1 -0
  18. package/common/api/HttpAPI.js +82 -30
  19. package/common/api/WebSocketAPI.d.ts +95 -0
  20. package/common/api/WebSocketAPI.d.ts.map +1 -0
  21. package/common/api/WebSocketAPI.js +313 -168
  22. package/common/controls/Control.d.ts +74 -0
  23. package/common/controls/Control.d.ts.map +1 -0
  24. package/common/controls/Control.js +167 -78
  25. package/common/index.d.ts +3 -0
  26. package/common/index.d.ts.map +1 -0
  27. package/common/index.js +18 -2
  28. package/common/layers/Layer.d.ts +80 -0
  29. package/common/layers/Layer.d.ts.map +1 -0
  30. package/common/layers/Layer.js +251 -134
  31. package/common/mixins/CopyrightMixin.d.ts +22 -0
  32. package/common/mixins/CopyrightMixin.d.ts.map +1 -0
  33. package/common/mixins/CopyrightMixin.js +70 -22
  34. package/common/mixins/MapboxLayerMixin.d.ts +27 -0
  35. package/common/mixins/MapboxLayerMixin.d.ts.map +1 -0
  36. package/common/mixins/MapboxLayerMixin.js +240 -0
  37. package/common/mixins/RealtimeLayerMixin.d.ts +58 -0
  38. package/common/mixins/RealtimeLayerMixin.d.ts.map +1 -0
  39. package/common/mixins/RealtimeLayerMixin.js +698 -429
  40. package/common/mixins/StopFinderMixin.d.ts +40 -0
  41. package/common/mixins/StopFinderMixin.d.ts.map +1 -0
  42. package/common/mixins/StopFinderMixin.js +195 -107
  43. package/common/mixins/UserInteractionsLayerMixin.d.ts +42 -0
  44. package/common/mixins/UserInteractionsLayerMixin.d.ts.map +1 -0
  45. package/common/mixins/UserInteractionsLayerMixin.js +222 -121
  46. package/common/styles/index.d.ts +5 -0
  47. package/common/styles/index.d.ts.map +1 -0
  48. package/common/styles/index.js +24 -4
  49. package/common/styles/realtimeDefaultStyle.d.ts +15 -0
  50. package/common/styles/realtimeDefaultStyle.d.ts.map +1 -0
  51. package/common/styles/realtimeDefaultStyle.js +236 -190
  52. package/common/styles/realtimeDelayStyle.d.ts +11 -0
  53. package/common/styles/realtimeDelayStyle.d.ts.map +1 -0
  54. package/common/styles/realtimeDelayStyle.js +25 -7
  55. package/common/styles/realtimeSimpleStyle.d.ts +3 -0
  56. package/common/styles/realtimeSimpleStyle.d.ts.map +1 -0
  57. package/common/styles/realtimeSimpleStyle.js +23 -17
  58. package/common/typedefs.d.ts +50 -0
  59. package/common/typedefs.d.ts.map +1 -0
  60. package/common/typedefs.js +21 -0
  61. package/common/utils/cleanStopTime.d.ts +7 -0
  62. package/common/utils/cleanStopTime.d.ts.map +1 -0
  63. package/common/utils/cleanStopTime.js +28 -17
  64. package/common/utils/compareDepartures.d.ts +9 -0
  65. package/common/utils/compareDepartures.d.ts.map +1 -0
  66. package/common/utils/compareDepartures.js +34 -22
  67. package/common/utils/createCanvas.d.ts +9 -0
  68. package/common/utils/createCanvas.d.ts.map +1 -0
  69. package/common/utils/createCanvas.js +28 -16
  70. package/common/utils/createTrackerFilters.d.ts +12 -0
  71. package/common/utils/createTrackerFilters.d.ts.map +1 -0
  72. package/common/utils/createTrackerFilters.js +75 -54
  73. package/common/utils/getLayersAsFlatArray.d.ts +3 -0
  74. package/common/utils/getLayersAsFlatArray.d.ts.map +1 -0
  75. package/common/utils/getLayersAsFlatArray.js +15 -13
  76. package/common/utils/getMapboxMapCopyrights.d.ts +8 -0
  77. package/common/utils/getMapboxMapCopyrights.d.ts.map +1 -0
  78. package/common/utils/getMapboxMapCopyrights.js +24 -17
  79. package/common/utils/getMapboxRender.d.ts +5 -0
  80. package/common/utils/getMapboxRender.d.ts.map +1 -0
  81. package/common/utils/getMapboxRender.js +77 -0
  82. package/common/utils/getMaplibreRender.d.ts +5 -0
  83. package/common/utils/getMaplibreRender.d.ts.map +1 -0
  84. package/common/utils/getMaplibreRender.js +38 -0
  85. package/common/utils/getRealtimeModeSuffix.d.ts +8 -0
  86. package/common/utils/getRealtimeModeSuffix.d.ts.map +1 -0
  87. package/common/utils/getRealtimeModeSuffix.js +11 -2
  88. package/common/utils/getUrlWithParams.d.ts +9 -0
  89. package/common/utils/getUrlWithParams.d.ts.map +1 -0
  90. package/common/utils/getUrlWithParams.js +20 -10
  91. package/common/utils/getVehiclePosition.d.ts +14 -0
  92. package/common/utils/getVehiclePosition.d.ts.map +1 -0
  93. package/common/utils/getVehiclePosition.js +63 -39
  94. package/common/utils/index.d.ts +12 -0
  95. package/common/utils/index.d.ts.map +1 -0
  96. package/common/utils/index.js +37 -9
  97. package/common/utils/removeDuplicate.d.ts +10 -0
  98. package/common/utils/removeDuplicate.d.ts.map +1 -0
  99. package/common/utils/removeDuplicate.js +29 -7
  100. package/common/utils/renderTrajectories.d.ts +20 -0
  101. package/common/utils/renderTrajectories.d.ts.map +1 -0
  102. package/common/utils/renderTrajectories.js +111 -78
  103. package/common/utils/sortByDelay.d.ts +3 -0
  104. package/common/utils/sortByDelay.d.ts.map +1 -0
  105. package/common/utils/sortByDelay.js +21 -17
  106. package/common/utils/timeUtils.d.ts +5 -0
  107. package/common/utils/timeUtils.d.ts.map +1 -0
  108. package/common/utils/timeUtils.js +47 -18
  109. package/common/utils/trackerConfig.d.ts +24 -0
  110. package/common/utils/trackerConfig.d.ts.map +1 -0
  111. package/common/utils/trackerConfig.js +171 -118
  112. package/iife.d.ts +3 -0
  113. package/iife.d.ts.map +1 -0
  114. package/iife.js +7 -0
  115. package/index.d.ts +6 -0
  116. package/index.d.ts.map +1 -0
  117. package/index.js +10 -7
  118. package/mapbox/controls/CopyrightControl.d.ts +32 -0
  119. package/mapbox/controls/CopyrightControl.d.ts.map +1 -0
  120. package/mapbox/controls/CopyrightControl.js +72 -28
  121. package/mapbox/controls/index.d.ts +2 -0
  122. package/mapbox/controls/index.d.ts.map +1 -0
  123. package/mapbox/controls/index.js +6 -1
  124. package/mapbox/index.d.ts +5 -0
  125. package/mapbox/index.d.ts.map +1 -0
  126. package/mapbox/index.js +20 -4
  127. package/mapbox/layers/Layer.d.ts +47 -0
  128. package/mapbox/layers/Layer.d.ts.map +1 -0
  129. package/mapbox/layers/Layer.js +137 -54
  130. package/mapbox/layers/RealtimeLayer.d.ts +118 -0
  131. package/mapbox/layers/RealtimeLayer.d.ts.map +1 -0
  132. package/mapbox/layers/RealtimeLayer.js +310 -183
  133. package/mapbox/layers/index.d.ts +3 -0
  134. package/mapbox/layers/index.d.ts.map +1 -0
  135. package/mapbox/layers/index.js +7 -2
  136. package/mapbox/utils.d.ts +8 -0
  137. package/mapbox/utils.d.ts.map +1 -0
  138. package/mapbox/utils.js +54 -29
  139. package/mbt.js +2052 -2109
  140. package/mbt.js.map +3 -3
  141. package/mbt.min.js +18 -18
  142. package/mbt.min.js.map +3 -3
  143. package/ol/controls/CopyrightControl.d.ts +31 -0
  144. package/ol/controls/CopyrightControl.d.ts.map +1 -0
  145. package/ol/controls/CopyrightControl.js +89 -41
  146. package/ol/controls/RoutingControl.d.ts +180 -0
  147. package/ol/controls/RoutingControl.d.ts.map +1 -0
  148. package/ol/controls/RoutingControl.js +666 -371
  149. package/ol/controls/StopFinderControl.d.ts +32 -0
  150. package/ol/controls/StopFinderControl.d.ts.map +1 -0
  151. package/ol/controls/StopFinderControl.js +59 -10
  152. package/ol/controls/index.d.ts +4 -0
  153. package/ol/controls/index.d.ts.map +1 -0
  154. package/ol/controls/index.js +9 -3
  155. package/ol/index.d.ts +6 -0
  156. package/ol/index.d.ts.map +1 -0
  157. package/ol/index.js +21 -5
  158. package/ol/layers/Layer.d.ts +49 -0
  159. package/ol/layers/Layer.d.ts.map +1 -0
  160. package/ol/layers/Layer.js +178 -81
  161. package/ol/layers/MapboxLayer.d.ts +42 -0
  162. package/ol/layers/MapboxLayer.d.ts.map +1 -0
  163. package/ol/layers/MapboxLayer.js +131 -198
  164. package/ol/layers/MapboxStyleLayer.d.ts +146 -0
  165. package/ol/layers/MapboxStyleLayer.d.ts.map +1 -0
  166. package/ol/layers/MapboxStyleLayer.js +382 -186
  167. package/ol/layers/MaplibreLayer.d.ts +27 -0
  168. package/ol/layers/MaplibreLayer.d.ts.map +1 -0
  169. package/ol/layers/MaplibreLayer.js +67 -138
  170. package/ol/layers/RealtimeLayer.d.ts +119 -0
  171. package/ol/layers/RealtimeLayer.d.ts.map +1 -0
  172. package/ol/layers/RealtimeLayer.js +327 -184
  173. package/ol/layers/RoutingLayer.d.ts +24 -0
  174. package/ol/layers/RoutingLayer.d.ts.map +1 -0
  175. package/ol/layers/RoutingLayer.js +111 -56
  176. package/ol/layers/VectorLayer.d.ts +23 -0
  177. package/ol/layers/VectorLayer.d.ts.map +1 -0
  178. package/ol/layers/VectorLayer.js +71 -21
  179. package/ol/layers/WMSLayer.d.ts +38 -0
  180. package/ol/layers/WMSLayer.d.ts.map +1 -0
  181. package/ol/layers/WMSLayer.js +105 -37
  182. package/ol/layers/index.d.ts +9 -0
  183. package/ol/layers/index.d.ts.map +1 -0
  184. package/ol/layers/index.js +19 -8
  185. package/ol/styles/fullTrajectoryDelayStyle.d.ts +4 -0
  186. package/ol/styles/fullTrajectoryDelayStyle.d.ts.map +1 -0
  187. package/ol/styles/fullTrajectoryDelayStyle.js +32 -28
  188. package/ol/styles/fullTrajectoryStyle.d.ts +4 -0
  189. package/ol/styles/fullTrajectoryStyle.d.ts.map +1 -0
  190. package/ol/styles/fullTrajectoryStyle.js +44 -40
  191. package/ol/styles/index.d.ts +3 -0
  192. package/ol/styles/index.d.ts.map +1 -0
  193. package/ol/styles/index.js +7 -2
  194. package/package.json +14 -36
  195. package/setupTests.d.ts +2 -0
  196. package/setupTests.d.ts.map +1 -0
  197. package/setupTests.js +15 -0
  198. package/types/index.d.ts +7 -6
  199. package/types/routing.d.ts +25 -25
  200. package/types/stops.d.ts +19 -19
  201. package/api/RealtimeAPI.test.js +0 -67
  202. package/api/RoutingAPI.test.js +0 -25
  203. package/api/StopsAPI.test.js +0 -22
  204. package/common/api/HttpAPI.test.js +0 -50
  205. package/common/api/WebSocketAPI.test.js +0 -311
  206. package/common/controls/Control.test.js +0 -87
  207. package/common/layers/Layer.test.js +0 -134
  208. package/common/mixins/UserInteractionsLayerMixin.test.js +0 -199
  209. package/common/utils/createTrackerFilters.test.js +0 -79
  210. package/common/utils/getMapboxMapCopyrights.test.js +0 -40
  211. package/common/utils/removeDuplicate.test.js +0 -19
  212. package/common/utils/timeUtils.test.js +0 -10
  213. package/common/utils/trackerConfig.test.js +0 -23
  214. package/mapbox/layers/Layer.test.js +0 -182
  215. package/mapbox/layers/RealtimeLayer.test.js +0 -10
  216. package/ol/controls/CopyrightControl.test.js +0 -165
  217. package/ol/controls/RoutingControl.test.js +0 -146
  218. package/ol/controls/StopFinderControl.test.js +0 -48
  219. package/ol/layers/Layer.test.js +0 -175
  220. package/ol/layers/MapboxLayer.test.js +0 -160
  221. package/ol/layers/MapboxStyleLayer.test.js +0 -226
  222. package/ol/layers/RealtimeLayer.test.js +0 -67
  223. package/ol/layers/RoutingLayer.test.js +0 -39
  224. package/ol/layers/VectorLayer.test.js +0 -76
  225. package/ol/layers/WMSLayer.test.js +0 -57
@@ -1,388 +1,683 @@
1
- import { Feature } from "ol";
2
- import { LineString, Point } from "ol/geom";
3
- import { Modify } from "ol/interaction";
4
- import { unByKey } from "ol/Observable";
5
- import { click } from "ol/events/condition";
6
- import { GeoJSON } from "ol/format";
7
- import { buffer } from "ol/extent";
8
- import { fromLonLat, toLonLat } from "ol/proj";
9
- import GeomType from "ol/geom/GeometryType";
10
- import { RoutingAPI } from "../../api";
11
- import Control from "../../common/controls/Control";
12
- import RoutingLayer from "../layers/RoutingLayer";
13
- const REGEX_VIA_POINT = /^([^@$!\n]*)(@?([\d.]+),([\d.]+))?(\$?([a-zA-Z0-9]{0,2}))$/;
14
- const REGEX_VIA_POINT_COORD = /^([\d.]+),([\d.]+)$/;
15
- const REGEX_VIA_POINT_STATION_ID = /^!([^$]*)(\$?([a-zA-Z0-9]{0,2}))$/;
16
- const STOP_FETCH_ABORT_CONTROLLER_KEY = "stop-fetch";
17
- const getFlatCoordinatesFromSegments = (segmentArray) => {
18
- const coords = [];
19
- segmentArray.forEach((seg) => {
20
- coords.push(...seg.getGeometry().getCoordinates());
21
- });
22
- return coords;
23
- };
24
- class RoutingControl extends Control {
25
- constructor(options = {}) {
26
- super(options);
27
- Object.defineProperties(this, {
28
- mot: {
29
- get: () => this.get("mot"),
30
- set: (newMot) => {
31
- if (newMot) {
32
- this.set("mot", newMot);
33
- if (this.viaPoints) {
34
- this.drawRoute();
35
- }
36
- }
37
- }
38
- },
39
- loading: {
40
- get: () => this.get("loading"),
41
- set: (newLoading) => {
42
- this.set("loading", newLoading);
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __assign = (this && this.__assign) || function () {
18
+ __assign = Object.assign || function(t) {
19
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
20
+ s = arguments[i];
21
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
+ t[p] = s[p];
43
23
  }
44
- },
45
- modify: {
46
- get: () => this.get("modify"),
47
- set: (modify) => {
48
- this.set("modify", modify);
24
+ return t;
25
+ };
26
+ return __assign.apply(this, arguments);
27
+ };
28
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
29
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
30
+ if (ar || !(i in from)) {
31
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
32
+ ar[i] = from[i];
49
33
  }
50
- }
51
- });
52
- this.loading = false;
53
- this.graphs = options.graphs || [["osm", 0, 99]];
54
- this.mot = options.mot || "bus";
55
- this.modify = options.modify !== false;
56
- this.routingApiParams = options.routingApiParams || {};
57
- this.useRawViaPoints = options.useRawViaPoints || false;
58
- this.snapToClosestStation = options.snapToClosestStation || false;
59
- this.cacheStationData = {};
60
- this.abortControllers = [];
61
- this.apiKey = options.apiKey;
62
- this.stopsApiKey = options.stopsApiKey || this.apiKey;
63
- this.segments = [];
64
- this.stopsApiUrl = options.stopsApiUrl || "https://api.geops.io/stops/v1/";
65
- this.api = new RoutingAPI({
66
- ...options
67
- });
68
- this.routingLayer = options.routingLayer || new RoutingLayer({
69
- name: "routing-layer",
70
- style: options.style
71
- });
72
- this.onRouteError = options.onRouteError || ((error) => {
73
- this.dispatchEvent({
74
- type: "change:route",
75
- target: this
76
- });
77
- this.reset();
78
- console.error(error);
79
- });
80
- this.viaPoints = [];
81
- this.onMapClick = this.onMapClick.bind(this);
82
- this.onModifyEnd = this.onModifyEnd.bind(this);
83
- this.onModifyStart = this.onModifyStart.bind(this);
84
- this.apiChangeListener = () => this.drawRoute();
85
- this.createModifyInteraction();
86
- }
87
- static getGraphsResolutions(graphs, map) {
88
- const view = map.getView();
89
- return graphs.map(([, minZoom, maxZoom]) => [
90
- view.getResolutionForZoom(minZoom),
91
- view.getResolutionForZoom(maxZoom || minZoom + 1)
92
- ]);
93
- }
94
- addViaPoint(coordinatesOrString, index = -1, overwrite = 0) {
95
- this.viaPoints.splice(index === -1 ? this.viaPoints.length : index, overwrite, coordinatesOrString);
96
- this.drawRoute();
97
- this.dispatchEvent({
98
- type: "change:route",
99
- target: this
100
- });
101
- }
102
- removeViaPoint(index = this.viaPoints.length - 1) {
103
- if (this.viaPoints.length && this.viaPoints[index]) {
104
- this.viaPoints.splice(index, 1);
105
34
  }
106
- this.drawRoute();
107
- this.dispatchEvent({
108
- type: "change:route",
109
- target: this
110
- });
111
- }
112
- setViaPoints(coordinateArray) {
113
- this.viaPoints = [...coordinateArray];
114
- this.drawRoute();
115
- this.dispatchEvent({
116
- type: "change:route",
117
- target: this
118
- });
119
- }
120
- reset() {
121
- this.abortRequests();
122
- this.viaPoints = [];
123
- this.routingLayer.olLayer.getSource().clear();
124
- this.dispatchEvent({
125
- type: "change:route",
126
- target: this
127
- });
128
- }
129
- abortRequests() {
130
- this.graphs.forEach(([graph]) => {
131
- if (this.abortControllers[graph]) {
132
- this.abortControllers[graph].abort();
133
- }
134
- this.abortControllers[graph] = new AbortController();
35
+ return to.concat(ar || Array.prototype.slice.call(from));
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ var ol_1 = require("ol");
39
+ var geom_1 = require("ol/geom");
40
+ var interaction_1 = require("ol/interaction");
41
+ var Observable_1 = require("ol/Observable");
42
+ var condition_1 = require("ol/events/condition");
43
+ var format_1 = require("ol/format");
44
+ var extent_1 = require("ol/extent");
45
+ var proj_1 = require("ol/proj");
46
+ var GeometryType_1 = require("ol/geom/GeometryType");
47
+ var api_1 = require("../../api");
48
+ var Control_1 = require("../../common/controls/Control");
49
+ var RoutingLayer_1 = require("../layers/RoutingLayer");
50
+ // Examples for a single hop:
51
+ // basel sbb a station named "basel sbb"
52
+ // ZUE, station "Zürich HB" by its common abbreviation
53
+ // Zürich Hauptbahnhof or HBF Zürich are all valid synonyms für "Zürich HB"
54
+ // @47.37811,8.53935 a station at position 47.37811, 8.53935
55
+ // @47.37811,8.53935$4 track 4 in a station at position 47.37811, 8.53935
56
+ // zürich hb@47.37811,8.53935$8 track 8 in station "Zürich HB" at position 47.37811, 8.53935
57
+ /** @private */
58
+ var REGEX_VIA_POINT = /^([^@$!\n]*)(@?([\d.]+),([\d.]+))?(\$?([a-zA-Z0-9]{0,2}))$/;
59
+ // Examples for a single hop:
60
+ //
61
+ // 47.37811,8.53935 a position 47.37811, 8.53935
62
+ /** @private */
63
+ var REGEX_VIA_POINT_COORD = /^([\d.]+),([\d.]+)$/;
64
+ // Examples for a single hop:
65
+ //
66
+ // !8596126 a station with id 8596126
67
+ // !8596126$4 a station with id 8596126
68
+ /** @private */
69
+ var REGEX_VIA_POINT_STATION_ID = /^!([^$]*)(\$?([a-zA-Z0-9]{0,2}))$/;
70
+ /** @private */
71
+ var STOP_FETCH_ABORT_CONTROLLER_KEY = 'stop-fetch';
72
+ /** @private */
73
+ var getFlatCoordinatesFromSegments = function (segmentArray) {
74
+ var coords = [];
75
+ segmentArray.forEach(function (seg) {
76
+ coords.push.apply(coords, seg.getGeometry().getCoordinates());
135
77
  });
136
- this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY]?.abort();
137
- this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY] = new AbortController();
138
- this.loading = false;
139
- }
140
- drawRoute() {
141
- this.abortRequests();
142
- this.routingLayer.olLayer.getSource().clear();
143
- if (!this.viaPoints.length) {
144
- return null;
145
- }
146
- if (this.viaPoints.length === 1) {
147
- return this.drawViaPoint(this.viaPoints[0], 0, this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY]);
78
+ return coords;
79
+ };
80
+ /**
81
+ * Display a route of a specified mean of transport.
82
+ *
83
+ * @example
84
+ * import { Map } from 'ol';
85
+ * import { RoutingControl } from 'mobility-toolbox-js/ol';
86
+ *
87
+ * const map = new Map({
88
+ * target: 'map'
89
+ * });
90
+ *
91
+ * const control = new RoutingControl();
92
+ *
93
+ * control.attachToMap(map)
94
+ *
95
+ * @classproperty {string} apiKey - Key used for RoutingApi requests.
96
+ * @classproperty {string} stopsApiKey - Key used for Stop lookup requests (defaults to apiKey).
97
+ * @classproperty {string} stopsApiUrl - Url used for Stop lookup requests (defaults to https://api.geops.io/stops/v1/lookup/).
98
+ * @classproperty {Array.<Array<graph="osm", minZoom=0, maxZoom=99>>} graphs - Array of routing graphs and min/max zoom levels. If you use the control in combination with the [geOps Maps API](https://developer.geops.io/apis/maps/), you may want to use the optimal level of generalizations: "[['gen4', 0, 8], ['gen3', 8, 9], ['gen2', 9, 11], ['gen1', 11, 13], ['osm', 13, 99]]"
99
+ * @classproperty {string} mot - Mean of transport to be used for routing.
100
+ * @classproperty {object} routingApiParams - object of additional parameters to pass to the routing api request.
101
+ * @classproperty {object} snapToClosestStation - If true, the routing will snap the coordinate to the closest station. Default to false.
102
+ * @classproperty {boolean} useRawViaPoints - Experimental property. Wen true, it allows the user to add via points using different kind of string. See "via" parameter defined by the [geOps Routing API](https://developer.geops.io/apis/routing/). Default to false, only array of coordinates and station's id are supported as via points.
103
+ * @classproperty {RoutingLayer|Layer} routingLayer - Layer for adding route features.
104
+ * @classproperty {function} onRouteError - Callback on error.
105
+ * @classproperty {boolean} loading - True if the control is requesting the backend.
106
+ * @see <a href="/example/ol-routing">Openlayers routing example</a>
107
+ *
108
+ * @extends {Control}
109
+ * @implements {RoutingInterface}
110
+ */
111
+ var RoutingControl = /** @class */ (function (_super) {
112
+ __extends(RoutingControl, _super);
113
+ function RoutingControl(options) {
114
+ if (options === void 0) { options = {}; }
115
+ var _this = _super.call(this, options) || this;
116
+ Object.defineProperties(_this, {
117
+ mot: {
118
+ get: function () { return _this.get('mot'); },
119
+ set: function (newMot) {
120
+ if (newMot) {
121
+ _this.set('mot', newMot);
122
+ if (_this.viaPoints) {
123
+ _this.drawRoute();
124
+ }
125
+ }
126
+ },
127
+ },
128
+ loading: {
129
+ get: function () { return _this.get('loading'); },
130
+ set: function (newLoading) {
131
+ _this.set('loading', newLoading);
132
+ },
133
+ },
134
+ modify: {
135
+ get: function () { return _this.get('modify'); },
136
+ set: function (modify) {
137
+ _this.set('modify', modify);
138
+ },
139
+ },
140
+ });
141
+ /** True if the control is requesting the backend. */
142
+ _this.loading = false;
143
+ /** @ignore */
144
+ _this.graphs = options.graphs || [['osm', 0, 99]];
145
+ /** @ignore */
146
+ _this.mot = options.mot || 'bus';
147
+ /** @ignore */
148
+ _this.modify = options.modify !== false;
149
+ /** @ignore */
150
+ _this.routingApiParams = options.routingApiParams || {};
151
+ /** @ignore */
152
+ _this.useRawViaPoints = options.useRawViaPoints || false;
153
+ /** @ignore */
154
+ _this.snapToClosestStation = options.snapToClosestStation || false;
155
+ /** @ignore */
156
+ _this.cacheStationData = {};
157
+ /** @ignore */
158
+ _this.abortControllers = [];
159
+ /** @ignore */
160
+ _this.apiKey = options.apiKey;
161
+ /** @ignore */
162
+ _this.stopsApiKey = options.stopsApiKey || _this.apiKey;
163
+ /** @ignore */
164
+ _this.segments = [];
165
+ /** @ignore */
166
+ _this.stopsApiUrl = options.stopsApiUrl || 'https://api.geops.io/stops/v1/';
167
+ /** @ignore */
168
+ _this.api = new api_1.RoutingAPI(__assign({}, options));
169
+ /** @ignore */
170
+ _this.routingLayer =
171
+ options.routingLayer ||
172
+ new RoutingLayer_1.default({
173
+ name: 'routing-layer',
174
+ style: options.style,
175
+ });
176
+ /** @ignore */
177
+ _this.onRouteError =
178
+ options.onRouteError ||
179
+ (function (error) {
180
+ _this.dispatchEvent({
181
+ type: 'change:route',
182
+ target: _this,
183
+ });
184
+ _this.reset();
185
+ // eslint-disable-next-line no-console
186
+ console.error(error);
187
+ });
188
+ /** @ignore */
189
+ _this.viaPoints = [];
190
+ /** @ignore */
191
+ _this.onMapClick = _this.onMapClick.bind(_this);
192
+ /** @ignore */
193
+ _this.onModifyEnd = _this.onModifyEnd.bind(_this);
194
+ /** @ignore */
195
+ _this.onModifyStart = _this.onModifyStart.bind(_this);
196
+ /** @ignore */
197
+ _this.apiChangeListener = function () { return _this.drawRoute(); };
198
+ /** @ignore */
199
+ _this.createModifyInteraction();
200
+ return _this;
148
201
  }
149
- const formattedViaPoints = this.viaPoints.map((viaPoint) => {
150
- if (Array.isArray(viaPoint)) {
151
- const projection = this.map.getView().getProjection();
152
- const [lon, lat] = toLonLat(viaPoint, projection);
153
- return this.snapToClosestStation ? [`@${lat}`, lon] : [lat, lon];
154
- }
155
- return this.useRawViaPoints ? viaPoint : `!${viaPoint}`;
156
- });
157
- this.loading = true;
158
- this.routingLayer.olLayer.getSource().clear();
159
- this.viaPoints.forEach((viaPoint, idx) => this.drawViaPoint(viaPoint, idx, this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY]));
160
- return Promise.all(this.graphs.map(([graph], index) => {
161
- return this.api.route({
162
- graph,
163
- via: `${formattedViaPoints.join("|")}`,
164
- mot: `${this.mot}`,
165
- "resolve-hops": false,
166
- elevation: false,
167
- "coord-radius": 100,
168
- "coord-punish": 1e3,
169
- ...this.routingApiParams
170
- }, this.abortControllers[graph]).then((featureCollection) => {
171
- this.segments = this.format.readFeatures(featureCollection);
172
- if (this.mot === "foot") {
173
- const uniqueVias = this.segments.reduce((resultVias, currentFeat) => {
174
- const segTrg = currentFeat.get("trg");
175
- return resultVias.find((via) => via[0] === segTrg[0] && via[1] === segTrg[1]) ? resultVias : [...resultVias, segTrg];
176
- }, []);
177
- this.segments = uniqueVias.map((via) => {
178
- const viaSegments = this.segments.filter((seg) => {
179
- const segTrg = seg.get("trg");
180
- return segTrg[0] === via[0] && segTrg[1] === via[1];
181
- });
182
- const coords2 = getFlatCoordinatesFromSegments(viaSegments);
183
- return new Feature({
184
- geometry: new LineString(coords2)
185
- });
186
- });
187
- }
188
- const coords = getFlatCoordinatesFromSegments(this.segments);
189
- const routeFeature = new Feature({
190
- geometry: new LineString(coords)
202
+ /**
203
+ * Calculate at which resolutions corresponds each generalizations.
204
+ *
205
+ * @private
206
+ */
207
+ RoutingControl.getGraphsResolutions = function (graphs, map) {
208
+ var view = map.getView();
209
+ return graphs.map(function (_a) {
210
+ var minZoom = _a[1], maxZoom = _a[2];
211
+ return [
212
+ view.getResolutionForZoom(minZoom),
213
+ view.getResolutionForZoom(maxZoom || minZoom + 1),
214
+ ];
191
215
  });
192
- routeFeature.set("graph", graph);
193
- routeFeature.set("mot", this.mot);
194
- routeFeature.set("minResolution", this.graphsResolutions[index][0]);
195
- routeFeature.set("maxResolution", this.graphsResolutions[index][1]);
196
- this.routingLayer.olLayer.getSource().addFeature(routeFeature);
197
- this.loading = false;
198
- }).catch((error) => {
199
- if (error.name === "AbortError") {
200
- return;
201
- }
202
- this.segments = [];
216
+ };
217
+ /**
218
+ * Adds/Replaces a viaPoint to the viaPoints array and redraws route:
219
+ * Adds a viaPoint at end of array by default.
220
+ * If an index is passed a viaPoint is added at the specified index.
221
+ * If an index is passed and overwrite x is > 0, x viaPoints at the specified
222
+ * index are replaced with a single new viaPoint.
223
+ * @param {number[]|string} coordinates Array of coordinates
224
+ * @param {number} [index=-1] Integer representing the index of the added viaPoint. If not specified, the viaPoint is added at the end of the array.
225
+ * @param {number} [overwrite=0] Marks the number of viaPoints that are removed at the specified index on add.
226
+ */
227
+ RoutingControl.prototype.addViaPoint = function (coordinatesOrString, index, overwrite) {
228
+ if (index === void 0) { index = -1; }
229
+ if (overwrite === void 0) { overwrite = 0; }
230
+ /* Add/Insert/Overwrite viapoint and redraw route */
231
+ this.viaPoints.splice(index === -1 ? this.viaPoints.length : index, overwrite, coordinatesOrString);
232
+ this.drawRoute();
203
233
  this.dispatchEvent({
204
- type: "error",
205
- target: this
234
+ type: 'change:route',
235
+ target: this,
206
236
  });
207
- this.onRouteError(error, this);
208
- this.loading = false;
209
- });
210
- }));
211
- }
212
- drawViaPoint(viaPoint, idx, abortController) {
213
- const pointFeature = new Feature();
214
- pointFeature.set("viaPointIdx", idx);
215
- if (Array.isArray(viaPoint)) {
216
- pointFeature.setGeometry(new Point(viaPoint));
217
- this.routingLayer.olLayer.getSource().addFeature(pointFeature);
218
- return Promise.resolve(pointFeature);
219
- }
220
- if (!this.useRawViaPoints || REGEX_VIA_POINT_STATION_ID.test(viaPoint)) {
221
- let stationId;
222
- let track2;
223
- if (this.useRawViaPoints) {
224
- [, stationId, , track2] = REGEX_VIA_POINT_STATION_ID.exec(viaPoint);
225
- } else {
226
- [stationId, track2] = viaPoint.split("$");
227
- }
228
- return fetch(`${this.stopsApiUrl}lookup/${stationId}?key=${this.stopsApiKey}`, { signal: abortController.signal }).then((res) => res.json()).then((stationData) => {
229
- const { coordinates } = stationData.features[0].geometry;
230
- this.cacheStationData[viaPoint] = fromLonLat(coordinates);
231
- pointFeature.set("viaPointTrack", track2);
232
- pointFeature.setGeometry(new Point(fromLonLat(coordinates)));
233
- this.routingLayer.olLayer.getSource().addFeature(pointFeature);
234
- return pointFeature;
235
- }).catch((error) => {
236
- if (error.name === "AbortError") {
237
- return;
237
+ };
238
+ /**
239
+ * Removes a viaPoint at the passed array index and redraws route
240
+ * By default the last viaPoint is removed.
241
+ * @param {number} index Integer representing the index of the viaPoint to delete.
242
+ */
243
+ RoutingControl.prototype.removeViaPoint = function (index) {
244
+ if (index === void 0) { index = this.viaPoints.length - 1; }
245
+ /* Remove viapoint and redraw route */
246
+ if (this.viaPoints.length && this.viaPoints[index]) {
247
+ this.viaPoints.splice(index, 1);
238
248
  }
249
+ this.drawRoute();
239
250
  this.dispatchEvent({
240
- type: "error",
241
- target: this
251
+ type: 'change:route',
252
+ target: this,
242
253
  });
243
- this.onRouteError(error, this);
244
- this.loading = false;
245
- });
246
- }
247
- if (this.useRawViaPoints && REGEX_VIA_POINT_COORD.test(viaPoint)) {
248
- const [lat2, lon2] = REGEX_VIA_POINT_COORD.exec(viaPoint);
249
- const coordinates = fromLonLat([parseFloat(lon2), parseFloat(lat2)], this.map.getView().getProjection());
250
- pointFeature.setGeometry(new Point(coordinates));
251
- this.routingLayer.olLayer.getSource().addFeature(pointFeature);
252
- return Promise.resolve(pointFeature);
253
- }
254
- const [, stationName, , lat, lon, , track] = REGEX_VIA_POINT.exec(viaPoint);
255
- if (lon && lat) {
256
- const coordinates = fromLonLat([parseFloat(lon), parseFloat(lat)], this.map.getView().getProjection());
257
- pointFeature.set("viaPointTrack", track);
258
- pointFeature.setGeometry(new Point(coordinates));
259
- this.routingLayer.olLayer.getSource().addFeature(pointFeature);
260
- return Promise.resolve(pointFeature);
261
- }
262
- if (stationName) {
263
- return fetch(`${this.stopsApiUrl}?key=${this.stopsApiKey}&q=${stationName}&limit=1`, { signal: abortController.signal }).then((res) => res.json()).then((stationData) => {
264
- const { coordinates } = stationData.features[0].geometry;
265
- this.cacheStationData[viaPoint] = fromLonLat(coordinates);
266
- pointFeature.set("viaPointTrack", track);
267
- pointFeature.setGeometry(new Point(fromLonLat(coordinates)));
268
- this.routingLayer.olLayer.getSource().addFeature(pointFeature);
269
- return pointFeature;
270
- }).catch((error) => {
254
+ };
255
+ /**
256
+ * Replaces the current viaPoints with a new coordinate array.
257
+ * @param {Array<Array<number>>} coordinateArray Array of nested coordinates
258
+ */
259
+ RoutingControl.prototype.setViaPoints = function (coordinateArray) {
260
+ this.viaPoints = __spreadArray([], coordinateArray, true);
261
+ this.drawRoute();
271
262
  this.dispatchEvent({
272
- type: "error",
273
- target: this
263
+ type: 'change:route',
264
+ target: this,
274
265
  });
275
- this.onRouteError(error, this);
266
+ };
267
+ /**
268
+ * Removes all viaPoints, clears the source and triggers a change event
269
+ */
270
+ RoutingControl.prototype.reset = function () {
271
+ // Clear viaPoints and source
272
+ this.abortRequests();
273
+ this.viaPoints = [];
274
+ this.routingLayer.olLayer.getSource().clear();
275
+ this.dispatchEvent({
276
+ type: 'change:route',
277
+ target: this,
278
+ });
279
+ };
280
+ /**
281
+ * Aborts viapoint and route requests
282
+ * @private
283
+ */
284
+ RoutingControl.prototype.abortRequests = function () {
285
+ var _this = this;
286
+ var _a;
287
+ // Abort Routing API requests
288
+ this.graphs.forEach(function (_a) {
289
+ var graph = _a[0];
290
+ if (_this.abortControllers[graph]) {
291
+ _this.abortControllers[graph].abort();
292
+ }
293
+ _this.abortControllers[graph] = new AbortController();
294
+ });
295
+ // Abort Stops API requests
296
+ (_a = this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY]) === null || _a === void 0 ? void 0 : _a.abort();
297
+ this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY] =
298
+ new AbortController();
276
299
  this.loading = false;
277
- return null;
278
- });
279
- }
280
- return Promise.resolve(null);
281
- }
282
- onMapClick(e) {
283
- const feats = e.target.getFeaturesAtPixel(e.pixel);
284
- const viaPoint = feats.find((feat) => feat.getGeometry()?.getType() === GeomType.POINT && feat.get("viaPointIdx") !== void 0);
285
- if (viaPoint) {
286
- this.removeViaPoint(viaPoint.get("viaPointIdx"));
287
- return;
288
- }
289
- this.addViaPoint(e.coordinate);
290
- }
291
- onModifyStart(evt) {
292
- let segmentIndex = -1;
293
- const route = evt.features.getArray().find((feat) => feat.getGeometry()?.getType() === GeomType.LINE_STRING);
294
- if (route) {
295
- const closestExtent = buffer(new Point(route.getGeometry().getClosestPoint(evt.mapBrowserEvent.coordinate)).getExtent(), 1e-3);
296
- segmentIndex = this.segments.findIndex((segment) => segment.getGeometry().intersectsExtent(closestExtent));
297
- }
298
- const viaPoint = (evt.features.getArray().filter((feat) => feat.getGeometry()?.getType() === GeomType.POINT) || [])[0];
299
- this.initialRouteDrag = {
300
- viaPoint,
301
- oldRoute: route && route.clone(),
302
- segmentIndex
303
300
  };
304
- }
305
- onModifyEnd(evt) {
306
- const coord = evt.mapBrowserEvent.coordinate;
307
- const { oldRoute, viaPoint, segmentIndex } = this.initialRouteDrag;
308
- if (viaPoint) {
309
- return this.addViaPoint(coord, viaPoint.get("viaPointIdx"), 1);
310
- }
311
- if (!oldRoute) {
312
- return this.addViaPoint(coord, 0, 1);
313
- }
314
- if (segmentIndex === -1) {
315
- return Promise.reject(new Error("No segment found"));
316
- }
317
- return this.addViaPoint(coord, segmentIndex + 1);
318
- }
319
- createDefaultElement() {
320
- this.element = document.createElement("button");
321
- this.element.id = "ol-toggle-routing";
322
- this.element.innerHTML = "Toggle Route Control";
323
- this.element.onclick = () => this.active ? this.deactivate() : this.activate();
324
- Object.assign(this.element.style, {
325
- position: "absolute",
326
- right: "10px",
327
- top: "10px"
328
- });
329
- }
330
- createModifyInteraction() {
331
- this.modifyInteraction = new Modify({
332
- source: this.routingLayer.olLayer.getSource(),
333
- pixelTolerance: 4,
334
- hitDetection: this.routingLayer.olLayer,
335
- deleteCondition: (e) => {
336
- const feats = e.target.getFeaturesAtPixel(e.pixel, {
337
- hitTolerance: 5
301
+ /**
302
+ * Draws route on map using an array of coordinates:
303
+ * If a single coordinate is passed a single point feature is added to map.
304
+ * If two or more coordinates are passed a request to the RoutingAPI fetches
305
+ * the route using the passed coordinates and the current mot.
306
+ * @private
307
+ */
308
+ RoutingControl.prototype.drawRoute = function () {
309
+ var _this = this;
310
+ /* Calls RoutingAPI to draw a route using the viaPoints array */
311
+ this.abortRequests();
312
+ this.routingLayer.olLayer.getSource().clear();
313
+ if (!this.viaPoints.length) {
314
+ return null;
315
+ }
316
+ if (this.viaPoints.length === 1) {
317
+ // Add point for first node
318
+ return this.drawViaPoint(this.viaPoints[0], 0, this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY]);
319
+ }
320
+ var formattedViaPoints = this.viaPoints.map(function (viaPoint) {
321
+ if (Array.isArray(viaPoint)) {
322
+ var projection = _this.map.getView().getProjection();
323
+ // viaPoint is a coordinate
324
+ // Coordinates need to be reversed as required by the backend RoutingAPI
325
+ var _a = (0, proj_1.toLonLat)(viaPoint, projection), lon = _a[0], lat = _a[1];
326
+ return _this.snapToClosestStation ? ["@".concat(lat), lon] : [lat, lon];
327
+ }
328
+ // viaPoint is a string to use as it is
329
+ return _this.useRawViaPoints ? viaPoint : "!".concat(viaPoint);
330
+ });
331
+ this.loading = true;
332
+ // Clear source
333
+ this.routingLayer.olLayer.getSource().clear();
334
+ // Create point features for the viaPoints
335
+ this.viaPoints.forEach(function (viaPoint, idx) {
336
+ return _this.drawViaPoint(viaPoint, idx, _this.abortControllers[STOP_FETCH_ABORT_CONTROLLER_KEY]);
338
337
  });
339
- const viaPoint = feats.find((feat) => feat.getGeometry()?.getType() === GeomType.POINT && feat.get("index"));
340
- if (click(e) && viaPoint) {
341
- this.removeViaPoint(viaPoint.get("index"));
342
- return true;
338
+ return Promise.all(this.graphs.map(function (_a, index) {
339
+ var graph = _a[0];
340
+ var signal = _this.abortControllers[graph].signal;
341
+ return _this.api
342
+ .route(__assign({ graph: graph, via: "".concat(formattedViaPoints.join('|')), mot: "".concat(_this.mot), 'resolve-hops': false, elevation: false, 'coord-radius': 100.0, 'coord-punish': 1000.0 }, _this.routingApiParams), { signal: signal })
343
+ .then(function (featureCollection) {
344
+ _this.segments = _this.format.readFeatures(featureCollection);
345
+ if (_this.mot === 'foot') {
346
+ // Extract unique values from viaPoint target value
347
+ var uniqueVias = _this.segments.reduce(function (resultVias, currentFeat) {
348
+ var segTrg = currentFeat.get('trg');
349
+ return resultVias.find(function (via) { return via[0] === segTrg[0] && via[1] === segTrg[1]; })
350
+ ? resultVias
351
+ : __spreadArray(__spreadArray([], resultVias, true), [segTrg], false);
352
+ }, []);
353
+ // Create LineString features from segments with same unique value
354
+ _this.segments = uniqueVias.map(function (via) {
355
+ var viaSegments = _this.segments.filter(function (seg) {
356
+ var segTrg = seg.get('trg');
357
+ return segTrg[0] === via[0] && segTrg[1] === via[1];
358
+ });
359
+ var coords = getFlatCoordinatesFromSegments(viaSegments);
360
+ return new ol_1.Feature({
361
+ geometry: new geom_1.LineString(coords),
362
+ });
363
+ });
364
+ }
365
+ // Create the new route. This route will be modifiable by the Modifiy interaction.
366
+ var coords = getFlatCoordinatesFromSegments(_this.segments);
367
+ var routeFeature = new ol_1.Feature({
368
+ geometry: new geom_1.LineString(coords),
369
+ });
370
+ routeFeature.set('graph', graph);
371
+ routeFeature.set('mot', _this.mot);
372
+ routeFeature.set('minResolution', _this.graphsResolutions[index][0]);
373
+ routeFeature.set('maxResolution', _this.graphsResolutions[index][1]);
374
+ _this.routingLayer.olLayer.getSource().addFeature(routeFeature);
375
+ _this.loading = false;
376
+ })
377
+ .catch(function (error) {
378
+ if (error.name === 'AbortError') {
379
+ // Ignore abort error
380
+ return;
381
+ }
382
+ _this.segments = [];
383
+ // Dispatch error event and execute error function
384
+ _this.dispatchEvent({
385
+ type: 'error',
386
+ target: _this,
387
+ });
388
+ _this.onRouteError(error, _this);
389
+ _this.loading = false;
390
+ });
391
+ }));
392
+ };
393
+ /**
394
+ * Draw a via point. This function can parse all the possibilitiies
395
+ *
396
+ * @private
397
+ */
398
+ RoutingControl.prototype.drawViaPoint = function (viaPoint, idx, abortController) {
399
+ var _a, _b;
400
+ var _this = this;
401
+ var pointFeature = new ol_1.Feature();
402
+ pointFeature.set('viaPointIdx', idx);
403
+ // The via point is a coordinate using the current map's projection
404
+ if (Array.isArray(viaPoint)) {
405
+ pointFeature.setGeometry(new geom_1.Point(viaPoint));
406
+ this.routingLayer.olLayer.getSource().addFeature(pointFeature);
407
+ return Promise.resolve(pointFeature);
343
408
  }
344
- return false;
345
- }
346
- });
347
- this.modifyInteraction.on("modifystart", this.onModifyStart);
348
- this.modifyInteraction.on("modifyend", this.onModifyEnd);
349
- this.modifyInteraction.setActive(false);
350
- }
351
- addListeners() {
352
- if (!this.modify) {
353
- return;
354
- }
355
- this.removeListeners();
356
- this.onMapClickKey = this.map.on("singleclick", this.onMapClick);
357
- }
358
- removeListeners() {
359
- unByKey(this.onMapClickKey);
360
- }
361
- activate() {
362
- super.activate();
363
- if (this.map) {
364
- this.format = new GeoJSON({
365
- featureProjection: this.map.getView().getProjection()
366
- });
367
- this.graphsResolutions = RoutingControl.getGraphsResolutions(this.graphs, this.map);
368
- this.map.removeInteraction(this.modifyInteraction);
369
- this.routingLayer.attachToMap(this.map);
370
- this.map.addInteraction(this.modifyInteraction);
371
- this.modifyInteraction.setActive(this.modify);
372
- this.addListeners();
373
- } else {
374
- this.format = new GeoJSON({ featureProjection: "EPSG:3857" });
375
- this.graphsResolutions = this.graphs;
376
- }
377
- }
378
- deactivate() {
379
- if (this.map) {
380
- this.routingLayer.detachFromMap(this.map);
381
- this.map.removeInteraction(this.modifyInteraction);
382
- this.removeListeners();
383
- this.reset();
384
- }
385
- super.deactivate();
386
- }
387
- }
388
- export default RoutingControl;
409
+ // Possibility to parse:
410
+ //
411
+ // !8596126 a station with id 8596126
412
+ // !8596126$4 a station with id 8596126
413
+ if (!this.useRawViaPoints || REGEX_VIA_POINT_STATION_ID.test(viaPoint)) {
414
+ var stationId = void 0;
415
+ var track_1;
416
+ if (this.useRawViaPoints) {
417
+ _a = REGEX_VIA_POINT_STATION_ID.exec(viaPoint), stationId = _a[1], track_1 = _a[3];
418
+ }
419
+ else {
420
+ _b = viaPoint.split('$'), stationId = _b[0], track_1 = _b[1];
421
+ }
422
+ return fetch("".concat(this.stopsApiUrl, "lookup/").concat(stationId, "?key=").concat(this.stopsApiKey), { signal: abortController.signal })
423
+ .then(function (res) { return res.json(); })
424
+ .then(function (stationData) {
425
+ var coordinates = stationData.features[0].geometry.coordinates;
426
+ _this.cacheStationData[viaPoint] = (0, proj_1.fromLonLat)(coordinates);
427
+ pointFeature.set('viaPointTrack', track_1);
428
+ pointFeature.setGeometry(new geom_1.Point((0, proj_1.fromLonLat)(coordinates)));
429
+ _this.routingLayer.olLayer.getSource().addFeature(pointFeature);
430
+ return pointFeature;
431
+ })
432
+ .catch(function (error) {
433
+ if (error.name === 'AbortError') {
434
+ // Ignore abort error
435
+ return;
436
+ }
437
+ // Dispatch error event and execute error function
438
+ _this.dispatchEvent({
439
+ type: 'error',
440
+ target: _this,
441
+ });
442
+ _this.onRouteError(error, _this);
443
+ _this.loading = false;
444
+ });
445
+ }
446
+ // Only when this.useRawViaPoints is true.
447
+ // Possibility to parse:
448
+ //
449
+ // 47.37811,8.53935 a position 47.37811, 8.53935
450
+ if (this.useRawViaPoints && REGEX_VIA_POINT_COORD.test(viaPoint)) {
451
+ var _c = REGEX_VIA_POINT_COORD.exec(viaPoint), lat_1 = _c[0], lon_1 = _c[1];
452
+ var coordinates = (0, proj_1.fromLonLat)([parseFloat(lon_1), parseFloat(lat_1)], this.map.getView().getProjection());
453
+ pointFeature.setGeometry(new geom_1.Point(coordinates));
454
+ this.routingLayer.olLayer.getSource().addFeature(pointFeature);
455
+ return Promise.resolve(pointFeature);
456
+ }
457
+ // Only when this.useRawViaPoints is true.
458
+ // It will parse the via point to find some name, id, track coordinates.
459
+ //
460
+ // Possibility to parse:
461
+ //
462
+ // @47.37811,8.53935 a station at position 47.37811, 8.53935
463
+ // @47.37811,8.53935$4 track 4 in a station at position 47.37811, 8.53935
464
+ // zürich hb@47.37811,8.53935$8 track 8 in station "Zürich HB" at position 47.37811, 8.53935
465
+ var _d = REGEX_VIA_POINT.exec(viaPoint), stationName = _d[1], lat = _d[3], lon = _d[4], track = _d[6];
466
+ if (lon && lat) {
467
+ var coordinates = (0, proj_1.fromLonLat)([parseFloat(lon), parseFloat(lat)], this.map.getView().getProjection());
468
+ pointFeature.set('viaPointTrack', track);
469
+ pointFeature.setGeometry(new geom_1.Point(coordinates));
470
+ this.routingLayer.olLayer.getSource().addFeature(pointFeature);
471
+ return Promise.resolve(pointFeature);
472
+ }
473
+ if (stationName) {
474
+ return fetch("".concat(this.stopsApiUrl, "?key=").concat(this.stopsApiKey, "&q=").concat(stationName, "&limit=1"), { signal: abortController.signal })
475
+ .then(function (res) { return res.json(); })
476
+ .then(function (stationData) {
477
+ var coordinates = stationData.features[0].geometry.coordinates;
478
+ _this.cacheStationData[viaPoint] = (0, proj_1.fromLonLat)(coordinates);
479
+ pointFeature.set('viaPointTrack', track);
480
+ pointFeature.setGeometry(new geom_1.Point((0, proj_1.fromLonLat)(coordinates)));
481
+ _this.routingLayer.olLayer.getSource().addFeature(pointFeature);
482
+ return pointFeature;
483
+ })
484
+ .catch(function (error) {
485
+ // Dispatch error event and execute error function
486
+ _this.dispatchEvent({
487
+ type: 'error',
488
+ target: _this,
489
+ });
490
+ _this.onRouteError(error, _this);
491
+ _this.loading = false;
492
+ return null;
493
+ });
494
+ }
495
+ return Promise.resolve(null);
496
+ };
497
+ /**
498
+ * Used on click on map while control is active:
499
+ * By default adds a viaPoint to the end of array.
500
+ * If an existing viaPoint is clicked removes the clicked viaPoint.
501
+ * @private
502
+ */
503
+ RoutingControl.prototype.onMapClick = function (e) {
504
+ var feats = e.target.getFeaturesAtPixel(e.pixel);
505
+ var viaPoint = feats.find(function (feat) {
506
+ var _a;
507
+ return ((_a = feat.getGeometry()) === null || _a === void 0 ? void 0 : _a.getType()) === GeometryType_1.default.POINT &&
508
+ feat.get('viaPointIdx') !== undefined;
509
+ });
510
+ if (viaPoint) {
511
+ // Remove existing viaPoint on click and abort viaPoint add
512
+ this.removeViaPoint(viaPoint.get('viaPointIdx'));
513
+ return;
514
+ }
515
+ this.addViaPoint(e.coordinate);
516
+ };
517
+ /**
518
+ * Used on start of the modify interaction. Stores relevant data
519
+ * in this.initialRouteDrag object
520
+ * @private
521
+ */
522
+ RoutingControl.prototype.onModifyStart = function (evt) {
523
+ // When modify start, we search the index of the segment that is modifying.
524
+ var segmentIndex = -1;
525
+ var route = evt.features
526
+ .getArray()
527
+ .find(function (feat) { var _a; return ((_a = feat.getGeometry()) === null || _a === void 0 ? void 0 : _a.getType()) === GeometryType_1.default.LINE_STRING; });
528
+ // Find the segment index that is being modified
529
+ if (route) {
530
+ // We use a buff extent to fix floating issues , see https://github.com/openlayers/openlayers/issues/7130#issuecomment-535856422
531
+ var closestExtent_1 = (0, extent_1.buffer)(new geom_1.Point(route.getGeometry().getClosestPoint(evt.mapBrowserEvent.coordinate)).getExtent(), 0.001);
532
+ segmentIndex = this.segments.findIndex(function (segment) {
533
+ return segment.getGeometry().intersectsExtent(closestExtent_1);
534
+ });
535
+ }
536
+ // Find the viaPoint that is being modified
537
+ var viaPoint = (evt.features
538
+ .getArray()
539
+ .filter(function (feat) { var _a; return ((_a = feat.getGeometry()) === null || _a === void 0 ? void 0 : _a.getType()) === GeometryType_1.default.POINT; }) ||
540
+ [])[0];
541
+ // Write object with modify info
542
+ /** @ignore */
543
+ this.initialRouteDrag = {
544
+ viaPoint: viaPoint,
545
+ oldRoute: route && route.clone(),
546
+ segmentIndex: segmentIndex,
547
+ };
548
+ };
549
+ /**
550
+ * Used on end of the modify interaction. Resolves feature modification:
551
+ * Line drag creates new viaPoint at the final coordinate of drag.
552
+ * Point drag replaces old viaPoint.
553
+ * @private
554
+ */
555
+ RoutingControl.prototype.onModifyEnd = function (evt) {
556
+ var coord = evt.mapBrowserEvent.coordinate;
557
+ var _a = this.initialRouteDrag, oldRoute = _a.oldRoute, viaPoint = _a.viaPoint, segmentIndex = _a.segmentIndex;
558
+ // If viaPoint is being relocated overwrite the old viaPoint
559
+ if (viaPoint) {
560
+ return this.addViaPoint(coord, viaPoint.get('viaPointIdx'), 1);
561
+ }
562
+ // In case there is no route overwrite first coordinate
563
+ if (!oldRoute) {
564
+ return this.addViaPoint(coord, 0, 1);
565
+ }
566
+ // We can't add a via point because we haven't found which segment has been modified.
567
+ if (segmentIndex === -1) {
568
+ return Promise.reject(new Error('No segment found'));
569
+ }
570
+ // Insert new viaPoint at the modified segment index + 1
571
+ return this.addViaPoint(coord, segmentIndex + 1);
572
+ };
573
+ /**
574
+ * Define a default element.
575
+ *
576
+ * @private
577
+ */
578
+ RoutingControl.prototype.createDefaultElement = function () {
579
+ var _this = this;
580
+ /** @ignore */
581
+ this.element = document.createElement('button');
582
+ this.element.id = 'ol-toggle-routing';
583
+ this.element.innerHTML = 'Toggle Route Control';
584
+ this.element.onclick = function () {
585
+ return _this.active ? _this.deactivate() : _this.activate();
586
+ };
587
+ Object.assign(this.element.style, {
588
+ position: 'absolute',
589
+ right: '10px',
590
+ top: '10px',
591
+ });
592
+ };
593
+ /**
594
+ * Create the interaction used to modify vertexes of features.
595
+ * @private
596
+ */
597
+ RoutingControl.prototype.createModifyInteraction = function () {
598
+ var _this = this;
599
+ /**
600
+ * @type {ol.interaction.Modify}
601
+ * @private
602
+ */
603
+ // Define and add modify interaction
604
+ this.modifyInteraction = new interaction_1.Modify({
605
+ source: this.routingLayer.olLayer.getSource(),
606
+ pixelTolerance: 4,
607
+ hitDetection: this.routingLayer.olLayer,
608
+ deleteCondition: function (e) {
609
+ var feats = e.target.getFeaturesAtPixel(e.pixel, {
610
+ hitTolerance: 5,
611
+ });
612
+ var viaPoint = feats.find(function (feat) {
613
+ var _a;
614
+ return ((_a = feat.getGeometry()) === null || _a === void 0 ? void 0 : _a.getType()) === GeometryType_1.default.POINT &&
615
+ feat.get('index');
616
+ });
617
+ if ((0, condition_1.click)(e) && viaPoint) {
618
+ // Remove node & viaPoint if an existing viaPoint was clicked
619
+ _this.removeViaPoint(viaPoint.get('index'));
620
+ return true;
621
+ }
622
+ return false;
623
+ },
624
+ });
625
+ this.modifyInteraction.on('modifystart', this.onModifyStart);
626
+ this.modifyInteraction.on('modifyend', this.onModifyEnd);
627
+ this.modifyInteraction.setActive(false);
628
+ };
629
+ /**
630
+ * Add click listener to map.
631
+ * @private
632
+ */
633
+ RoutingControl.prototype.addListeners = function () {
634
+ if (!this.modify) {
635
+ return;
636
+ }
637
+ this.removeListeners();
638
+ /** @ignore */
639
+ this.onMapClickKey = this.map.on('singleclick', this.onMapClick);
640
+ };
641
+ /**
642
+ * Remove click listener from map.
643
+ * @private
644
+ */
645
+ RoutingControl.prototype.removeListeners = function () {
646
+ (0, Observable_1.unByKey)(this.onMapClickKey);
647
+ };
648
+ RoutingControl.prototype.activate = function () {
649
+ _super.prototype.activate.call(this);
650
+ if (this.map) {
651
+ /** @ignore */
652
+ this.format = new format_1.GeoJSON({
653
+ featureProjection: this.map.getView().getProjection(),
654
+ });
655
+ /** @ignore */
656
+ this.graphsResolutions = RoutingControl.getGraphsResolutions(this.graphs, this.map);
657
+ // Clean the modifyInteraction if present
658
+ this.map.removeInteraction(this.modifyInteraction);
659
+ // Add modify interaction, RoutingLayer and listeners
660
+ this.routingLayer.attachToMap(this.map);
661
+ this.map.addInteraction(this.modifyInteraction);
662
+ this.modifyInteraction.setActive(this.modify);
663
+ this.addListeners();
664
+ }
665
+ else {
666
+ // fall back to some default values if map is not available
667
+ this.format = new format_1.GeoJSON({ featureProjection: 'EPSG:3857' });
668
+ this.graphsResolutions = this.graphs;
669
+ }
670
+ };
671
+ RoutingControl.prototype.deactivate = function () {
672
+ if (this.map) {
673
+ // Remove modify interaction, RoutingLayer, listeners and viaPoints
674
+ this.routingLayer.detachFromMap(this.map);
675
+ this.map.removeInteraction(this.modifyInteraction);
676
+ this.removeListeners();
677
+ this.reset();
678
+ }
679
+ _super.prototype.deactivate.call(this);
680
+ };
681
+ return RoutingControl;
682
+ }(Control_1.default));
683
+ exports.default = RoutingControl;