mobility-toolbox-js 2.0.0-beta.33 → 2.0.0-beta.36

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 (116) hide show
  1. package/api/RealtimeAPI.d.ts +6 -6
  2. package/api/RealtimeAPI.d.ts.map +1 -1
  3. package/api/RealtimeAPI.js +613 -0
  4. package/api/RoutingAPI.d.ts.map +1 -1
  5. package/api/RoutingAPI.js +35 -0
  6. package/api/StopsAPI.d.ts +1 -1
  7. package/api/StopsAPI.d.ts.map +1 -1
  8. package/api/StopsAPI.js +38 -0
  9. package/api/index.d.ts +3 -4
  10. package/api/index.d.ts.map +1 -1
  11. package/api/index.js +3 -0
  12. package/api/typedefs.js +73 -0
  13. package/common/api/HttpAPI.d.ts.map +1 -1
  14. package/common/api/HttpAPI.js +57 -0
  15. package/common/api/WebSocketAPI.d.ts +2 -2
  16. package/common/api/WebSocketAPI.d.ts.map +1 -1
  17. package/common/api/WebSocketAPI.js +290 -0
  18. package/common/controls/Control.d.ts +5 -5
  19. package/common/controls/Control.d.ts.map +1 -1
  20. package/common/controls/Control.js +137 -0
  21. package/common/index.js +2 -0
  22. package/common/layers/Layer.d.ts +11 -11
  23. package/common/layers/Layer.d.ts.map +1 -1
  24. package/common/layers/Layer.js +223 -0
  25. package/common/mixins/CopyrightMixin.js +43 -0
  26. package/common/mixins/MapboxLayerMixin.js +198 -0
  27. package/common/mixins/RealtimeLayerMixin.js +650 -0
  28. package/common/mixins/StopFinderMixin.d.ts +3 -3
  29. package/common/mixins/StopFinderMixin.d.ts.map +1 -1
  30. package/common/mixins/StopFinderMixin.js +156 -0
  31. package/common/mixins/UserInteractionsLayerMixin.js +192 -0
  32. package/common/styles/index.js +4 -0
  33. package/common/styles/realtimeDefaultStyle.js +239 -0
  34. package/common/styles/realtimeDelayStyle.js +13 -0
  35. package/common/styles/realtimeSimpleStyle.js +22 -0
  36. package/common/typedefs.js +22 -0
  37. package/common/utils/cleanStopTime.js +28 -0
  38. package/common/utils/compareDepartures.d.ts +1 -1
  39. package/common/utils/compareDepartures.d.ts.map +1 -1
  40. package/common/utils/compareDepartures.js +34 -0
  41. package/common/utils/createCanvas.js +27 -0
  42. package/common/utils/createTrackerFilters.d.ts +1 -1
  43. package/common/utils/createTrackerFilters.d.ts.map +1 -1
  44. package/common/utils/createTrackerFilters.js +67 -0
  45. package/common/utils/getLayersAsFlatArray.js +14 -0
  46. package/common/utils/getMapboxMapCopyrights.js +24 -0
  47. package/common/utils/getMapboxRender.js +74 -0
  48. package/common/utils/getMaplibreRender.js +35 -0
  49. package/common/utils/getRealtimeModeSuffix.js +7 -0
  50. package/common/utils/getUrlWithParams.js +18 -0
  51. package/common/utils/getVehiclePosition.js +63 -0
  52. package/common/utils/index.js +12 -0
  53. package/common/utils/removeDuplicate.d.ts +1 -1
  54. package/common/utils/removeDuplicate.d.ts.map +1 -1
  55. package/common/utils/removeDuplicate.js +15 -0
  56. package/common/utils/renderTrajectories.js +107 -0
  57. package/common/utils/sortByDelay.js +20 -0
  58. package/common/utils/timeUtils.js +39 -0
  59. package/common/utils/trackerConfig.js +170 -0
  60. package/iife.js +5 -0
  61. package/index.d.ts +4 -0
  62. package/index.js +10 -0
  63. package/mapbox/controls/CopyrightControl.d.ts +0 -1
  64. package/mapbox/controls/CopyrightControl.d.ts.map +1 -1
  65. package/mapbox/controls/CopyrightControl.js +53 -0
  66. package/mapbox/controls/index.js +2 -0
  67. package/mapbox/index.js +4 -0
  68. package/mapbox/layers/Layer.d.ts +1 -1
  69. package/mapbox/layers/Layer.d.ts.map +1 -1
  70. package/mapbox/layers/Layer.js +97 -0
  71. package/mapbox/layers/RealtimeLayer.d.ts +4 -4
  72. package/mapbox/layers/RealtimeLayer.d.ts.map +1 -1
  73. package/mapbox/layers/RealtimeLayer.js +270 -0
  74. package/mapbox/layers/index.js +2 -0
  75. package/mapbox/utils.js +43 -0
  76. package/mbt.js +6 -5
  77. package/mbt.js.map +2 -2
  78. package/mbt.min.js +2 -2
  79. package/mbt.min.js.map +2 -2
  80. package/ol/controls/CopyrightControl.js +69 -0
  81. package/ol/controls/RoutingControl.d.ts +6 -5
  82. package/ol/controls/RoutingControl.d.ts.map +1 -1
  83. package/ol/controls/RoutingControl.js +622 -0
  84. package/ol/controls/StopFinderControl.js +36 -0
  85. package/ol/controls/index.js +3 -0
  86. package/ol/index.js +5 -0
  87. package/ol/layers/Layer.d.ts +1 -1
  88. package/ol/layers/Layer.d.ts.map +1 -1
  89. package/ol/layers/Layer.js +148 -0
  90. package/ol/layers/MapboxLayer.d.ts +7 -7
  91. package/ol/layers/MapboxLayer.d.ts.map +1 -1
  92. package/ol/layers/MapboxLayer.js +101 -0
  93. package/ol/layers/MapboxStyleLayer.d.ts +3 -3
  94. package/ol/layers/MapboxStyleLayer.d.ts.map +1 -1
  95. package/ol/layers/MapboxStyleLayer.js +340 -0
  96. package/ol/layers/MaplibreLayer.d.ts +1 -1
  97. package/ol/layers/MaplibreLayer.d.ts.map +1 -1
  98. package/ol/layers/MaplibreLayer.js +35 -0
  99. package/ol/layers/RealtimeLayer.d.ts +2 -2
  100. package/ol/layers/RealtimeLayer.d.ts.map +1 -1
  101. package/ol/layers/RealtimeLayer.js +294 -0
  102. package/ol/layers/RoutingLayer.d.ts +2 -2
  103. package/ol/layers/RoutingLayer.d.ts.map +1 -1
  104. package/ol/layers/RoutingLayer.js +84 -0
  105. package/ol/layers/VectorLayer.d.ts +1 -1
  106. package/ol/layers/VectorLayer.d.ts.map +1 -1
  107. package/ol/layers/VectorLayer.js +38 -0
  108. package/ol/layers/WMSLayer.d.ts +1 -1
  109. package/ol/layers/WMSLayer.d.ts.map +1 -1
  110. package/ol/layers/WMSLayer.js +72 -0
  111. package/ol/layers/index.js +8 -0
  112. package/ol/styles/fullTrajectoryDelayStyle.js +33 -0
  113. package/ol/styles/fullTrajectoryStyle.js +44 -0
  114. package/ol/styles/index.js +2 -0
  115. package/package.json +2 -2
  116. package/setupTests.js +13 -0
