maplibre-gl-raster 0.4.0 → 0.5.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.
|
@@ -17263,10 +17263,18 @@ var WEB_MERCATOR_CODES = new Set([
|
|
|
17263
17263
|
102100,
|
|
17264
17264
|
102113
|
|
17265
17265
|
]);
|
|
17266
|
+
var GEOGRAPHIC_WGS84 = 4326;
|
|
17267
|
+
var EARTH_RADIUS = 6378137;
|
|
17268
|
+
var DEG2RAD = Math.PI / 180;
|
|
17266
17269
|
var identity = (x, y) => [x, y];
|
|
17270
|
+
var geographicTo3857 = (lon, lat) => [EARTH_RADIUS * lon * DEG2RAD, EARTH_RADIUS * Math.log(Math.tan(Math.PI / 4 + lat * DEG2RAD / 2))];
|
|
17271
|
+
var geographicFrom3857 = (x, y) => [x / EARTH_RADIUS / DEG2RAD, (2 * Math.atan(Math.exp(y / EARTH_RADIUS)) - Math.PI / 2) / DEG2RAD];
|
|
17267
17272
|
function isWebMercatorCrs(crs) {
|
|
17268
17273
|
return typeof crs === "number" && WEB_MERCATOR_CODES.has(crs);
|
|
17269
17274
|
}
|
|
17275
|
+
function isGeographicWgs84Crs(crs) {
|
|
17276
|
+
return crs === GEOGRAPHIC_WGS84;
|
|
17277
|
+
}
|
|
17270
17278
|
/**
|
|
17271
17279
|
* {@link COGLayer} that reprojects a Web-Mercator source with the identity
|
|
17272
17280
|
* transform instead of a proj4 round-trip.
|
|
@@ -17287,23 +17295,33 @@ function isWebMercatorCrs(crs) {
|
|
|
17287
17295
|
*
|
|
17288
17296
|
* For a source already in EPSG:3857 the source→3857 transform *is* the
|
|
17289
17297
|
* identity, so we substitute it directly: exact (no precision loss), wrap-free,
|
|
17290
|
-
* and cheaper than proj4.
|
|
17291
|
-
*
|
|
17292
|
-
*
|
|
17298
|
+
* and cheaper than proj4. For a geographic EPSG:4326 source — equally common
|
|
17299
|
+
* for global rasters, e.g. the CHIRPS precipitation COG — the source→3857
|
|
17300
|
+
* transform is the spherical mercator forward, which we substitute with a
|
|
17301
|
+
* wrap-free implementation (`geographicTo3857`) so the antimeridian padding
|
|
17302
|
+
* columns no longer fold to the other hemisphere. Both substitutions only
|
|
17303
|
+
* touch the source↔3857 transforms; the 4326 bounds transforms are left
|
|
17304
|
+
* untouched — they back the geographic bounds and the globe view.
|
|
17293
17305
|
*
|
|
17294
17306
|
* The fix lives here rather than upstream because deck.gl-geotiff hard-codes the
|
|
17295
17307
|
* projection setup inside `_parseGeoTIFF` and exposes no hook for it;
|
|
17296
17308
|
* `_tilesetDescriptor()` is the one seam through which the built descriptor
|
|
17297
17309
|
* flows to both tile traversal and per-tile rendering. Remove this once
|
|
17298
|
-
* deck.gl-geotiff short-circuits same-CRS reprojection
|
|
17310
|
+
* deck.gl-geotiff short-circuits same-CRS reprojection and clamps the
|
|
17311
|
+
* antimeridian overhang itself.
|
|
17299
17312
|
*/
|
|
17300
17313
|
var WebMercatorCOGLayer = class extends COGLayer {
|
|
17301
17314
|
static layerName = "WebMercatorCOGLayer";
|
|
17302
17315
|
_tilesetDescriptor() {
|
|
17303
17316
|
const descriptor = super._tilesetDescriptor();
|
|
17304
|
-
if (descriptor
|
|
17317
|
+
if (!descriptor) return descriptor;
|
|
17318
|
+
const crs = this.state.geotiff?.crs;
|
|
17319
|
+
if (descriptor.projectTo3857 !== identity && isWebMercatorCrs(crs)) {
|
|
17305
17320
|
descriptor.projectTo3857 = identity;
|
|
17306
17321
|
descriptor.projectFrom3857 = identity;
|
|
17322
|
+
} else if (descriptor.projectTo3857 !== geographicTo3857 && isGeographicWgs84Crs(crs)) {
|
|
17323
|
+
descriptor.projectTo3857 = geographicTo3857;
|
|
17324
|
+
descriptor.projectFrom3857 = geographicFrom3857;
|
|
17307
17325
|
}
|
|
17308
17326
|
return descriptor;
|
|
17309
17327
|
}
|
|
@@ -18067,7 +18085,50 @@ function deriveLayerName(source) {
|
|
|
18067
18085
|
//#region src/lib/state/LayerManager.ts
|
|
18068
18086
|
/** Default engine when none is configured: the deck.gl GPU pipeline. */
|
|
18069
18087
|
var DEFAULT_ENGINE = "maplibre-gl-raster";
|
|
18070
|
-
|
|
18088
|
+
/**
|
|
18089
|
+
* The band indexes a layer actually samples, deduped and sorted. Mirrors the
|
|
18090
|
+
* `requested` logic in render-pipeline's buildRenderTile: RGB samples the first
|
|
18091
|
+
* three entries (R, G, B); single-band / colormap / palette the first one. The
|
|
18092
|
+
* render pipeline looks textures up by band number, not slot order, so the
|
|
18093
|
+
* fetch order is irrelevant — sorting makes the set order-independent, so
|
|
18094
|
+
* reassigning RGB channels among the same bands does not force a refetch.
|
|
18095
|
+
* Always yields at least band 1 so a layer with an empty/invalid selection
|
|
18096
|
+
* still fetches something to draw.
|
|
18097
|
+
*
|
|
18098
|
+
* The sampled channels are sliced off **before** dedupe/sort so a state that
|
|
18099
|
+
* carries more entries than channels (e.g. `bands: [12, 1, 2, 3, 4]`) can't
|
|
18100
|
+
* sort-then-cap a band that a channel still samples (here the red channel's
|
|
18101
|
+
* 12) out of the fetched set. By construction the result is ≤ 3 entries — well
|
|
18102
|
+
* within the CompositeBands shader's {@link MAX_BAND_SLOTS} texture slots.
|
|
18103
|
+
*/
|
|
18104
|
+
function fetchBandsFor(layer) {
|
|
18105
|
+
const bands = layer.state.bands;
|
|
18106
|
+
const sampled = layer.state.mode === "rgb" ? (bands && bands.length > 0 ? bands : [
|
|
18107
|
+
1,
|
|
18108
|
+
2,
|
|
18109
|
+
3
|
|
18110
|
+
]).slice(0, 3) : [bands?.[0] ?? 1];
|
|
18111
|
+
const unique = [...new Set(sampled.filter((b) => Number.isInteger(b) && b >= 1))].sort((a, b) => a - b);
|
|
18112
|
+
if (unique.length === 0) unique.push(1);
|
|
18113
|
+
return unique.slice(0, 4);
|
|
18114
|
+
}
|
|
18115
|
+
/**
|
|
18116
|
+
* The deck.gl layer id for a raster layer, with its fetched band set encoded.
|
|
18117
|
+
*
|
|
18118
|
+
* The tile loader only fetches {@link fetchBandsFor} (≤ MAX_BAND_SLOTS) bands,
|
|
18119
|
+
* so a single-band view of e.g. band 12 needs band 12 in the tile textures.
|
|
18120
|
+
* deck.gl's `TileLayer` does **not** refetch when `getTileData` changes — its
|
|
18121
|
+
* RasterTileLayer wrapper sets no `getTileData` updateTrigger, so a swapped
|
|
18122
|
+
* loader closure is silently ignored and the previously fetched bands stay
|
|
18123
|
+
* cached. The one reliable way to refetch is to remount the layer, which
|
|
18124
|
+
* deck.gl does when the layer id changes. Encoding the (sorted) band set in the
|
|
18125
|
+
* id therefore makes a band-selection change refetch the newly selected bands,
|
|
18126
|
+
* while leaving the id — and thus the tile cache — stable across opacity,
|
|
18127
|
+
* colormap, rescale and RGB-channel-reorder changes that don't alter the set.
|
|
18128
|
+
*/
|
|
18129
|
+
function cogLayerId(layer, fetchBands) {
|
|
18130
|
+
return `${layer.id}#b${fetchBands.join("-")}`;
|
|
18131
|
+
}
|
|
18071
18132
|
/** Uploads an embedded color table as a 2D-array texture for the Colormap
|
|
18072
18133
|
* shader module. Unlike `createColormapTexture` (which uses linear filtering
|
|
18073
18134
|
* for smooth continuous colormaps), palette lookups must be NEAREST-filtered:
|
|
@@ -18600,8 +18661,10 @@ var LayerManager = class {
|
|
|
18600
18661
|
}
|
|
18601
18662
|
_buildCogLayer(layer) {
|
|
18602
18663
|
const renderTile = this._renderTileFor(layer);
|
|
18664
|
+
const fetchBands = fetchBandsFor(layer);
|
|
18665
|
+
const getTileData = makeMultiBandTileLoader(fetchBands);
|
|
18603
18666
|
return new WebMercatorCOGLayer({
|
|
18604
|
-
id: layer
|
|
18667
|
+
id: cogLayerId(layer, fetchBands),
|
|
18605
18668
|
geotiff: layer.geotiff,
|
|
18606
18669
|
opacity: layer.state.opacity,
|
|
18607
18670
|
getTileData,
|
|
@@ -19548,7 +19611,7 @@ var SettingsSection = class {
|
|
|
19548
19611
|
}
|
|
19549
19612
|
const state = layer.state;
|
|
19550
19613
|
const mode = state.mode;
|
|
19551
|
-
const bandOptions = Array.from({ length: Math.
|
|
19614
|
+
const bandOptions = Array.from({ length: Math.max(1, layer.bandCount ?? 1) }, (_, i) => i + 1);
|
|
19552
19615
|
const paletteActive = mode === "single" && state.colormap === "palette" && layer.palette !== null;
|
|
19553
19616
|
this._body.appendChild(this._buildModeField(state, mode, bandOptions));
|
|
19554
19617
|
this._body.appendChild(this._buildBandsField(layer, state, mode, bandOptions));
|
|
@@ -20897,4 +20960,4 @@ var RasterControl = class {
|
|
|
20897
20960
|
//#endregion
|
|
20898
20961
|
export { computeAutoStats as C, createResilientEpsgResolver as E, MAX_SAMPLE_TILES as S, readBandNames as T, COLORMAP_ROW_COUNT as _, loadColormapSprite as a, autoRangeFor as b, classNames as c, generateId as d, throttle as f, COLORMAP_OPTIONS as g, COLORMAP_NAMES as h, isKnownColormap as i, debounce as l, COLORMAP_DISPLAY_NAMES as m, Colorbar as n, sampleColormapStops as o, loadGeoTIFF as p, PALETTE_COLORMAP as r, clamp as s, RasterControl as t, formatNumericValue as u, colormapDisplayName as v, percentileFromHistogram as w, statsForBand as x, colormaps_default as y };
|
|
20899
20962
|
|
|
20900
|
-
//# sourceMappingURL=RasterControl-
|
|
20963
|
+
//# sourceMappingURL=RasterControl-vzjXiCsa.js.map
|