@open-pioneer/map 0.0.0-dev-20241120114910
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/CHANGELOG.md +354 -0
- package/LICENSE +202 -0
- package/MapRegistryImpl.d.ts +17 -0
- package/MapRegistryImpl.js +91 -0
- package/MapRegistryImpl.js.map +1 -0
- package/README.md +871 -0
- package/_virtual/_virtual-pioneer-module_react-hooks.js +7 -0
- package/_virtual/_virtual-pioneer-module_react-hooks.js.map +1 -0
- package/api/BaseFeature.d.ts +31 -0
- package/api/MapConfig.d.ts +111 -0
- package/api/MapModel.d.ts +229 -0
- package/api/MapRegistry.d.ts +48 -0
- package/api/index.d.ts +15 -0
- package/api/layers/GroupLayer.d.ts +50 -0
- package/api/layers/GroupLayer.js +6 -0
- package/api/layers/GroupLayer.js.map +1 -0
- package/api/layers/SimpleLayer.d.ts +27 -0
- package/api/layers/SimpleLayer.js +6 -0
- package/api/layers/SimpleLayer.js.map +1 -0
- package/api/layers/WMSLayer.d.ts +57 -0
- package/api/layers/WMSLayer.js +6 -0
- package/api/layers/WMSLayer.js.map +1 -0
- package/api/layers/WMTSLayer.d.ts +33 -0
- package/api/layers/WMTSLayer.js +6 -0
- package/api/layers/WMTSLayer.js.map +1 -0
- package/api/layers/base.d.ts +242 -0
- package/api/layers/base.js +9 -0
- package/api/layers/base.js.map +1 -0
- package/api/layers/index.d.ts +5 -0
- package/api/shared.d.ts +10 -0
- package/assets/images/mapMarker.png +0 -0
- package/index.d.ts +1 -0
- package/index.js +15 -0
- package/index.js.map +1 -0
- package/internalTestSupport.d.ts +8 -0
- package/internalTestSupport.js +2 -0
- package/internalTestSupport.js.map +1 -0
- package/layers/BkgTopPlusOpen.d.ts +21 -0
- package/layers/BkgTopPlusOpen.js +61 -0
- package/layers/BkgTopPlusOpen.js.map +1 -0
- package/model/AbstractLayer.d.ts +25 -0
- package/model/AbstractLayer.js +186 -0
- package/model/AbstractLayer.js.map +1 -0
- package/model/AbstractLayerBase.d.ts +54 -0
- package/model/AbstractLayerBase.js +119 -0
- package/model/AbstractLayerBase.js.map +1 -0
- package/model/Highlights.d.ts +42 -0
- package/model/Highlights.js +272 -0
- package/model/Highlights.js.map +1 -0
- package/model/LayerCollectionImpl.d.ts +27 -0
- package/model/LayerCollectionImpl.js +228 -0
- package/model/LayerCollectionImpl.js.map +1 -0
- package/model/MapModelImpl.d.ts +46 -0
- package/model/MapModelImpl.js +271 -0
- package/model/MapModelImpl.js.map +1 -0
- package/model/SublayersCollectionImpl.d.ts +18 -0
- package/model/SublayersCollectionImpl.js +31 -0
- package/model/SublayersCollectionImpl.js.map +1 -0
- package/model/createMapModel.d.ts +4 -0
- package/model/createMapModel.js +157 -0
- package/model/createMapModel.js.map +1 -0
- package/model/layers/GroupLayerImpl.d.ts +39 -0
- package/model/layers/GroupLayerImpl.js +88 -0
- package/model/layers/GroupLayerImpl.js.map +1 -0
- package/model/layers/SimpleLayerImpl.d.ts +13 -0
- package/model/layers/SimpleLayerImpl.js +19 -0
- package/model/layers/SimpleLayerImpl.js.map +1 -0
- package/model/layers/WMSLayerImpl.d.ts +41 -0
- package/model/layers/WMSLayerImpl.js +297 -0
- package/model/layers/WMSLayerImpl.js.map +1 -0
- package/model/layers/WMTSLayerImpl.d.ts +17 -0
- package/model/layers/WMTSLayerImpl.js +156 -0
- package/model/layers/WMTSLayerImpl.js.map +1 -0
- package/package.json +86 -0
- package/projections.d.ts +27 -0
- package/projections.js +15 -0
- package/projections.js.map +1 -0
- package/services.d.ts +1 -0
- package/services.js +2 -0
- package/services.js.map +1 -0
- package/ui/CssProps.d.ts +9 -0
- package/ui/CssProps.js +13 -0
- package/ui/CssProps.js.map +1 -0
- package/ui/DefaultMapProvider.d.ts +39 -0
- package/ui/DefaultMapProvider.js +24 -0
- package/ui/DefaultMapProvider.js.map +1 -0
- package/ui/MapAnchor.d.ts +36 -0
- package/ui/MapAnchor.js +28 -0
- package/ui/MapAnchor.js.map +1 -0
- package/ui/MapContainer.d.ts +50 -0
- package/ui/MapContainer.js +191 -0
- package/ui/MapContainer.js.map +1 -0
- package/ui/MapContainerContext.d.ts +7 -0
- package/ui/MapContainerContext.js +17 -0
- package/ui/MapContainerContext.js.map +1 -0
- package/ui/computeMapAnchorStyles.d.ts +3 -0
- package/ui/computeMapAnchorStyles.js +51 -0
- package/ui/computeMapAnchorStyles.js.map +1 -0
- package/ui/hooks.d.ts +34 -0
- package/ui/hooks.js +73 -0
- package/ui/hooks.js.map +1 -0
- package/ui/styles.css +10 -0
- package/ui/styles.css.map +1 -0
- package/ui/useMapModel.d.ts +58 -0
- package/ui/useMapModel.js +59 -0
- package/ui/useMapModel.js.map +1 -0
- package/util/capabilities-utils.d.ts +2 -0
- package/util/capabilities-utils.js +11 -0
- package/util/capabilities-utils.js.map +1 -0
- package/util/geometry-utils.d.ts +7 -0
- package/util/geometry-utils.js +25 -0
- package/util/geometry-utils.js.map +1 -0
- package/util/ol-test-support.d.ts +2 -0
- package/util/ol-test-support.js +24 -0
- package/util/ol-test-support.js.map +1 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { computed, watch, batch, reactive } from '@conterra/reactivity-core';
|
|
2
|
+
import { createLogger, destroyResource, isAbortError } from '@open-pioneer/core';
|
|
3
|
+
import WMSCapabilities from 'ol/format/WMSCapabilities.js';
|
|
4
|
+
import ImageLayer from 'ol/layer/Image.js';
|
|
5
|
+
import ImageWMS from 'ol/source/ImageWMS.js';
|
|
6
|
+
import { fetchCapabilities } from '../../util/capabilities-utils.js';
|
|
7
|
+
import { AbstractLayer } from '../AbstractLayer.js';
|
|
8
|
+
import { AbstractLayerBase } from '../AbstractLayerBase.js';
|
|
9
|
+
import { SublayersCollectionImpl } from '../SublayersCollectionImpl.js';
|
|
10
|
+
|
|
11
|
+
const LOG = createLogger("map:WMSLayer");
|
|
12
|
+
class WMSLayerImpl extends AbstractLayer {
|
|
13
|
+
#url;
|
|
14
|
+
#sublayers;
|
|
15
|
+
#layer;
|
|
16
|
+
#source;
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
#capabilities;
|
|
19
|
+
#abortController = new AbortController();
|
|
20
|
+
#visibleSublayers;
|
|
21
|
+
#sublayersWatch;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
const layer = new ImageLayer();
|
|
24
|
+
super({
|
|
25
|
+
...config,
|
|
26
|
+
olLayer: layer
|
|
27
|
+
});
|
|
28
|
+
const source = new ImageWMS({
|
|
29
|
+
...config.sourceOptions,
|
|
30
|
+
url: config.url,
|
|
31
|
+
params: {
|
|
32
|
+
...config.sourceOptions?.params
|
|
33
|
+
},
|
|
34
|
+
// Use http service to load tiles; needed for authentication etc.
|
|
35
|
+
imageLoadFunction: (wrapper, url) => {
|
|
36
|
+
return this.#loadImage(wrapper, url).catch((error) => {
|
|
37
|
+
LOG.error(`Failed to load tile at '${url}'`, error);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
this.#url = config.url;
|
|
42
|
+
this.#source = source;
|
|
43
|
+
this.#layer = layer;
|
|
44
|
+
this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));
|
|
45
|
+
this.#visibleSublayers = computed(() => this.#getVisibleLayerNames(), {
|
|
46
|
+
equal(a, b) {
|
|
47
|
+
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.#sublayersWatch = watch(
|
|
51
|
+
() => [this.#visibleSublayers.value],
|
|
52
|
+
([layers]) => {
|
|
53
|
+
this.#updateLayersParam(layers);
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
immediate: true
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
destroy() {
|
|
61
|
+
this.#abortController.abort();
|
|
62
|
+
this.#sublayersWatch = destroyResource(this.#sublayersWatch);
|
|
63
|
+
super.destroy();
|
|
64
|
+
}
|
|
65
|
+
get type() {
|
|
66
|
+
return "wms";
|
|
67
|
+
}
|
|
68
|
+
get legend() {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
get url() {
|
|
72
|
+
return this.#url;
|
|
73
|
+
}
|
|
74
|
+
get layers() {
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
get sublayers() {
|
|
78
|
+
return this.#sublayers;
|
|
79
|
+
}
|
|
80
|
+
get capabilities() {
|
|
81
|
+
return this.#capabilities;
|
|
82
|
+
}
|
|
83
|
+
__attachToMap(map) {
|
|
84
|
+
super.__attachToMap(map);
|
|
85
|
+
for (const sublayer of this.#sublayers.getSublayers()) {
|
|
86
|
+
sublayer.__attach(map, this, this);
|
|
87
|
+
}
|
|
88
|
+
const getNestedSublayer = (sublayers, layers) => {
|
|
89
|
+
for (const sublayer of sublayers) {
|
|
90
|
+
const nested = sublayer.sublayers.getSublayers();
|
|
91
|
+
if (nested.length) {
|
|
92
|
+
getNestedSublayer(nested, layers);
|
|
93
|
+
} else {
|
|
94
|
+
if (sublayer.name) {
|
|
95
|
+
layers.push(sublayer);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
this.#fetchWMSCapabilities().then((result) => {
|
|
101
|
+
batch(() => {
|
|
102
|
+
const parser = new WMSCapabilities();
|
|
103
|
+
const capabilities = parser.read(result);
|
|
104
|
+
this.#capabilities = capabilities;
|
|
105
|
+
const layers = [];
|
|
106
|
+
getNestedSublayer(this.#sublayers.getSublayers(), layers);
|
|
107
|
+
for (const layer of layers) {
|
|
108
|
+
const legendUrl = getWMSLegendUrl(capabilities, layer.name);
|
|
109
|
+
layer.__setLegend(legendUrl);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}).catch((error) => {
|
|
113
|
+
if (isAbortError(error)) {
|
|
114
|
+
LOG.debug(`Layer ${this.id} has been destroyed before fetching capabilities`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
LOG.error(`Failed to fetch WMS capabilities for layer ${this.id}`, error);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Gathers the visibility of _all_ sublayers and assembles the 'layers' WMS parameter.
|
|
122
|
+
* The parameters are then applied to the WMS source.
|
|
123
|
+
*/
|
|
124
|
+
#updateLayersParam(layers) {
|
|
125
|
+
this.#source.updateParams({
|
|
126
|
+
"LAYERS": layers
|
|
127
|
+
});
|
|
128
|
+
const source = layers.length === 0 ? null : this.#source;
|
|
129
|
+
if (this.#layer.getSource() !== source) {
|
|
130
|
+
this.#layer.setSource(source);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
#getVisibleLayerNames() {
|
|
134
|
+
const layers = [];
|
|
135
|
+
const visitSublayer = (sublayer) => {
|
|
136
|
+
if (!sublayer.visible) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const nestedSublayers = sublayer.sublayers.__getRawSublayers();
|
|
140
|
+
if (nestedSublayers.length) {
|
|
141
|
+
for (const nestedSublayer of nestedSublayers) {
|
|
142
|
+
visitSublayer(nestedSublayer);
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
if (sublayer.name) {
|
|
146
|
+
layers.push(sublayer.name);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
for (const sublayer of this.sublayers.__getRawSublayers()) {
|
|
151
|
+
visitSublayer(sublayer);
|
|
152
|
+
}
|
|
153
|
+
return layers;
|
|
154
|
+
}
|
|
155
|
+
async #fetchWMSCapabilities() {
|
|
156
|
+
const httpService = this.map.__sharedDependencies.httpService;
|
|
157
|
+
const url = `${this.#url}?LANGUAGE=ger&SERVICE=WMS&REQUEST=GetCapabilities`;
|
|
158
|
+
return fetchCapabilities(url, httpService, this.#abortController.signal);
|
|
159
|
+
}
|
|
160
|
+
async #loadImage(imageWrapper, imageUrl) {
|
|
161
|
+
const httpService = this.map.__sharedDependencies.httpService;
|
|
162
|
+
const image = imageWrapper.getImage();
|
|
163
|
+
const response = await httpService.fetch(imageUrl);
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
throw new Error(`Request failed with status ${response.status}.`);
|
|
166
|
+
}
|
|
167
|
+
const blob = await response.blob();
|
|
168
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
169
|
+
const finish = () => {
|
|
170
|
+
URL.revokeObjectURL(objectUrl);
|
|
171
|
+
image.removeEventListener("load", finish);
|
|
172
|
+
image.removeEventListener("error", finish);
|
|
173
|
+
};
|
|
174
|
+
image.addEventListener("load", finish);
|
|
175
|
+
image.addEventListener("error", finish);
|
|
176
|
+
image.src = objectUrl;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
class WMSSublayerImpl extends AbstractLayerBase {
|
|
180
|
+
#parent;
|
|
181
|
+
#parentLayer;
|
|
182
|
+
#name;
|
|
183
|
+
#legend = reactive();
|
|
184
|
+
#sublayers;
|
|
185
|
+
#visible;
|
|
186
|
+
constructor(config) {
|
|
187
|
+
super(config);
|
|
188
|
+
this.#name = config.name;
|
|
189
|
+
this.#visible = reactive(config.visible ?? true);
|
|
190
|
+
this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));
|
|
191
|
+
}
|
|
192
|
+
get type() {
|
|
193
|
+
return "wms-sublayer";
|
|
194
|
+
}
|
|
195
|
+
get name() {
|
|
196
|
+
return this.#name;
|
|
197
|
+
}
|
|
198
|
+
get layers() {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
get sublayers() {
|
|
202
|
+
return this.#sublayers;
|
|
203
|
+
}
|
|
204
|
+
get parent() {
|
|
205
|
+
const parent = this.#parent;
|
|
206
|
+
if (!parent) {
|
|
207
|
+
throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);
|
|
208
|
+
}
|
|
209
|
+
return parent;
|
|
210
|
+
}
|
|
211
|
+
get parentLayer() {
|
|
212
|
+
const parentLayer = this.#parentLayer;
|
|
213
|
+
if (!parentLayer) {
|
|
214
|
+
throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);
|
|
215
|
+
}
|
|
216
|
+
return parentLayer;
|
|
217
|
+
}
|
|
218
|
+
get legend() {
|
|
219
|
+
return this.#legend.value;
|
|
220
|
+
}
|
|
221
|
+
get visible() {
|
|
222
|
+
return this.#visible.value;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Called by the parent layer when it is attached to the map to attach all sublayers.
|
|
226
|
+
*/
|
|
227
|
+
__attach(map, parentLayer, parent) {
|
|
228
|
+
super.__attachToMap(map);
|
|
229
|
+
if (this.#parent) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`WMS sublayer '${this.id}' has already been attached to parent '${this.#parent.id}'`
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
this.#parent = parent;
|
|
235
|
+
if (this.#parentLayer) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`WMS sublayer '${this.id}' has already been attached to parent layer '${this.#parentLayer.id}'`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
this.#parentLayer = parentLayer;
|
|
241
|
+
for (const sublayer of this.sublayers.__getRawSublayers()) {
|
|
242
|
+
sublayer.__attach(map, parentLayer, this);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Called by the parent layer to update the legend on load.
|
|
247
|
+
*/
|
|
248
|
+
__setLegend(legendUrl) {
|
|
249
|
+
this.#legend.value = legendUrl;
|
|
250
|
+
}
|
|
251
|
+
setVisible(newVisibility) {
|
|
252
|
+
this.#visible.value = newVisibility;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function constructSublayers(sublayerConfigs = []) {
|
|
256
|
+
const sublayers = [];
|
|
257
|
+
try {
|
|
258
|
+
for (const sublayerConfig of sublayerConfigs) {
|
|
259
|
+
sublayers.push(new WMSSublayerImpl(sublayerConfig));
|
|
260
|
+
}
|
|
261
|
+
return sublayers;
|
|
262
|
+
} catch (e) {
|
|
263
|
+
while (sublayers.length) {
|
|
264
|
+
const layer = sublayers.pop();
|
|
265
|
+
layer?.destroy();
|
|
266
|
+
}
|
|
267
|
+
throw new Error("Failed to construct sublayers.", { cause: e });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function getWMSLegendUrl(capabilities, layerName) {
|
|
271
|
+
const capabilitiesContent = capabilities?.Capability;
|
|
272
|
+
const rootLayerCapabilities = capabilitiesContent?.Layer;
|
|
273
|
+
let url = void 0;
|
|
274
|
+
const searchNestedLayer = (layer) => {
|
|
275
|
+
for (const currentLayer of layer) {
|
|
276
|
+
if (currentLayer?.Name === layerName) {
|
|
277
|
+
const activeLayer = currentLayer;
|
|
278
|
+
const styles = activeLayer.Style;
|
|
279
|
+
if (!styles || !styles.length) {
|
|
280
|
+
LOG.debug("No style in WMS layer capabilities - giving up.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const activeStyle = styles[0];
|
|
284
|
+
url = activeStyle.LegendURL?.[0]?.OnlineResource;
|
|
285
|
+
} else if (currentLayer.Layer) {
|
|
286
|
+
searchNestedLayer(currentLayer.Layer);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
if (rootLayerCapabilities) {
|
|
291
|
+
searchNestedLayer(rootLayerCapabilities.Layer);
|
|
292
|
+
}
|
|
293
|
+
return url;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export { WMSLayerImpl, getWMSLegendUrl };
|
|
297
|
+
//# sourceMappingURL=WMSLayerImpl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WMSLayerImpl.js","sources":["WMSLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n batch,\n computed,\n Reactive,\n reactive,\n ReadonlyReactive,\n watch\n} from \"@conterra/reactivity-core\";\nimport { createLogger, destroyResource, isAbortError, Resource } from \"@open-pioneer/core\";\nimport { ImageWrapper } from \"ol\";\nimport WMSCapabilities from \"ol/format/WMSCapabilities\";\nimport ImageLayer from \"ol/layer/Image\";\nimport type ImageSource from \"ol/source/Image\";\nimport ImageWMS from \"ol/source/ImageWMS\";\nimport { WMSLayer, WMSLayerConfig, WMSSublayer, WMSSublayerConfig } from \"../../api\";\nimport { fetchCapabilities } from \"../../util/capabilities-utils\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { SublayersCollectionImpl } from \"../SublayersCollectionImpl\";\n\nconst LOG = createLogger(\"map:WMSLayer\");\n\nexport class WMSLayerImpl extends AbstractLayer implements WMSLayer {\n #url: string;\n #sublayers: SublayersCollectionImpl<WMSSublayerImpl>;\n #layer: ImageLayer<ImageSource>;\n #source: ImageWMS;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #capabilities: Record<string, any> | undefined;\n readonly #abortController = new AbortController();\n\n #visibleSublayers: ReadonlyReactive<string[]>;\n #sublayersWatch: Resource | undefined;\n\n constructor(config: WMSLayerConfig) {\n const layer = new ImageLayer();\n super({\n ...config,\n olLayer: layer\n });\n const source = new ImageWMS({\n ...config.sourceOptions,\n url: config.url,\n params: {\n ...config.sourceOptions?.params\n },\n // Use http service to load tiles; needed for authentication etc.\n imageLoadFunction: (wrapper, url) => {\n return this.#loadImage(wrapper, url).catch((error) => {\n LOG.error(`Failed to load tile at '${url}'`, error);\n });\n }\n });\n this.#url = config.url;\n this.#source = source;\n this.#layer = layer;\n this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));\n this.#visibleSublayers = computed(() => this.#getVisibleLayerNames(), {\n equal(a, b) {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n });\n\n this.#sublayersWatch = watch(\n () => [this.#visibleSublayers.value],\n ([layers]) => {\n this.#updateLayersParam(layers);\n },\n {\n immediate: true\n }\n );\n }\n\n destroy() {\n this.#abortController.abort();\n this.#sublayersWatch = destroyResource(this.#sublayersWatch);\n super.destroy();\n }\n\n get type() {\n return \"wms\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n get url(): string {\n return this.#url;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): SublayersCollectionImpl<WMSSublayerImpl> {\n return this.#sublayers;\n }\n\n get capabilities() {\n return this.#capabilities;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer.__attach(map, this, this);\n }\n\n /** Find all leaf nodes representing a layer in the structure */\n const getNestedSublayer = (sublayers: WMSSublayerImpl[], layers: WMSSublayerImpl[]) => {\n for (const sublayer of sublayers) {\n const nested = sublayer.sublayers.getSublayers();\n if (nested.length) {\n getNestedSublayer(nested, layers);\n } else {\n if (sublayer.name) {\n layers.push(sublayer);\n }\n }\n }\n };\n\n this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(result);\n this.#capabilities = capabilities;\n\n const layers: WMSSublayerImpl[] = [];\n getNestedSublayer(this.#sublayers.getSublayers(), layers);\n\n for (const layer of layers) {\n const legendUrl = getWMSLegendUrl(capabilities, layer.name!);\n layer.__setLegend(legendUrl);\n }\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer ${this.id} has been destroyed before fetching capabilities`);\n return;\n }\n LOG.error(`Failed to fetch WMS capabilities for layer ${this.id}`, error);\n });\n }\n\n /**\n * Gathers the visibility of _all_ sublayers and assembles the 'layers' WMS parameter.\n * The parameters are then applied to the WMS source.\n */\n #updateLayersParam(layers: string[]) {\n this.#source.updateParams({\n \"LAYERS\": layers\n });\n\n // only set source if there are visible sublayers, otherwise\n // we send an invalid http request\n const source = layers.length === 0 ? null : this.#source;\n if (this.#layer.getSource() !== source) {\n this.#layer.setSource(source);\n }\n }\n\n #getVisibleLayerNames() {\n const layers: string[] = [];\n const visitSublayer = (sublayer: WMSSublayerImpl) => {\n if (!sublayer.visible) {\n return;\n }\n\n const nestedSublayers = sublayer.sublayers.__getRawSublayers();\n if (nestedSublayers.length) {\n for (const nestedSublayer of nestedSublayers) {\n visitSublayer(nestedSublayer);\n }\n } else {\n /**\n * Push sublayer only, if layer name is not an empty string | undefined | ...\n */\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\n }\n };\n\n for (const sublayer of this.sublayers.__getRawSublayers()) {\n visitSublayer(sublayer);\n }\n return layers;\n }\n\n async #fetchWMSCapabilities(): Promise<string> {\n const httpService = this.map.__sharedDependencies.httpService;\n const url = `${this.#url}?LANGUAGE=ger&SERVICE=WMS&REQUEST=GetCapabilities`;\n return fetchCapabilities(url, httpService, this.#abortController.signal);\n }\n\n async #loadImage(imageWrapper: ImageWrapper, imageUrl: string): Promise<void> {\n const httpService = this.map.__sharedDependencies.httpService;\n const image = imageWrapper.getImage() as HTMLImageElement;\n\n const response = await httpService.fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n }\n}\n\nclass WMSSublayerImpl extends AbstractLayerBase implements WMSSublayer {\n #parent: WMSSublayerImpl | WMSLayerImpl | undefined;\n #parentLayer: WMSLayerImpl | undefined;\n #name: string | undefined;\n #legend = reactive<string | undefined>();\n #sublayers: SublayersCollectionImpl<WMSSublayerImpl>;\n #visible: Reactive<boolean>;\n\n constructor(config: WMSSublayerConfig) {\n super(config);\n this.#name = config.name;\n this.#visible = reactive(config.visible ?? true);\n this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));\n }\n\n get type() {\n return \"wms-sublayer\" as const;\n }\n\n get name(): string | undefined {\n return this.#name;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): SublayersCollectionImpl<WMSSublayerImpl> {\n return this.#sublayers;\n }\n\n get parent(): WMSSublayerImpl | WMSLayerImpl {\n const parent = this.#parent;\n if (!parent) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parent;\n }\n\n get parentLayer(): WMSLayerImpl {\n const parentLayer = this.#parentLayer;\n if (!parentLayer) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parentLayer;\n }\n\n get legend(): string | undefined {\n return this.#legend.value;\n }\n\n get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * Called by the parent layer when it is attached to the map to attach all sublayers.\n */\n __attach(\n map: MapModelImpl,\n parentLayer: WMSLayerImpl,\n parent: WMSLayerImpl | WMSSublayerImpl\n ): void {\n super.__attachToMap(map);\n if (this.#parent) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent '${this.#parent.id}'`\n );\n }\n this.#parent = parent;\n if (this.#parentLayer) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent layer '${this.#parentLayer.id}'`\n );\n }\n this.#parentLayer = parentLayer;\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers.__getRawSublayers()) {\n sublayer.__attach(map, parentLayer, this);\n }\n }\n\n /**\n * Called by the parent layer to update the legend on load.\n */\n __setLegend(legendUrl: string | undefined) {\n this.#legend.value = legendUrl;\n }\n\n setVisible(newVisibility: boolean): void {\n this.#visible.value = newVisibility;\n }\n}\n\nfunction constructSublayers(sublayerConfigs: WMSSublayerConfig[] = []): WMSSublayerImpl[] {\n const sublayers: WMSSublayerImpl[] = [];\n try {\n for (const sublayerConfig of sublayerConfigs) {\n sublayers.push(new WMSSublayerImpl(sublayerConfig));\n }\n return sublayers;\n } catch (e) {\n // Ensure previous sublayers are destroyed if a single constructor throws\n while (sublayers.length) {\n const layer = sublayers.pop()!;\n layer?.destroy();\n }\n throw new Error(\"Failed to construct sublayers.\", { cause: e });\n }\n}\n\n/** extract the legend url from the service capabilities */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getWMSLegendUrl(capabilities: Record<string, any>, layerName: string) {\n const capabilitiesContent = capabilities?.Capability;\n const rootLayerCapabilities = capabilitiesContent?.Layer;\n let url: string | undefined = undefined;\n\n /** Recurse search for the currrent layer within the parsed capabilities service*/\n //eslint-disable-next-line @typescript-eslint/no-explicit-any\n const searchNestedLayer = (layer: Record<string, any>[]) => {\n for (const currentLayer of layer) {\n // spec. if, a layer has a <Name>, then it is a map layer\n if (currentLayer?.Name === layerName) {\n const activeLayer = currentLayer;\n const styles = activeLayer.Style;\n if (!styles || !styles.length) {\n LOG.debug(\"No style in WMS layer capabilities - giving up.\");\n return;\n }\n // by parsing of the service capabilities, every child inherits the parent's legend\n // theorfore, extract the legendURL from the first style object in the array (its own legend)\n const activeStyle = styles[0];\n url = activeStyle.LegendURL?.[0]?.OnlineResource;\n } else if (currentLayer.Layer) {\n searchNestedLayer(currentLayer.Layer);\n }\n }\n };\n if (rootLayerCapabilities) {\n searchNestedLayer(rootLayerCapabilities.Layer);\n }\n return url;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { WMTSLayer, WMTSLayerConfig } from "../../api";
|
|
2
|
+
import { AbstractLayer } from "../AbstractLayer";
|
|
3
|
+
import { MapModelImpl } from "../MapModelImpl";
|
|
4
|
+
export declare class WMTSLayerImpl extends AbstractLayer implements WMTSLayer {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(config: WMTSLayerConfig);
|
|
7
|
+
get type(): "wmts";
|
|
8
|
+
destroy(): void;
|
|
9
|
+
get legend(): string | undefined;
|
|
10
|
+
get sublayers(): undefined;
|
|
11
|
+
get layers(): undefined;
|
|
12
|
+
__attachToMap(map: MapModelImpl): void;
|
|
13
|
+
get url(): string;
|
|
14
|
+
get name(): string;
|
|
15
|
+
get matrixSet(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare function getWMTSLegendUrl(capabilities: Record<string, any>, activeLayerId: string | undefined, activeStyleId: string | undefined): string | undefined;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { createLogger, isAbortError } from '@open-pioneer/core';
|
|
2
|
+
import TileState from 'ol/TileState.js';
|
|
3
|
+
import WMTSCapabilities from 'ol/format/WMTSCapabilities.js';
|
|
4
|
+
import TileLayer from 'ol/layer/Tile.js';
|
|
5
|
+
import WMTS, { optionsFromCapabilities } from 'ol/source/WMTS.js';
|
|
6
|
+
import { fetchCapabilities } from '../../util/capabilities-utils.js';
|
|
7
|
+
import { AbstractLayer } from '../AbstractLayer.js';
|
|
8
|
+
import { ImageTile } from 'ol';
|
|
9
|
+
import { reactive } from '@conterra/reactivity-core';
|
|
10
|
+
|
|
11
|
+
const LOG = createLogger("map:WMTSLayer");
|
|
12
|
+
class WMTSLayerImpl extends AbstractLayer {
|
|
13
|
+
#url;
|
|
14
|
+
#name;
|
|
15
|
+
#matrixSet;
|
|
16
|
+
#layer;
|
|
17
|
+
#source;
|
|
18
|
+
#sourceOptions;
|
|
19
|
+
#legend = reactive();
|
|
20
|
+
#abortController = new AbortController();
|
|
21
|
+
constructor(config) {
|
|
22
|
+
const layer = new TileLayer();
|
|
23
|
+
super({
|
|
24
|
+
...config,
|
|
25
|
+
olLayer: layer
|
|
26
|
+
});
|
|
27
|
+
this.#url = config.url;
|
|
28
|
+
this.#name = config.name;
|
|
29
|
+
this.#layer = layer;
|
|
30
|
+
this.#matrixSet = config.matrixSet;
|
|
31
|
+
this.#sourceOptions = config.sourceOptions;
|
|
32
|
+
}
|
|
33
|
+
get type() {
|
|
34
|
+
return "wmts";
|
|
35
|
+
}
|
|
36
|
+
destroy() {
|
|
37
|
+
this.#abortController.abort();
|
|
38
|
+
super.destroy();
|
|
39
|
+
}
|
|
40
|
+
get legend() {
|
|
41
|
+
return this.#legend.value;
|
|
42
|
+
}
|
|
43
|
+
get sublayers() {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
get layers() {
|
|
47
|
+
return void 0;
|
|
48
|
+
}
|
|
49
|
+
__attachToMap(map) {
|
|
50
|
+
super.__attachToMap(map);
|
|
51
|
+
this.#fetchWMTSCapabilities().then((result) => {
|
|
52
|
+
const parser = new WMTSCapabilities();
|
|
53
|
+
const capabilities = parser.read(result);
|
|
54
|
+
const options = optionsFromCapabilities(capabilities, {
|
|
55
|
+
layer: this.#name,
|
|
56
|
+
matrixSet: this.#matrixSet
|
|
57
|
+
});
|
|
58
|
+
if (!options) {
|
|
59
|
+
throw new Error("Layer was not found in capabilities");
|
|
60
|
+
}
|
|
61
|
+
const source = new WMTS({
|
|
62
|
+
...options,
|
|
63
|
+
...this.#sourceOptions,
|
|
64
|
+
tileLoadFunction: (tile, tileUrl) => {
|
|
65
|
+
this.#loadTile(tile, tileUrl);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
this.#source = source;
|
|
69
|
+
this.#layer.setSource(this.#source);
|
|
70
|
+
const activeStyleId = source.getStyle();
|
|
71
|
+
const legendUrl = getWMTSLegendUrl(capabilities, this.name, activeStyleId);
|
|
72
|
+
this.#legend.value = legendUrl;
|
|
73
|
+
}).catch((error) => {
|
|
74
|
+
if (isAbortError(error)) {
|
|
75
|
+
LOG.error(`Layer ${this.name} has been destroyed before fetching the data`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
LOG.error(`Failed fetching WMTS capabilities for Layer ${this.name}`, error);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
get url() {
|
|
82
|
+
return this.#url;
|
|
83
|
+
}
|
|
84
|
+
get name() {
|
|
85
|
+
return this.#name;
|
|
86
|
+
}
|
|
87
|
+
get matrixSet() {
|
|
88
|
+
return this.#matrixSet;
|
|
89
|
+
}
|
|
90
|
+
async #fetchWMTSCapabilities() {
|
|
91
|
+
const httpService = this.map.__sharedDependencies.httpService;
|
|
92
|
+
return fetchCapabilities(this.#url, httpService, this.#abortController.signal);
|
|
93
|
+
}
|
|
94
|
+
async #loadTile(tile, tileUrl) {
|
|
95
|
+
const httpService = this.map.__sharedDependencies.httpService;
|
|
96
|
+
try {
|
|
97
|
+
if (!(tile instanceof ImageTile)) {
|
|
98
|
+
throw new Error("Only 'ImageTile' is supported for now.");
|
|
99
|
+
}
|
|
100
|
+
const image = tile.getImage();
|
|
101
|
+
if (!isHtmlImage(image)) {
|
|
102
|
+
throw new Error("Only <img> tags are supported as tiles for now.");
|
|
103
|
+
}
|
|
104
|
+
const response = await httpService.fetch(tileUrl);
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
throw new Error(`Tile request failed with status ${response.status}.`);
|
|
107
|
+
}
|
|
108
|
+
const blob = await response.blob();
|
|
109
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
110
|
+
const finish = () => {
|
|
111
|
+
URL.revokeObjectURL(objectUrl);
|
|
112
|
+
image.removeEventListener("load", finish);
|
|
113
|
+
image.removeEventListener("error", finish);
|
|
114
|
+
};
|
|
115
|
+
image.addEventListener("load", finish);
|
|
116
|
+
image.addEventListener("error", finish);
|
|
117
|
+
image.src = objectUrl;
|
|
118
|
+
} catch (e) {
|
|
119
|
+
tile.setState(TileState.ERROR);
|
|
120
|
+
if (!isAbortError(e)) {
|
|
121
|
+
LOG.error("Failed to load tile", e);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function isHtmlImage(htmlElement) {
|
|
127
|
+
return htmlElement.tagName === "IMG";
|
|
128
|
+
}
|
|
129
|
+
function getWMTSLegendUrl(capabilities, activeLayerId, activeStyleId) {
|
|
130
|
+
const content = capabilities?.Contents;
|
|
131
|
+
const layers = content?.Layer;
|
|
132
|
+
let activeLayer = layers?.find((layer) => layer?.Identifier === activeLayerId);
|
|
133
|
+
if (!activeLayer) {
|
|
134
|
+
LOG.debug("Failed to find the active layer in WMTS layer capabilities.");
|
|
135
|
+
activeLayer = layers?.[0];
|
|
136
|
+
if (!activeLayer) {
|
|
137
|
+
LOG.debug("No layer in WMTS capabilities - giving up.");
|
|
138
|
+
return void 0;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const styles = activeLayer.Style;
|
|
142
|
+
let activeStyle = styles?.find((style) => style?.Identifier === activeStyleId);
|
|
143
|
+
if (!activeStyle) {
|
|
144
|
+
LOG.debug("Failed to find active style in WMTS layer.");
|
|
145
|
+
activeStyle = styles?.[0];
|
|
146
|
+
if (!activeStyle) {
|
|
147
|
+
LOG.debug("No style in WMTS layer capabilities - giving up.");
|
|
148
|
+
return void 0;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const legendUrl = activeStyle.LegendURL?.[0]?.href;
|
|
152
|
+
return legendUrl;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export { WMTSLayerImpl, getWMTSLegendUrl };
|
|
156
|
+
//# sourceMappingURL=WMTSLayerImpl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WMTSLayerImpl.js","sources":["WMTSLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger, isAbortError } from \"@open-pioneer/core\";\nimport Tile from \"ol/Tile\";\nimport TileState from \"ol/TileState\";\nimport WMTSCapabilities from \"ol/format/WMTSCapabilities\";\nimport TileLayer from \"ol/layer/Tile\";\nimport type TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities } from \"ol/source/WMTS\";\nimport { WMTSLayer, WMTSLayerConfig } from \"../../api\";\nimport { fetchCapabilities } from \"../../util/capabilities-utils\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { ImageTile } from \"ol\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport { reactive } from \"@conterra/reactivity-core\";\n\nconst LOG = createLogger(\"map:WMTSLayer\");\n\nexport class WMTSLayerImpl extends AbstractLayer implements WMTSLayer {\n #url: string;\n #name: string;\n #matrixSet: string;\n #layer: TileLayer<TileSourceType>;\n #source: WMTS | undefined;\n #sourceOptions?: Partial<WMSSourceOptions>;\n #legend = reactive<string | undefined>();\n readonly #abortController = new AbortController();\n\n constructor(config: WMTSLayerConfig) {\n const layer = new TileLayer();\n super({\n ...config,\n olLayer: layer\n });\n this.#url = config.url;\n this.#name = config.name;\n this.#layer = layer;\n this.#matrixSet = config.matrixSet;\n this.#sourceOptions = config.sourceOptions;\n }\n\n get type() {\n return \"wmts\" as const;\n }\n\n destroy(): void {\n this.#abortController.abort();\n super.destroy();\n }\n\n get legend(): string | undefined {\n return this.#legend.value;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n this.#fetchWMTSCapabilities()\n .then((result: string) => {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(result);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(\"Layer was not found in capabilities\");\n }\n const source = new WMTS({\n ...options,\n ...this.#sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n });\n this.#source = source;\n this.#layer.setSource(this.#source);\n const activeStyleId = source.getStyle();\n const legendUrl = getWMTSLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.error(`Layer ${this.name} has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed fetching WMTS capabilities for Layer ${this.name}`, error);\n });\n }\n\n get url() {\n return this.#url;\n }\n\n get name() {\n return this.#name;\n }\n\n get matrixSet() {\n return this.#matrixSet;\n }\n\n async #fetchWMTSCapabilities(): Promise<string> {\n const httpService = this.map.__sharedDependencies.httpService;\n return fetchCapabilities(this.#url, httpService, this.#abortController.signal);\n }\n\n async #loadTile(tile: Tile, tileUrl: string): Promise<void> {\n const httpService = this.map.__sharedDependencies.httpService;\n try {\n if (!(tile instanceof ImageTile)) {\n throw new Error(\"Only 'ImageTile' is supported for now.\");\n }\n\n const image = tile.getImage();\n if (!isHtmlImage(image)) {\n // Could also be canvas or video\n throw new Error(\"Only <img> tags are supported as tiles for now.\");\n }\n\n const response = await httpService.fetch(tileUrl);\n if (!response.ok) {\n throw new Error(`Tile request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n } catch (e) {\n tile.setState(TileState.ERROR);\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load tile\", e);\n }\n }\n }\n}\n\nfunction isHtmlImage(htmlElement: HTMLElement): htmlElement is HTMLImageElement {\n return htmlElement.tagName === \"IMG\";\n}\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function getWMTSLegendUrl(\n capabilities: Record<string, any>,\n activeLayerId: string | undefined,\n activeStyleId: string | undefined\n): string | undefined {\n const content = capabilities?.Contents;\n const layers = content?.Layer;\n\n let activeLayer = layers?.find((layer: any) => layer?.Identifier === activeLayerId);\n if (!activeLayer) {\n LOG.debug(\"Failed to find the active layer in WMTS layer capabilities.\");\n activeLayer = layers?.[0];\n if (!activeLayer) {\n LOG.debug(\"No layer in WMTS capabilities - giving up.\");\n return undefined;\n }\n }\n\n const styles = activeLayer.Style;\n let activeStyle = styles?.find((style: any) => style?.Identifier === activeStyleId);\n if (!activeStyle) {\n LOG.debug(\"Failed to find active style in WMTS layer.\");\n activeStyle = styles?.[0];\n if (!activeStyle) {\n LOG.debug(\"No style in WMTS layer capabilities - giving up.\");\n return undefined;\n }\n }\n\n const legendUrl = activeStyle.LegendURL?.[0]?.href;\n return legendUrl as string | undefined;\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "module",
|
|
3
|
+
"name": "@open-pioneer/map",
|
|
4
|
+
"version": "0.0.0-dev-20241120114910",
|
|
5
|
+
"description": "This package integrates OpenLayers maps into an open pioneer trails application.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"open-pioneer-trails"
|
|
8
|
+
],
|
|
9
|
+
"homepage": "https://github.com/open-pioneer",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/open-pioneer/trails-openlayers-base-packages",
|
|
14
|
+
"directory": "src/packages/map"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@open-pioneer/chakra-integration": "^2.4.0-dev.20241120092632",
|
|
18
|
+
"@open-pioneer/core": "^2.4.0-dev.20241120092632",
|
|
19
|
+
"@open-pioneer/http": "^2.4.0-dev.20241120092632",
|
|
20
|
+
"@open-pioneer/react-utils": "^2.4.0-dev.20241120092632",
|
|
21
|
+
"@open-pioneer/runtime": "^2.4.0-dev.20241120092632",
|
|
22
|
+
"@types/proj4": "^2.5.2",
|
|
23
|
+
"ol": "^10.2.1",
|
|
24
|
+
"proj4": "^2.12.1",
|
|
25
|
+
"react": "^18.3.1",
|
|
26
|
+
"react-dom": "^18.3.1",
|
|
27
|
+
"react-use": "^17.5.1",
|
|
28
|
+
"uuid": "^10.0.0",
|
|
29
|
+
"@conterra/reactivity-core": "^0.4.3"
|
|
30
|
+
},
|
|
31
|
+
"exports": {
|
|
32
|
+
"./package.json": "./package.json",
|
|
33
|
+
".": {
|
|
34
|
+
"import": "./index.js",
|
|
35
|
+
"types": "./index.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./internalTestSupport": {
|
|
38
|
+
"import": "./internalTestSupport.js",
|
|
39
|
+
"types": "./internalTestSupport.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./services": {
|
|
42
|
+
"import": "./services.js",
|
|
43
|
+
"types": "./services.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./ui/styles.css": "./ui/styles.css"
|
|
46
|
+
},
|
|
47
|
+
"openPioneerFramework": {
|
|
48
|
+
"styles": "./ui/styles.css",
|
|
49
|
+
"services": [
|
|
50
|
+
{
|
|
51
|
+
"serviceName": "MapRegistryImpl",
|
|
52
|
+
"provides": [
|
|
53
|
+
{
|
|
54
|
+
"interfaceName": "map.MapRegistry"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"references": [
|
|
58
|
+
{
|
|
59
|
+
"referenceName": "providers",
|
|
60
|
+
"type": "all",
|
|
61
|
+
"interfaceName": "map.MapConfigProvider"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"referenceName": "httpService",
|
|
65
|
+
"type": "unique",
|
|
66
|
+
"interfaceName": "http.HttpService"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"servicesModule": "./services",
|
|
72
|
+
"i18n": {
|
|
73
|
+
"languages": []
|
|
74
|
+
},
|
|
75
|
+
"ui": {
|
|
76
|
+
"references": [
|
|
77
|
+
{
|
|
78
|
+
"type": "unique",
|
|
79
|
+
"interfaceName": "map.MapRegistry"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
"properties": [],
|
|
84
|
+
"packageFormatVersion": "1.0.0"
|
|
85
|
+
}
|
|
86
|
+
}
|
package/projections.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ProjectionDefinition as Proj4ProjectionDefinition } from "proj4";
|
|
2
|
+
export type ProjectionDefinition = string | Proj4ProjectionDefinition;
|
|
3
|
+
/**
|
|
4
|
+
* Adds new registrations to the global [proj4js](https://github.com/proj4js/proj4js) definition set.
|
|
5
|
+
*
|
|
6
|
+
* See the proj4js documentation for more details.
|
|
7
|
+
*
|
|
8
|
+
* Example:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { registerProjections } from "@open-pioneer/map";
|
|
12
|
+
*
|
|
13
|
+
* registerProjections({
|
|
14
|
+
* "EPSG:25832": "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs",
|
|
15
|
+
* // ... more projections
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @param projections
|
|
20
|
+
* An object containing (key, definition) pairs. The key must be projection name (such as `"EPSG:4326"`).
|
|
21
|
+
* The value can be a string defining the projection or an existing proj4 definition object.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerProjections(projections: Record<string, ProjectionDefinition>): void;
|
|
24
|
+
/**
|
|
25
|
+
* Searches the global [proj4js](https://github.com/proj4js/proj4js) definition set for a definition with the given name.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getProjection(name: string): Proj4ProjectionDefinition;
|
package/projections.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { register } from 'ol/proj/proj4.js';
|
|
2
|
+
import proj4 from 'proj4';
|
|
3
|
+
|
|
4
|
+
function registerProjections(projections) {
|
|
5
|
+
for (const [name, definition] of Object.entries(projections)) {
|
|
6
|
+
proj4.defs(name, definition);
|
|
7
|
+
}
|
|
8
|
+
register(proj4);
|
|
9
|
+
}
|
|
10
|
+
function getProjection(name) {
|
|
11
|
+
return proj4.defs(name);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { getProjection, registerProjections };
|
|
15
|
+
//# sourceMappingURL=projections.js.map
|