@@ -1 +1 @@
1
- {"version":3,"file":"compareDepartures.d.ts","sourceRoot":"","sources":["../../../src/common/utils/compareDepartures.js"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,2FA8BC"}
1
+ {"version":3,"file":"compareDepartures.d.ts","sourceRoot":"","sources":["../../../src/common/utils/compareDepartures.js"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,sCAJW,MAAM,KACN,MAAM,0CAiChB"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Compare two given departures for sort alogithm,
3
+ * @param {Object} a First departure.
4
+ * @param {Object} b Second departure.
5
+ * @private
6
+ */
7
+ const compareDepartures = (a, b, sortByMinArrivalTime = false) => {
8
+ // First LEAVING and HIDDEN, then BOARDING and then sorted by time.
9
+ const topStates = ['HIDDEN', 'LEAVING', 'BOARDING'];
10
+ const aTop = a.has_fzo && topStates.indexOf(a.state) > -1;
11
+ const bTop = b.has_fzo && topStates.indexOf(b.state) > -1;
12
+ if (aTop || bTop) {
13
+ if (aTop !== bTop) {
14
+ return aTop ? -1 : 1;
15
+ }
16
+ if (a.state !== b.state) {
17
+ // one is leaving
18
+ return topStates.indexOf(a.state) - topStates.indexOf(b.state);
19
+ }
20
+ }
21
+ let aDuration = null;
22
+ let bDuration = null;
23
+ const now = Date.now();
24
+ if (sortByMinArrivalTime) {
25
+ aDuration = new Date(a.min_arrival_time || a.time).getTime() - now;
26
+ bDuration = new Date(b.min_arrival_time || b.time).getTime() - now;
27
+ }
28
+ else {
29
+ aDuration = new Date(a.time).getTime() - now;
30
+ bDuration = new Date(b.time).getTime() - now;
31
+ }
32
+ return aDuration - bDuration;
33
+ };
34
+ export default compareDepartures;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * This function try to create a canvas element and return it.
3
+ * it uses document.createElement('canvas') if document is available
4
+ * or new OffscreenCanvas(width, height) if OffscreenCanvas is avalaible (for web worker)
5
+ * or it returns null if neither is available.
6
+ */
7
+ const createCanvas = (width, height) => {
8
+ let canvas = null;
9
+ // Prevent SSR errors
10
+ if (typeof window === 'undefined') {
11
+ return null;
12
+ }
13
+ if (document === null || document === void 0 ? void 0 : document.createElement) {
14
+ canvas = document.createElement('canvas');
15
+ canvas.width = width;
16
+ canvas.height = height;
17
+ }
18
+ else if (OffscreenCanvas) {
19
+ canvas = new OffscreenCanvas(width, height);
20
+ }
21
+ else {
22
+ // eslint-disable-next-line no-console
23
+ console.error("We didn't find a way to create a canvas element, document.createElement('canvas') and new OffscrenCanvas() are not supported");
24
+ }
25
+ return canvas;
26
+ };
27
+ export default createCanvas;
@@ -8,5 +8,5 @@ export default createFilters;
8
8
  * @param {Regexp} regexLine - A regex aplly of vehcile's name.
9
9
  * @private
10
10
  */
11
- declare function createFilters(line: string | Array<string>, route: string | Array<string>, operator: string | Array<string>, regexLine: Regexp): (t: any) => boolean;
11
+ declare function createFilters(line: string | Array<string>, route: string | Array<string>, operator: string | Array<string>, regexLine: Regexp): ((t: any) => boolean) | null;
12
12
  //# sourceMappingURL=createTrackerFilters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createTrackerFilters.d.ts","sourceRoot":"","sources":["../../../src/common/utils/createTrackerFilters.js"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,qCANW,MAAM,GAAC,MAAM,MAAM,CAAC,SACpB,MAAM,GAAC,MAAM,MAAM,CAAA,YACnB,MAAM,GAAC,MAAM,MAAM,CAAA,0CA+E7B"}
1
+ {"version":3,"file":"createTrackerFilters.d.ts","sourceRoot":"","sources":["../../../src/common/utils/createTrackerFilters.js"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,qCANW,MAAM,GAAC,MAAM,MAAM,CAAC,SACpB,MAAM,GAAC,MAAM,MAAM,CAAA,YACnB,MAAM,GAAC,MAAM,MAAM,CAAA,mDA+E7B"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Return a filter functions based on some parameters of a vehicle.
3
+ *
4
+ * @param {string|Array<string>} line - A list of vehicle's name to filter. Names can be separated by a comma. Ex: 'S1,S2,S3'
5
+ * @param {string|Array<string} route - A list of vehicle's route (contained in routeIdentifier property) to filter. Indentifiers can be separated by a comma. Ex: 'id1,id2,id3'
6
+ * @param {string|Array<string} operator A list of vehicle's operator to filter. Operators can be separated by a comma. Ex: 'SBB,DB'
7
+ * @param {Regexp} regexLine - A regex aplly of vehcile's name.
8
+ * @private
9
+ */
10
+ const createFilters = (line, route, operator, regexLine) => {
11
+ const filterList = [];
12
+ if (!line && !route && !operator && !regexLine) {
13
+ return null;
14
+ }
15
+ if (regexLine) {
16
+ const regexLineList = typeof regexLine === 'string' ? [regexLine] : regexLine;
17
+ const lineFilter = (item) => {
18
+ const name = item.properties.name ||
19
+ (item.properties.line && item.properties.line.name) ||
20
+ '';
21
+ if (!name) {
22
+ return false;
23
+ }
24
+ return regexLineList.some((regexStr) => new RegExp(regexStr, 'i').test(name));
25
+ };
26
+ filterList.push(lineFilter);
27
+ }
28
+ if (line) {
29
+ const lineFiltersList = typeof line === 'string' ? line.split(',') : line;
30
+ const lineList = lineFiltersList.map((l) => l.replace(/\s+/g, '').toUpperCase());
31
+ const lineFilter = (item) => {
32
+ const { line: linee, name } = item.properties;
33
+ const lineName = (name || (linee && linee.name) || '').toUpperCase();
34
+ if (!lineName) {
35
+ return false;
36
+ }
37
+ return lineList.includes(lineName);
38
+ };
39
+ filterList.push(lineFilter);
40
+ }
41
+ if (route) {
42
+ const routes = typeof route === 'string' ? route.split(',') : route;
43
+ const routeList = routes.map((item) => parseInt(item, 10));
44
+ const routeFilter = (item) => {
45
+ const routeId = parseInt(item.properties.routeIdentifier.split('.')[0], 10);
46
+ return routeList.includes(routeId);
47
+ };
48
+ filterList.push(routeFilter);
49
+ }
50
+ if (operator) {
51
+ const operatorList = typeof operator === 'string' ? [operator] : operator;
52
+ const operatorFilter = (item) => operatorList.some((op) => new RegExp(op, 'i').test(item.properties.operator));
53
+ filterList.push(operatorFilter);
54
+ }
55
+ if (!filterList.length) {
56
+ return null;
57
+ }
58
+ return (t) => {
59
+ for (let i = 0; i < filterList.length; i += 1) {
60
+ if (!filterList[i](t)) {
61
+ return false;
62
+ }
63
+ }
64
+ return true;
65
+ };
66
+ };
67
+ export default createFilters;
@@ -0,0 +1,14 @@
1
+ const getLayersAsFlatArray = (layersOrLayer) => {
2
+ let layers = layersOrLayer;
3
+ if (!Array.isArray(layers)) {
4
+ layers = [layersOrLayer];
5
+ }
6
+ let flatLayers = [];
7
+ layers.forEach((layer) => {
8
+ flatLayers.push(layer);
9
+ const { children } = layer;
10
+ flatLayers = flatLayers.concat(getLayersAsFlatArray(children || []));
11
+ });
12
+ return flatLayers;
13
+ };
14
+ export default getLayersAsFlatArray;
@@ -0,0 +1,24 @@
1
+ import removeDuplicate from './removeDuplicate';
2
+ /**
3
+ * Return the copyright a Mapbox map.
4
+ * @param {mapboxgl.Map} map A Mapbox map
5
+ * @ignore
6
+ */
7
+ const getMapboxMapCopyrights = (map) => {
8
+ if (!map || !map.style) {
9
+ return [];
10
+ }
11
+ const { sourceCaches } = map.style;
12
+ let copyrights = [];
13
+ Object.values(sourceCaches).forEach((sourceCache) => {
14
+ if (sourceCache.used) {
15
+ const source = sourceCache.getSource();
16
+ const attribution = source.attribution || (source.options && source.options.attribution);
17
+ if (attribution) {
18
+ copyrights = copyrights.concat(attribution.replace(/&copy;/g, '©').split(/(<a.*?<\/a>)/));
19
+ }
20
+ }
21
+ });
22
+ return removeDuplicate(copyrights);
23
+ };
24
+ export default getMapboxMapCopyrights;
@@ -0,0 +1,74 @@
1
+ /* eslint-disable no-underscore-dangle */
2
+ import { toLonLat } from 'ol/proj';
3
+ /**
4
+ * Return the render function fo the olLayer of a MaplibreLayer
5
+ */
6
+ export default function getMapboxRender(mapoxLayer) {
7
+ return (frameState) => {
8
+ const { map, mbMap, renderState, olLayer } = mapoxLayer;
9
+ if (!map || !mbMap) {
10
+ return null;
11
+ }
12
+ let changed = false;
13
+ const canvas = mbMap.getCanvas();
14
+ const { viewState } = frameState;
15
+ const visible = olLayer.getVisible();
16
+ if (renderState.visible !== visible) {
17
+ canvas.style.display = visible ? 'block' : 'none';
18
+ renderState.visible = visible;
19
+ // Needed since mapbox-gl 1.9.0.
20
+ // Without you don't see others ol layers on top.
21
+ canvas.style.position = 'absolute';
22
+ }
23
+ const opacity = olLayer.getOpacity();
24
+ if (renderState.opacity !== opacity) {
25
+ canvas.style.opacity = opacity;
26
+ renderState.opacity = opacity;
27
+ }
28
+ // adjust view parameters in mapbox
29
+ const { rotation } = viewState;
30
+ if (renderState.rotation !== rotation) {
31
+ mbMap.rotateTo((-(rotation || 0) * 180) / Math.PI, {
32
+ animate: false,
33
+ });
34
+ changed = true;
35
+ renderState.rotation = rotation;
36
+ }
37
+ if (renderState.zoom !== viewState.zoom ||
38
+ renderState.center[0] !== viewState.center[0] ||
39
+ renderState.center[1] !== viewState.center[1]) {
40
+ mbMap.jumpTo({
41
+ center: toLonLat(viewState.center),
42
+ zoom: viewState.zoom - 1,
43
+ animate: false,
44
+ });
45
+ changed = true;
46
+ renderState.zoom = viewState.zoom;
47
+ renderState.center = viewState.center;
48
+ }
49
+ const size = map.getSize();
50
+ if (renderState.size[0] !== size[0] || renderState.size[1] !== size[1]) {
51
+ changed = true;
52
+ renderState.size = size;
53
+ }
54
+ // cancel the scheduled update & trigger synchronous redraw
55
+ // see https://github.com/mapbox/mapbox-gl-js/issues/7893#issue-408992184
56
+ // NOTE: THIS MIGHT BREAK WHEN UPDATING MAPBOX
57
+ if (mbMap && mbMap.style && mbMap.isStyleLoaded() && changed) {
58
+ try {
59
+ if (mbMap._frame) {
60
+ mbMap._frame.cancel();
61
+ mbMap._frame = null;
62
+ }
63
+ mbMap._render();
64
+ }
65
+ catch (err) {
66
+ // ignore render errors because it's probably related to
67
+ // a render during an update of the style.
68
+ // eslint-disable-next-line no-console
69
+ console.warn(err);
70
+ }
71
+ }
72
+ return mbMap.getContainer();
73
+ };
74
+ }
@@ -0,0 +1,35 @@
1
+ import { toLonLat } from 'ol/proj';
2
+ import { toDegrees } from 'ol/math';
3
+ /**
4
+ * Return the render function fo the olLayer of a MaplibreLayer
5
+ */
6
+ export default function getMaplibreRender(maplibreLayer) {
7
+ return (frameState) => {
8
+ const { map, mbMap, olLayer } = maplibreLayer;
9
+ if (!map || !mbMap) {
10
+ return null;
11
+ }
12
+ const canvas = mbMap.getCanvas();
13
+ const { viewState } = frameState;
14
+ const opacity = olLayer.getOpacity();
15
+ canvas.style.opacity = opacity;
16
+ // adjust view parameters in mapbox
17
+ mbMap.jumpTo({
18
+ center: toLonLat(viewState.center),
19
+ zoom: viewState.zoom - 1,
20
+ bearing: toDegrees(-viewState.rotation),
21
+ animate: false,
22
+ });
23
+ if (!canvas.isConnected) {
24
+ // The canvas is not connected to the DOM, request a map rendering at the next animation frame
25
+ // to set the canvas size.
26
+ map.render();
27
+ }
28
+ else if (canvas.width !== frameState.size[0] ||
29
+ canvas.height !== frameState.size[1]) {
30
+ mbMap.resize();
31
+ }
32
+ mbMap.redraw();
33
+ return mbMap.getContainer();
34
+ };
35
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Get the websocket channel suffix, depending on the current mode.
3
+ * @param {String} mode Mode 'topographic' ou 'schematic'.
4
+ * @private
5
+ */
6
+ const getModeSuffix = (mode, modes) => mode === modes.SCHEMATIC ? '_schematic' : '';
7
+ export default getModeSuffix;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Return the styleUrl with apiKey parameters set.
3
+ * @param {string} url a url.
4
+ * @param {Object<String,String>} params a list of key/value pair to add to the url.
5
+ * @ignore
6
+ */
7
+ const getUrlWithParams = (url, params) => {
8
+ // Clean requets parameters, removing undefined and null values.
9
+ const newUrl = new URL(url);
10
+ const searchParams = params || {};
11
+ Object.entries(searchParams).forEach(([key, value]) => {
12
+ if (value !== undefined && value !== null) {
13
+ newUrl.searchParams.set(key, value);
14
+ }
15
+ });
16
+ return newUrl;
17
+ };
18
+ export default getUrlWithParams;
@@ -0,0 +1,63 @@
1
+ import GeomType from 'ol/geom/GeometryType';
2
+ /**
3
+ * Interpolate or not the vehicle position from a trajectory at a specific date.
4
+ *
5
+ * @param {number} now Current date to interpolate a position with. In ms.
6
+ * @param {RealtimeTrajectory} trajectory The trajectory to interpolate.
7
+ * @param {boolean} noInterpolate If true, the vehicle position is not interpolated on each render but only once.
8
+ * @returns
9
+ */
10
+ const getVehiclePosition = (now, trajectory, noInterpolate) => {
11
+ const { time_intervals: timeIntervals, olGeometry: geometry, coordinate, } = trajectory.properties;
12
+ let coord;
13
+ let rotation;
14
+ if (noInterpolate && coordinate) {
15
+ coord = coordinate;
16
+ }
17
+ else if (geometry.getType() === GeomType.POINT) {
18
+ coord = geometry.getCoordinates();
19
+ }
20
+ else if (geometry.getType() === GeomType.LINE_STRING) {
21
+ const intervals = timeIntervals || [[]];
22
+ const firstInterval = intervals[0];
23
+ const lastInterval = intervals[intervals.length - 1];
24
+ // Between the last time interval of a trajectory event and the beginning
25
+ // of the new trajectory event, there is few seconds, can be 6 to 30
26
+ // seconds (that's why the vehicle jumps sometimes).
27
+ // So we make the choice here to display the last (or the first) position
28
+ // of an trajectory event instead of removing them, if the current date is
29
+ // outside the time intervals we display the vehicle at the last (or first) position known.
30
+ if (now < firstInterval[0]) {
31
+ // Display first position known.
32
+ [, , rotation] = firstInterval;
33
+ coord = geometry.getFirstCoordinate();
34
+ }
35
+ else if (now > lastInterval[0]) {
36
+ // Display last position known.
37
+ [, , rotation] = lastInterval;
38
+ coord = geometry.getLastCoordinate();
39
+ }
40
+ else {
41
+ // Interpolate position using time intervals.
42
+ for (let j = 0; j < intervals.length - 1; j += 1) {
43
+ // Rotation only available in realtime layer.
44
+ const [start, startFrac] = intervals[j];
45
+ const [end, endFrac] = intervals[j + 1];
46
+ if (start <= now && now <= end) {
47
+ // interpolate position inside the time interval.
48
+ const timeFrac = Math.min((now - start) / (end - start), 1);
49
+ const geomFrac = timeFrac * (endFrac - startFrac) + startFrac;
50
+ coord = geometry.getCoordinateAt(geomFrac);
51
+ [, , rotation] = intervals[j];
52
+ break;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ else {
58
+ // eslint-disable-next-line no-console
59
+ console.error('This geometry type is not supported. Only Point or LineString are. Current geometry: ', geometry);
60
+ }
61
+ return { coord, rotation };
62
+ };
63
+ export default getVehiclePosition;
@@ -0,0 +1,12 @@
1
+ export { default as getUrlWithParams } from './getUrlWithParams';
2
+ export { default as getMapboxMapCopyrights } from './getMapboxMapCopyrights';
3
+ export { default as removeDuplicate } from './removeDuplicate';
4
+ export { default as createTrackerFilters } from './createTrackerFilters';
5
+ export { default as getLayersAsFlatArray } from './getLayersAsFlatArray';
6
+ export * from './timeUtils';
7
+ export { default as sortByDelay } from './sortByDelay';
8
+ export { default as renderTrajectories } from './renderTrajectories';
9
+ export { default as getMaplibreRender } from './getMaplibreRender';
10
+ export { default as getMapboxRender } from './getMapboxRender';
11
+ import * as trackerConfig_1 from './trackerConfig';
12
+ export { trackerConfig_1 as trackerConfig };
@@ -6,5 +6,5 @@ export default removeDuplicate;
6
6
  * @param {array} array Array of values.
7
7
  * @ignore
8
8
  */
9
- declare function removeDuplicate(array: any[]): any[];
9
+ declare function removeDuplicate(array: any): any[];
10
10
  //# sourceMappingURL=removeDuplicate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"removeDuplicate.d.ts","sourceRoot":"","sources":["../../../src/common/utils/removeDuplicate.js"],"names":[],"mappings":";AAAA;;;;;;GAMG;AACH,sDAYC"}
1
+ {"version":3,"file":"removeDuplicate.d.ts","sourceRoot":"","sources":["../../../src/common/utils/removeDuplicate.js"],"names":[],"mappings":";AAAA;;;;;;GAMG;AACH,oDAYC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This function remove duplicates lower case string value of an array.
3
+ * It removes also null, undefined or non string values.
4
+ *
5
+ * @param {array} array Array of values.
6
+ * @ignore
7
+ */
8
+ const removeDuplicate = (array) => {
9
+ const arrWithoutEmptyValues = array.filter((val) => val !== undefined && val !== null && val.trim && val.trim());
10
+ const lowerCasesValues = arrWithoutEmptyValues.map((str) => str.toLowerCase());
11
+ const uniqueLowerCaseValues = [...new Set(lowerCasesValues)];
12
+ const uniqueValues = uniqueLowerCaseValues.map((uniqueStr) => arrWithoutEmptyValues.find((str) => str.toLowerCase() === uniqueStr));
13
+ return uniqueValues;
14
+ };
15
+ export default removeDuplicate;
@@ -0,0 +1,107 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import { compose, apply, create } from 'ol/transform';
3
+ import getVehiclePosition from './getVehiclePosition';
4
+ /**
5
+ * Draw all the trajectories available in a canvas.
6
+ * @param {HTMLCanvas|HTMLOffscreenCanvas} The canvas where to draw the trajectories.
7
+ * @param {ViewState} trajectories An array of trajectories.
8
+ * @param {Function} style A function that returns a canvas representing a vehicle of a specific trajectory.
9
+ * @param {ViewState} viewState The view state of the map.
10
+ * @param {boolean} options.hoverVehicleId The id of the vehicle to highlight.
11
+ * @param {boolean} options.selectedVehicleId The id of the vehicle to select.
12
+ * @param {boolean} options.noInterpolate If true trajectories are not interpolated but
13
+ * drawn at the last known coordinate. Use this for performance optimization
14
+ * during map navigation.
15
+ * @private
16
+ */
17
+ const renderTrajectories = (canvas, trajectories, style, viewState, options) => {
18
+ if (!canvas) {
19
+ return {};
20
+ }
21
+ const { time = Date.now(), size = [], center, resolution, rotation = 0, pixelRatio, } = viewState;
22
+ const { noInterpolate = false, hoverVehicleId, selectedVehicleId } = options;
23
+ const context = canvas.getContext('2d');
24
+ context.clearRect(0, 0, canvas.width, canvas.height);
25
+ const [width, height] = size;
26
+ if (width && height && (canvas.width !== width || canvas.height !== height)) {
27
+ [canvas.width, canvas.height] = [width * pixelRatio, height * pixelRatio];
28
+ }
29
+ const coordinateToPixelTransform = compose(create(), size[0] / 2, size[1] / 2, 1 / resolution, -1 / resolution, -rotation, -center[0], -center[1]);
30
+ // Offscreen canvas has not style attribute
31
+ if (canvas.style) {
32
+ canvas.style.width = `${canvas.width / pixelRatio}px`;
33
+ canvas.style.height = `${canvas.height / pixelRatio}px`;
34
+ }
35
+ let hoverVehicleImg;
36
+ let hoverVehiclePx;
37
+ let hoverVehicleWidth;
38
+ let hoverVehicleHeight;
39
+ let selectedVehicleImg;
40
+ let selectedVehiclePx;
41
+ let selectedVehicleWidth;
42
+ let selectedVehicleHeight;
43
+ const renderedTrajectories = [];
44
+ for (let i = trajectories.length - 1; i >= 0; i -= 1) {
45
+ const trajectory = trajectories[i];
46
+ // We simplify the trajectory object
47
+ const { train_id: id, timeOffset } = trajectory.properties;
48
+ // We set the rotation and the timeFraction of the trajectory (used by tralis).
49
+ // if rotation === null that seems there is no rotation available.
50
+ const { coord, rotation: rotationIcon } = getVehiclePosition(time - (timeOffset || 0), trajectory, noInterpolate);
51
+ // We store the current vehicle position to the trajectory.
52
+ trajectories[i].properties.coordinate = coord;
53
+ trajectories[i].properties.rotation = rotationIcon;
54
+ if (!coord) {
55
+ // eslint-disable-next-line no-continue
56
+ continue;
57
+ }
58
+ let px = apply(coordinateToPixelTransform, [...coord]);
59
+ if (!px) {
60
+ // eslint-disable-next-line no-continue
61
+ continue;
62
+ }
63
+ px = px.map((p) => p * pixelRatio);
64
+ if (px[0] < 0 ||
65
+ px[0] > canvas.width ||
66
+ px[1] < 0 ||
67
+ px[1] > canvas.height) {
68
+ // eslint-disable-next-line no-continue
69
+ continue;
70
+ }
71
+ const vehicleImg = style(trajectory, viewState, options);
72
+ if (!vehicleImg) {
73
+ // eslint-disable-next-line no-continue
74
+ continue;
75
+ }
76
+ const imgWidth = vehicleImg.width;
77
+ const imgHeight = vehicleImg.height;
78
+ if (hoverVehicleId !== id && selectedVehicleId !== id) {
79
+ context.drawImage(vehicleImg, px[0] - imgWidth / 2, px[1] - imgHeight / 2, imgWidth, imgHeight);
80
+ }
81
+ if (hoverVehicleId && hoverVehicleId === id) {
82
+ // Store the canvas to draw it at the end
83
+ hoverVehicleImg = vehicleImg;
84
+ hoverVehiclePx = px;
85
+ hoverVehicleWidth = imgWidth;
86
+ hoverVehicleHeight = imgHeight;
87
+ }
88
+ if (selectedVehicleId && selectedVehicleId === id) {
89
+ // Store the canvas to draw it at the end
90
+ selectedVehicleImg = vehicleImg;
91
+ selectedVehiclePx = px;
92
+ selectedVehicleWidth = imgWidth;
93
+ selectedVehicleHeight = imgHeight;
94
+ }
95
+ renderedTrajectories.push(trajectory);
96
+ }
97
+ if (selectedVehicleImg) {
98
+ context.drawImage(selectedVehicleImg, selectedVehiclePx[0] - selectedVehicleWidth / 2, selectedVehiclePx[1] - selectedVehicleHeight / 2, selectedVehicleWidth, selectedVehicleHeight);
99
+ }
100
+ if (hoverVehicleImg) {
101
+ context.drawImage(hoverVehicleImg, hoverVehiclePx[0] - hoverVehicleWidth / 2, hoverVehiclePx[1] - hoverVehicleHeight / 2, hoverVehicleWidth, hoverVehicleHeight);
102
+ }
103
+ return {
104
+ renderedTrajectories,
105
+ };
106
+ };
107
+ export default renderTrajectories;
@@ -0,0 +1,20 @@
1
+ const sortByDelay = (traj1, traj2) => {
2
+ const props1 = traj1.properties;
3
+ const props2 = traj2.properties;
4
+ if (props1.delay === null && props2.delay !== null) {
5
+ return 1;
6
+ }
7
+ if (props2.delay === null && props1.delay !== null) {
8
+ return -1;
9
+ }
10
+ // We put cancelled train inbetween green and yellow trains
11
+ // >=180000ms corresponds to yellow train
12
+ if (props1.cancelled && !props2.cancelled) {
13
+ return props2.delay < 180000 ? -1 : 1;
14
+ }
15
+ if (props2.cancelled && !props1.cancelled) {
16
+ return props1.delay < 180000 ? 1 : -1;
17
+ }
18
+ return props2.delay - props1.delay;
19
+ };
20
+ export default sortByDelay;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Get a Date object as UTC date string .
3
+ * ex: 2019 09 01
4
+ * @ignore
5
+ */
6
+ export const getUTCDateString = (now = new Date()) => {
7
+ let month = (now.getUTCMonth() + 1).toString();
8
+ month = month.length === 1 ? `0${month}` : month;
9
+ let day = now.getUTCDate().toString();
10
+ day = day.length === 1 ? `0${day}` : day;
11
+ return [now.getUTCFullYear(), month, day].join('');
12
+ };
13
+ /**
14
+ * Get the UTC time string of Date object.
15
+ * ex: 09:05:01.123
16
+ * @ignore
17
+ */
18
+ export const getUTCTimeString = (date) => [
19
+ date.getUTCHours(),
20
+ date.getUTCMinutes(),
21
+ `${date.getUTCSeconds()}.${date.getUTCMilliseconds()}`,
22
+ ].join(':');
23
+ /**
24
+ * Returns a string representation of a number, with a zero if the number is lower than 10.
25
+ * @ignore
26
+ */
27
+ export const pad = (integer) => (integer < 10 ? `0${integer}` : integer);
28
+ /**
29
+ * Returns a 'hh:mm' string from a time in ms.
30
+ * @param {Number} timeInMs Time in milliseconds.
31
+ * @ignore
32
+ */
33
+ export const getHoursAndMinutes = (timeInMs) => {
34
+ if (!timeInMs || timeInMs <= 0) {
35
+ return '';
36
+ }
37
+ const date = new Date(timeInMs);
38
+ return `${pad(date.getHours())}:${pad(date.getMinutes())}`;
39
+ };