maplibre-gl-raster 0.14.9 → 0.14.11

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.
@@ -18151,18 +18151,35 @@ function deriveLayerName(source) {
18151
18151
  }
18152
18152
  //#endregion
18153
18153
  //#region src/lib/state/CogTilerEngine.ts
18154
+ /** Resample histogram buckets by their covered interval, preserving the total.
18155
+ * Point-mapping a short histogram leaves artificial empty gaps between bars. */
18156
+ function resampleHistogram(counts, targetBins = 128) {
18157
+ const output = new Array(targetBins).fill(0);
18158
+ if (counts.length === 0) return output;
18159
+ if (counts.length === targetBins) return counts.slice();
18160
+ const sourceWidth = 1 / counts.length;
18161
+ const targetWidth = 1 / targetBins;
18162
+ for (let source = 0; source < counts.length; source++) {
18163
+ const count = counts[source] ?? 0;
18164
+ if (!Number.isFinite(count) || count === 0) continue;
18165
+ const sourceStart = source * sourceWidth;
18166
+ const sourceEnd = (source + 1) * sourceWidth;
18167
+ const firstTarget = Math.floor(sourceStart * targetBins);
18168
+ const lastTarget = Math.min(targetBins - 1, Math.ceil(sourceEnd * targetBins) - 1);
18169
+ for (let target = firstTarget; target <= lastTarget; target++) {
18170
+ const overlap = Math.max(0, Math.min(sourceEnd, (target + 1) * targetWidth) - Math.max(sourceStart, target * targetWidth));
18171
+ output[target] += count * (overlap / sourceWidth);
18172
+ }
18173
+ }
18174
+ return output;
18175
+ }
18154
18176
  /** Convert cog-tiler's TiTiler-style statistics into the panel's 128-bin shape. */
