@panoramax/web-viewer 5.0.0-develop-d26305dd → 5.0.0-develop-be5ba1a7

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 (153) hide show
  1. package/build/cjs/index.js +1 -1
  2. package/build/cjs/index_photoviewer.js +1 -1
  3. package/build/esm/components/core/Basic.js +1 -1
  4. package/build/esm/translations/el.json +92 -1
  5. package/package.json +1 -1
  6. package/build/bundle.cjs +0 -3399
  7. package/build/bundle.cjs.map +0 -1
  8. package/build/bundle_photoviewer.cjs +0 -2510
  9. package/build/bundle_photoviewer.cjs.map +0 -1
  10. package/build/components/core/Basic.css +0 -56
  11. package/build/components/core/Basic.js +0 -378
  12. package/build/components/core/CoverageMap.css +0 -10
  13. package/build/components/core/CoverageMap.js +0 -169
  14. package/build/components/core/Editor.css +0 -33
  15. package/build/components/core/Editor.js +0 -398
  16. package/build/components/core/PhotoViewer.css +0 -70
  17. package/build/components/core/PhotoViewer.js +0 -650
  18. package/build/components/core/Viewer.css +0 -130
  19. package/build/components/core/Viewer.js +0 -711
  20. package/build/components/core/index.js +0 -10
  21. package/build/components/index.js +0 -11
  22. package/build/components/index_photoviewer.js +0 -6
  23. package/build/components/layout/BottomDrawer.js +0 -258
  24. package/build/components/layout/CorneredGrid.js +0 -143
  25. package/build/components/layout/Mini.js +0 -121
  26. package/build/components/layout/Tabs.js +0 -140
  27. package/build/components/layout/index.js +0 -9
  28. package/build/components/menus/LocationPrecisionDoc.js +0 -42
  29. package/build/components/menus/MapBackground.js +0 -110
  30. package/build/components/menus/MapFilters.js +0 -567
  31. package/build/components/menus/MapLayers.js +0 -238
  32. package/build/components/menus/MapLegend.js +0 -68
  33. package/build/components/menus/MiniPictureLegend.js +0 -73
  34. package/build/components/menus/PictureLegend.js +0 -379
  35. package/build/components/menus/PictureMetadata.js +0 -380
  36. package/build/components/menus/PlayerOptions.js +0 -93
  37. package/build/components/menus/QualityScoreDoc.js +0 -42
  38. package/build/components/menus/ReportForm.js +0 -132
  39. package/build/components/menus/SemanticsDoc.js +0 -38
  40. package/build/components/menus/SemanticsDownload.js +0 -33
  41. package/build/components/menus/SemanticsFilters.js +0 -153
  42. package/build/components/menus/SemanticsList.js +0 -413
  43. package/build/components/menus/SemanticsMetadata.js +0 -368
  44. package/build/components/menus/Share.js +0 -105
  45. package/build/components/menus/index.js +0 -22
  46. package/build/components/menus/index_photoviewer.js +0 -11
  47. package/build/components/styles.js +0 -557
  48. package/build/components/ui/AnnotationsSwitch.js +0 -159
  49. package/build/components/ui/Button.js +0 -77
  50. package/build/components/ui/ButtonGroup.css +0 -59
  51. package/build/components/ui/ButtonGroup.js +0 -69
  52. package/build/components/ui/CopyButton.js +0 -110
  53. package/build/components/ui/Grade.js +0 -54
  54. package/build/components/ui/GradeFilter.js +0 -122
  55. package/build/components/ui/IconSwitch.js +0 -193
  56. package/build/components/ui/LinkButton.js +0 -67
  57. package/build/components/ui/ListGroup.js +0 -66
  58. package/build/components/ui/ListItem.js +0 -90
  59. package/build/components/ui/Loader.js +0 -203
  60. package/build/components/ui/Map.css +0 -63
  61. package/build/components/ui/Map.js +0 -853
  62. package/build/components/ui/MapMore.js +0 -175
  63. package/build/components/ui/Photo.css +0 -50
  64. package/build/components/ui/Photo.js +0 -1502
  65. package/build/components/ui/Popup.js +0 -145
  66. package/build/components/ui/ProgressBar.js +0 -104
  67. package/build/components/ui/QualityScore.js +0 -147
  68. package/build/components/ui/SearchBar.js +0 -374
  69. package/build/components/ui/SemanticsEditor.js +0 -191
  70. package/build/components/ui/SemanticsTable.js +0 -88
  71. package/build/components/ui/Switch.js +0 -139
  72. package/build/components/ui/TogglableGroup.js +0 -157
  73. package/build/components/ui/index.js +0 -29
  74. package/build/components/ui/index_photoviewer.js +0 -21
  75. package/build/components/ui/widgets/CopyCoordinates.js +0 -75
  76. package/build/components/ui/widgets/GeoSearch.css +0 -21
  77. package/build/components/ui/widgets/GeoSearch.js +0 -150
  78. package/build/components/ui/widgets/Legend.js +0 -190
  79. package/build/components/ui/widgets/LevelSelect.css +0 -51
  80. package/build/components/ui/widgets/LevelSelect.js +0 -143
  81. package/build/components/ui/widgets/MapFiltersButton.js +0 -114
  82. package/build/components/ui/widgets/MapLayersButton.js +0 -79
  83. package/build/components/ui/widgets/OSMEditors.js +0 -155
  84. package/build/components/ui/widgets/PictureLegendActions.js +0 -99
  85. package/build/components/ui/widgets/Player.css +0 -7
  86. package/build/components/ui/widgets/Player.js +0 -154
  87. package/build/components/ui/widgets/SemanticsFiltersButton.js +0 -65
  88. package/build/components/ui/widgets/Zoom.js +0 -84
  89. package/build/components/ui/widgets/index.js +0 -16
  90. package/build/components/ui/widgets/index_photoviewer.js +0 -7
  91. package/build/img/arrow_360.svg +0 -14
  92. package/build/img/arrow_flat.svg +0 -11
  93. package/build/img/arrow_triangle.svg +0 -9
  94. package/build/img/arrow_turn.svg +0 -8
  95. package/build/img/bg_aerial.jpg +0 -0
  96. package/build/img/bg_streets.jpg +0 -0
  97. package/build/img/loader_base.jpg +0 -0
  98. package/build/img/logo_dead.svg +0 -91
  99. package/build/img/marker.svg +0 -17
  100. package/build/img/marker_blue.svg +0 -20
  101. package/build/img/osm.svg +0 -49
  102. package/build/img/panoramax.svg +0 -13
  103. package/build/img/switch_big.svg +0 -54
  104. package/build/img/switch_mini.svg +0 -48
  105. package/build/img/wd.svg +0 -1
  106. package/build/index_photoviewer.js +0 -4
  107. package/build/package.json +0 -148
  108. package/build/servers.js +0 -14
  109. package/build/translations/ar.json +0 -1
  110. package/build/translations/be.json +0 -257
  111. package/build/translations/br.json +0 -81
  112. package/build/translations/cy.json +0 -117
  113. package/build/translations/da.json +0 -300
  114. package/build/translations/de.json +0 -309
  115. package/build/translations/en.json +0 -294
  116. package/build/translations/eo.json +0 -235
  117. package/build/translations/es.json +0 -292
  118. package/build/translations/fi.json +0 -1
  119. package/build/translations/fr.json +0 -294
  120. package/build/translations/hr.json +0 -294
  121. package/build/translations/hu.json +0 -294
  122. package/build/translations/it.json +0 -306
  123. package/build/translations/ja.json +0 -182
  124. package/build/translations/ko.json +0 -1
  125. package/build/translations/nl.json +0 -305
  126. package/build/translations/nn.json +0 -1
  127. package/build/translations/pl.json +0 -169
  128. package/build/translations/pt.json +0 -296
  129. package/build/translations/pt_BR.json +0 -304
  130. package/build/translations/sv.json +0 -182
  131. package/build/translations/ti.json +0 -9
  132. package/build/translations/tr.json +0 -297
  133. package/build/translations/uk.json +0 -268
  134. package/build/translations/zh_Hant.json +0 -309
  135. package/build/utils/API.js +0 -928
  136. package/build/utils/InitParameters.js +0 -521
  137. package/build/utils/MapStyleComposer.js +0 -889
  138. package/build/utils/PanoraMapProtocol.js +0 -49
  139. package/build/utils/PhotoAdapter.js +0 -49
  140. package/build/utils/PresetsManager.js +0 -148
  141. package/build/utils/SemanticsMapProtocol.js +0 -144
  142. package/build/utils/URLHandler.js +0 -426
  143. package/build/utils/geocoder.js +0 -203
  144. package/build/utils/i18n.js +0 -128
  145. package/build/utils/index.js +0 -17
  146. package/build/utils/index_photoviewer.js +0 -14
  147. package/build/utils/indoor.js +0 -200
  148. package/build/utils/map.js +0 -788
  149. package/build/utils/picture.js +0 -507
  150. package/build/utils/semantics.js +0 -321
  151. package/build/utils/services.js +0 -148
  152. package/build/utils/utils.js +0 -433
  153. package/build/utils/widgets.js +0 -110
