ol-stac 1.5.1 → 1.6.0
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/README.md +2 -1
- package/http.d.ts +35 -0
- package/http.d.ts.map +1 -0
- package/http.js +101 -0
- package/http.js.map +1 -0
- package/layer/STAC.d.ts +224 -17
- package/layer/STAC.d.ts.map +1 -1
- package/layer/STAC.js +404 -66
- package/layer/STAC.js.map +1 -1
- package/layer/type.d.ts +88 -0
- package/layer/type.d.ts.map +1 -0
- package/layer/type.js +83 -0
- package/layer/type.js.map +1 -0
- package/package.json +3 -2
- package/proj.d.ts.map +1 -1
- package/proj.js +51 -5
- package/proj.js.map +1 -1
- package/shim/ogcTileUtil.d.ts +11 -0
- package/shim/ogcTileUtil.d.ts.map +1 -0
- package/shim/ogcTileUtil.js +20 -0
- package/shim/ogcTileUtil.js.map +1 -0
- package/shim/proj4.d.ts +9 -0
- package/shim/proj4.d.ts.map +1 -0
- package/shim/proj4.js +28 -0
- package/shim/proj4.js.map +1 -0
- package/source/GeoZarr.d.ts +601 -0
- package/source/GeoZarr.d.ts.map +1 -0
- package/source/GeoZarr.js +1990 -0
- package/source/GeoZarr.js.map +1 -0
- package/source/type.d.ts +20 -3
- package/source/type.d.ts.map +1 -1
- package/source/type.js +19 -2
- package/source/type.js.map +1 -1
- package/util.d.ts +131 -1
- package/util.d.ts.map +1 -1
- package/util.js +808 -44
- package/util.js.map +1 -1
package/layer/STAC.js
CHANGED
|
@@ -22,12 +22,14 @@ import { PMTilesRasterSource, PMTilesVectorSource } from 'ol-pmtiles';
|
|
|
22
22
|
import * as pmtiles from 'pmtiles';
|
|
23
23
|
import create, { Asset } from 'stac-js';
|
|
24
24
|
import { fixGeoJson, toGeoJSON, unionBoundingBox } from 'stac-js/src/geo.js';
|
|
25
|
-
import { geojsonMediaType, geotiffMediaTypes, wozMediaTypes, } from 'stac-js/src/mediatypes.js';
|
|
25
|
+
import { geojsonMediaType, geotiffMediaTypes, wozMediaTypes, zarrMediaTypes, } from 'stac-js/src/mediatypes.js';
|
|
26
26
|
import { isObject } from 'stac-js/src/utils.js';
|
|
27
27
|
import ErrorEvent from '../events/ErrorEvent.js';
|
|
28
|
+
import { createImageLoadFunction, createTileLoadFunction } from '../http.js';
|
|
28
29
|
import { getProjection } from '../proj.js';
|
|
29
30
|
import SourceType from '../source/type.js';
|
|
30
|
-
import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, getBoundsStyle,
|
|
31
|
+
import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, exceedsDisplayLimit, getBoundsStyle, getDisplayPixels, getGeoTiffSourceInfoFromAsset, getGeoTiffStyleFromAsset, getGeoZarrSourceOptionsFromAsset, getGeoZarrStyleFromAsset, getSpecificWebMapUrl, isScalar, toContinuousBBox, toOlExtent, } from '../util.js';
|
|
32
|
+
import LayerType from './type.js';
|
|
31
33
|
/**
|
|
32
34
|
* @typedef {import("ol/extent.js").Extent} Extent
|
|
33
35
|
*/
|
|
@@ -55,6 +57,18 @@ import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, getBoundsS
|
|
|
55
57
|
/**
|
|
56
58
|
* @typedef {import('../source/type.js').SourceOptions} SourceOptions
|
|
57
59
|
*/
|
|
60
|
+
/**
|
|
61
|
+
* @typedef {import('./type.js').LayerOptions} LayerOptions
|
|
62
|
+
*/
|
|
63
|
+
/**
|
|
64
|
+
* @typedef {import('../http.js').GetHeadersFn} GetHeadersFn
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* @typedef {import('../http.js').OnErrorFn} OnErrorFn
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* @typedef {function((import("ol/Image.js").default|import("ol/Tile.js").default), string): void} LoadFunction
|
|
71
|
+
*/
|
|
58
72
|
/**
|
|
59
73
|
* @typedef {Object} Options
|
|
60
74
|
* @property {string} [url] The STAC URL. Any of `url` and `data` must be provided.
|
|
@@ -75,8 +89,15 @@ import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, getBoundsS
|
|
|
75
89
|
* Optional function that can be used to configure the underlying sources. The function can do any additional work
|
|
76
90
|
* and return the completed options or a promise for the same. The function will be called with the current source options
|
|
77
91
|
* and the STAC Asset or Link.
|
|
78
|
-
* This can be useful for
|
|
79
|
-
*
|
|
92
|
+
* This can be useful for advanced per-source customization such as signed URLs.
|
|
93
|
+
* To add credentials via query parameters, use the `getRequestUrl` option instead;
|
|
94
|
+
* to send credentials via HTTP headers, use the `getRequestHeaders` option instead.
|
|
95
|
+
* @property {function(LayerType, LayerOptions, (Asset|Link)):(LayerOptions|Promise<LayerOptions>)} [getLayerOptions]
|
|
96
|
+
* Optional function that can be used to configure the individual layers that are created for the assets and links.
|
|
97
|
+
* The function can do any additional (asynchronous) work and return the completed options or a promise for the same.
|
|
98
|
+
* The function will be called with the layer type, the current layer options and the STAC Asset or Link.
|
|
99
|
+
* This can be useful to customize the layers, e.g. to apply a style to a GeoTIFF or GeoZarr layer that is
|
|
100
|
+
* loaded from the STAC metadata.
|
|
80
101
|
* @property {boolean} [displayFootprint=true] Allows to hide the footprints (bounding box/geometry) of the STAC object
|
|
81
102
|
* by default.
|
|
82
103
|
* @property {boolean} [displayGeoTiffByDefault=false] Allow to choose non-cloud-optimized GeoTiffs as default image to show,
|
|
@@ -85,8 +106,16 @@ import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, getBoundsS
|
|
|
85
106
|
* i.e. assets with any of the roles `thumbnail`, `overview`, or a link with relation type `preview`.
|
|
86
107
|
* The previews are usually not covering the full extents and as such may be placed incorrectly on the map.
|
|
87
108
|
* For performance reasons, it is recommended to enable this option if you pass in STAC API Items instead of `displayOverview`.
|
|
88
|
-
* @property {boolean} [displayOverview=true] Allow to display COGs
|
|
109
|
+
* @property {boolean} [displayOverview=true] Allow to display COGs, Zarr and, if `displayGeoTiffByDefault` is enabled, GeoTiffs,
|
|
89
110
|
* usually an asset with role `overview` or `visual`.
|
|
111
|
+
* Zarr assets other than Web-Optimized Zarr are only displayed if the STAC metadata declares what to render
|
|
112
|
+
* (see the datacube extension) and the store is within the `maxDisplayPixels` limit.
|
|
113
|
+
* @property {number} [maxDisplayPixels=16777216] The maximum number of pixels the coarsest resolution level
|
|
114
|
+
* of a GeoTIFF or Zarr asset may have to be displayed client-side, as displaying the full extent of an asset
|
|
115
|
+
* loads every tile of that level. Files without (sufficient) overviews can easily exceed this limit.
|
|
116
|
+
* Larger assets are not chosen for the default visualization, and selecting one explicitly through `assets`
|
|
117
|
+
* reports an error through the `error` event (or renders through the tile server if `buildTileUrlTemplate`
|
|
118
|
+
* and `useTileLayerAsFallback` are set). Set to `Infinity` to display assets of any size.
|
|
90
119
|
* @property {string|boolean|Array<Link|string>} [displayWebMapLink=false] Allow to display a layer
|
|
91
120
|
* based on the information provided through the web map links extension.
|
|
92
121
|
* If an array of links or link ids (property `id` in a Link Object) is provided, all corresponding layers will be shown.
|
|
@@ -94,13 +123,19 @@ import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, getBoundsS
|
|
|
94
123
|
* it lets this library choose a web map link to show, but only if no other data is shown.
|
|
95
124
|
* To disable the functionality set this to `false`.
|
|
96
125
|
* @property {import("ol/layer/WebGLTile.js").Style|null} [style=null] The style for GeoTIFF and GeoZarr layers (WebGLTileLayer style).
|
|
126
|
+
* @property {Array<import("ol/color.js").Color|string>|null} [defaultColormap=null] The colors of the colormap
|
|
127
|
+
* that is used for continuous single-band data when neither the STAC metadata nor the `style` option define
|
|
128
|
+
* a coloring. The colors are evenly distributed over the value range of the data (e.g. from the STAC
|
|
129
|
+
* `statistics`). If not set, the data is stretched to grayscale.
|
|
97
130
|
* @property {Style} [boundsStyle] The style for the overall bounds / footprint.
|
|
98
131
|
* @property {Style} [collectionStyle] The style for individual children in a list of STAC Items or Collections.
|
|
99
132
|
* @property {null|string} [crossOrigin] For thumbnails: The `crossOrigin` attribute for loaded images / tiles.
|
|
100
133
|
* See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.
|
|
101
|
-
* @property {function((Asset|Link)):Promise<string>|string|null} [buildTileUrlTemplate=null] A function that generates a URL template for a tile server (XYZ),
|
|
134
|
+
* @property {function((Asset|Link)):Promise<string|null>|string|null} [buildTileUrlTemplate=null] A function that generates a URL template for a tile server (XYZ),
|
|
102
135
|
* which will be used instead of the client-side GeoTIFF rendering (except if `useTileLayerAsFallback` is `true`).
|
|
103
136
|
* The function provided can return a promise (i.e. be async) or a string.
|
|
137
|
+
* The function can return `null` to not pass the given asset or link to the tile server,
|
|
138
|
+
* e.g. to filter by media type or protocol. In this case client-side rendering is used instead.
|
|
104
139
|
* @property {boolean} [useTileLayerAsFallback=false] Uses the given URL template only when the client-side GeoTIFF rendering fails.
|
|
105
140
|
* @property {number} [opacity=1] Opacity (0, 1).
|
|
106
141
|
* @property {boolean} [visible=true] Visibility.
|
|
@@ -124,6 +159,22 @@ import { LABEL_EXTENSION, defaultBoundsStyle, defaultCollectionStyle, getBoundsS
|
|
|
124
159
|
* @property {function(string,string):(*)} [httpRequestFn=null] Sets a custom function to make HTTP requests with.
|
|
125
160
|
* The first parameter is the URL to request and the output is a promise that resolves with the response body.
|
|
126
161
|
* The second parameter is the return type, either `json` (default) or `text`.
|
|
162
|
+
* The STAC Asset or Link the request is made for is passed as third parameter, if available.
|
|
163
|
+
* @property {Object<string, string>|function((Asset|Link|STACObject|null), string):(Object<string, string>|null)} [getRequestHeaders=null]
|
|
164
|
+
* The HTTP headers (e.g. for authentication) to send with the requests made by this layer,
|
|
165
|
+
* either as a plain object or as a function that returns the headers (or `null` for none) and
|
|
166
|
+
* is called with the STAC Asset or Link that is shown (if available) and the URL that is requested.
|
|
167
|
+
* Use a function to restrict the headers to specific hosts, as tile server URLs and asset URLs
|
|
168
|
+
* may point to hosts that should not receive the credentials.
|
|
169
|
+
* The headers are attached to requests made by the default `httpRequestFn`, to GeoTIFF, GeoZarr
|
|
170
|
+
* and PMTiles requests, and via image/tile load functions (through the Fetch API and object URLs)
|
|
171
|
+
* to preview images and XYZ, TileJSON, WMS and WMTS tiles.
|
|
172
|
+
* @property {function((Asset|Link|STACObject|null), string):(string|null)} [getRequestUrl=null]
|
|
173
|
+
* Rewrites a URL before a request is made or a source is created, e.g. to append query
|
|
174
|
+
* parameters for authentication (signed URLs, API keys). The function is called with the
|
|
175
|
+
* STAC Asset or Link that is shown (if available) and the URL, and returns the new URL or
|
|
176
|
+
* `null` to keep the URL unchanged. The rewrite is applied before `getSourceOptions` is called.
|
|
177
|
+
* For tiled sources the tile URL template is rewritten, not the individual tile URLs.
|
|
127
178
|
*/
|
|
128
179
|
/**
|
|
129
180
|
* @classdesc
|
|
@@ -159,6 +210,21 @@ class STACLayer extends LayerGroup {
|
|
|
159
210
|
* @private
|
|
160
211
|
*/
|
|
161
212
|
this.getSourceOptions_ = options.getSourceOptions;
|
|
213
|
+
/**
|
|
214
|
+
* @type {function(LayerType, LayerOptions, (Asset|Link)):(LayerOptions|Promise<LayerOptions>)}
|
|
215
|
+
* @private
|
|
216
|
+
*/
|
|
217
|
+
this.getLayerOptions_ = options.getLayerOptions;
|
|
218
|
+
/**
|
|
219
|
+
* @type {Object<string, string>|function((Asset|Link|STACObject|null), string):(Object<string, string>|null)|null}
|
|
220
|
+
* @private
|
|
221
|
+
*/
|
|
222
|
+
this.getRequestHeaders_ = options.getRequestHeaders || null;
|
|
223
|
+
/**
|
|
224
|
+
* @type {function((Asset|Link|STACObject|null), string):(string|null)|null}
|
|
225
|
+
* @private
|
|
226
|
+
*/
|
|
227
|
+
this.getRequestUrl_ = options.getRequestUrl || null;
|
|
162
228
|
/**
|
|
163
229
|
* @type {Array<STAC>|null}
|
|
164
230
|
* @private
|
|
@@ -209,7 +275,12 @@ class STACLayer extends LayerGroup {
|
|
|
209
275
|
*/
|
|
210
276
|
this.displayWebMapLink_ = options.displayWebMapLink || false;
|
|
211
277
|
/**
|
|
212
|
-
* @type {
|
|
278
|
+
* @type {number|undefined}
|
|
279
|
+
* @private
|
|
280
|
+
*/
|
|
281
|
+
this.maxDisplayPixels_ = options.maxDisplayPixels;
|
|
282
|
+
/**
|
|
283
|
+
* @type {function((Asset|Link)):Promise<string|null>|string|null}
|
|
213
284
|
* @private
|
|
214
285
|
*/
|
|
215
286
|
this.buildTileUrlTemplate_ = options.buildTileUrlTemplate || null;
|
|
@@ -223,6 +294,11 @@ class STACLayer extends LayerGroup {
|
|
|
223
294
|
* @private
|
|
224
295
|
*/
|
|
225
296
|
this.style_ = options.style || null;
|
|
297
|
+
/**
|
|
298
|
+
* @type {Array<import("ol/color.js").Color|string>|null}
|
|
299
|
+
* @private
|
|
300
|
+
*/
|
|
301
|
+
this.defaultColormap_ = options.defaultColormap || null;
|
|
226
302
|
/**
|
|
227
303
|
* @type {Style}
|
|
228
304
|
* @private
|
|
@@ -268,19 +344,70 @@ class STACLayer extends LayerGroup {
|
|
|
268
344
|
if (!options.url) {
|
|
269
345
|
throw new Error('Either url or data must be provided');
|
|
270
346
|
}
|
|
271
|
-
this.fetch_(options.url)
|
|
347
|
+
this.fetch_(this.getRequestUrlFor_(options.url))
|
|
272
348
|
.then((data) => this.configure_(data, options.url, options.children, options.assets, options.bands))
|
|
273
349
|
.catch((error) => this.handleError_(error));
|
|
274
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Rewrites the given URL based on the `getRequestUrl` option.
|
|
353
|
+
*
|
|
354
|
+
* @param {string} url The URL that is requested.
|
|
355
|
+
* @param {Asset|Link|STACObject|null} [ref] The STAC Asset or Link that is shown, if available.
|
|
356
|
+
* @return {string} The rewritten URL, or the given URL if it is not rewritten.
|
|
357
|
+
*/
|
|
358
|
+
getRequestUrlFor_(url, ref = null) {
|
|
359
|
+
if (typeof this.getRequestUrl_ === 'function' && typeof url === 'string') {
|
|
360
|
+
const newUrl = this.getRequestUrl_(ref, url);
|
|
361
|
+
if (typeof newUrl === 'string' && newUrl.length > 0) {
|
|
362
|
+
return newUrl;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return url;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Returns the HTTP headers to send for the given URL, based on the
|
|
369
|
+
* `getRequestHeaders` option.
|
|
370
|
+
*
|
|
371
|
+
* @param {string} url The URL that is requested.
|
|
372
|
+
* @param {Asset|Link|STACObject|null} [ref] The STAC Asset or Link that is shown, if available.
|
|
373
|
+
* @return {Object<string, string>|null} The headers, or `null` if there are none.
|
|
374
|
+
*/
|
|
375
|
+
getRequestHeadersFor_(url, ref = null) {
|
|
376
|
+
let headers = this.getRequestHeaders_;
|
|
377
|
+
if (typeof headers === 'function') {
|
|
378
|
+
headers = headers(ref, url);
|
|
379
|
+
}
|
|
380
|
+
if (isObject(headers) && Object.keys(headers).length > 0) {
|
|
381
|
+
return /** @type {Object<string, string>} */ (headers);
|
|
382
|
+
}
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Creates a load function for images or tiles that attaches the headers
|
|
387
|
+
* from the `getRequestHeaders` option and reports errors through the
|
|
388
|
+
* layer's error event, or `undefined` if no headers are configured.
|
|
389
|
+
*
|
|
390
|
+
* @param {function(GetHeadersFn, OnErrorFn=):LoadFunction} factory `createImageLoadFunction` or `createTileLoadFunction`.
|
|
391
|
+
* @param {Asset|Link|STACObject|null} ref The STAC Asset or Link that is shown, if available.
|
|
392
|
+
* @return {LoadFunction|undefined} The load function.
|
|
393
|
+
*/
|
|
394
|
+
createLoadFunction_(factory, ref) {
|
|
395
|
+
if (!this.getRequestHeaders_) {
|
|
396
|
+
return undefined;
|
|
397
|
+
}
|
|
398
|
+
return factory((url) => this.getRequestHeadersFor_(url, ref), (error) => this.handleError_(error));
|
|
399
|
+
}
|
|
275
400
|
/**
|
|
276
401
|
* Default function make HTTP requests with.
|
|
277
402
|
*
|
|
278
403
|
* @param {string} url The URL to request and the output is a promise that resolves with the response body.
|
|
279
404
|
* @param {string} responseType The return type, either `json` (default) or `text`.
|
|
405
|
+
* @param {Asset|Link|STACObject|null} [ref] The STAC Asset or Link the request is made for, if available.
|
|
280
406
|
* @return {Promise<*>} The (parsed) response body.
|
|
281
407
|
*/
|
|
282
|
-
async fetch_(url, responseType = 'json') {
|
|
283
|
-
const
|
|
408
|
+
async fetch_(url, responseType = 'json', ref = null) {
|
|
409
|
+
const headers = this.getRequestHeadersFor_(url, ref);
|
|
410
|
+
const response = await fetch(url, headers ? { headers } : undefined);
|
|
284
411
|
if (!response.ok) {
|
|
285
412
|
throw new Error(`Unexpected response from ${url}: ${response.status}`);
|
|
286
413
|
}
|
|
@@ -478,18 +605,21 @@ class STACLayer extends LayerGroup {
|
|
|
478
605
|
* @type {import("ol/source/ImageStatic.js").Options}
|
|
479
606
|
*/
|
|
480
607
|
let options = {
|
|
481
|
-
url: image.getAbsoluteUrl(),
|
|
608
|
+
url: this.getRequestUrlFor_(image.getAbsoluteUrl(), image),
|
|
482
609
|
projection,
|
|
483
610
|
imageExtent: toOlExtent(bbox, projection),
|
|
484
611
|
crossOrigin: this.crossOrigin_,
|
|
485
612
|
};
|
|
613
|
+
const imageLoadFunction = this.createLoadFunction_(createImageLoadFunction, image);
|
|
614
|
+
if (imageLoadFunction) {
|
|
615
|
+
options.imageLoadFunction = imageLoadFunction;
|
|
616
|
+
}
|
|
486
617
|
if (this.getSourceOptions_) {
|
|
487
618
|
// @ts-ignore
|
|
488
619
|
options = await this.getSourceOptions_(SourceType.ImageStatic, options, image);
|
|
489
620
|
}
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
});
|
|
621
|
+
const layerOptions = await this.updateLayerOptions_(LayerType.Image, { source: new StaticImage(options) }, image);
|
|
622
|
+
const layer = new ImageLayer(layerOptions);
|
|
493
623
|
this.addLayer_(layer, image);
|
|
494
624
|
return layer;
|
|
495
625
|
}
|
|
@@ -503,16 +633,21 @@ class STACLayer extends LayerGroup {
|
|
|
503
633
|
*/
|
|
504
634
|
async addLayerForLink(link) {
|
|
505
635
|
// Replace any occurances of {s} if possible, otherwise return
|
|
506
|
-
|
|
636
|
+
let url = getSpecificWebMapUrl(link);
|
|
507
637
|
if (!url) {
|
|
508
638
|
return;
|
|
509
639
|
}
|
|
640
|
+
url = this.getRequestUrlFor_(url, link);
|
|
510
641
|
const options = {
|
|
511
642
|
attributions: link.getMetadata('attribution') ||
|
|
512
643
|
this.getData().getMetadata('attribution'),
|
|
513
644
|
crossOrigin: this.crossOrigin_,
|
|
514
645
|
url,
|
|
515
646
|
};
|
|
647
|
+
const tileLoadFunction = this.createLoadFunction_(createTileLoadFunction, link);
|
|
648
|
+
if (tileLoadFunction && link.rel !== 'pmtiles') {
|
|
649
|
+
options.tileLoadFunction = tileLoadFunction;
|
|
650
|
+
}
|
|
516
651
|
const updateOptions = async (type, options) => {
|
|
517
652
|
if (this.getSourceOptions_) {
|
|
518
653
|
options = await this.getSourceOptions_(type, options, link);
|
|
@@ -521,28 +656,82 @@ class STACLayer extends LayerGroup {
|
|
|
521
656
|
};
|
|
522
657
|
const sources = [];
|
|
523
658
|
switch (link.rel) {
|
|
524
|
-
case 'pmtiles':
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
let
|
|
528
|
-
|
|
659
|
+
case 'pmtiles': {
|
|
660
|
+
const snapshot = JSON.stringify(options);
|
|
661
|
+
/** @type {*} */
|
|
662
|
+
let pmOptions = await updateOptions(SourceType.PMTiles, options);
|
|
663
|
+
// Whether getSourceOptions reacted to SourceType.PMTiles,
|
|
664
|
+
// see the backward compatibility handling below
|
|
665
|
+
const handled = JSON.stringify(pmOptions) !== snapshot;
|
|
666
|
+
const headers = this.getRequestHeadersFor_(pmOptions.url, link);
|
|
667
|
+
const withHeaders = (url) => headers && typeof url === 'string'
|
|
668
|
+
? new pmtiles.FetchSource(url, new Headers(headers))
|
|
669
|
+
: url;
|
|
670
|
+
let pmtilesHeader;
|
|
671
|
+
try {
|
|
672
|
+
const p = new pmtiles.PMTiles(withHeaders(pmOptions.url));
|
|
673
|
+
pmtilesHeader = await p.getHeader();
|
|
674
|
+
}
|
|
675
|
+
catch (error) {
|
|
676
|
+
this.handleError_(error);
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
let type;
|
|
680
|
+
switch (pmtilesHeader.tileType) {
|
|
529
681
|
case pmtiles.TileType.Mvt:
|
|
530
|
-
|
|
682
|
+
type = SourceType.PMTilesVector;
|
|
531
683
|
break;
|
|
532
684
|
case pmtiles.TileType.Avif:
|
|
533
685
|
case pmtiles.TileType.Jpeg:
|
|
534
686
|
case pmtiles.TileType.Png:
|
|
535
687
|
case pmtiles.TileType.Webp:
|
|
536
|
-
|
|
688
|
+
type = SourceType.PMTilesRaster;
|
|
537
689
|
break;
|
|
538
690
|
default:
|
|
539
691
|
return; // Unsupported
|
|
540
692
|
}
|
|
693
|
+
if (!handled) {
|
|
694
|
+
// Backward compatibility for getSourceOptions callbacks that don't
|
|
695
|
+
// handle SourceType.PMTiles yet: call them with the deprecated
|
|
696
|
+
// type-specific source type once the tile type is known.
|
|
697
|
+
// As before v1.6.0, these rewrites don't apply to the tile type
|
|
698
|
+
// sniff above. TODO: Remove in 2.0.0
|
|
699
|
+
pmOptions = await updateOptions(type, pmOptions);
|
|
700
|
+
}
|
|
701
|
+
pmOptions.url = withHeaders(pmOptions.url);
|
|
702
|
+
const source = type === SourceType.PMTilesVector
|
|
703
|
+
? new PMTilesVectorSource(pmOptions)
|
|
704
|
+
: new PMTilesRasterSource(pmOptions);
|
|
541
705
|
sources.push(source);
|
|
542
706
|
break;
|
|
543
|
-
|
|
544
|
-
|
|
707
|
+
}
|
|
708
|
+
case 'tilejson': {
|
|
709
|
+
/** @type {*} */
|
|
710
|
+
const tjOptions = await updateOptions(SourceType.TileJSON, options);
|
|
711
|
+
if (tjOptions.jsonp || tjOptions.tileJSON) {
|
|
712
|
+
// Let the source load the manifest itself (e.g. via JSONP)
|
|
713
|
+
sources.push(new TileJSON(tjOptions));
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
716
|
+
// Load the manifest through the request function so that
|
|
717
|
+
// credentials are attached
|
|
718
|
+
let tileJSON;
|
|
719
|
+
try {
|
|
720
|
+
tileJSON = await this.fetch_(tjOptions.url, 'json', link);
|
|
721
|
+
}
|
|
722
|
+
catch (error) {
|
|
723
|
+
this.handleError_(error);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
if (isObject(tileJSON) && Array.isArray(tileJSON.tiles)) {
|
|
727
|
+
// The tile templates from the manifest must be rewritten as well
|
|
728
|
+
tileJSON.tiles = tileJSON.tiles.map((template) => this.getRequestUrlFor_(template, link));
|
|
729
|
+
}
|
|
730
|
+
delete tjOptions.url;
|
|
731
|
+
tjOptions.tileJSON = tileJSON;
|
|
732
|
+
sources.push(new TileJSON(tjOptions));
|
|
545
733
|
break;
|
|
734
|
+
}
|
|
546
735
|
case 'wms':
|
|
547
736
|
if (!Array.isArray(link['wms:layers'])) {
|
|
548
737
|
break;
|
|
@@ -569,7 +758,7 @@ class STACLayer extends LayerGroup {
|
|
|
569
758
|
}
|
|
570
759
|
break;
|
|
571
760
|
case 'wmts':
|
|
572
|
-
const wmtsCapabilities = await this.getWmtsCapabilities_(url, link['wmts:encoding']);
|
|
761
|
+
const wmtsCapabilities = await this.getWmtsCapabilities_(url, link, link['wmts:encoding']);
|
|
573
762
|
if (!wmtsCapabilities) {
|
|
574
763
|
return;
|
|
575
764
|
}
|
|
@@ -593,6 +782,10 @@ class STACLayer extends LayerGroup {
|
|
|
593
782
|
if (opts === null) {
|
|
594
783
|
continue;
|
|
595
784
|
}
|
|
785
|
+
if (wmtsOptions.tileLoadFunction) {
|
|
786
|
+
// Not passed through by optionsFromCapabilities
|
|
787
|
+
opts.tileLoadFunction = wmtsOptions.tileLoadFunction;
|
|
788
|
+
}
|
|
596
789
|
if (typeof link.uriTemplate === 'string') {
|
|
597
790
|
let uriTemplate = link.uriTemplate;
|
|
598
791
|
const vars = isObject(link.variables) ? link.variables : {};
|
|
@@ -616,7 +809,7 @@ class STACLayer extends LayerGroup {
|
|
|
616
809
|
}
|
|
617
810
|
}
|
|
618
811
|
delete opts.urls;
|
|
619
|
-
opts.url = uriTemplate;
|
|
812
|
+
opts.url = this.getRequestUrlFor_(uriTemplate, link);
|
|
620
813
|
}
|
|
621
814
|
sources.push(new WMTS(opts));
|
|
622
815
|
}
|
|
@@ -627,34 +820,42 @@ class STACLayer extends LayerGroup {
|
|
|
627
820
|
default:
|
|
628
821
|
return;
|
|
629
822
|
}
|
|
630
|
-
return sources.map((source) => {
|
|
823
|
+
return await Promise.all(sources.map(async (source) => {
|
|
631
824
|
let layer;
|
|
632
825
|
if (source instanceof VectorTileSource) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
declutter: true,
|
|
636
|
-
});
|
|
826
|
+
const layerOptions = await this.updateLayerOptions_(LayerType.VectorTile, { source, declutter: true }, link);
|
|
827
|
+
layer = new VectorTileLayer(layerOptions);
|
|
637
828
|
}
|
|
638
829
|
else if (source instanceof PMTilesRasterSource) {
|
|
639
|
-
|
|
830
|
+
const layerOptions = await this.updateLayerOptions_(LayerType.WebGLTile, { source }, link);
|
|
831
|
+
layer = new WebGLTileLayer(layerOptions);
|
|
640
832
|
}
|
|
641
833
|
else {
|
|
642
|
-
|
|
834
|
+
const layerOptions = await this.updateLayerOptions_(LayerType.Tile, { source }, link);
|
|
835
|
+
layer = new TileLayer(layerOptions);
|
|
643
836
|
}
|
|
644
837
|
this.addLayer_(layer, link);
|
|
645
838
|
return layer;
|
|
646
|
-
});
|
|
839
|
+
}));
|
|
647
840
|
}
|
|
648
841
|
/**
|
|
649
842
|
* @param {Asset} [asset] A STAC Asset
|
|
843
|
+
* @param {boolean} [autoDisplay] Whether the asset was chosen automatically
|
|
844
|
+
* (not explicitly requested): skip it silently instead of reporting an
|
|
845
|
+
* error when it can't be displayed within the configured limits.
|
|
650
846
|
* @return {Promise<Layer|undefined>} Resolves with a Layer or undefined when complete.
|
|
651
847
|
* @private
|
|
652
848
|
*/
|
|
653
|
-
async addGeoTiff_(asset) {
|
|
849
|
+
async addGeoTiff_(asset, autoDisplay = false) {
|
|
654
850
|
if (this.buildTileUrlTemplate_ && !this.useTileLayerAsFallback_) {
|
|
655
|
-
|
|
851
|
+
const layer = await this.addTileLayerForImagery_(asset);
|
|
852
|
+
// If no tile server URL was provided for the asset, continue with client-side rendering
|
|
853
|
+
if (layer) {
|
|
854
|
+
return layer;
|
|
855
|
+
}
|
|
656
856
|
}
|
|
657
857
|
const sourceInfo = getGeoTiffSourceInfoFromAsset(asset, this.bands_);
|
|
858
|
+
sourceInfo.url = this.getRequestUrlFor_(sourceInfo.url, asset);
|
|
658
859
|
/**
|
|
659
860
|
* @type {import("ol/source/GeoTIFF.js").Options}
|
|
660
861
|
*/
|
|
@@ -667,10 +868,14 @@ class STACLayer extends LayerGroup {
|
|
|
667
868
|
if (projection) {
|
|
668
869
|
options.projection = projection;
|
|
669
870
|
}
|
|
670
|
-
const
|
|
671
|
-
if (
|
|
871
|
+
const metadataStyle = getGeoTiffStyleFromAsset(asset, sourceInfo, this.defaultColormap_);
|
|
872
|
+
if (metadataStyle) {
|
|
672
873
|
options.normalize = false;
|
|
673
874
|
}
|
|
875
|
+
const headers = this.getRequestHeadersFor_(sourceInfo.url, asset);
|
|
876
|
+
if (headers) {
|
|
877
|
+
options.sourceOptions = { headers };
|
|
878
|
+
}
|
|
674
879
|
if (this.getSourceOptions_) {
|
|
675
880
|
// @ts-ignore
|
|
676
881
|
options = await this.getSourceOptions_(SourceType.GeoTIFF, options, asset);
|
|
@@ -690,34 +895,51 @@ class STACLayer extends LayerGroup {
|
|
|
690
895
|
});
|
|
691
896
|
try {
|
|
692
897
|
await status;
|
|
693
|
-
|
|
898
|
+
if (this.checkDisplayLimit_(source, asset, autoDisplay)) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* @type {import("ol/layer/WebGLTile.js").Options}
|
|
903
|
+
*/
|
|
904
|
+
let layerOptions = { source };
|
|
694
905
|
if (this.style_) {
|
|
695
906
|
layerOptions.style = this.style_;
|
|
696
907
|
}
|
|
697
|
-
else if (
|
|
698
|
-
layerOptions.style =
|
|
908
|
+
else if (metadataStyle) {
|
|
909
|
+
layerOptions.style = metadataStyle;
|
|
699
910
|
}
|
|
911
|
+
layerOptions = await this.updateLayerOptions_(LayerType.WebGLTile, layerOptions, asset);
|
|
700
912
|
const layer = new WebGLTileLayer(layerOptions);
|
|
701
913
|
this.addLayer_(layer, asset);
|
|
702
914
|
return layer;
|
|
703
915
|
}
|
|
704
916
|
catch (error) {
|
|
705
917
|
if (this.useTileLayerAsFallback_) {
|
|
706
|
-
|
|
918
|
+
const layer = await this.addTileLayerForImagery_(asset);
|
|
919
|
+
if (layer) {
|
|
920
|
+
return layer;
|
|
921
|
+
}
|
|
707
922
|
}
|
|
708
923
|
this.handleError_(error);
|
|
709
924
|
}
|
|
710
925
|
}
|
|
711
926
|
/**
|
|
712
927
|
* @param {Asset|Link} [data] A STAC Asset or Link
|
|
713
|
-
* @return {Promise<TileLayer>} Resolves with a TileLayer
|
|
928
|
+
* @return {Promise<TileLayer|undefined>} Resolves with a TileLayer, or undefined if no tile server URL was provided.
|
|
714
929
|
* @private
|
|
715
930
|
*/
|
|
716
931
|
async addTileLayerForImagery_(data) {
|
|
932
|
+
if (typeof this.buildTileUrlTemplate_ !== 'function') {
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
717
935
|
let url = this.buildTileUrlTemplate_(data);
|
|
718
936
|
if (url instanceof Promise) {
|
|
719
937
|
url = await url;
|
|
720
938
|
}
|
|
939
|
+
if (!url) {
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
url = this.getRequestUrlFor_(url, data);
|
|
721
943
|
/**
|
|
722
944
|
* @type {import("ol/source/XYZ.js").Options}
|
|
723
945
|
*/
|
|
@@ -725,15 +947,33 @@ class STACLayer extends LayerGroup {
|
|
|
725
947
|
crossOrigin: this.crossOrigin_,
|
|
726
948
|
url,
|
|
727
949
|
};
|
|
950
|
+
const tileLoadFunction = this.createLoadFunction_(createTileLoadFunction, data);
|
|
951
|
+
if (tileLoadFunction) {
|
|
952
|
+
options.tileLoadFunction = tileLoadFunction;
|
|
953
|
+
}
|
|
728
954
|
if (this.getSourceOptions_) {
|
|
729
955
|
options = await this.getSourceOptions_(SourceType.XYZ, options, data);
|
|
730
956
|
}
|
|
731
|
-
const
|
|
732
|
-
|
|
733
|
-
});
|
|
957
|
+
const layerOptions = await this.updateLayerOptions_(LayerType.Tile, { source: new XYZ(options) }, data);
|
|
958
|
+
const layer = new TileLayer(layerOptions);
|
|
734
959
|
this.addLayer_(layer, data);
|
|
735
960
|
return layer;
|
|
736
961
|
}
|
|
962
|
+
/**
|
|
963
|
+
* Passes the layer options through the `getLayerOptions` function, if given.
|
|
964
|
+
*
|
|
965
|
+
* @param {LayerType} type The type of the layer that is going to be created.
|
|
966
|
+
* @param {LayerOptions} options The layer options.
|
|
967
|
+
* @param {Asset|Link} reference The STAC Asset or Link the layer is created for.
|
|
968
|
+
* @return {Promise<*>} The updated layer options.
|
|
969
|
+
* @private
|
|
970
|
+
*/
|
|
971
|
+
async updateLayerOptions_(type, options, reference) {
|
|
972
|
+
if (this.getLayerOptions_) {
|
|
973
|
+
options = await this.getLayerOptions_(type, options, reference);
|
|
974
|
+
}
|
|
975
|
+
return options;
|
|
976
|
+
}
|
|
737
977
|
/**
|
|
738
978
|
* @param {Layer|LayerGroup} [layer] A Layer to add to the LayerGroup
|
|
739
979
|
* @param {STACObject} [data] The STAC object, can be any class exposed by stac-js
|
|
@@ -766,7 +1006,7 @@ class STACLayer extends LayerGroup {
|
|
|
766
1006
|
geojson = data.toGeoJSON(fixAntimeridian);
|
|
767
1007
|
}
|
|
768
1008
|
if (geojson) {
|
|
769
|
-
const layer = this.
|
|
1009
|
+
const layer = new VectorLayer(this.getGeoJsonLayerOptions_(geojson, getBoundsStyle(this.boundsStyle_, this), this.displayFootprint_));
|
|
770
1010
|
layer.set('bounds', true);
|
|
771
1011
|
layer.on('change', () => this.setMap_(layer.getMapInternal()));
|
|
772
1012
|
this.addLayer_(layer, data, 1);
|
|
@@ -781,8 +1021,9 @@ class STACLayer extends LayerGroup {
|
|
|
781
1021
|
*/
|
|
782
1022
|
async addGeoJson_(asset) {
|
|
783
1023
|
try {
|
|
784
|
-
const geojson = await this.fetch_(asset.getAbsoluteUrl());
|
|
785
|
-
const
|
|
1024
|
+
const geojson = await this.fetch_(this.getRequestUrlFor_(asset.getAbsoluteUrl(), asset), 'json', asset);
|
|
1025
|
+
const layerOptions = await this.updateLayerOptions_(LayerType.Vector, this.getGeoJsonLayerOptions_(geojson), asset);
|
|
1026
|
+
const layer = new VectorLayer(layerOptions);
|
|
786
1027
|
this.addLayer_(layer, asset);
|
|
787
1028
|
return layer;
|
|
788
1029
|
}
|
|
@@ -791,15 +1032,15 @@ class STACLayer extends LayerGroup {
|
|
|
791
1032
|
}
|
|
792
1033
|
}
|
|
793
1034
|
/**
|
|
794
|
-
* Creates a GeoJSON vector layer from the given GeoJSON object.
|
|
1035
|
+
* Creates the options for a GeoJSON vector layer from the given GeoJSON object.
|
|
795
1036
|
*
|
|
796
1037
|
* @param {GeoJSON} [geojson] The GeoJSON object.
|
|
797
1038
|
* @param {Style} [style] The style for the layer.
|
|
798
1039
|
* @param {boolean} [visible] Whether the layer is visible.
|
|
799
|
-
* @return {
|
|
1040
|
+
* @return {import("ol/layer/Vector.js").Options} The vector layer options.
|
|
800
1041
|
* @private
|
|
801
1042
|
*/
|
|
802
|
-
|
|
1043
|
+
getGeoJsonLayerOptions_(geojson, style = null, visible = true) {
|
|
803
1044
|
const format = new GeoJSON();
|
|
804
1045
|
const source = new VectorSource({
|
|
805
1046
|
format,
|
|
@@ -814,7 +1055,7 @@ class STACLayer extends LayerGroup {
|
|
|
814
1055
|
if (!style) {
|
|
815
1056
|
style = defaultCollectionStyle;
|
|
816
1057
|
}
|
|
817
|
-
return
|
|
1058
|
+
return { source, style, visible };
|
|
818
1059
|
}
|
|
819
1060
|
/**
|
|
820
1061
|
* Adds GeoJSON labels and GeoTIFF source imagery to the map based on the label extension.
|
|
@@ -849,7 +1090,7 @@ class STACLayer extends LayerGroup {
|
|
|
849
1090
|
if (labelAsset && sourceLinks.length > 0) {
|
|
850
1091
|
const promises = sourceLinks.map(async (link) => {
|
|
851
1092
|
try {
|
|
852
|
-
const response = await this.fetch_(link.getAbsoluteUrl());
|
|
1093
|
+
const response = await this.fetch_(this.getRequestUrlFor_(link.getAbsoluteUrl(), link), 'json', link);
|
|
853
1094
|
const stac = create(response);
|
|
854
1095
|
return stac;
|
|
855
1096
|
}
|
|
@@ -869,17 +1110,78 @@ class STACLayer extends LayerGroup {
|
|
|
869
1110
|
this.handleError_(error);
|
|
870
1111
|
}
|
|
871
1112
|
}
|
|
872
|
-
|
|
1113
|
+
/**
|
|
1114
|
+
* Checks the `maxDisplayPixels` limit for the given source.
|
|
1115
|
+
* Returns `true` when the layer must not be added: automatically chosen
|
|
1116
|
+
* assets are limited silently, for explicitly requested assets an error
|
|
1117
|
+
* is thrown so that callers can fall back or report it.
|
|
1118
|
+
* @param {import('ol/source/Tile.js').default} source The configured (ready) source.
|
|
1119
|
+
* @param {Asset} asset The asset the source was created for.
|
|
1120
|
+
* @param {boolean} autoDisplay Whether the asset was chosen automatically.
|
|
1121
|
+
* @return {boolean} `true` if the asset must not be displayed.
|
|
1122
|
+
* @private
|
|
1123
|
+
*/
|
|
1124
|
+
checkDisplayLimit_(source, asset, autoDisplay) {
|
|
1125
|
+
if (!exceedsDisplayLimit(source, this.maxDisplayPixels_)) {
|
|
1126
|
+
return false;
|
|
1127
|
+
}
|
|
1128
|
+
if (!autoDisplay) {
|
|
1129
|
+
const megapixels = Math.ceil(getDisplayPixels(source) / 1048576);
|
|
1130
|
+
const error = new Error(`Asset ${asset.getKey()} is too large to display safely` +
|
|
1131
|
+
` (~${megapixels} megapixels at the coarsest resolution);` +
|
|
1132
|
+
` set the maxDisplayPixels option to display it anyway`);
|
|
1133
|
+
// Allows applications to detect the error without matching the message
|
|
1134
|
+
error.name = 'DisplayLimitError';
|
|
1135
|
+
throw error;
|
|
1136
|
+
}
|
|
1137
|
+
return true;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Adds a layer for a GeoZarr asset.
|
|
1141
|
+
* @param {Asset} asset The Zarr asset to show.
|
|
1142
|
+
* @param {boolean} [autoDisplay] Whether the asset was chosen automatically
|
|
1143
|
+
* (not explicitly requested): skip it silently instead of reporting an
|
|
1144
|
+
* error when it doesn't declare what to render or can't be displayed
|
|
1145
|
+
* within the configured limits.
|
|
1146
|
+
* @return {Promise<Layer|undefined>} The layer, if one was added.
|
|
1147
|
+
* @private
|
|
1148
|
+
*/
|
|
1149
|
+
async addGeoZarr_(asset, autoDisplay = false) {
|
|
873
1150
|
if (this.buildTileUrlTemplate_ && !this.useTileLayerAsFallback_) {
|
|
874
|
-
|
|
1151
|
+
const layer = await this.addTileLayerForImagery_(asset);
|
|
1152
|
+
// If no tile server URL was provided for the asset, continue with client-side rendering
|
|
1153
|
+
if (layer) {
|
|
1154
|
+
return layer;
|
|
1155
|
+
}
|
|
875
1156
|
}
|
|
876
1157
|
let options = getGeoZarrSourceOptionsFromAsset(asset, this.bands_);
|
|
1158
|
+
// Web-Optimized Zarr describes its bands in the store metadata,
|
|
1159
|
+
// everything else must declare what to render in the STAC metadata
|
|
1160
|
+
// (or provide it through getSourceOptions for explicitly selected assets)
|
|
1161
|
+
const declaresRendering = () => asset.isType(wozMediaTypes) ||
|
|
1162
|
+
Boolean(options.variable) ||
|
|
1163
|
+
Boolean(options.bands && options.bands.length > 0);
|
|
1164
|
+
if (autoDisplay && !declaresRendering()) {
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
options.url = this.getRequestUrlFor_(options.url, asset);
|
|
1168
|
+
const projection = await getProjection(asset);
|
|
1169
|
+
if (projection) {
|
|
1170
|
+
options.projection = projection;
|
|
1171
|
+
}
|
|
1172
|
+
const headers = this.getRequestHeadersFor_(options.url, asset);
|
|
1173
|
+
if (headers) {
|
|
1174
|
+
options.storeOptions = { headers };
|
|
1175
|
+
}
|
|
877
1176
|
if (this.getSourceOptions_) {
|
|
878
1177
|
// @ts-ignore
|
|
879
1178
|
options = await this.getSourceOptions_(SourceType.GeoZarr, options, asset);
|
|
880
1179
|
}
|
|
881
1180
|
try {
|
|
882
|
-
|
|
1181
|
+
if (!declaresRendering()) {
|
|
1182
|
+
throw new Error(`Asset ${asset.getKey()} declares neither bands nor a datacube variable to render`);
|
|
1183
|
+
}
|
|
1184
|
+
const GeoZarr = (await import('../source/GeoZarr.js')).default;
|
|
883
1185
|
const source = new GeoZarr(options);
|
|
884
1186
|
await new Promise((resolve, reject) => {
|
|
885
1187
|
source.on('change', () => {
|
|
@@ -891,17 +1193,33 @@ class STACLayer extends LayerGroup {
|
|
|
891
1193
|
}
|
|
892
1194
|
});
|
|
893
1195
|
});
|
|
894
|
-
|
|
1196
|
+
if (this.checkDisplayLimit_(source, asset, autoDisplay)) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* @type {import("ol/layer/WebGLTile.js").Options}
|
|
1201
|
+
*/
|
|
1202
|
+
let layerOptions = { source };
|
|
895
1203
|
if (this.style_) {
|
|
896
1204
|
layerOptions.style = this.style_;
|
|
897
1205
|
}
|
|
1206
|
+
else {
|
|
1207
|
+
const style = getGeoZarrStyleFromAsset(asset, options, this.defaultColormap_);
|
|
1208
|
+
if (style) {
|
|
1209
|
+
layerOptions.style = style;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
layerOptions = await this.updateLayerOptions_(LayerType.WebGLTile, layerOptions, asset);
|
|
898
1213
|
const layer = new WebGLTileLayer(layerOptions);
|
|
899
1214
|
this.addLayer_(layer, asset);
|
|
900
1215
|
return layer;
|
|
901
1216
|
}
|
|
902
1217
|
catch (error) {
|
|
903
1218
|
if (this.useTileLayerAsFallback_) {
|
|
904
|
-
|
|
1219
|
+
const layer = await this.addTileLayerForImagery_(asset);
|
|
1220
|
+
if (layer) {
|
|
1221
|
+
return layer;
|
|
1222
|
+
}
|
|
905
1223
|
}
|
|
906
1224
|
this.handleError_(error);
|
|
907
1225
|
}
|
|
@@ -946,7 +1264,7 @@ class STACLayer extends LayerGroup {
|
|
|
946
1264
|
if (ref.isType(geotiffMediaTypes)) {
|
|
947
1265
|
return await this.addGeoTiff_(ref);
|
|
948
1266
|
}
|
|
949
|
-
if (ref.isType(
|
|
1267
|
+
if (ref.isType(zarrMediaTypes)) {
|
|
950
1268
|
return await this.addGeoZarr_(ref);
|
|
951
1269
|
}
|
|
952
1270
|
if (ref.canBrowserDisplayImage()) {
|
|
@@ -978,14 +1296,13 @@ class STACLayer extends LayerGroup {
|
|
|
978
1296
|
// Find a GeoTiff asset that we can visualize
|
|
979
1297
|
const geotiff = data.getDefaultGeoFile('geotiff', true, !this.displayGeoTiffByDefault_);
|
|
980
1298
|
if (geotiff) {
|
|
981
|
-
layer = await this.addGeoTiff_(geotiff);
|
|
1299
|
+
layer = await this.addGeoTiff_(geotiff, true);
|
|
982
1300
|
}
|
|
983
1301
|
}
|
|
984
1302
|
if (this.displayOverview_ && !layer) {
|
|
985
|
-
|
|
986
|
-
const geozarr = data.getDefaultGeoFile('geozarr', true, true);
|
|
1303
|
+
const geozarr = data.getDefaultGeoFile('geozarr', true, false);
|
|
987
1304
|
if (geozarr) {
|
|
988
|
-
layer = await this.addGeoZarr_(geozarr);
|
|
1305
|
+
layer = await this.addGeoZarr_(geozarr, true);
|
|
989
1306
|
}
|
|
990
1307
|
}
|
|
991
1308
|
// Show web map links if available
|
|
@@ -1071,6 +1388,26 @@ class STACLayer extends LayerGroup {
|
|
|
1071
1388
|
}
|
|
1072
1389
|
}
|
|
1073
1390
|
}
|
|
1391
|
+
/**
|
|
1392
|
+
* Set the colors of the colormap that is used for continuous single-band
|
|
1393
|
+
* data when neither the STAC metadata nor the `style` option define a
|
|
1394
|
+
* coloring. The colors are evenly distributed over the value range of the
|
|
1395
|
+
* data (e.g. from the STAC `statistics`). Set to `null` to stretch the
|
|
1396
|
+
* data to grayscale instead.
|
|
1397
|
+
* @param {Array<import("ol/color.js").Color|string>|null} colormap The colors of the colormap.
|
|
1398
|
+
* @return {Promise} Resolves once the layers are updated.
|
|
1399
|
+
* @api
|
|
1400
|
+
*/
|
|
1401
|
+
async setDefaultColormap(colormap) {
|
|
1402
|
+
if (colormap === this.defaultColormap_) {
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
this.defaultColormap_ = colormap || null;
|
|
1406
|
+
// The layers are recreated, as switching between a styled and an
|
|
1407
|
+
// unstyled visualization also changes how the sources are configured
|
|
1408
|
+
// (e.g. the normalization of GeoTIFF sources)
|
|
1409
|
+
await this.updateLayers();
|
|
1410
|
+
}
|
|
1074
1411
|
/**
|
|
1075
1412
|
* Update the assets to be rendered.
|
|
1076
1413
|
* @param {Array<string|Asset>|null} assets The assets to show.
|
|
@@ -1244,18 +1581,19 @@ class STACLayer extends LayerGroup {
|
|
|
1244
1581
|
/**
|
|
1245
1582
|
* Gets the WMTS capabilities from the given web-map-links URL.
|
|
1246
1583
|
* @param {string} url Base URL for the WMTS
|
|
1584
|
+
* @param {Link} link The web map link the request is made for.
|
|
1247
1585
|
* @param {string} [encoding] The request encoding, either `kvp` (default) or `rest`.
|
|
1248
1586
|
* @return {Promise<Object|null>} Resolves with the WMTS Capabilities object
|
|
1249
1587
|
* @private
|
|
1250
1588
|
*/
|
|
1251
|
-
async getWmtsCapabilities_(url, encoding = 'kvp') {
|
|
1589
|
+
async getWmtsCapabilities_(url, link, encoding = 'kvp') {
|
|
1252
1590
|
try {
|
|
1253
1591
|
const urlObj = new URL(url);
|
|
1254
1592
|
if (encoding !== 'rest') {
|
|
1255
1593
|
urlObj.searchParams.set('service', 'wmts');
|
|
1256
1594
|
urlObj.searchParams.set('request', 'GetCapabilities');
|
|
1257
1595
|
}
|
|
1258
|
-
const response = await this.fetch_(urlObj.toString(), 'text');
|
|
1596
|
+
const response = await this.fetch_(urlObj.toString(), 'text', link);
|
|
1259
1597
|
return new WMTSCapabilities().read(response);
|
|
1260
1598
|
}
|
|
1261
1599
|
catch (_) {
|