18155
18177
  function fromCogStatistics(raw) {
18156
18178
  const perBand = /* @__PURE__ */ new Map();
18157
18179
  for (const [key, stats] of Object.entries(raw)) {
18158
18180
  const band = Number(key.replace(/^b/, ""));
18159
18181
  if (!Number.isInteger(band) || !Number.isFinite(stats.min) || !Number.isFinite(stats.max)) continue;
18160
- const histogram = new Array(128).fill(0);
18161
- const counts = stats.histogram?.[0] ?? [];
18162
- for (let i = 0; i < counts.length; i++) {
18163
- const target = Math.min(127, Math.floor((i + .5) / counts.length * 128));
18164
- histogram[target] += counts[i] ?? 0;
18165
- }
18182
+ const histogram = resampleHistogram(stats.histogram?.[0] ?? []);
18166
18183
  perBand.set(band, {
18167
18184
  min: stats.min,
18168
18185
  max: stats.max,
@@ -20575,7 +20592,7 @@ async function readPixelValues(tiff, lngLat, options) {
20575
20592
  index: b + 1,
20576
20593
  name: names?.get(b + 1) ?? null,
20577
20594
  value,
20578
- isNodata: nodata !== null && value === nodata
20595
+ isNodata: nodata !== null && (Number.isNaN(nodata) ? Number.isNaN(value) : value === nodata)
20579
20596
  });
20580
20597
  }
20581
20598
  return {
@@ -20693,6 +20710,27 @@ var PixelInspector = class {
20693
20710
  this._popup = null;
20694
20711
  this._enabled = false;
20695
20712
  }
20713
+ /**
20714
+ * Read one raster layer at a WGS84 coordinate without changing inspect mode.
20715
+ *
20716
+ * Hosts use this to include raster values in their own identify UI. Mosaic
20717
+ * members and assets follow the same topmost-first selection as the built-in
20718
+ * click inspector.
20719
+ *
20720
+ * @param target - Raster layer to read
20721
+ * @param lngLat - WGS84 longitude and latitude
20722
+ * @param signal - Optional cancellation signal
20723
+ * @returns The pixel reading, or null when the layer is unavailable or the
20724
+ * coordinate falls outside its data
20725
+ */
20726
+ async read(target, lngLat, signal) {
20727
+ if (!target || !isReadable(target) || signal?.aborted) return null;
20728
+ const assets = target.mosaicAssets ? assetsAt(target, lngLat) : null;
20729
+ const images = assets ? [] : imagesAt(target, lngLat);
20730
+ if ((assets ?? images).length === 0) return null;
20731
+ const readSignal = signal ?? new AbortController().signal;
20732
+ return assets ? this._readFirstAsset(assets, lngLat, readSignal, target.bandNames) : this._readFirst(images, lngLat, readSignal, target.bandNames);
20733
+ }
20696
20734
  _onClick = (e) => {
20697
20735
  const lngLat = [e.lngLat.lng, e.lngLat.lat];
20698
20736
  this._abort?.abort();
@@ -20702,16 +20740,10 @@ var PixelInspector = class {
20702
20740
  this._show(lngLat, this._messageContent(messageFor(target)));
20703
20741
  return;
20704
20742
  }
20705
- const assets = target.mosaicAssets ? assetsAt(target, lngLat) : null;
20706
- const images = assets ? [] : imagesAt(target, lngLat);
20707
- if ((assets ?? images).length === 0) {
20708
- this._show(lngLat, this._messageContent("No data at this location."));
20709
- return;
20710
- }
20711
20743
  const controller = new AbortController();
20712
20744
  this._abort = controller;
20713
20745
  this._show(lngLat, this._messageContent("Reading…"));
20714
- (assets ? this._readFirstAsset(assets, lngLat, controller.signal, target.bandNames) : this._readFirst(images, lngLat, controller.signal, target.bandNames)).then((reading) => {
20746
+ this.read(target, lngLat, controller.signal).then((reading) => {
20715
20747
  if (controller.signal.aborted) return;
20716
20748
  this._show(lngLat, reading ? this._readingContent(reading, target) : this._messageContent("No data at this location."));
20717
20749
  }).catch(() => {
@@ -22809,6 +22841,19 @@ var RasterControl = class {
22809
22841
  return this._inspector?.enabled ?? false;
22810
22842
  }
22811
22843
  /**
22844
+ * Read one managed raster at a WGS84 coordinate without enabling inspect UI.
22845
+ *
22846
+ * @param id - Raster layer id
22847
+ * @param lngLat - WGS84 longitude and latitude
22848
+ * @param options - Optional cancellation signal
22849
+ * @returns The pixel reading, or null when the layer is unavailable or the
22850
+ * coordinate falls outside its data
22851
+ */
22852
+ readRasterPixel(id, lngLat, options) {
22853
+ const layer = this._layerManager?.getLayer(id) ?? null;
22854
+ return this._inspector?.read(layer, lngLat, options?.signal) ?? Promise.resolve(null);
22855
+ }
22856
+ /**
22812
22857
  * Gets the active rendering engine.
22813
22858
  *
22814
22859
  * @returns The current engine, or the configured default before the control
@@ -23207,4 +23252,4 @@ var RasterControl = class {
23207
23252
  //#endregion
23208
23253
  export { Photometric as $, DEFAULT_TITILER_ENDPOINT as A, COLORMAP_ROW_COUNT as B, throttle as C, loadVrt as D, isVrtUrl as E, loadColormapSprite as F, statsForBand as G, colormaps_default as H, sampleColormapStops as I, mergeAutoStats as J, MAX_SAMPLE_TILES as K, COLORMAP_DISPLAY_NAMES as L, isMosaicJsonUrl as M, PALETTE_COLORMAP as N, parseVrt as O, isKnownColormap as P, Compression as Q, COLORMAP_NAMES as R, generateId as S, isVrtFile as T, DEFAULT_INDEX_RANGE as U, colormapDisplayName as V, autoRangeFor as W, percentileFromHistogram as X, mergeBandStats as Y, readBandNames as Z, parseMosaic as _, NORMALIZED_DIFFERENCE_INDICES as a, debounce as b, readPixelValues as c, MAX_MOSAIC_ASSETS as d, PlanarConfiguration as et, MosaicUnsupportedError as f, mosaicMinZoom as g, mosaicInitialView as h, CUSTOM_NORMALIZED_DIFFERENCE as i, createResilientEpsgResolver as it, TITILER_TMS as j, loadGeoTIFF as k, DEFAULT_ENGINE as l, loadMosaic as m, Colorbar as n, SampleFormat as nt, guessBandForRole as o, assetUrlToHttps as p, computeAutoStats as q, CUSTOM_INDEX_ID as r, TiffTag as rt, indexById as s, RasterControl as t, Predictor as tt, LayerManager as u, clamp as v, VrtUnsupportedError as w, formatNumericValue as x, classNames as y, COLORMAP_OPTIONS as z };
23209
23254
 
23210
- //# sourceMappingURL=RasterControl-CPtuFlxg.js.map
23255
+ //# sourceMappingURL=RasterControl-CSXMtSuG.js.map