@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.
- package/build/cjs/index.js +1 -1
- package/build/cjs/index_photoviewer.js +1 -1
- package/build/esm/components/core/Basic.js +1 -1
- package/build/esm/translations/el.json +92 -1
- package/package.json +1 -1
- package/build/bundle.cjs +0 -3399
- package/build/bundle.cjs.map +0 -1
- package/build/bundle_photoviewer.cjs +0 -2510
- package/build/bundle_photoviewer.cjs.map +0 -1
- package/build/components/core/Basic.css +0 -56
- package/build/components/core/Basic.js +0 -378
- package/build/components/core/CoverageMap.css +0 -10
- package/build/components/core/CoverageMap.js +0 -169
- package/build/components/core/Editor.css +0 -33
- package/build/components/core/Editor.js +0 -398
- package/build/components/core/PhotoViewer.css +0 -70
- package/build/components/core/PhotoViewer.js +0 -650
- package/build/components/core/Viewer.css +0 -130
- package/build/components/core/Viewer.js +0 -711
- package/build/components/core/index.js +0 -10
- package/build/components/index.js +0 -11
- package/build/components/index_photoviewer.js +0 -6
- package/build/components/layout/BottomDrawer.js +0 -258
- package/build/components/layout/CorneredGrid.js +0 -143
- package/build/components/layout/Mini.js +0 -121
- package/build/components/layout/Tabs.js +0 -140
- package/build/components/layout/index.js +0 -9
- package/build/components/menus/LocationPrecisionDoc.js +0 -42
- package/build/components/menus/MapBackground.js +0 -110
- package/build/components/menus/MapFilters.js +0 -567
- package/build/components/menus/MapLayers.js +0 -238
- package/build/components/menus/MapLegend.js +0 -68
- package/build/components/menus/MiniPictureLegend.js +0 -73
- package/build/components/menus/PictureLegend.js +0 -379
- package/build/components/menus/PictureMetadata.js +0 -380
- package/build/components/menus/PlayerOptions.js +0 -93
- package/build/components/menus/QualityScoreDoc.js +0 -42
- package/build/components/menus/ReportForm.js +0 -132
- package/build/components/menus/SemanticsDoc.js +0 -38
- package/build/components/menus/SemanticsDownload.js +0 -33
- package/build/components/menus/SemanticsFilters.js +0 -153
- package/build/components/menus/SemanticsList.js +0 -413
- package/build/components/menus/SemanticsMetadata.js +0 -368
- package/build/components/menus/Share.js +0 -105
- package/build/components/menus/index.js +0 -22
- package/build/components/menus/index_photoviewer.js +0 -11
- package/build/components/styles.js +0 -557
- package/build/components/ui/AnnotationsSwitch.js +0 -159
- package/build/components/ui/Button.js +0 -77
- package/build/components/ui/ButtonGroup.css +0 -59
- package/build/components/ui/ButtonGroup.js +0 -69
- package/build/components/ui/CopyButton.js +0 -110
- package/build/components/ui/Grade.js +0 -54
- package/build/components/ui/GradeFilter.js +0 -122
- package/build/components/ui/IconSwitch.js +0 -193
- package/build/components/ui/LinkButton.js +0 -67
- package/build/components/ui/ListGroup.js +0 -66
- package/build/components/ui/ListItem.js +0 -90
- package/build/components/ui/Loader.js +0 -203
- package/build/components/ui/Map.css +0 -63
- package/build/components/ui/Map.js +0 -853
- package/build/components/ui/MapMore.js +0 -175
- package/build/components/ui/Photo.css +0 -50
- package/build/components/ui/Photo.js +0 -1502
- package/build/components/ui/Popup.js +0 -145
- package/build/components/ui/ProgressBar.js +0 -104
- package/build/components/ui/QualityScore.js +0 -147
- package/build/components/ui/SearchBar.js +0 -374
- package/build/components/ui/SemanticsEditor.js +0 -191
- package/build/components/ui/SemanticsTable.js +0 -88
- package/build/components/ui/Switch.js +0 -139
- package/build/components/ui/TogglableGroup.js +0 -157
- package/build/components/ui/index.js +0 -29
- package/build/components/ui/index_photoviewer.js +0 -21
- package/build/components/ui/widgets/CopyCoordinates.js +0 -75
- package/build/components/ui/widgets/GeoSearch.css +0 -21
- package/build/components/ui/widgets/GeoSearch.js +0 -150
- package/build/components/ui/widgets/Legend.js +0 -190
- package/build/components/ui/widgets/LevelSelect.css +0 -51
- package/build/components/ui/widgets/LevelSelect.js +0 -143
- package/build/components/ui/widgets/MapFiltersButton.js +0 -114
- package/build/components/ui/widgets/MapLayersButton.js +0 -79
- package/build/components/ui/widgets/OSMEditors.js +0 -155
- package/build/components/ui/widgets/PictureLegendActions.js +0 -99
- package/build/components/ui/widgets/Player.css +0 -7
- package/build/components/ui/widgets/Player.js +0 -154
- package/build/components/ui/widgets/SemanticsFiltersButton.js +0 -65
- package/build/components/ui/widgets/Zoom.js +0 -84
- package/build/components/ui/widgets/index.js +0 -16
- package/build/components/ui/widgets/index_photoviewer.js +0 -7
- package/build/img/arrow_360.svg +0 -14
- package/build/img/arrow_flat.svg +0 -11
- package/build/img/arrow_triangle.svg +0 -9
- package/build/img/arrow_turn.svg +0 -8
- package/build/img/bg_aerial.jpg +0 -0
- package/build/img/bg_streets.jpg +0 -0
- package/build/img/loader_base.jpg +0 -0
- package/build/img/logo_dead.svg +0 -91
- package/build/img/marker.svg +0 -17
- package/build/img/marker_blue.svg +0 -20
- package/build/img/osm.svg +0 -49
- package/build/img/panoramax.svg +0 -13
- package/build/img/switch_big.svg +0 -54
- package/build/img/switch_mini.svg +0 -48
- package/build/img/wd.svg +0 -1
- package/build/index_photoviewer.js +0 -4
- package/build/package.json +0 -148
- package/build/servers.js +0 -14
- package/build/translations/ar.json +0 -1
- package/build/translations/be.json +0 -257
- package/build/translations/br.json +0 -81
- package/build/translations/cy.json +0 -117
- package/build/translations/da.json +0 -300
- package/build/translations/de.json +0 -309
- package/build/translations/en.json +0 -294
- package/build/translations/eo.json +0 -235
- package/build/translations/es.json +0 -292
- package/build/translations/fi.json +0 -1
- package/build/translations/fr.json +0 -294
- package/build/translations/hr.json +0 -294
- package/build/translations/hu.json +0 -294
- package/build/translations/it.json +0 -306
- package/build/translations/ja.json +0 -182
- package/build/translations/ko.json +0 -1
- package/build/translations/nl.json +0 -305
- package/build/translations/nn.json +0 -1
- package/build/translations/pl.json +0 -169
- package/build/translations/pt.json +0 -296
- package/build/translations/pt_BR.json +0 -304
- package/build/translations/sv.json +0 -182
- package/build/translations/ti.json +0 -9
- package/build/translations/tr.json +0 -297
- package/build/translations/uk.json +0 -268
- package/build/translations/zh_Hant.json +0 -309
- package/build/utils/API.js +0 -928
- package/build/utils/InitParameters.js +0 -521
- package/build/utils/MapStyleComposer.js +0 -889
- package/build/utils/PanoraMapProtocol.js +0 -49
- package/build/utils/PhotoAdapter.js +0 -49
- package/build/utils/PresetsManager.js +0 -148
- package/build/utils/SemanticsMapProtocol.js +0 -144
- package/build/utils/URLHandler.js +0 -426
- package/build/utils/geocoder.js +0 -203
- package/build/utils/i18n.js +0 -128
- package/build/utils/index.js +0 -17
- package/build/utils/index_photoviewer.js +0 -14
- package/build/utils/indoor.js +0 -200
- package/build/utils/map.js +0 -788
- package/build/utils/picture.js +0 -507
- package/build/utils/semantics.js +0 -321
- package/build/utils/services.js +0 -148
- package/build/utils/utils.js +0 -433
- package/build/utils/widgets.js +0 -110
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import Protobuf from "pbf";
|
|
2
|
-
import {VectorTile} from "@mapbox/vector-tile";
|
|
3
|
-
import {fromVectorTileJs} from "@maplibre/vt-pbf";
|
|
4
|
-
|
|
5
|
-
// Minimum amount of pictures in a tile to consider it "crowded"
|
|
6
|
-
const CROWDED_TILE_SIZE = 5000;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* PanoraMap Protocol adds a new URI scheme "panora://" (or "panoras://") to MapLibre.
|
|
10
|
-
* It allows adding custom information on top of existing Panoramax Vector Tiles.
|
|
11
|
-
* @class Panoramax.utils.PanoraMapProtocol
|
|
12
|
-
* @typicalname panoraMapProtocol
|
|
13
|
-
*/
|
|
14
|
-
export default class PanoraMapProtocol {
|
|
15
|
-
/**
|
|
16
|
-
* Get a single tile
|
|
17
|
-
* @param {object} params MapLibre parameters
|
|
18
|
-
* @param {AbortController} abort The abort signal handler
|
|
19
|
-
* @returns {object} The tile, as expected by MapLibre
|
|
20
|
-
* @memberof Panoramax.utils.PanoraMapProtocol#
|
|
21
|
-
*/
|
|
22
|
-
tile() {
|
|
23
|
-
return (params, abort) => {
|
|
24
|
-
abort = abort || new AbortController();
|
|
25
|
-
const url = params.url.replace(/^panora/, "http");
|
|
26
|
-
return fetch(url, { signal: abort.signal })
|
|
27
|
-
.then((response) => response.arrayBuffer())
|
|
28
|
-
.then((data) => new VectorTile(new Protobuf(data)))
|
|
29
|
-
.then((tile) => {
|
|
30
|
-
// Skip process if pictures are not available
|
|
31
|
-
if(!tile.layers.pictures || tile.layers.pictures.length >= CROWDED_TILE_SIZE) { return tile; }
|
|
32
|
-
|
|
33
|
-
Object.values(tile.layers).forEach(layer => {
|
|
34
|
-
const oldFeat = layer.feature.bind(layer);
|
|
35
|
-
layer.feature = (index) => {
|
|
36
|
-
const feature = oldFeat(index);
|
|
37
|
-
// Mark tile as "uncrowded"
|
|
38
|
-
feature.properties.uncrowded = true;
|
|
39
|
-
return feature;
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return tile;
|
|
44
|
-
})
|
|
45
|
-
.then((tile) => fromVectorTileJs(tile).buffer)
|
|
46
|
-
.then((data) => ({ data }));
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { EquirectangularTilesAdapter } from "@photo-sphere-viewer/equirectangular-tiles-adapter";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Override of PSV EquirectangularTilesAdapter for fine-tweaking.
|
|
5
|
-
* @class Panoramax.utils.PhotoAdapter
|
|
6
|
-
* @private
|
|
7
|
-
*/
|
|
8
|
-
export default class PhotoAdapter extends EquirectangularTilesAdapter {
|
|
9
|
-
constructor(viewer, config) {
|
|
10
|
-
super(viewer, config);
|
|
11
|
-
this._shouldGoFast = config.shouldGoFast || (() => true);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Override to skip loading SD images according to shouldGoFast option.
|
|
16
|
-
*/
|
|
17
|
-
loadTexture(panorama, loader) {
|
|
18
|
-
if(!panorama.origBaseUrl) { panorama.origBaseUrl = panorama.baseUrl; }
|
|
19
|
-
else { panorama.baseUrl = panorama.origBaseUrl; }
|
|
20
|
-
|
|
21
|
-
// Fast mode + thumbnail available + no HD image loaded yet + flat picture
|
|
22
|
-
if(
|
|
23
|
-
this._shouldGoFast()
|
|
24
|
-
&& panorama.thumbUrl
|
|
25
|
-
&& !panorama.hdLoaded
|
|
26
|
-
// eslint-disable-next-line eqeqeq
|
|
27
|
-
&& panorama.rows == 1
|
|
28
|
-
) {
|
|
29
|
-
panorama.baseUrl = panorama.thumbUrl;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return super.loadTexture(panorama, loader).then(data => {
|
|
33
|
-
if(panorama.baseUrl === panorama.origBaseUrl) {
|
|
34
|
-
panorama.hdLoaded = true;
|
|
35
|
-
}
|
|
36
|
-
return data;
|
|
37
|
-
}).catch(e => {
|
|
38
|
-
console.error("Can't load texture", e);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Override to skip loading tiles according to shouldGoFast option.
|
|
44
|
-
* @private
|
|
45
|
-
*/
|
|
46
|
-
__loadTiles(tiles) {
|
|
47
|
-
if(!this._shouldGoFast()) { super.__loadTiles(tiles); }
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { PanoramaxPresetsURL } from "./services.js";
|
|
2
|
-
|
|
3
|
-
// Iconify aliases for whole collections
|
|
4
|
-
const ICON_COLLECTIONS_SUB = {
|
|
5
|
-
"fas": "fa7-solid"
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
// Iconify aliases for specific icons
|
|
9
|
-
const ICON_SUBS = {
|
|
10
|
-
// "fa6-solid:directions": "fa6-solid:diamond-turn-right"
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Presets Manager handle retrieval of presets against dedicated endpoint.
|
|
15
|
-
* It allows an easily search between all presets, and handles translations.
|
|
16
|
-
*
|
|
17
|
-
* @class Panoramax.utils.PresetsManager
|
|
18
|
-
* @typicalname presetsManager
|
|
19
|
-
* @param {string} [lang] The user prefered language. Defaults to web browser preferences.
|
|
20
|
-
* @param {boolean} [skipLoad=false] Set to true to disable automatic load of API data
|
|
21
|
-
*/
|
|
22
|
-
export default class PresetManager {
|
|
23
|
-
constructor(lang = null, skipLoad = false) {
|
|
24
|
-
this._ready = false;
|
|
25
|
-
this._presets = null;
|
|
26
|
-
this._translations = {};
|
|
27
|
-
if(!skipLoad) { this._load(lang); }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Downloads various JSON file against presets API.
|
|
32
|
-
* @private
|
|
33
|
-
*/
|
|
34
|
-
async _load(lang) {
|
|
35
|
-
lang = lang?.substring(0, 2) || window.navigator.languages[0]?.substring(0, 2);
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
const [translationsENRes, translationsLangRes, presetsRes] = await Promise.all([
|
|
39
|
-
fetch(`${PanoramaxPresetsURL()}/translations/en.min.json`),
|
|
40
|
-
lang ? fetch(`${PanoramaxPresetsURL()}/translations/${lang}.min.json`) : Promise.resolve({ok: true}),
|
|
41
|
-
fetch(`${PanoramaxPresetsURL()}/presets.min.json`),
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
!translationsENRes || !translationsLangRes || !presetsRes
|
|
46
|
-
|| !translationsENRes.ok || !translationsLangRes.ok || !presetsRes.ok
|
|
47
|
-
) {
|
|
48
|
-
this._ready = -1;
|
|
49
|
-
throw new Error("Presets service is not available");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this._presets = await presetsRes.json();
|
|
53
|
-
this._translations.en = (await translationsENRes.json())?.en?.presets;
|
|
54
|
-
if(lang) {
|
|
55
|
-
this._translations[lang] = (await translationsLangRes.json())?.[lang]?.presets;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Post-process presets
|
|
59
|
-
Object.entries(this._presets).forEach(([pid,p]) => {
|
|
60
|
-
// Add labels
|
|
61
|
-
if(this._translations[lang]?.presets?.[pid]?.name) {
|
|
62
|
-
p.name = this._translations[lang].presets[pid].name;
|
|
63
|
-
}
|
|
64
|
-
else if(this._translations.en?.presets?.[pid]?.name) {
|
|
65
|
-
p.name = this._translations.en.presets[pid].name;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Create iconify-compatible icon
|
|
69
|
-
if(p.icon) {
|
|
70
|
-
const iconColl = p.icon.split("-")[0];
|
|
71
|
-
const iconCollSub = ICON_COLLECTIONS_SUB[iconColl];
|
|
72
|
-
p.iconify = iconCollSub ? p.icon.replace(iconColl+"-", iconCollSub+":") : p.icon.split("-")[0]+":"+p.icon.split("-").slice(1).join("-");
|
|
73
|
-
if(ICON_SUBS[p.iconify]) { p.iconify = ICON_SUBS[p.iconify]; }
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
this._ready = true;
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.error("Presets service throws an error:", error);
|
|
80
|
-
this._ready = -1;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Resolves when the all necessary data was downloaded.
|
|
86
|
-
* @memberOf Panoramax.utils.PresetsManager#
|
|
87
|
-
* @returns {Promise}
|
|
88
|
-
*/
|
|
89
|
-
async onceReady() {
|
|
90
|
-
if(!this._ready) {
|
|
91
|
-
await new Promise(resolve => setTimeout(resolve, 250));
|
|
92
|
-
return this.onceReady();
|
|
93
|
-
}
|
|
94
|
-
else if(this._ready === -1) { return Promise.reject(); }
|
|
95
|
-
else { return Promise.resolve(); }
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Find the best matching preset for a given STAC feature.
|
|
100
|
-
* @memberOf Panoramax.utils.PresetsManager#
|
|
101
|
-
* @returns {Promise}
|
|
102
|
-
* @fulfil {object|null} The preset JSON that best matches, or null if no matches
|
|
103
|
-
*/
|
|
104
|
-
async getPreset(f) {
|
|
105
|
-
return await this.getPresets(f).then(res => res.shift());
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Find all matching presets for a given STAC feature.
|
|
110
|
-
* @memberOf Panoramax.utils.PresetsManager#
|
|
111
|
-
* @returns {Promise}
|
|
112
|
-
* @fulfil {object[]|null} The all JSON presets that best matches, or null if no matches
|
|
113
|
-
*/
|
|
114
|
-
async getPresets(f) {
|
|
115
|
-
return await this.onceReady().then(() => {
|
|
116
|
-
const candidatePresets = Object.values(this._presets).filter(p => {
|
|
117
|
-
if(Object.keys(p.tags).length === 0) { return false; }
|
|
118
|
-
|
|
119
|
-
// Check if every tag on preset exists in feature
|
|
120
|
-
for(let pk in p.tags) {
|
|
121
|
-
const pv = p.tags[pk];
|
|
122
|
-
if(!f.semantics.find(s => s.action !== "delete" && s.key === pk && (pv === "*" || pv === s.value))) {
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return true;
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// Sort by best matching
|
|
130
|
-
candidatePresets.sort((a,b) => {
|
|
131
|
-
const nbTagsA = Object.keys(a.tags).length;
|
|
132
|
-
const nbTagsB = Object.keys(b.tags).length;
|
|
133
|
-
|
|
134
|
-
if(nbTagsA > nbTagsB) { return -1; }
|
|
135
|
-
else if(nbTagsA === nbTagsB) {
|
|
136
|
-
const nbTagsStarA = Object.values(a.tags).filter(v => v === "*").length;
|
|
137
|
-
const nbTagsStarB = Object.values(b.tags).filter(v => v === "*").length;
|
|
138
|
-
if(nbTagsStarA < nbTagsStarB) { return -1; }
|
|
139
|
-
else if(nbTagsStarA > nbTagsStarB) { return 1; }
|
|
140
|
-
else { return 0; }
|
|
141
|
-
}
|
|
142
|
-
else { return 1; }
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
return candidatePresets;
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import geojsonvt from "geojson-vt";
|
|
2
|
-
import { fromGeojsonVt } from "@maplibre/vt-pbf";
|
|
3
|
-
|
|
4
|
-
export const SEMANTICS_OVERLAY_MINZOOM = 15;
|
|
5
|
-
export const SEMANTICS_OVERLAY_MAXZOOM = 19;
|
|
6
|
-
const LIMIT_PER_ZOOM = { 15: 100, 16: 300, 17: 500, 18: 800, 19: 1000 };
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Semantics Map Protocol adds a new URI scheme "sem://" to MapLibre.
|
|
10
|
-
* It allows loading tile per tile metadata from semantics API, seamlessly.
|
|
11
|
-
* You can use them with URI like:
|
|
12
|
-
* - `sem:///"semantics.osm|traffic_sign" IS NOT NULL/{z}/{x}/{y}`
|
|
13
|
-
* - `sem:///"semantics.osm|traffic_sign"='yes'/{z}/{x}/{y}`
|
|
14
|
-
* @class Panoramax.utils.SemanticsMapProtocol
|
|
15
|
-
* @param {Panoramax.components.core.Basic} parent The parent component
|
|
16
|
-
* @typicalname semMapProtocol
|
|
17
|
-
*/
|
|
18
|
-
export default class SemanticsMapProtocol {
|
|
19
|
-
constructor(parent) {
|
|
20
|
-
this.tiles = new Map();
|
|
21
|
-
this._parent = parent;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Removes all previously stored tiles in cache.
|
|
26
|
-
* @memberof Panoramax.utils.SemanticsMapProtocol#
|
|
27
|
-
*/
|
|
28
|
-
clearCache() {
|
|
29
|
-
this.tiles = new Map();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Transforms a XYZ tile coordinates into GPS bounding box coordinates
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
|
-
_tileToBbox(x, y, z) {
|
|
37
|
-
const n = Math.pow(2, z);
|
|
38
|
-
const lon1 = x / n * 360 - 180;
|
|
39
|
-
const lon2 = (x + 1) / n * 360 - 180;
|
|
40
|
-
const lat1 = Math.atan(Math.sinh(Math.PI * (1 - 2 * y / n))) * 180 / Math.PI;
|
|
41
|
-
const lat2 = Math.atan(Math.sinh(Math.PI * (1 - 2 * (y + 1) / n))) * 180 / Math.PI;
|
|
42
|
-
return [lon1, lat2, lon2, lat1];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Merge and override semantics attribute to get a flat tags object.
|
|
47
|
-
* @private
|
|
48
|
-
*/
|
|
49
|
-
_semanticsToBasicProps(f) {
|
|
50
|
-
const tags = {};
|
|
51
|
-
|
|
52
|
-
// Set or append function
|
|
53
|
-
const setOrAppend = kv => {
|
|
54
|
-
if(tags[kv.key]) {
|
|
55
|
-
tags[kv.key].add(kv.value);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
tags[kv.key] = new Set([kv.value]);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// Read all level of semantics
|
|
63
|
-
(f.properties?.collection?.semantics || []).forEach(setOrAppend);
|
|
64
|
-
(f.properties?.semantics || []).forEach(setOrAppend);
|
|
65
|
-
(f.properties?.annotations || []).forEach(a => a.semantics.forEach(setOrAppend));
|
|
66
|
-
|
|
67
|
-
Object.keys(tags).forEach(k => tags[k] = [...tags[k]].join(";"));
|
|
68
|
-
|
|
69
|
-
// Add Panoramax IDs as well
|
|
70
|
-
tags.picid = f.id;
|
|
71
|
-
tags.seqid = f.collection;
|
|
72
|
-
|
|
73
|
-
return tags;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Get a single tile
|
|
78
|
-
* @param {object} params MapLibre parameters
|
|
79
|
-
* @param {AbortController} abort The abort signal handler
|
|
80
|
-
* @returns {object} The tile, as expected by MapLibre
|
|
81
|
-
* @memberof Panoramax.utils.SemanticsMapProtocol#
|
|
82
|
-
*/
|
|
83
|
-
tile() {
|
|
84
|
-
return (params, abort) => {
|
|
85
|
-
abort = abort || new AbortController();
|
|
86
|
-
const match = params.url.match(/^sem:\/\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
|
|
87
|
-
if (!match) {throw new Error("Invalid URL");}
|
|
88
|
-
|
|
89
|
-
// Look for cache
|
|
90
|
-
if(this.tiles.has(params.url)) {
|
|
91
|
-
return { data: this.tiles.get(params.url).buffer.slice(0) };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const [, f, z, x, y] = match;
|
|
95
|
-
|
|
96
|
-
// Download from API
|
|
97
|
-
const bbox = this._tileToBbox(parseInt(x), parseInt(y), parseInt(z));
|
|
98
|
-
const url = `${this._parent.getAPI()._endpoint}/search?bbox=${bbox.join(",")}&limit=${LIMIT_PER_ZOOM[parseInt(z)]}&sortby=id&filter=${encodeURIComponent(f)}`;
|
|
99
|
-
return fetch(url, { signal: abort.signal })
|
|
100
|
-
.then(res => res.json())
|
|
101
|
-
.then(geojson => {
|
|
102
|
-
if(geojson.features) {
|
|
103
|
-
geojson.type = "FeatureCollection";
|
|
104
|
-
|
|
105
|
-
// Handle empty results
|
|
106
|
-
if(geojson.features.length === 0) {
|
|
107
|
-
const mvt = new Uint8Array();
|
|
108
|
-
this.tiles.set(params.url, mvt);
|
|
109
|
-
return { data: mvt.buffer.slice(0) };
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Remove useless stuff
|
|
113
|
-
geojson.features = geojson.features
|
|
114
|
-
.filter(f => {
|
|
115
|
-
let keep = f.properties?.semantics?.length > 0 || f.properties?.annotations?.length > 0;
|
|
116
|
-
|
|
117
|
-
// Look if sequence has indoor level
|
|
118
|
-
if(!keep) {
|
|
119
|
-
if(f.properties?.collection?.semantics?.find(s => s.key === "osm|level")) {
|
|
120
|
-
keep = true;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
return keep;
|
|
125
|
-
})
|
|
126
|
-
.map(f => ({
|
|
127
|
-
type: f.type,
|
|
128
|
-
geometry: f.geometry,
|
|
129
|
-
id: f.id,
|
|
130
|
-
properties: this._semanticsToBasicProps(f)
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Transform GeoJSON into MVT
|
|
135
|
-
const tileIndex = geojsonvt(geojson, {minZoom: SEMANTICS_OVERLAY_MINZOOM, maxZoom: SEMANTICS_OVERLAY_MAXZOOM});
|
|
136
|
-
const tile = tileIndex.getTile(z, x, y);
|
|
137
|
-
if(!tile) { throw new Error("Can't create tile"); }
|
|
138
|
-
const mvt = fromGeojsonVt({ layer: tile }, { version: 2 });
|
|
139
|
-
this.tiles.set(params.url, mvt);
|
|
140
|
-
return { data: mvt.buffer.slice(0) };
|
|
141
|
-
});
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|