@@ -1,788 +0,0 @@
1
- import {
2
- COLORS, GPS_VALUES, QUALITYSCORE_GPS_VALUES,
3
- QUALITYSCORE_POND_GPS, QUALITYSCORE_POND_RES, QUALITYSCORE_RES_360_VALUES,
4
- QUALITYSCORE_RES_FLAT_VALUES, QUALITYSCORE_VALUES, isNullId, svgToImg,
5
- } from "./utils.js";
6
-
7
- const LoaderImg = await fetch(new URL("../img/marker.svg", import.meta.url).href).then(res => res.text());
8
-
9
- export const RASTER_LAYER_ID = "pnx-aerial";
10
-
11
- export const TILES_PICTURES_ZOOM = 15;
12
- export const TILES_PICTURES_SYMBOL_ZOOM = 19;
13
-
14
- const CROWDED_TILE_COND = ["!", ["has", "uncrowded"]];
15
- const EQUIRECT_COND = ["==", ["get", "type"], "equirectangular"];
16
-
17
- function getVectorStyles(noCrowded) {
18
- return {
19
- PICTURES: {
20
- "paint": {
21
- "circle-radius": ["interpolate", ["linear"], ["zoom"],
22
- TILES_PICTURES_ZOOM, 0,
23
- TILES_PICTURES_ZOOM+0.5, noCrowded ? 1 : ["case", CROWDED_TILE_COND, 0, 1],
24
- TILES_PICTURES_ZOOM+1.5, noCrowded ? 2 : ["case", CROWDED_TILE_COND, 0, 2],
25
- TILES_PICTURES_ZOOM+2, noCrowded ? 4 : ["case", CROWDED_TILE_COND, 1, 4],
26
- TILES_PICTURES_ZOOM+3, noCrowded ? 5 : ["case", CROWDED_TILE_COND, 3, 5],
27
- TILES_PICTURES_ZOOM+5, noCrowded ? 7 : ["case", CROWDED_TILE_COND, 5, 7],
28
- TILES_PICTURES_ZOOM+7, noCrowded ? 7 : ["case", CROWDED_TILE_COND, 7, 7],
29
- ],
30
- "circle-opacity": ["interpolate", ["linear"], ["zoom"],
31
- TILES_PICTURES_ZOOM, 0,
32
- TILES_PICTURES_ZOOM+0.5, noCrowded ? 1 : ["case", CROWDED_TILE_COND, 0, 1],
33
- TILES_PICTURES_ZOOM+1.5, noCrowded ? 1 : ["case", CROWDED_TILE_COND, 0, 1],
34
- TILES_PICTURES_ZOOM+2, 1
35
- ],
36
- "circle-stroke-opacity": ["case",
37
- ["all", CROWDED_TILE_COND, EQUIRECT_COND], 0.2,
38
- EQUIRECT_COND, 0.4,
39
- 0
40
- ],
41
- "circle-stroke-width": ["interpolate", ["linear"], ["zoom"],
42
- TILES_PICTURES_ZOOM+2.5, 0,
43
- TILES_PICTURES_ZOOM+3.5, noCrowded ? ["case",
44
- EQUIRECT_COND, 10,
45
- 2
46
- ] : ["case",
47
- ["all", CROWDED_TILE_COND, EQUIRECT_COND], 0,
48
- EQUIRECT_COND, 10,
49
- CROWDED_TILE_COND, 0,
50
- 2
51
- ],
52
- TILES_PICTURES_ZOOM+4.5, noCrowded ? ["case",
53
- EQUIRECT_COND, 10,
54
- 2
55
- ]: ["case",
56
- ["all", CROWDED_TILE_COND, EQUIRECT_COND], 10,
57
- EQUIRECT_COND, 10,
58
- CROWDED_TILE_COND, 0,
59
- 2
60
- ]
61
- ],
62
- },
63
- "layout": {}
64
- },
65
- SEQUENCES: {
66
- "paint": {
67
- "line-width": ["interpolate", ["linear"], ["zoom"],
68
- 0, 0.5,
69
- 10, 1.5,
70
- TILES_PICTURES_ZOOM-0.5, 1.5,
71
- TILES_PICTURES_ZOOM+0.5, noCrowded ? 2 : ["case", CROWDED_TILE_COND, 0.5, 2],
72
- 22, noCrowded ? 4 : ["case", CROWDED_TILE_COND, 1, 4],
73
- ],
74
- },
75
- "layout": {
76
- "line-cap": "square",
77
- }
78
- },
79
- SEQUENCES_PLUS: {
80
- "paint": {
81
- "line-width": ["interpolate", ["linear"], ["zoom"], 0, 15, TILES_PICTURES_ZOOM+1, 30],
82
- "line-opacity": 0,
83
- "line-color": "#ff0000",
84
- },
85
- "layout": {
86
- "line-cap": "square",
87
- }
88
- },
89
- GRID: {
90
- "layout": {
91
- "circle-sort-key": ["get","coef"]
92
- },
93
- "paint": {
94
- "circle-color": ["interpolate",["linear"],["get","coef"],
95
- 0, "#FFA726",
96
- 0.5, "#E65100",
97
- 1, "#3E2723"
98
- ],
99
- "circle-opacity": ["interpolate",["linear"],["zoom"],
100
- 4, 0.5,
101
- 5, 1,
102
- 6.75, 1,
103
- 7, 0
104
- ],
105
- "circle-radius": ["interpolate",["linear"],["zoom"],
106
- 1, ["match",["get","coef"], 0, 0, 1],
107
- 5, ["match",["get","coef"], 0, 0, 2.5],
108
- 7, ["match",["get","coef"], 0, 0, 7]
109
- ]
110
- },
111
- }
112
- };
113
- }
114
-
115
- export const VECTOR_STYLES = getVectorStyles(false);
116
- export const VECTOR_STYLES_NOCROWD = getVectorStyles(true);
117
-
118
- // See MapLibre docs for explanation of expressions magic: https://maplibre.org/maplibre-style-spec/expressions/
119
- const MAP_EXPR_QUALITYSCORE_RES_360 = ["case", ["has", "h_pixel_density"], ["step", ["get", "h_pixel_density"], ...QUALITYSCORE_RES_360_VALUES], 1];
120
- const MAP_EXPR_QUALITYSCORE_RES_FLAT = ["case", ["has", "h_pixel_density"], ["step", ["get", "h_pixel_density"], ...QUALITYSCORE_RES_FLAT_VALUES], 1];
121
- const MAP_EXPR_QUALITYSCORE_RES = [
122
- "case", ["==", ["get", "type"], "equirectangular"],
123
- MAP_EXPR_QUALITYSCORE_RES_360, MAP_EXPR_QUALITYSCORE_RES_FLAT
124
- ];
125
- export const MAP_EXPR_QUALITYSCORE_GPS = ["case", ["has", "gps_accuracy"], ["step", ["get", "gps_accuracy"], ...QUALITYSCORE_GPS_VALUES], 1];
126
- // Note: score is also calculated in widgets/popup code
127
- export const MAP_EXPR_QUALITYSCORE = [
128
- "round",
129
- ["+",
130
- ["*", MAP_EXPR_QUALITYSCORE_RES, QUALITYSCORE_POND_RES],
131
- ["*", MAP_EXPR_QUALITYSCORE_GPS, QUALITYSCORE_POND_GPS]]
132
- ];
133
-
134
- // Themes
135
- const oneDay = 24 * 60 * 60 * 1000;
136
- const toDate = d => new Date(d).toISOString().split("T")[0];
137
- const dayNow = Date.now();
138
- const day1month = toDate(dayNow - 30 * oneDay);
139
- const day1year = toDate(dayNow - 365 * oneDay);
140
- const day2years = toDate(dayNow - 2 * 365 * oneDay);
141
-
142
- export const MAP_THEMES_STYLES = {
143
- default: {
144
- id: "default",
145
- sort: [],
146
- color: [COLORS.BASE]
147
- },
148
- age: {
149
- id: "age",
150
- sort: [
151
- ["!", ["any", ["has", "date"], ["has", "ts"]]], 0,
152
- [">=", ["coalesce", ["get", "date"], ["get", "ts"]], day1month], 50,
153
- [">=", ["coalesce", ["get", "date"], ["get", "ts"]], day1year], 49,
154
- [">=", ["coalesce", ["get", "date"], ["get", "ts"]], day2years], 48,
155
- ],
156
- color: [
157
- ["!", ["any", ["has", "date"], ["has", "ts"]]], COLORS.BASE,
158
- [">=", ["coalesce", ["get", "date"], ["get", "ts"]], day1month], COLORS.PALETTE_4,
159
- [">=", ["coalesce", ["get", "date"], ["get", "ts"]], day1year], COLORS.PALETTE_3,
160
- [">=", ["coalesce", ["get", "date"], ["get", "ts"]], day2years], COLORS.PALETTE_2,
161
- COLORS.PALETTE_1
162
- ]
163
- },
164
- type: {
165
- id: "type",
166
- sort: [
167
- ["!", ["has", "type"]], 0,
168
- ["==", ["get", "type"], "equirectangular"], 50,
169
- ],
170
- color: [
171
- ["!", ["has", "type"]], COLORS.BASE,
172
- ["==", ["get", "type"], "equirectangular"], COLORS.QUALI_1,
173
- COLORS.QUALI_2
174
- ]
175
- },
176
- score: {
177
- id: "score",
178
- sort: [
179
- ["==", MAP_EXPR_QUALITYSCORE, 5], 80,
180
- ["==", MAP_EXPR_QUALITYSCORE, 4], 65,
181
- ["==", MAP_EXPR_QUALITYSCORE, 3], 50,
182
- ["==", MAP_EXPR_QUALITYSCORE, 2], 35,
183
- ["==", MAP_EXPR_QUALITYSCORE, 1], 20,
184
- ],
185
- color: [
186
- ["==", MAP_EXPR_QUALITYSCORE, 5], QUALITYSCORE_VALUES[0].color,
187
- ["==", MAP_EXPR_QUALITYSCORE, 4], QUALITYSCORE_VALUES[1].color,
188
- ["==", MAP_EXPR_QUALITYSCORE, 3], QUALITYSCORE_VALUES[2].color,
189
- ["==", MAP_EXPR_QUALITYSCORE, 2], QUALITYSCORE_VALUES[3].color,
190
- QUALITYSCORE_VALUES[4].color,
191
- ]
192
- },
193
- gps: {
194
- id: "gps",
195
- sort: [
196
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 5], 80,
197
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 4], 65,
198
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 3], 50,
199
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 2], 35,
200
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 1], 20,
201
- ],
202
- color: [
203
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 5], GPS_VALUES[0].color,
204
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 4], GPS_VALUES[1].color,
205
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 3], GPS_VALUES[2].color,
206
- ["==", MAP_EXPR_QUALITYSCORE_GPS, 2], GPS_VALUES[3].color,
207
- GPS_VALUES[4].color
208
- ]
209
- },
210
- };
211
-
212
- /**
213
- * Get the GIF shown while thumbnail loads
214
- * @param {object} lang Translations
215
- * @returns The DOM element for this GIF
216
- * @private
217
- */
218
- export function getThumbGif(lang) {
219
- const thumbGif = document.createElement("img");
220
- svgToImg(LoaderImg, thumbGif);
221
- thumbGif.alt = lang.loading;
222
- thumbGif.title = lang.loading;
223
- thumbGif.classList.add("pnx-map-thumb", "pnx-map-thumb-loader");
224
- return thumbGif;
225
- }
226
-
227
- export function isNullCoordinates(c) {
228
- return (
229
- c === null
230
- || c === undefined
231
- || (Array.isArray(c) && (
232
- (c.length === 2 && c[0] === 0 && c[1] === 0)
233
- || c.length < 2
234
- ))
235
- );
236
- }
237
-
238
- /**
239
- * Is given layer a label layer.
240
- *
241
- * This is useful for inserting new vector layer before labels in MapLibre.
242
- * @param {object} l The layer to check
243
- * @returns {boolean} True if it's a label layer
244
- * @private
245
- */
246
- export function isLabelLayer(l) {
247
- return l.type === "symbol"
248
- && l?.layout?.["text-field"] !== undefined
249
- && (l.minzoom === undefined || l.minzoom < 15);
250
- }
251
-
252
- /**
253
- * Does given style contain logged-in grid statistics ?
254
- * @param {object} style The MapLibre JSON style definition
255
- * @returns {boolean} True if contains fields for logged-in grid statistics.
256
- * @private
257
- */
258
- export function hasStyleLoggedGridStats(style) {
259
- const fields = style?.metadata?.["panoramax:fields"] || {};
260
- return (fields?.grid?.includes("logged_coef_360_pictures")
261
- && fields?.grid?.includes("logged_coef_flat_pictures")
262
- && fields?.grid?.includes("logged_coef")) || false;
263
- }
264
-
265
- /**
266
- * Get normalized layers definition for Panoramax data display
267
- * @param {object} style The MapLibre style JSON
268
- * @returns {object[]} Complete list of Panoramax layers
269
- * @private
270
- */
271
- export function getPanoramaxLayers(style) {
272
- const s = Object.keys(style.sources)[0];
273
- const isVT = style.sources[s].type === "vector";
274
- const vt = isVT ? VECTOR_STYLES : VECTOR_STYLES_NOCROWD;
275
-
276
- const layers = [
277
- // Basic sequences
278
- {
279
- "id": `${s}_sequences`,
280
- "type": "line",
281
- "source": s,
282
- "source-layer": isVT ? "sequences" : undefined,
283
- "layout": {
284
- ...vt.SEQUENCES.layout
285
- },
286
- "paint": {
287
- ...vt.SEQUENCES.paint,
288
- "line-color": COLORS.BASE,
289
- },
290
- },
291
-
292
- // Padded sequence (for easier click)
293
- {
294
- "id": `${s}_sequences_plus`,
295
- "type": "line",
296
- "source": s,
297
- "source-layer": isVT ? "sequences" : undefined,
298
- "layout": {
299
- ...vt.SEQUENCES_PLUS.layout
300
- },
301
- "paint": {
302
- ...vt.SEQUENCES_PLUS.paint
303
- },
304
- },
305
-
306
- // Pictures
307
- {
308
- "id": `${s}_pictures`,
309
- "type": "circle",
310
- "source": s,
311
- "source-layer": isVT ? "pictures" : undefined,
312
- "layout": {
313
- ...vt.PICTURES.layout
314
- },
315
- "paint": {
316
- ...vt.PICTURES.paint,
317
- "circle-color": COLORS.BASE,
318
- },
319
- }
320
- ];
321
-
322
- if(style?.metadata?.["panoramax:fields"]?.grid) {
323
- layers.push({
324
- "id": `${s}_grid`,
325
- "type": "circle",
326
- "source": s,
327
- "source-layer": "grid",
328
- "layout": {
329
- ...vt.GRID.layout
330
- },
331
- "paint": {
332
- ...vt.GRID.paint
333
- },
334
- });
335
- }
336
-
337
- return layers;
338
- }
339
-
340
- /**
341
- * Get comprehensive values from map filters form
342
- * @param {Element} mapFiltersMenu The MapFilters DOM Element
343
- * @param {Element} mapThemeSelect The Map Theme select DOM Element
344
- * @param {boolean} hasQualityScore Set to true if vector tiles embed quality score data
345
- * @return {object} The map filters as JSON
346
- */
347
- export function mapFiltersFormValues(mapFiltersMenu, mapThemeSelect, hasQualityScore) {
348
- const fMinDate = mapFiltersMenu?.shadowRoot.getElementById("pnx-filter-date-from");
349
- const fMaxDate = mapFiltersMenu?.shadowRoot.getElementById("pnx-filter-date-end");
350
- const fTypes = mapFiltersMenu?.shadowRoot.querySelectorAll("input[name='pnx-filter-type']");
351
- const fPicSource = mapFiltersMenu?.shadowRoot.getElementById("pnx-pictures-source");
352
-
353
- let type = "";
354
- for(let fTypeId = 0 ; fTypeId < fTypes.length; fTypeId++) {
355
- const fType = fTypes[fTypeId];
356
- if(fType.checked) {
357
- type = fType.value;
358
- break;
359
- }
360
- }
361
-
362
- let qualityscore = [];
363
- let gps = [];
364
- if(hasQualityScore) {
365
- // Quality score itself
366
- const fScore = mapFiltersMenu?.shadowRoot.getElementById("pnx-filter-qualityscore");
367
- qualityscore = (fScore?.grade || "").split(",").map(v => parseInt(v)).filter(v => !isNaN(v));
368
-
369
- // GPS precision
370
- const fGPS = mapFiltersMenu?.shadowRoot.getElementById("pnx-filter-gps");
371
- gps = (fGPS?.grade || "").split(",").map(v => parseInt(v)).filter(v => !isNaN(v));
372
- }
373
-
374
- return {
375
- minDate: fMinDate?.value,
376
- maxDate: fMaxDate?.value,
377
- pic_type: type,
378
- theme: mapThemeSelect?.value,
379
- qualityscore,
380
- gps,
381
- source: fPicSource?.checked ? "local" : "metacatalog",
382
- };
383
- }
384
-
385
- /**
386
- * Transforms map filters into MapLibre-like JSON filters
387
- * @param {object} filters Filters returned by MapFilters widgets
388
- * @param {boolean} [hasGridStats=false] Set to true if vector tiles offer grid statistics
389
- * @param {object} [featuresRestrictions] Rules to restrict display of pictures & sequences
390
- * @returns {object} Set of variables { mapFilters, mapSeqFilters, mapPicFilters, reloadMapStyle }
391
- */
392
- export function mapFiltersToLayersFilters(filters, hasGridStats = false, featuresRestrictions = null) {
393
- let mapFilters = {};
394
- let mapSeqFilters = [];
395
- let mapPicFilters = [];
396
- let reloadMapStyle = false;
397
-
398
- if(filters.minDate && filters.minDate !== "") {
399
- mapFilters.minDate = filters.minDate;
400
- mapSeqFilters.push([">=", ["get", "date"], filters.minDate]);
401
- mapPicFilters.push([">=", ["get", "ts"], filters.minDate]);
402
- }
403
-
404
- if(filters.maxDate && filters.maxDate !== "") {
405
- mapFilters.maxDate = filters.maxDate;
406
- mapSeqFilters.push(["<=", ["get", "date"], filters.maxDate]);
407
-
408
- // Get tomorrow date for pictures filtering
409
- // (because ts is date+time, so comparing date only string would fail otherwise)
410
- let d = new Date(filters.maxDate);
411
- d.setDate(d.getDate() + 1);
412
- d = d.toISOString().split("T")[0];
413
- mapPicFilters.push(["<=", ["get", "ts"], d]);
414
- }
415
-
416
- if(filters.pic_type && filters.pic_type !== "") {
417
- mapFilters.pic_type = filters.pic_type === "flat" ? "flat" : "equirectangular";
418
- mapSeqFilters.push(["==", ["get", "type"], mapFilters.pic_type]);
419
- mapPicFilters.push(["==", ["get", "type"], mapFilters.pic_type]);
420
- }
421
-
422
- if(hasGridStats) {
423
- reloadMapStyle = true;
424
- }
425
-
426
- if(filters.camera && filters.camera !== "") {
427
- mapFilters.camera = filters.camera;
428
- // Low/high model hack : to enable fuzzy filtering of camera make and model
429
- const lowModel = filters.camera.toLowerCase().trim() + " ";
430
- const highModel = filters.camera.toLowerCase().trim() + "zzzzzzzzzzzzzzzzzzzz";
431
- const collator = ["collator", { "case-sensitive": false, "diacritic-sensitive": false } ];
432
- mapSeqFilters.push([">=", ["get", "model"], lowModel, collator]);
433
- mapSeqFilters.push(["<=", ["get", "model"], highModel, collator]);
434
- mapPicFilters.push([">=", ["get", "model"], lowModel, collator]);
435
- mapPicFilters.push(["<=", ["get", "model"], highModel, collator]);
436
- }
437
-
438
- if(filters.qualityscore && filters.qualityscore.length > 0) {
439
- mapFilters.qualityscore = filters.qualityscore;
440
- mapSeqFilters.push(["in", MAP_EXPR_QUALITYSCORE, ["literal", mapFilters.qualityscore]]);
441
- mapPicFilters.push(["in", MAP_EXPR_QUALITYSCORE, ["literal", mapFilters.qualityscore]]);
442
- }
443
-
444
- if(filters.gps && filters.gps.length > 0) {
445
- mapFilters.gps = filters.gps;
446
- mapSeqFilters.push(["in", MAP_EXPR_QUALITYSCORE_GPS, ["literal", mapFilters.gps]]);
447
- mapPicFilters.push(["in", MAP_EXPR_QUALITYSCORE_GPS, ["literal", mapFilters.gps]]);
448
- }
449
-
450
- if(filters.theme && MAP_THEMES_STYLES[filters.theme]) {
451
- mapFilters.theme = filters.theme;
452
- reloadMapStyle = true;
453
- }
454
-
455
- if(featuresRestrictions?.pictures && featuresRestrictions.pictures.features?.length >= 0) {
456
- if(featuresRestrictions.pictures.rule === "keep") {
457
- mapPicFilters.push(["in", ["get", "id"], ["literal", featuresRestrictions.pictures.features]]);
458
- }
459
- else if(featuresRestrictions.pictures.features.length > 0) {
460
- mapPicFilters.push(["!", ["in", ["get", "id"], ["literal", featuresRestrictions.pictures.features]]]);
461
- }
462
- }
463
-
464
- if(featuresRestrictions?.sequences && featuresRestrictions.sequences.features?.length >= 0) {
465
- if(featuresRestrictions.sequences.rule === "keep") {
466
- mapSeqFilters.push(["in", ["get", "id"], ["literal", featuresRestrictions.sequences.features]]);
467
- }
468
- else if(featuresRestrictions.sequences.features.length > 0) {
469
- mapSeqFilters.push(["!", ["in", ["get", "id"], ["literal", featuresRestrictions.sequences.features]]]);
470
- }
471
- }
472
-
473
-
474
- if(mapSeqFilters.length == 0) { mapSeqFilters = null; }
475
- else {
476
- mapSeqFilters.unshift("all");
477
- }
478
-
479
- if(mapPicFilters.length == 0) { mapPicFilters = null; }
480
- else {
481
- mapPicFilters.unshift("all");
482
- mapPicFilters = ["step", ["zoom"],
483
- true,
484
- TILES_PICTURES_ZOOM, mapPicFilters
485
- ];
486
- }
487
-
488
- return { mapFilters, mapSeqFilters, mapPicFilters, reloadMapStyle };
489
- }
490
-
491
- /**
492
- * Is the given Panoramax endpoint showing data of a single user ?
493
- * @param {string} endpoint The endpoint ID
494
- * @returns {boolean} True if single user
495
- */
496
- export function isPanoramaxEndpointSingleUser(endpoint) {
497
- return !["default", "metacatalog", "", null, undefined].includes(endpoint);
498
- }
499
-
500
- /**
501
- * Switches used coef value in MapLibre style JSON expression
502
- * @param {*} expr The MapLibre style expression
503
- * @param {string} newCoefVal The new coef value to use
504
- * @returns {*} The switched expression
505
- * @private
506
- */
507
- export function switchCoefValue(expr, newCoefVal) {
508
- if(Array.isArray(expr)) {
509
- return expr.map(v => switchCoefValue(v, newCoefVal));
510
- }
511
- else if(typeof expr === "object" && expr !== null) {
512
- const newExpr = {};
513
- for (const key in expr) {
514
- newExpr[key] = switchCoefValue(expr[key], newCoefVal);
515
- }
516
- return newExpr;
517
- }
518
- else if(typeof expr === "string" && (expr.startsWith("coef") || expr.startsWith("logged_coef"))) {
519
- return newCoefVal;
520
- }
521
- return expr;
522
- }
523
-
524
- /**
525
- * Creates links between map and photo elements.
526
- * This enable interactions like click on map showing picture.
527
- *
528
- * @param {CoreView} parent The view containing both Photo and Map elements
529
- * @private
530
- */
531
- export function linkMapAndPhoto(parent) {
532
- // Switched picture
533
- const onPicLoad = e => {
534
- if(isNullId(e.detail.picId)) {
535
- parent.map.displayPictureMarker();
536
- if(parent?.isMapWide?.()) {
537
- parent?.mini?.setAttribute("collapsed", "");
538
- }
539
- }
540
- else {
541
- parent.map.displayPictureMarker(
542
- e.detail.lon,
543
- e.detail.lat,
544
- parent.psv.getXY().x,
545
- e.detail.first && !isNullCoordinates(parent._initParams?.getMapPostInit()?.center), // Skip centering if precise coordinates are set from URL
546
- e.detail.picId
547
- );
548
-
549
- if(parent?.isMapWide?.()) {
550
- parent?.mini?.removeAttribute("collapsed");
551
- }
552
- }
553
- };
554
- parent.psv.addEventListener("picture-loading", onPicLoad);
555
- parent.psv.addEventListener("picture-loaded", onPicLoad);
556
-
557
- // Picture view rotated
558
- parent.psv.addEventListener("view-rotated", () => {
559
- let x = parent.psv.getPosition().yaw * (180 / Math.PI);
560
- x += parent.psv.getPictureOriginalHeading();
561
- parent.map._picMarker.setRotation(x);
562
- });
563
-
564
- // Picture preview
565
- parent.psv.addEventListener("picture-preview-started", e => {
566
- // Show marker corresponding to selection
567
- parent.map._picMarkerPreview
568
- .setLngLat(e.detail.coordinates)
569
- .setRotation(e.detail.direction || 0)
570
- .addTo(parent.map);
571
- });
572
-
573
- parent.psv.addEventListener("picture-preview-stopped", () => {
574
- parent.map._picMarkerPreview.remove();
575
- });
576
-
577
- parent.psv.addEventListener("picture-loaded", e => {
578
- if (parent.isWidthSmall() && parent._picPopup && e.detail.picId == parent._picPopup._picId) {
579
- parent._picPopup.remove();
580
- }
581
- });
582
-
583
- // Picture click
584
- parent.map.on("picture-click", e => {
585
- parent.select(e.seqId, e.picId);
586
- if(!parent.psv._myVTour.state.currentNode && parent?._setFocus) { parent._setFocus("pic"); }
587
- });
588
-
589
- // Sequence click
590
- parent.map.on("sequence-click", e => {
591
- (parent.getAPI?.() || parent.api).getPicturesAroundCoordinates(
592
- e.coordinates.lat,
593
- e.coordinates.lng,
594
- 0.01,
595
- 1,
596
- e.seqId
597
- ).then(results => {
598
- if(results?.features?.length > 0) {
599
- parent.select(results.features[0]?.collection, results.features[0].id);
600
- if(!parent.psv.getPictureMetadata() && parent?._setFocus) { parent._setFocus("pic"); }
601
- }
602
- });
603
- });
604
-
605
- // Focus changes
606
- if(parent._setFocus) {
607
- // PSV double click
608
- parent.psv.addEventListener("dblclick", () => { if(parent.isMapWide()) { parent._setFocus("pic"); } });
609
-
610
- // Map double-click: unselect if focused, toggle focus if unfocused
611
- parent.map.on("dblclick", () => {
612
- if(!parent.isMapWide()) { parent._setFocus("map"); }
613
- else if(parent.psv.getPicturesNavigation() === "any") { parent.select(); }
614
- });
615
- }
616
- }
617
-
618
- /**
619
- * Adds events related to keyboard
620
- * @private
621
- */
622
- export function initMapKeyboardHandler(parent) {
623
- parent.map.keyboard.keydown = function(e) {
624
- if (e.altKey || e.ctrlKey || e.metaKey) {return;}
625
-
626
- // Custom keys
627
- switch(e.key) {
628
- case "*":
629
- case "5":
630
- parent.moveCenter();
631
- return;
632
-
633
- case "PageUp":
634
- case "9":
635
- parent.psv.goToNextPicture();
636
- return;
637
-
638
- case "PageDown":
639
- case "3":
640
- parent.psv.goToPrevPicture();
641
- return;
642
-
643
- case "Home":
644
- case "7":
645
- e.stopPropagation();
646
- parent._toggleFocus();
647
- return;
648
-
649
- case "End":
650
- case "1":
651
- parent.mini.toggleAttribute("collapsed");
652
- return;
653
-
654
- case " ":
655
- case "0":
656
- parent.psv.toggleSequencePlaying();
657
- return;
658
- }
659
-
660
- let zoomDir = 0;
661
- let bearingDir = 0;
662
- let pitchDir = 0;
663
- let xDir = 0;
664
- let yDir = 0;
665
-
666
- switch (e.keyCode) {
667
- case 61:
668
- case 107:
669
- case 171:
670
- case 187:
671
- zoomDir = 1;
672
- break;
673
-
674
- case 189:
675
- case 109:
676
- case 173:
677
- zoomDir = -1;
678
- break;
679
-
680
- case 37:
681
- case 100:
682
- if (e.shiftKey) {
683
- bearingDir = -1;
684
- } else {
685
- e.preventDefault();
686
- xDir = -1;
687
- }
688
- break;
689
-
690
- case 39:
691
- case 102:
692
- if (e.shiftKey) {
693
- bearingDir = 1;
694
- } else {
695
- e.preventDefault();
696
- xDir = 1;
697
- }
698
- break;
699
-
700
- case 38:
701
- case 104:
702
- if (e.shiftKey) {
703
- pitchDir = 1;
704
- } else {
705
- e.preventDefault();
706
- yDir = -1;
707
- }
708
- break;
709
-
710
- case 40:
711
- case 98:
712
- if (e.shiftKey) {
713
- pitchDir = -1;
714
- } else {
715
- e.preventDefault();
716
- yDir = 1;
717
- }
718
- break;
719
-
720
- default:
721
- return;
722
- }
723
-
724
- if (this._rotationDisabled) {
725
- bearingDir = 0;
726
- pitchDir = 0;
727
- }
728
-
729
- return {
730
- cameraAnimation: (map) => {
731
- const tr = this._tr;
732
- map.easeTo({
733
- duration: 300,
734
- easeId: "keyboardHandler",
735
- easing: t => t * (2-t),
736
- zoom: zoomDir ? Math.round(tr.zoom) + zoomDir * (e.shiftKey ? 2 : 1) : tr.zoom,
737
- bearing: tr.bearing + bearingDir * this._bearingStep,
738
- pitch: tr.pitch + pitchDir * this._pitchStep,
739
- offset: [-xDir * this._panStep, -yDir * this._panStep],
740
- center: tr.center
741
- }, {originalEvent: e});
742
- }
743
- };
744
- }.bind(parent.map.keyboard);
745
- }
746
-
747
- const MAP_PARAMS_STORAGE = "pnx-map-parameters";
748
-
749
- /**
750
- * Reads map parameters from localStorage
751
- * @private
752
- */
753
- export function getMapParamsFromLocalStorage() {
754
- const params = localStorage.getItem(MAP_PARAMS_STORAGE);
755
- if(!params) { return {}; }
756
- try {
757
- return JSON.parse(params);
758
- }
759
- catch(e) {
760
- console.warn("Can't read map parameters stored in localStorage", e);
761
- return {};
762
- }
763
- }
764
-
765
- /**
766
- * Save map parameters into localStorage.
767
- * @private
768
- */
769
- export function saveMapParamsToLocalStorage(map) {
770
- // Save map state in localStorage
771
- const save = () => localStorage.setItem(MAP_PARAMS_STORAGE, JSON.stringify({
772
- center: Object.fromEntries(Object.entries(map.getCenter()).map(([k,v]) => ([k,v.toFixed(7)]))),
773
- zoom: map.getZoom().toFixed(1),
774
- background: map._parent.mapStyleComposer.basemap,
775
- theme: map._parent.mapStyleComposer.panoramaxTheme,
776
- endpoint: map._parent.mapStyleComposer.panoramax,
777
- }));
778
-
779
- // Add events to know when to rewrite info
780
- map._parent.mapStyleComposer.addEventListener("filters-changed", save);
781
- map._parent.mapStyleComposer.addEventListener("theme-changed", save);
782
- map._parent.mapStyleComposer.addEventListener("basemap-changed", save);
783
- map._parent.mapStyleComposer.addEventListener("panoramax-changed", save);
784
- map.on("moveend", save);
785
- map.on("zoomend", save);
786
- map.on("dragend", save);
787
- map.on("boxzoomend", save);
788
- }