bruce-cesium 7.2.7 → 7.2.9

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.
@@ -40604,61 +40604,27 @@
40604
40604
  }
40605
40605
 
40606
40606
  (function (TextureFrameSeriesAnimator) {
40607
- TextureFrameSeriesAnimator.LAYOUT_TILES = "tiles";
40608
- // The only generation this renderer draws. Anything else is refused rather than half read: the
40609
- // shapes differ enough that a partial reading produces a plausible wrong surface, which is worse
40610
- // than an empty one.
40611
- TextureFrameSeriesAnimator.SUPPORTED_VERSION = 3;
40612
- // Value in R at 8 bits, or high in R and low in G at 16.
40613
- TextureFrameSeriesAnimator.FORMAT_U8 = "u8";
40614
- TextureFrameSeriesAnimator.FORMAT_RG16 = "rg16";
40615
- // Declared as a field with one value, so a second mode can be added later without an absent
40616
- // Encoding having to mean anything.
40617
- TextureFrameSeriesAnimator.ENCODING_ABSOLUTE = "absolute";
40618
- TextureFrameSeriesAnimator.LAYER_VALUE = "Value";
40619
- TextureFrameSeriesAnimator.LAYER_VALUE_MIN = "ValueMin";
40620
- TextureFrameSeriesAnimator.LAYER_VALUE_MAX = "ValueMax";
40621
- TextureFrameSeriesAnimator.LAYER_BASELINE = "Baseline";
40622
- // The per-texel correction that was applied, published only on an archive that was transformed.
40623
- TextureFrameSeriesAnimator.LAYER_VALUE_SHIFT = "ValueShift";
40624
40607
  /**
40625
40608
  * Turns a published value map into the flat shape this renderer works in, or null when it cannot be drawn.
40626
40609
  * @param published the archive's Data.generation
40627
40610
  */
40628
40611
  function Adapt(published) {
40629
- if (!published || published.Version !== TextureFrameSeriesAnimator.SUPPORTED_VERSION) {
40630
- const found = published && published.Version != null ? published.Version : "none";
40631
- const at = published && published.Identity ? published.Identity.Generated : undefined;
40632
- // In theory should be no files.
40633
- console.warn("bruce-cesium: value map version " + found + " is not supported (this build reads "
40634
- + TextureFrameSeriesAnimator.SUPPORTED_VERSION + "), so nothing will be drawn for it."
40635
- + (at ? " The archive was generated at " + at + " and needs regenerating." : ""));
40612
+ const refused = BModels.ClientFileValueMap.Metadata.Unreadable(published);
40613
+ if (refused) {
40614
+ console.warn("bruce-cesium: " + refused + " Nothing will be drawn for it.");
40636
40615
  return null;
40637
40616
  }
40638
40617
  const geometry = published.Geometry || {};
40639
- const tiles = published.Tiles || [];
40640
- if (geometry.Layout !== TextureFrameSeriesAnimator.LAYOUT_TILES || tiles.length === 0) {
40641
- const at = published.Identity ? published.Identity.Generated : undefined;
40642
- console.warn("bruce-cesium: value map declares no tiles, so nothing will be drawn for it."
40643
- + (at ? " The archive was generated at " + at + " and needs regenerating." : ""));
40644
- return null;
40645
- }
40646
40618
  const value = published.Value || {};
40647
- if (value.Encoding && value.Encoding !== TextureFrameSeriesAnimator.ENCODING_ABSOLUTE) {
40648
- const at = published.Identity ? published.Identity.Generated : undefined;
40649
- console.warn("bruce-cesium: value map encoding " + value.Encoding + " is not supported"
40650
- + " (this build reads " + TextureFrameSeriesAnimator.ENCODING_ABSOLUTE + "), so nothing will be drawn for it."
40651
- + (at ? " The archive was generated at " + at + " and needs regenerating." : ""));
40652
- return null;
40653
- }
40654
40619
  const series = published.Series || {};
40655
- const layerRange = declaredRange(published, TextureFrameSeriesAnimator.LAYER_VALUE_MIN);
40620
+ const layerRange = BModels.ClientFileValueMap.Metadata.LayerRange(published, BModels.ClientFileValueMap.Metadata.LAYER_VALUE_MIN);
40621
+ const tiles = BModels.ClientFileValueMap.Metadata.TilesOf(published);
40656
40622
  const flat = {
40657
40623
  Frames: [],
40658
40624
  ValueMin: value.Min,
40659
40625
  ValueMax: value.Max,
40660
- Format: value.Format || TextureFrameSeriesAnimator.FORMAT_U8,
40661
- Encoding: value.Encoding || TextureFrameSeriesAnimator.ENCODING_ABSOLUTE,
40626
+ Format: value.Format || BModels.ClientFileValueMap.Metadata.FORMAT_U8,
40627
+ Encoding: value.Encoding || BModels.ClientFileValueMap.Metadata.ENCODING_ABSOLUTE,
40662
40628
  Units: value.Units,
40663
40629
  West: geometry.West,
40664
40630
  East: geometry.East,
@@ -40668,8 +40634,8 @@
40668
40634
  ResolutionY: geometry.ResolutionY,
40669
40635
  PixelPlacement: geometry.PixelPlacement,
40670
40636
  Times: series.Times,
40671
- ExtremesValueMin: layerRange ? layerRange.min : undefined,
40672
- ExtremesValueMax: layerRange ? layerRange.max : undefined,
40637
+ ExtremesValueMin: layerRange ? layerRange.Min : undefined,
40638
+ ExtremesValueMax: layerRange ? layerRange.Max : undefined,
40673
40639
  // The delivered values are what gets drawn. What the source called them, and any shift
40674
40640
  // applied on the way, travel for labels and analysis rather than for placement.
40675
40641
  SourceVerticalDatum: published.ValueSource ? published.ValueSource.VerticalDatum : undefined,
@@ -40679,50 +40645,35 @@
40679
40645
  SourceValueMax: published.ValueSource ? published.ValueSource.Max : undefined
40680
40646
  };
40681
40647
  flat.Tiles = tiles.map((tile) => adaptTile(tile, series.Times));
40682
- // The coarsest tile covers the whole extent, so it is what a caller wanting one time list reads.
40648
+ // The tiles arrive coarsest first, so the first one covers the whole extent and is what a
40649
+ // caller wanting one time list reads.
40683
40650
  flat.Frames = flat.Tiles[0].Frames;
40684
- warnIfUnshifted(published, flat);
40651
+ warnIfUnshifted(published);
40685
40652
  return flat;
40686
40653
  }
40687
40654
  TextureFrameSeriesAnimator.Adapt = Adapt;
40688
40655
  /*
40689
40656
  * Says so when an archive's heights are not on the ellipsoid they will be drawn against.
40690
40657
  */
40691
- function warnIfUnshifted(published, flat) {
40692
- const datum = flat.SourceVerticalDatum;
40693
- if (!datum || datum === TextureFrameSeriesAnimator.DATUM_ELLIPSOIDAL || flat.Transform) {
40694
- return;
40658
+ function warnIfUnshifted(published) {
40659
+ const said = BModels.ClientFileValueMap.Metadata.UnshiftedWarning(published);
40660
+ if (said) {
40661
+ console.warn("bruce-cesium: " + said);
40695
40662
  }
40696
- const at = published.Identity ? published.Identity.Generated : undefined;
40697
- console.warn("bruce-cesium: value map heights are in " + datum + " and report no transform, so"
40698
- + " they are not ellipsoidal and will draw at the wrong height when placed absolutely."
40699
- + (at ? " The archive was generated at " + at + " and needs regenerating with the shift"
40700
- + " applied." : ""));
40701
- }
40702
- /*
40703
- * The Min and Max a named layer declares, since a statistics layer is encoded over the true data
40704
- * range rather than over the frames' own.
40705
- */
40706
- function declaredRange(published, name) {
40707
- const layers = published.Layers || [];
40708
- for (const layer of layers) {
40709
- if (layer.Name === name && typeof layer.Min === "number" && typeof layer.Max === "number") {
40710
- return { min: layer.Min, max: layer.Max };
40711
- }
40712
- }
40713
- return null;
40714
40663
  }
40715
40664
  /*
40716
40665
  * One tile, with its per-time value rasters lined up against the shared time list.
40717
40666
  */
40718
40667
  function adaptTile(tile, times) {
40719
- const layers = tile.Layers || {};
40720
- const perTime = layers[TextureFrameSeriesAnimator.LAYER_VALUE] || [];
40721
- const frames = perTime.map((entry, index) => ({
40722
- Timestamp: times && times[index] ? times[index] : "",
40723
- ByteOffset: entry.Bytes.Offset,
40724
- ByteLength: entry.Bytes.Length
40725
- }));
40668
+ const perTime = (tile.Layers && tile.Layers[BModels.ClientFileValueMap.Metadata.LAYER_VALUE]) || [];
40669
+ const frames = perTime.map((_entry, index) => {
40670
+ const at = BModels.ClientFileValueMap.Metadata.BytesOf(tile, BModels.ClientFileValueMap.Metadata.LAYER_VALUE, index);
40671
+ return {
40672
+ Timestamp: times && times[index] ? times[index] : "",
40673
+ ByteOffset: at ? at.Offset : 0,
40674
+ ByteLength: at ? at.Length : 0
40675
+ };
40676
+ });
40726
40677
  return {
40727
40678
  Level: tile.Level,
40728
40679
  X: tile.X,
@@ -40735,16 +40686,17 @@
40735
40686
  ResolutionX: tile.ResolutionX,
40736
40687
  ResolutionY: tile.ResolutionY,
40737
40688
  Frames: frames,
40738
- Floor: single(layers[TextureFrameSeriesAnimator.LAYER_VALUE_MIN]),
40739
- Ceiling: single(layers[TextureFrameSeriesAnimator.LAYER_VALUE_MAX]),
40740
- BaselineMask: single(layers[TextureFrameSeriesAnimator.LAYER_BASELINE])
40689
+ Floor: entryFor(tile, BModels.ClientFileValueMap.Metadata.LAYER_VALUE_MIN),
40690
+ Ceiling: entryFor(tile, BModels.ClientFileValueMap.Metadata.LAYER_VALUE_MAX),
40691
+ BaselineMask: entryFor(tile, BModels.ClientFileValueMap.Metadata.LAYER_BASELINE)
40741
40692
  };
40742
40693
  }
40743
- function single(layer) {
40744
- if (!layer || !layer.Bytes) {
40745
- return undefined;
40746
- }
40747
- return { ByteOffset: layer.Bytes.Offset, ByteLength: layer.Bytes.Length };
40694
+ /*
40695
+ * One tile's single copy of a layer, in the byte shape this renderer's fetching works in.
40696
+ */
40697
+ function entryFor(tile, name) {
40698
+ const at = BModels.ClientFileValueMap.Metadata.BytesOf(tile, name);
40699
+ return at ? { ByteOffset: at.Offset, ByteLength: at.Length } : undefined;
40748
40700
  }
40749
40701
  /**
40750
40702
  * How to turn a delivered value into the number the source published, or null when the archive
@@ -40790,7 +40742,7 @@
40790
40742
  * @param metadata the archive's Data.generation
40791
40743
  */
40792
40744
  function IsPackedValue(metadata) {
40793
- return Boolean(metadata && metadata.Format === TextureFrameSeriesAnimator.FORMAT_RG16);
40745
+ return Boolean(metadata) && BModels.ClientFileValueMap.Metadata.IsPacked({ Value: { Format: metadata.Format } });
40794
40746
  }
40795
40747
  TextureFrameSeriesAnimator.IsPackedValue = IsPackedValue;
40796
40748
  /**
@@ -40800,10 +40752,7 @@
40800
40752
  * @param at index of the texel's red channel
40801
40753
  */
40802
40754
  function NormalisedAt(metadata, pixels, at) {
40803
- if (IsPackedValue(metadata)) {
40804
- return (pixels[at] * 256 + pixels[at + 1]) / 65535;
40805
- }
40806
- return pixels[at] / 255;
40755
+ return BModels.ClientFileValueMap.Metadata.NormalisedAt(pixels, at, IsPackedValue(metadata) ? BModels.ClientFileValueMap.Metadata.FORMAT_RG16 : BModels.ClientFileValueMap.Metadata.FORMAT_U8);
40807
40756
  }
40808
40757
  TextureFrameSeriesAnimator.NormalisedAt = NormalisedAt;
40809
40758
  // Values already sit on the ellipsoid Cesium measures against, so nothing is added to place them.
@@ -40836,13 +40785,10 @@
40836
40785
  * @param value in the attribute's units
40837
40786
  */
40838
40787
  function NormalisePosition(metadata, value) {
40839
- const lo = metadata && typeof metadata.ValueMin === "number" ? metadata.ValueMin : 0;
40840
- const hi = metadata && typeof metadata.ValueMax === "number" ? metadata.ValueMax : 1;
40841
- const span = hi - lo;
40842
- if (!(span > 0)) {
40843
- return 0;
40844
- }
40845
- return Math.min(1, Math.max(0, (value - lo) / span));
40788
+ return BModels.ClientFileValueMap.Metadata.Normalise(value, {
40789
+ Min: metadata && typeof metadata.ValueMin === "number" ? metadata.ValueMin : 0,
40790
+ Max: metadata && typeof metadata.ValueMax === "number" ? metadata.ValueMax : 1
40791
+ });
40846
40792
  }
40847
40793
  TextureFrameSeriesAnimator.NormalisePosition = NormalisePosition;
40848
40794
  /**
@@ -41320,27 +41266,8 @@
41320
41266
  * Composite resolution, capped by what can be uploaded as a texture every frame.
41321
41267
  */
41322
41268
  compositeSize(tiles, target) {
41323
- let finest = Number.MAX_VALUE;
41324
- for (const tile of tiles) {
41325
- if (tile.TexelMetres > 0) {
41326
- finest = Math.min(finest, tile.TexelMetres);
41327
- }
41328
- }
41329
- if (!(finest > 0) || finest === Number.MAX_VALUE) {
41330
- finest = 1;
41331
- }
41332
- const mid = (target.South + target.North) / 2 * Math.PI / 180;
41333
- const widthM = Math.max((target.East - target.West) * 111320 * Math.cos(mid), 1);
41334
- const heightM = Math.max((target.North - target.South) * 110574, 1);
41335
- let width = Math.ceil(widthM / finest);
41336
- let height = Math.ceil(heightM / finest);
41337
- const longest = Math.max(width, height);
41338
- if (longest > MAX_COMPOSITE_TEXELS) {
41339
- const shrink = MAX_COMPOSITE_TEXELS / longest;
41340
- width = Math.max(1, Math.round(width * shrink));
41341
- height = Math.max(1, Math.round(height * shrink));
41342
- }
41343
- return { width: Math.max(1, width), height: Math.max(1, height) };
41269
+ const size = BModels.ClientFileValueMap.Grid.CompositeSize(tiles, target, MAX_COMPOSITE_TEXELS);
41270
+ return { width: size.Width, height: size.Height };
41344
41271
  }
41345
41272
  /*
41346
41273
  * Applies the ramp, borders and baseline mask to raw value pixels, whatever produced them.
@@ -41464,20 +41391,20 @@
41464
41391
  const size = this.compositeSize(tiles, target);
41465
41392
  // One request for the whole extremes block. They sit contiguously after the frames, so
41466
41393
  // fetching per tile would be 164 round trips for an 82 tile pyramid.
41467
- let lo = Number.MAX_SAFE_INTEGER;
41468
- let hi = 0;
41394
+ const ranges = [];
41469
41395
  for (const tile of tiles) {
41470
41396
  for (const at of [tile.Floor, tile.Ceiling]) {
41471
- if (!at) {
41472
- continue;
41397
+ if (at) {
41398
+ ranges.push({ Offset: at.ByteOffset, Length: at.ByteLength });
41473
41399
  }
41474
- lo = Math.min(lo, at.ByteOffset);
41475
- hi = Math.max(hi, at.ByteOffset + at.ByteLength);
41476
41400
  }
41477
41401
  }
41478
- if (!(hi > lo)) {
41402
+ const span = BModels.ClientFileValueMap.Metadata.SpanOf(ranges);
41403
+ if (!span) {
41479
41404
  return;
41480
41405
  }
41406
+ const lo = span.Offset;
41407
+ const hi = span.Offset + span.Length;
41481
41408
  const response = await fetch(this.archiveUrl, { headers: { Range: `bytes=${lo}-${hi - 1}` } });
41482
41409
  const block = await response.arrayBuffer();
41483
41410
  if (this.disposed) {
@@ -41522,13 +41449,8 @@
41522
41449
  * background shows between them.
41523
41450
  */
41524
41451
  tileRect(tile, target, size) {
41525
- const spanLon = target.East - target.West;
41526
- const spanLat = target.North - target.South;
41527
- const x0 = Math.round((tile.West - target.West) / spanLon * size.width);
41528
- const x1 = Math.round((tile.East - target.West) / spanLon * size.width);
41529
- const y0 = Math.round((target.North - tile.North) / spanLat * size.height);
41530
- const y1 = Math.round((target.North - tile.South) / spanLat * size.height);
41531
- return { x: x0, y: y0, w: Math.max(1, x1 - x0), h: Math.max(1, y1 - y0) };
41452
+ const rect = BModels.ClientFileValueMap.Grid.TileRect(tile, target, { Width: size.width, Height: size.height });
41453
+ return { x: rect.Left, y: rect.Top, w: rect.Width, h: rect.Height };
41532
41454
  }
41533
41455
  /*
41534
41456
  * Decodes many tile images at once.
@@ -42424,7 +42346,7 @@
42424
42346
 
42425
42347
  (function (DisplacedSurfacePrimitive) {
42426
42348
  // Grid densities a tile can draw at, coarsest first.
42427
- const TIERS = [32, 64, 128, 192];
42349
+ const TIERS = [32, 64, 128, 192, 256, 384];
42428
42350
  // Tiles per side the extent is cut into.
42429
42351
  const TILES_PER_SIDE = 6;
42430
42352
  // Screen pixels one grid cell should cover. Lower means finer meshes sooner.
@@ -43072,6 +42994,7 @@ void main() {
43072
42994
  const camera = frameState.camera;
43073
42995
  const fovy = camera.frustum && camera.frustum.fovy ? camera.frustum.fovy : Cesium.Math.PI_OVER_THREE;
43074
42996
  const pixelsPerRadian = frameState.context.drawingBufferHeight / fovy;
42997
+ const ceiling = this.tierCeiling();
43075
42998
  for (const tile of this.tiles) {
43076
42999
  if (!tile.centre) {
43077
43000
  tile.tier = TIERS[0];
@@ -43082,13 +43005,33 @@ void main() {
43082
43005
  const wanted = screenPixels / TARGET_CELL_PIXELS;
43083
43006
  let tier = TIERS[0];
43084
43007
  for (const candidate of TIERS) {
43085
- if (candidate <= wanted) {
43008
+ if (candidate <= wanted && candidate <= ceiling) {
43086
43009
  tier = candidate;
43087
43010
  }
43088
43011
  }
43089
43012
  tile.tier = tier;
43090
43013
  }
43091
43014
  }
43015
+ /*
43016
+ * The finest tier worth drawing for this surface, from the texture behind it.
43017
+ *
43018
+ * Subdividing past one vertex per texel spends vertices resolving detail the source does not
43019
+ * carry, so the ladder is capped one step above the texel count rather than run to its top.
43020
+ */
43021
+ tierCeiling() {
43022
+ const source = this.source;
43023
+ if (!source || !source.width || !source.height) {
43024
+ return TIERS[TIERS.length - 1];
43025
+ }
43026
+ const perSide = Math.sqrt(this.tiles.length) || TILES_PER_SIDE;
43027
+ const texelsPerTile = Math.max(source.width, source.height) / perSide;
43028
+ for (const candidate of TIERS) {
43029
+ if (candidate >= texelsPerTile) {
43030
+ return candidate;
43031
+ }
43032
+ }
43033
+ return TIERS[TIERS.length - 1];
43034
+ }
43092
43035
  shouldReselect(frameState, nowMs) {
43093
43036
  if (this.selectionDirty) {
43094
43037
  return true;
@@ -43101,9 +43044,23 @@ void main() {
43101
43044
  return true;
43102
43045
  }
43103
43046
  const moved = Cesium.Cartesian3.distance(eye, this.lastEyePosition);
43104
- const anchor = this.tiles[0].centre;
43105
- const reference = anchor ? Math.max(1, Cesium.Cartesian3.distance(eye, anchor)) : 1;
43106
- return moved / reference > MOVEMENT_THRESHOLD;
43047
+ return moved / this.nearestTileDistance(eye) > MOVEMENT_THRESHOLD;
43048
+ }
43049
+ /*
43050
+ * Distance to the closest tile, measured the way selectTiers measures each one.
43051
+ */
43052
+ nearestTileDistance(eye) {
43053
+ let nearest = Number.POSITIVE_INFINITY;
43054
+ for (const tile of this.tiles) {
43055
+ if (!tile.centre) {
43056
+ continue;
43057
+ }
43058
+ const distance = Cesium.Cartesian3.distance(eye, tile.centre) - tile.radius;
43059
+ if (distance < nearest) {
43060
+ nearest = distance;
43061
+ }
43062
+ }
43063
+ return isFinite(nearest) ? Math.max(1, nearest) : 1;
43107
43064
  }
43108
43065
  commandFor(context, tile, mesh) {
43109
43066
  if (!this.shaderProgram) {
@@ -44339,7 +44296,7 @@ void main() {
44339
44296
  return { dataUri: null, effective: null };
44340
44297
  }
44341
44298
  await api.Loading;
44342
- const clientFile = await BModels.ClientFile.FindGeneratedTexture({ api, entityTypeSourceId, attribute });
44299
+ const { file: clientFile } = await BModels.ClientFileValueMap.Get({ api, entityTypeSourceId, attribute });
44343
44300
  if (!clientFile) {
44344
44301
  return { dataUri: null, effective: null };
44345
44302
  }
@@ -45819,7 +45776,7 @@ void main() {
45819
45776
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
45820
45777
  })(exports.StyleUtils || (exports.StyleUtils = {}));
45821
45778
 
45822
- const VERSION = "7.2.7";
45779
+ const VERSION = "7.2.9";
45823
45780
  /**
45824
45781
  * Updates the environment instance used by bruce-cesium to one specified.
45825
45782
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.