bruce-cesium 7.2.2 → 7.2.4
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/dist/bruce-cesium.es5.js +437 -377
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +441 -382
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +2 -1
- package/dist/lib/bruce-cesium.js.map +1 -1
- package/dist/lib/rendering/displaced-surface-primitive.js +51 -43
- package/dist/lib/rendering/displaced-surface-primitive.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine-polygon.js +30 -39
- package/dist/lib/rendering/entity-render-engine-polygon.js.map +1 -1
- package/dist/lib/rendering/texture-frame-series-animator.js +279 -267
- package/dist/lib/rendering/texture-frame-series-animator.js.map +1 -1
- package/dist/lib/rendering/texture-value-labels.js +71 -25
- package/dist/lib/rendering/texture-value-labels.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +2 -1
- package/dist/types/rendering/displaced-surface-primitive.d.ts +2 -10
- package/dist/types/rendering/texture-frame-series-animator.d.ts +166 -66
- package/dist/types/rendering/texture-value-labels.d.ts +22 -0
- package/package.json +2 -2
package/dist/bruce-cesium.es5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Cesium from 'cesium';
|
|
2
|
-
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature,
|
|
3
|
-
import { Cartes, Entity as Entity$1, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style,
|
|
2
|
+
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, DistanceDisplayCondition, Math as Math$1, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, Matrix4, HeightReference, ColorBlendMode, ShadowMode, ClassificationType, Model, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, Cartesian2, HorizontalOrigin, VerticalOrigin, ConstantPositionProperty, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, ArcType, CornerType, Rectangle, SceneTransforms, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, HeadingPitchRange, Ion, IonResource, Cesium3DTileStyle, Cesium3DTileColorBlendMode, Cesium3DTileset, OrthographicFrustum, EasingFunction, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Intersect, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, CustomDataSource, GeometryInstance, PolygonPipeline, CesiumInspector, defined, ClockRange, DynamicEnvironmentMapManager, EllipsoidGeodesic, sampleTerrainMostDetailed, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
|
|
3
|
+
import { Cartes, Entity as Entity$1, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Api, Bounds, Color as Color$1, Geometry as Geometry$1, Carto, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, BruceApi, AccountConcept, RecordChangeFeed, EntityRelation, Camera, ProgramKey, ProjectViewLegacyTile, EntitySource, Account, AccountLimits, Session, UrlUtils, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, ProjectViewBookmarkGroup, EntityRelationType, EntityHistoricData } from 'bruce-models';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Ensures a number is returned from a given value.
|
|
@@ -40400,38 +40400,229 @@ function loadImage(src) {
|
|
|
40400
40400
|
|
|
40401
40401
|
var TextureFrameSeriesAnimator;
|
|
40402
40402
|
(function (TextureFrameSeriesAnimator) {
|
|
40403
|
-
// Values are measured up from the ground beneath them.
|
|
40404
|
-
TextureFrameSeriesAnimator.QUANTITY_THICKNESS = "thickness";
|
|
40405
|
-
// Values are heights against a vertical datum, so they need that datum to be placed.
|
|
40406
|
-
TextureFrameSeriesAnimator.QUANTITY_ELEVATION = "elevation";
|
|
40407
40403
|
TextureFrameSeriesAnimator.LAYOUT_TILES = "tiles";
|
|
40404
|
+
// The only generation this renderer draws. Anything else is refused rather than half read: the
|
|
40405
|
+
// shapes differ enough that a partial reading produces a plausible wrong surface, which is worse
|
|
40406
|
+
// than an empty one.
|
|
40407
|
+
TextureFrameSeriesAnimator.SUPPORTED_VERSION = 3;
|
|
40408
|
+
// Value in R at 8 bits, or high in R and low in G at 16.
|
|
40409
|
+
TextureFrameSeriesAnimator.FORMAT_U8 = "u8";
|
|
40410
|
+
TextureFrameSeriesAnimator.FORMAT_RG16 = "rg16";
|
|
40411
|
+
// Declared as a field with one value, so a second mode can be added later without an absent
|
|
40412
|
+
// Encoding having to mean anything.
|
|
40413
|
+
TextureFrameSeriesAnimator.ENCODING_ABSOLUTE = "absolute";
|
|
40414
|
+
TextureFrameSeriesAnimator.LAYER_VALUE = "Value";
|
|
40415
|
+
TextureFrameSeriesAnimator.LAYER_VALUE_MIN = "ValueMin";
|
|
40416
|
+
TextureFrameSeriesAnimator.LAYER_VALUE_MAX = "ValueMax";
|
|
40417
|
+
TextureFrameSeriesAnimator.LAYER_BASELINE = "Baseline";
|
|
40418
|
+
// The per-texel correction that was applied, published only on an archive that was transformed.
|
|
40419
|
+
TextureFrameSeriesAnimator.LAYER_VALUE_SHIFT = "ValueShift";
|
|
40408
40420
|
/**
|
|
40409
|
-
*
|
|
40421
|
+
* Turns a published value map into the flat shape this renderer works in, or null when it cannot be drawn.
|
|
40422
|
+
* @param published the archive's Data.generation
|
|
40423
|
+
*/
|
|
40424
|
+
function Adapt(published) {
|
|
40425
|
+
if (!published || published.Version !== TextureFrameSeriesAnimator.SUPPORTED_VERSION) {
|
|
40426
|
+
const found = published && published.Version != null ? published.Version : "none";
|
|
40427
|
+
const at = published && published.Identity ? published.Identity.Generated : undefined;
|
|
40428
|
+
// In theory should be no files.
|
|
40429
|
+
console.warn("bruce-cesium: value map version " + found + " is not supported (this build reads "
|
|
40430
|
+
+ TextureFrameSeriesAnimator.SUPPORTED_VERSION + "), so nothing will be drawn for it."
|
|
40431
|
+
+ (at ? " The archive was generated at " + at + " and needs regenerating." : ""));
|
|
40432
|
+
return null;
|
|
40433
|
+
}
|
|
40434
|
+
const geometry = published.Geometry || {};
|
|
40435
|
+
const tiles = published.Tiles || [];
|
|
40436
|
+
if (geometry.Layout !== TextureFrameSeriesAnimator.LAYOUT_TILES || tiles.length === 0) {
|
|
40437
|
+
const at = published.Identity ? published.Identity.Generated : undefined;
|
|
40438
|
+
console.warn("bruce-cesium: value map declares no tiles, so nothing will be drawn for it."
|
|
40439
|
+
+ (at ? " The archive was generated at " + at + " and needs regenerating." : ""));
|
|
40440
|
+
return null;
|
|
40441
|
+
}
|
|
40442
|
+
const value = published.Value || {};
|
|
40443
|
+
if (value.Encoding && value.Encoding !== TextureFrameSeriesAnimator.ENCODING_ABSOLUTE) {
|
|
40444
|
+
const at = published.Identity ? published.Identity.Generated : undefined;
|
|
40445
|
+
console.warn("bruce-cesium: value map encoding " + value.Encoding + " is not supported"
|
|
40446
|
+
+ " (this build reads " + TextureFrameSeriesAnimator.ENCODING_ABSOLUTE + "), so nothing will be drawn for it."
|
|
40447
|
+
+ (at ? " The archive was generated at " + at + " and needs regenerating." : ""));
|
|
40448
|
+
return null;
|
|
40449
|
+
}
|
|
40450
|
+
const series = published.Series || {};
|
|
40451
|
+
const layerRange = declaredRange(published, TextureFrameSeriesAnimator.LAYER_VALUE_MIN);
|
|
40452
|
+
const flat = {
|
|
40453
|
+
Frames: [],
|
|
40454
|
+
ValueMin: value.Min,
|
|
40455
|
+
ValueMax: value.Max,
|
|
40456
|
+
Format: value.Format || TextureFrameSeriesAnimator.FORMAT_U8,
|
|
40457
|
+
Encoding: value.Encoding || TextureFrameSeriesAnimator.ENCODING_ABSOLUTE,
|
|
40458
|
+
Units: value.Units,
|
|
40459
|
+
West: geometry.West,
|
|
40460
|
+
East: geometry.East,
|
|
40461
|
+
South: geometry.South,
|
|
40462
|
+
North: geometry.North,
|
|
40463
|
+
ResolutionX: geometry.ResolutionX,
|
|
40464
|
+
ResolutionY: geometry.ResolutionY,
|
|
40465
|
+
PixelPlacement: geometry.PixelPlacement,
|
|
40466
|
+
Times: series.Times,
|
|
40467
|
+
ExtremesValueMin: layerRange ? layerRange.min : undefined,
|
|
40468
|
+
ExtremesValueMax: layerRange ? layerRange.max : undefined,
|
|
40469
|
+
// The delivered values are what gets drawn. What the source called them, and any shift
|
|
40470
|
+
// applied on the way, travel for labels and analysis rather than for placement.
|
|
40471
|
+
SourceVerticalDatum: published.ValueSource ? published.ValueSource.VerticalDatum : undefined,
|
|
40472
|
+
Transform: published.ValueSource ? published.ValueSource.Transform : undefined,
|
|
40473
|
+
SourceUnits: published.ValueSource ? published.ValueSource.Units : undefined,
|
|
40474
|
+
SourceValueMin: published.ValueSource ? published.ValueSource.Min : undefined,
|
|
40475
|
+
SourceValueMax: published.ValueSource ? published.ValueSource.Max : undefined
|
|
40476
|
+
};
|
|
40477
|
+
flat.Tiles = tiles.map((tile) => adaptTile(tile, series.Times));
|
|
40478
|
+
// The coarsest tile covers the whole extent, so it is what a caller wanting one time list reads.
|
|
40479
|
+
flat.Frames = flat.Tiles[0].Frames;
|
|
40480
|
+
warnIfUnshifted(published, flat);
|
|
40481
|
+
return flat;
|
|
40482
|
+
}
|
|
40483
|
+
TextureFrameSeriesAnimator.Adapt = Adapt;
|
|
40484
|
+
/*
|
|
40485
|
+
* Says so when an archive's heights are not on the ellipsoid they will be drawn against.
|
|
40486
|
+
*/
|
|
40487
|
+
function warnIfUnshifted(published, flat) {
|
|
40488
|
+
const datum = flat.SourceVerticalDatum;
|
|
40489
|
+
if (!datum || datum === TextureFrameSeriesAnimator.DATUM_ELLIPSOIDAL || flat.Transform) {
|
|
40490
|
+
return;
|
|
40491
|
+
}
|
|
40492
|
+
const at = published.Identity ? published.Identity.Generated : undefined;
|
|
40493
|
+
console.warn("bruce-cesium: value map heights are in " + datum + " and report no transform, so"
|
|
40494
|
+
+ " they are not ellipsoidal and will draw at the wrong height when placed absolutely."
|
|
40495
|
+
+ (at ? " The archive was generated at " + at + " and needs regenerating with the shift"
|
|
40496
|
+
+ " applied." : ""));
|
|
40497
|
+
}
|
|
40498
|
+
/*
|
|
40499
|
+
* The Min and Max a named layer declares, since a statistics layer is encoded over the true data
|
|
40500
|
+
* range rather than over the frames' own.
|
|
40501
|
+
*/
|
|
40502
|
+
function declaredRange(published, name) {
|
|
40503
|
+
const layers = published.Layers || [];
|
|
40504
|
+
for (const layer of layers) {
|
|
40505
|
+
if (layer.Name === name && typeof layer.Min === "number" && typeof layer.Max === "number") {
|
|
40506
|
+
return { min: layer.Min, max: layer.Max };
|
|
40507
|
+
}
|
|
40508
|
+
}
|
|
40509
|
+
return null;
|
|
40510
|
+
}
|
|
40511
|
+
/*
|
|
40512
|
+
* One tile, with its per-time value rasters lined up against the shared time list.
|
|
40513
|
+
*/
|
|
40514
|
+
function adaptTile(tile, times) {
|
|
40515
|
+
const layers = tile.Layers || {};
|
|
40516
|
+
const perTime = layers[TextureFrameSeriesAnimator.LAYER_VALUE] || [];
|
|
40517
|
+
const frames = perTime.map((entry, index) => ({
|
|
40518
|
+
Timestamp: times && times[index] ? times[index] : "",
|
|
40519
|
+
ByteOffset: entry.Bytes.Offset,
|
|
40520
|
+
ByteLength: entry.Bytes.Length
|
|
40521
|
+
}));
|
|
40522
|
+
return {
|
|
40523
|
+
Level: tile.Level,
|
|
40524
|
+
X: tile.X,
|
|
40525
|
+
Y: tile.Y,
|
|
40526
|
+
West: tile.West,
|
|
40527
|
+
East: tile.East,
|
|
40528
|
+
South: tile.South,
|
|
40529
|
+
North: tile.North,
|
|
40530
|
+
TexelMetres: tile.TexelMetres,
|
|
40531
|
+
ResolutionX: tile.ResolutionX,
|
|
40532
|
+
ResolutionY: tile.ResolutionY,
|
|
40533
|
+
Frames: frames,
|
|
40534
|
+
Floor: single(layers[TextureFrameSeriesAnimator.LAYER_VALUE_MIN]),
|
|
40535
|
+
Ceiling: single(layers[TextureFrameSeriesAnimator.LAYER_VALUE_MAX]),
|
|
40536
|
+
BaselineMask: single(layers[TextureFrameSeriesAnimator.LAYER_BASELINE])
|
|
40537
|
+
};
|
|
40538
|
+
}
|
|
40539
|
+
function single(layer) {
|
|
40540
|
+
if (!layer || !layer.Bytes) {
|
|
40541
|
+
return undefined;
|
|
40542
|
+
}
|
|
40543
|
+
return { ByteOffset: layer.Bytes.Offset, ByteLength: layer.Bytes.Length };
|
|
40544
|
+
}
|
|
40545
|
+
/**
|
|
40546
|
+
* How to turn a delivered value into the number the source published, or null when the archive
|
|
40547
|
+
* does not say enough to do it.
|
|
40548
|
+
* @param metadata the archive's Data.generation
|
|
40549
|
+
*/
|
|
40550
|
+
function SourceMap(metadata) {
|
|
40551
|
+
if (!metadata) {
|
|
40552
|
+
return null;
|
|
40553
|
+
}
|
|
40554
|
+
const { ValueMin, ValueMax, SourceValueMin, SourceValueMax } = metadata;
|
|
40555
|
+
if (typeof ValueMin !== "number" || typeof ValueMax !== "number"
|
|
40556
|
+
|| typeof SourceValueMin !== "number" || typeof SourceValueMax !== "number") {
|
|
40557
|
+
return null;
|
|
40558
|
+
}
|
|
40559
|
+
const delivered = ValueMax - ValueMin;
|
|
40560
|
+
// A single delivered value describes no line, so all that can be recovered is where it sits.
|
|
40561
|
+
const scale = delivered !== 0 ? (SourceValueMax - SourceValueMin) / delivered : 1;
|
|
40562
|
+
return { scale, offset: SourceValueMin - ValueMin * scale };
|
|
40563
|
+
}
|
|
40564
|
+
TextureFrameSeriesAnimator.SourceMap = SourceMap;
|
|
40565
|
+
/**
|
|
40566
|
+
* Whether anything was applied to the values on the way out of the source.
|
|
40567
|
+
* @param metadata the archive's Data.generation
|
|
40568
|
+
*/
|
|
40569
|
+
function IsTransformed(metadata) {
|
|
40570
|
+
return Boolean(metadata && metadata.Transform);
|
|
40571
|
+
}
|
|
40572
|
+
TextureFrameSeriesAnimator.IsTransformed = IsTransformed;
|
|
40573
|
+
/**
|
|
40574
|
+
* A delivered value in the source's own terms, or unchanged when it cannot be turned back.
|
|
40575
|
+
* @param map from SourceMap(), null when the archive does not say enough
|
|
40576
|
+
*/
|
|
40577
|
+
function ToSource(map, value) {
|
|
40578
|
+
return map ? value * map.scale + map.offset : value;
|
|
40579
|
+
}
|
|
40580
|
+
TextureFrameSeriesAnimator.ToSource = ToSource;
|
|
40581
|
+
/**
|
|
40582
|
+
* Whether the archive's frames carry a 16 bit value packed across R and G.
|
|
40410
40583
|
*
|
|
40411
|
-
*
|
|
40412
|
-
*
|
|
40584
|
+
* Every consumer that reads a texel has to ask: taking R alone from a packed frame yields a
|
|
40585
|
+
* plausible surface quantised to 255 steps of the full range rather than an obvious failure.
|
|
40586
|
+
* @param metadata the archive's Data.generation
|
|
40587
|
+
*/
|
|
40588
|
+
function IsPackedValue(metadata) {
|
|
40589
|
+
return Boolean(metadata && metadata.Format === TextureFrameSeriesAnimator.FORMAT_RG16);
|
|
40590
|
+
}
|
|
40591
|
+
TextureFrameSeriesAnimator.IsPackedValue = IsPackedValue;
|
|
40592
|
+
/**
|
|
40593
|
+
* The normalised 0 to 1 value at a texel, from whichever format the archive packed it in.
|
|
40413
40594
|
* @param metadata the archive's Data.generation
|
|
40595
|
+
* @param pixels untinted RGBA value pixels
|
|
40596
|
+
* @param at index of the texel's red channel
|
|
40414
40597
|
*/
|
|
40415
|
-
function
|
|
40416
|
-
if (
|
|
40417
|
-
return 1;
|
|
40598
|
+
function NormalisedAt(metadata, pixels, at) {
|
|
40599
|
+
if (IsPackedValue(metadata)) {
|
|
40600
|
+
return (pixels[at] * 256 + pixels[at + 1]) / 65535;
|
|
40418
40601
|
}
|
|
40419
|
-
return
|
|
40602
|
+
return pixels[at] / 255;
|
|
40420
40603
|
}
|
|
40421
|
-
TextureFrameSeriesAnimator.
|
|
40604
|
+
TextureFrameSeriesAnimator.NormalisedAt = NormalisedAt;
|
|
40605
|
+
// Values already sit on the ellipsoid Cesium measures against, so nothing is added to place them.
|
|
40606
|
+
TextureFrameSeriesAnimator.DATUM_ELLIPSOIDAL = "WGS84";
|
|
40422
40607
|
/**
|
|
40423
|
-
* Whether
|
|
40608
|
+
* Whether the values are heights against a vertical datum rather than a thickness.
|
|
40609
|
+
*
|
|
40610
|
+
* A thickness rises from wherever the polygon sits and a height already knows where it belongs, so
|
|
40611
|
+
* this is what decides whether the polygon's own altitude may be added underneath it.
|
|
40424
40612
|
* @param metadata the archive's Data.generation
|
|
40425
40613
|
*/
|
|
40426
|
-
function
|
|
40427
|
-
return
|
|
40428
|
-
|
|
40429
|
-
|
|
40430
|
-
|
|
40431
|
-
|
|
40432
|
-
|
|
40433
|
-
|
|
40434
|
-
|
|
40614
|
+
function IsDatumHeight(metadata) {
|
|
40615
|
+
return Boolean(metadata && metadata.SourceVerticalDatum);
|
|
40616
|
+
}
|
|
40617
|
+
TextureFrameSeriesAnimator.IsDatumHeight = IsDatumHeight;
|
|
40618
|
+
/**
|
|
40619
|
+
* The archive's tiles, which Adapt() guarantees are present.
|
|
40620
|
+
* @param metadata the archive's Data.generation
|
|
40621
|
+
*/
|
|
40622
|
+
function TilesOf(metadata) {
|
|
40623
|
+
return (metadata && metadata.Tiles) || [];
|
|
40624
|
+
}
|
|
40625
|
+
TextureFrameSeriesAnimator.TilesOf = TilesOf;
|
|
40435
40626
|
/**
|
|
40436
40627
|
* Turns a value in the attribute's own units into the 0 to 1 position the ramp is indexed by.
|
|
40437
40628
|
*
|
|
@@ -40450,44 +40641,18 @@ var TextureFrameSeriesAnimator;
|
|
|
40450
40641
|
return Math.min(1, Math.max(0, (value - lo) / span));
|
|
40451
40642
|
}
|
|
40452
40643
|
TextureFrameSeriesAnimator.NormalisePosition = NormalisePosition;
|
|
40453
|
-
/**
|
|
40454
|
-
* Whether the frames are a departure from each cell's own normal rather than a raw reading.
|
|
40455
|
-
*
|
|
40456
|
-
* Worth asking before labelling anything: the two measures need different words for the same
|
|
40457
|
-
* number, and calling an anomaly "water depth" is a worse error than the coarse ramp it replaced.
|
|
40458
|
-
* @param metadata the archive's Data.generation
|
|
40459
|
-
*/
|
|
40460
|
-
function IsAnomalyMeasure(metadata) {
|
|
40461
|
-
return Boolean(metadata && metadata.Measure === TextureFrameSeriesAnimator.MEASURE_ANOMALY);
|
|
40462
|
-
}
|
|
40463
|
-
TextureFrameSeriesAnimator.IsAnomalyMeasure = IsAnomalyMeasure;
|
|
40464
|
-
/**
|
|
40465
|
-
* How much the value moves anywhere in the series, in source units.
|
|
40466
|
-
*
|
|
40467
|
-
* Falls back to the published range, which is the right answer for an anomaly archive (its range
|
|
40468
|
-
* IS the movement) and the only available one for an archive predating AnomalyMax.
|
|
40469
|
-
* @param metadata the archive's Data.generation
|
|
40470
|
-
*/
|
|
40471
|
-
function MovingRange(metadata) {
|
|
40472
|
-
if (!metadata) {
|
|
40473
|
-
return undefined;
|
|
40474
|
-
}
|
|
40475
|
-
if (typeof metadata.AnomalyMax === "number" && metadata.AnomalyMax > 0) {
|
|
40476
|
-
return metadata.AnomalyMax;
|
|
40477
|
-
}
|
|
40478
|
-
if (typeof metadata.ValueMin === "number" && typeof metadata.ValueMax === "number") {
|
|
40479
|
-
return Math.abs(metadata.ValueMax - metadata.ValueMin);
|
|
40480
|
-
}
|
|
40481
|
-
return undefined;
|
|
40482
|
-
}
|
|
40483
|
-
TextureFrameSeriesAnimator.MovingRange = MovingRange;
|
|
40484
40644
|
/**
|
|
40485
40645
|
* Detects whether a ClientFile's `Data.generation` metadata describes a frame archive rather than a single static image,
|
|
40486
40646
|
* so a caller can decide whether to construct an Animator or fall back to the existing static-texture path.
|
|
40487
|
-
* @param data ClientFile.Data
|
|
40647
|
+
* @param data ClientFile.Data
|
|
40488
40648
|
*/
|
|
40489
40649
|
function IsFrameArchiveMetadata(data) {
|
|
40490
|
-
|
|
40650
|
+
const generation = data && data.generation;
|
|
40651
|
+
if (!generation) {
|
|
40652
|
+
return false;
|
|
40653
|
+
}
|
|
40654
|
+
return (typeof generation.Version === "number" ||
|
|
40655
|
+
(Array.isArray(generation.Frames) && generation.Frames.length > 0));
|
|
40491
40656
|
}
|
|
40492
40657
|
TextureFrameSeriesAnimator.IsFrameArchiveMetadata = IsFrameArchiveMetadata;
|
|
40493
40658
|
// First resolvable static number out of a calculator field list, since that is all a border needs.
|
|
@@ -40533,10 +40698,27 @@ var TextureFrameSeriesAnimator;
|
|
|
40533
40698
|
TextureFrameSeriesAnimator.AppearanceSignature = AppearanceSignature;
|
|
40534
40699
|
const MAX_COMPOSITE_TEXELS = 2048;
|
|
40535
40700
|
const VALUE_DILATE_PASSES = 2;
|
|
40701
|
+
/*
|
|
40702
|
+
* Rewrites a packed 16 bit value as the 8 bit grey the colour ramps index on.
|
|
40703
|
+
*
|
|
40704
|
+
* All three channels, since a ramp is free to read any of them and a leftover low byte in G would
|
|
40705
|
+
* show up as a green cast on the one that reads them all.
|
|
40706
|
+
*/
|
|
40707
|
+
function flattenPacked(pixels, packed) {
|
|
40708
|
+
if (!packed) {
|
|
40709
|
+
return;
|
|
40710
|
+
}
|
|
40711
|
+
for (let i = 0; i < pixels.length; i += 4) {
|
|
40712
|
+
const grey = Math.round((pixels[i] * 256 + pixels[i + 1]) / 65535 * 255);
|
|
40713
|
+
pixels[i] = grey;
|
|
40714
|
+
pixels[i + 1] = grey;
|
|
40715
|
+
pixels[i + 2] = grey;
|
|
40716
|
+
}
|
|
40717
|
+
}
|
|
40536
40718
|
/*
|
|
40537
40719
|
* Bleeds covered values outward into uncovered texels, leaving alpha untouched.
|
|
40538
40720
|
*/
|
|
40539
|
-
function dilateValues(value, width, height, passes) {
|
|
40721
|
+
function dilateValues(value, width, height, passes, packed) {
|
|
40540
40722
|
const texels = width * height;
|
|
40541
40723
|
const filled = new Uint8Array(texels);
|
|
40542
40724
|
for (let p = 0; p < texels; p++) {
|
|
@@ -40560,15 +40742,25 @@ var TextureFrameSeriesAnimator;
|
|
|
40560
40742
|
if (nx < 0 || ny < 0 || nx >= width || ny >= height || !wasFilled[ny * width + nx]) {
|
|
40561
40743
|
continue;
|
|
40562
40744
|
}
|
|
40563
|
-
|
|
40745
|
+
const at = (ny * width + nx) * 4;
|
|
40746
|
+
// Averaged as a value rather than per byte: averaging a packed low byte
|
|
40747
|
+
// on its own wraps at every 256th step and speckles the bled edge.
|
|
40748
|
+
sum += packed ? source[at] * 256 + source[at + 1] : source[at];
|
|
40564
40749
|
hits++;
|
|
40565
40750
|
}
|
|
40566
40751
|
}
|
|
40567
40752
|
if (hits > 0) {
|
|
40568
40753
|
const v = Math.round(sum / hits);
|
|
40569
|
-
|
|
40570
|
-
|
|
40571
|
-
|
|
40754
|
+
if (packed) {
|
|
40755
|
+
value[p * 4] = (v >> 8) & 255;
|
|
40756
|
+
value[p * 4 + 1] = v & 255;
|
|
40757
|
+
value[p * 4 + 2] = 0;
|
|
40758
|
+
}
|
|
40759
|
+
else {
|
|
40760
|
+
value[p * 4] = v;
|
|
40761
|
+
value[p * 4 + 1] = v;
|
|
40762
|
+
value[p * 4 + 2] = v;
|
|
40763
|
+
}
|
|
40572
40764
|
filled[p] = 1;
|
|
40573
40765
|
}
|
|
40574
40766
|
}
|
|
@@ -40606,7 +40798,6 @@ var TextureFrameSeriesAnimator;
|
|
|
40606
40798
|
// forcing Cesium to re-upload the texture only when something changed.
|
|
40607
40799
|
this.pool = [document.createElement("canvas"), document.createElement("canvas")];
|
|
40608
40800
|
this.poolIdx = 0;
|
|
40609
|
-
this.scratch = null;
|
|
40610
40801
|
this.valueDims = null;
|
|
40611
40802
|
this.presentVersion = 0;
|
|
40612
40803
|
this.extremesLoad = null;
|
|
@@ -40629,7 +40820,7 @@ var TextureFrameSeriesAnimator;
|
|
|
40629
40820
|
this.highColor = (mask && Color$1.ColorFromStr(mask.maxColor)) || DEFAULT_HIGH_COLOR;
|
|
40630
40821
|
// Positions are authored in the attribute's units and normalised once here, so the
|
|
40631
40822
|
// per-pixel loop stays a comparison against 0 to 1 like the two-colour path.
|
|
40632
|
-
const points = mask
|
|
40823
|
+
const points = mask && mask.points;
|
|
40633
40824
|
this.rampStops = (points && points.length > 0)
|
|
40634
40825
|
? points.map((p) => ({
|
|
40635
40826
|
position: NormalisePosition(options.metadata, p.position),
|
|
@@ -40655,9 +40846,8 @@ var TextureFrameSeriesAnimator;
|
|
|
40655
40846
|
this.produceValueCanvas = Boolean(options.produceValueCanvas);
|
|
40656
40847
|
this.metadata = options.metadata;
|
|
40657
40848
|
this.drapeExtent = options.drapeExtent;
|
|
40658
|
-
this.tiles =
|
|
40659
|
-
this.
|
|
40660
|
-
this.maskBaseline = (_c = options.maskBaseline) !== null && _c !== void 0 ? _c : Boolean(options.baselineMask);
|
|
40849
|
+
this.tiles = TilesOf(options.metadata);
|
|
40850
|
+
this.maskBaseline = (_c = options.maskBaseline) !== null && _c !== void 0 ? _c : this.tiles.some((tile) => Boolean(tile.BaselineMask));
|
|
40661
40851
|
this.valueCanvas = this.produceValueCanvas ? document.createElement("canvas") : null;
|
|
40662
40852
|
this.driveMaterial = options.driveMaterial !== false;
|
|
40663
40853
|
this.originalMaterial = options.entity.polygon.material;
|
|
@@ -40833,32 +41023,20 @@ var TextureFrameSeriesAnimator;
|
|
|
40833
41023
|
}
|
|
40834
41024
|
async fetchAndTint(idx) {
|
|
40835
41025
|
const tiles = this.tiles;
|
|
40836
|
-
|
|
40837
|
-
|
|
40838
|
-
|
|
40839
|
-
|
|
40840
|
-
|
|
40841
|
-
|
|
40842
|
-
|
|
40843
|
-
|
|
40844
|
-
const at = tile.Frames[idx];
|
|
40845
|
-
if (!at) {
|
|
40846
|
-
continue;
|
|
40847
|
-
}
|
|
40848
|
-
lo = Math.min(lo, at.ByteOffset);
|
|
40849
|
-
hi = Math.max(hi, at.ByteOffset + at.ByteLength);
|
|
41026
|
+
// Every tile's frame for one timestep sits contiguously, because the generator writes
|
|
41027
|
+
// frame major. So a tiled frame is still ONE range request, not one per tile.
|
|
41028
|
+
let lo = Number.MAX_SAFE_INTEGER;
|
|
41029
|
+
let hi = 0;
|
|
41030
|
+
for (const tile of tiles) {
|
|
41031
|
+
const at = tile.Frames[idx];
|
|
41032
|
+
if (!at) {
|
|
41033
|
+
continue;
|
|
40850
41034
|
}
|
|
40851
|
-
|
|
40852
|
-
|
|
40853
|
-
buffer = await response.arrayBuffer();
|
|
40854
|
-
}
|
|
40855
|
-
else {
|
|
40856
|
-
const entry = this.frames[idx];
|
|
40857
|
-
const start = entry.ByteOffset;
|
|
40858
|
-
const end = entry.ByteOffset + entry.ByteLength - 1;
|
|
40859
|
-
const response = await fetch(this.archiveUrl, { headers: { Range: `bytes=${start}-${end}` } });
|
|
40860
|
-
buffer = await response.arrayBuffer();
|
|
41035
|
+
lo = Math.min(lo, at.ByteOffset);
|
|
41036
|
+
hi = Math.max(hi, at.ByteOffset + at.ByteLength);
|
|
40861
41037
|
}
|
|
41038
|
+
const response = await fetch(this.archiveUrl, { headers: { Range: `bytes=${lo}-${hi - 1}` } });
|
|
41039
|
+
const buffer = await response.arrayBuffer();
|
|
40862
41040
|
if (this.disposed) {
|
|
40863
41041
|
return;
|
|
40864
41042
|
}
|
|
@@ -40868,9 +41046,7 @@ var TextureFrameSeriesAnimator;
|
|
|
40868
41046
|
if (this.disposed) {
|
|
40869
41047
|
return;
|
|
40870
41048
|
}
|
|
40871
|
-
const decoded = tiles
|
|
40872
|
-
? await this.composeTiles(tiles, idx, buffer, span)
|
|
40873
|
-
: await this.decodeAndTint(buffer);
|
|
41049
|
+
const decoded = await this.composeTiles(tiles, idx, buffer, lo);
|
|
40874
41050
|
if (this.disposed) {
|
|
40875
41051
|
return;
|
|
40876
41052
|
}
|
|
@@ -40881,26 +41057,6 @@ var TextureFrameSeriesAnimator;
|
|
|
40881
41057
|
this.beginCrossfadeTo(idx);
|
|
40882
41058
|
}
|
|
40883
41059
|
}
|
|
40884
|
-
/**
|
|
40885
|
-
* Decodes one frame's raw PNG bytes (as returned by a Range GET) and applies the grayscale color mask.
|
|
40886
|
-
*/
|
|
40887
|
-
async decodeAndTint(buffer) {
|
|
40888
|
-
const blob = new Blob([buffer], { type: "image/png" });
|
|
40889
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
40890
|
-
let image;
|
|
40891
|
-
try {
|
|
40892
|
-
image = await loadImage(objectUrl);
|
|
40893
|
-
}
|
|
40894
|
-
finally {
|
|
40895
|
-
URL.revokeObjectURL(objectUrl);
|
|
40896
|
-
}
|
|
40897
|
-
const canvas = document.createElement("canvas");
|
|
40898
|
-
canvas.width = image.width;
|
|
40899
|
-
canvas.height = image.height;
|
|
40900
|
-
const ctx = canvas.getContext("2d");
|
|
40901
|
-
ctx.drawImage(image, 0, 0);
|
|
40902
|
-
return this.tint(ctx.getImageData(0, 0, canvas.width, canvas.height));
|
|
40903
|
-
}
|
|
40904
41060
|
/*
|
|
40905
41061
|
* Draws every tile of one frame into a single raster covering the drape extent.
|
|
40906
41062
|
*/
|
|
@@ -40973,6 +41129,10 @@ var TextureFrameSeriesAnimator;
|
|
|
40973
41129
|
// Copied before tinting: the ramp is a lerp between two colours, so the value cannot be
|
|
40974
41130
|
// recovered from the tinted pixels afterwards.
|
|
40975
41131
|
const valuePixels = this.produceValueCanvas ? new Uint8ClampedArray(imageData.data) : undefined;
|
|
41132
|
+
// The ramp indexes on R as an 8 bit grey, so a packed frame is flattened to one here
|
|
41133
|
+
// rather than teaching every ramp function a second format.
|
|
41134
|
+
// The copy above keeps the packed pair, which is what displacement and labels read.
|
|
41135
|
+
flattenPacked(imageData.data, IsPackedValue(this.metadata));
|
|
40976
41136
|
// Stops win when supplied: they can express a band and a hidden floor, which a two
|
|
40977
41137
|
// colour ramp cannot. The pair stays the fallback so an older style still draws.
|
|
40978
41138
|
if (this.rampStops && this.rampStops.length > 0) {
|
|
@@ -40986,72 +41146,20 @@ var TextureFrameSeriesAnimator;
|
|
|
40986
41146
|
}
|
|
40987
41147
|
this.applyBaselineMask(imageData.data, valuePixels, canvas.width, canvas.height);
|
|
40988
41148
|
if (valuePixels) {
|
|
40989
|
-
dilateValues(valuePixels, canvas.width, canvas.height, VALUE_DILATE_PASSES);
|
|
41149
|
+
dilateValues(valuePixels, canvas.width, canvas.height, VALUE_DILATE_PASSES, IsPackedValue(this.metadata));
|
|
40990
41150
|
}
|
|
40991
41151
|
return { pixels: imageData.data, width: canvas.width, height: canvas.height, valuePixels };
|
|
40992
41152
|
}
|
|
40993
41153
|
/*
|
|
40994
|
-
* Paints one frame's pixels onto a canvas
|
|
41154
|
+
* Paints one frame's composited pixels onto a canvas.
|
|
40995
41155
|
*/
|
|
40996
41156
|
writeInto(canvas, pixels, dims) {
|
|
40997
|
-
const rect = this.sourceRect(dims);
|
|
40998
|
-
if (!rect) {
|
|
40999
|
-
canvas.width = dims.width;
|
|
41000
|
-
canvas.height = dims.height;
|
|
41001
|
-
const direct = canvas.getContext("2d");
|
|
41002
|
-
const image = direct.createImageData(dims.width, dims.height);
|
|
41003
|
-
image.data.set(pixels);
|
|
41004
|
-
direct.putImageData(image, 0, 0);
|
|
41005
|
-
return;
|
|
41006
|
-
}
|
|
41007
|
-
if (!this.scratch) {
|
|
41008
|
-
this.scratch = document.createElement("canvas");
|
|
41009
|
-
}
|
|
41010
|
-
this.scratch.width = dims.width;
|
|
41011
|
-
this.scratch.height = dims.height;
|
|
41012
|
-
const scratchCtx = this.scratch.getContext("2d");
|
|
41013
|
-
const image = scratchCtx.createImageData(dims.width, dims.height);
|
|
41014
|
-
image.data.set(pixels);
|
|
41015
|
-
scratchCtx.putImageData(image, 0, 0);
|
|
41016
41157
|
canvas.width = dims.width;
|
|
41017
41158
|
canvas.height = dims.height;
|
|
41018
41159
|
const ctx = canvas.getContext("2d");
|
|
41019
|
-
|
|
41020
|
-
|
|
41021
|
-
ctx.
|
|
41022
|
-
ctx.clearRect(0, 0, dims.width, dims.height);
|
|
41023
|
-
ctx.drawImage(this.scratch, rect.x, rect.y, rect.width, rect.height, 0, 0, dims.width, dims.height);
|
|
41024
|
-
}
|
|
41025
|
-
/*
|
|
41026
|
-
* The part of the archive raster that the drape extent covers, in source pixels.
|
|
41027
|
-
*/
|
|
41028
|
-
sourceRect(dims) {
|
|
41029
|
-
const drape = this.drapeExtent;
|
|
41030
|
-
const m = this.metadata;
|
|
41031
|
-
// A composited frame was drawn into the drape extent already, so resampling it again
|
|
41032
|
-
// would apply the same correction twice.
|
|
41033
|
-
if (this.tiles) {
|
|
41034
|
-
return null;
|
|
41035
|
-
}
|
|
41036
|
-
if (!drape || !m || m.West == null || m.East == null || m.South == null || m.North == null) {
|
|
41037
|
-
return null;
|
|
41038
|
-
}
|
|
41039
|
-
const spanLon = m.East - m.West;
|
|
41040
|
-
const spanLat = m.North - m.South;
|
|
41041
|
-
if (!(spanLon > 0) || !(spanLat > 0)) {
|
|
41042
|
-
return null;
|
|
41043
|
-
}
|
|
41044
|
-
const x = (drape.West - m.West) / spanLon * dims.width;
|
|
41045
|
-
const width = (drape.East - drape.West) / spanLon * dims.width;
|
|
41046
|
-
const y = (m.North - drape.North) / spanLat * dims.height;
|
|
41047
|
-
const height = (drape.North - drape.South) / spanLat * dims.height;
|
|
41048
|
-
// A drape that already matches the archive is the common case and must not pay for a
|
|
41049
|
-
// resample, nor lose a half pixel to rounding.
|
|
41050
|
-
if (Math.abs(x) < 0.01 && Math.abs(y) < 0.01
|
|
41051
|
-
&& Math.abs(width - dims.width) < 0.01 && Math.abs(height - dims.height) < 0.01) {
|
|
41052
|
-
return null;
|
|
41053
|
-
}
|
|
41054
|
-
return { x, y, width, height };
|
|
41160
|
+
const image = ctx.createImageData(dims.width, dims.height);
|
|
41161
|
+
image.data.set(pixels);
|
|
41162
|
+
ctx.putImageData(image, 0, 0);
|
|
41055
41163
|
}
|
|
41056
41164
|
/**
|
|
41057
41165
|
* The archive's per-cell floor and ceiling rasters, once EnsureExtremes has resolved.
|
|
@@ -41063,45 +41171,16 @@ var TextureFrameSeriesAnimator;
|
|
|
41063
41171
|
* Fetches and decodes the floor and ceiling rasters, at most once.
|
|
41064
41172
|
*/
|
|
41065
41173
|
EnsureExtremes() {
|
|
41066
|
-
if (this.extremesLoad) {
|
|
41067
|
-
return this.extremesLoad;
|
|
41068
|
-
}
|
|
41069
|
-
if (this.tiles) {
|
|
41174
|
+
if (!this.extremesLoad) {
|
|
41070
41175
|
this.extremesLoad = this.loadTiledExtremes();
|
|
41071
|
-
|
|
41072
|
-
}
|
|
41073
|
-
const floor = this.metadata && this.metadata.Floor;
|
|
41074
|
-
const ceiling = this.metadata && this.metadata.Ceiling;
|
|
41075
|
-
if (!floor && !ceiling) {
|
|
41076
|
-
this.extremesLoad = Promise.resolve();
|
|
41077
|
-
return this.extremesLoad;
|
|
41078
|
-
}
|
|
41079
|
-
this.extremesLoad = Promise.all([
|
|
41080
|
-
floor ? this.loadImageDataAt(floor) : Promise.resolve(null),
|
|
41081
|
-
ceiling ? this.loadImageDataAt(ceiling) : Promise.resolve(null)
|
|
41082
|
-
]).then(([f, c]) => {
|
|
41083
|
-
if (this.disposed) {
|
|
41084
|
-
return;
|
|
41085
|
-
}
|
|
41086
|
-
this.floorPixels = f;
|
|
41087
|
-
this.ceilingPixels = c;
|
|
41088
|
-
}).catch((e) => {
|
|
41089
|
-
// Missing extremes cost a label its range, and must not take the animation with them.
|
|
41090
|
-
console.warn("TextureFrameSeriesAnimator: could not load the extremes rasters.", e);
|
|
41091
|
-
});
|
|
41176
|
+
}
|
|
41092
41177
|
return this.extremesLoad;
|
|
41093
41178
|
}
|
|
41094
41179
|
/*
|
|
41095
41180
|
* Composites each tile's baseline mask into one covering the composited frames.
|
|
41096
|
-
*
|
|
41097
|
-
* A tiled archive publishes the mask per tile, so reading the archive level BaselineMask
|
|
41098
|
-
* finds nothing and hiding dry cells silently does nothing at all.
|
|
41099
41181
|
*/
|
|
41100
41182
|
async loadTiledBaselineMask() {
|
|
41101
41183
|
const tiles = this.tiles;
|
|
41102
|
-
if (!tiles) {
|
|
41103
|
-
return;
|
|
41104
|
-
}
|
|
41105
41184
|
const entries = tiles.map((tile) => tile.BaselineMask);
|
|
41106
41185
|
let lo = Number.MAX_SAFE_INTEGER;
|
|
41107
41186
|
let hi = 0;
|
|
@@ -41155,14 +41234,11 @@ var TextureFrameSeriesAnimator;
|
|
|
41155
41234
|
/*
|
|
41156
41235
|
* Composites each tile's floor and ceiling into rasters matching the composited frames.
|
|
41157
41236
|
*
|
|
41158
|
-
* A
|
|
41159
|
-
*
|
|
41237
|
+
* A label indexes them by the same texel as the value canvas, so they have to be laid out the
|
|
41238
|
+
* same way rather than fetched as whole-extent rasters.
|
|
41160
41239
|
*/
|
|
41161
41240
|
async loadTiledExtremes() {
|
|
41162
41241
|
const tiles = this.tiles;
|
|
41163
|
-
if (!tiles) {
|
|
41164
|
-
return;
|
|
41165
|
-
}
|
|
41166
41242
|
const target = this.compositeExtent();
|
|
41167
41243
|
const size = this.compositeSize(tiles, target);
|
|
41168
41244
|
// One request for the whole extremes block. They sit contiguously after the frames, so
|
|
@@ -41257,70 +41333,6 @@ var TextureFrameSeriesAnimator;
|
|
|
41257
41333
|
}
|
|
41258
41334
|
}));
|
|
41259
41335
|
}
|
|
41260
|
-
/*
|
|
41261
|
-
* Range GETs one entry and decodes it to an image.
|
|
41262
|
-
*/
|
|
41263
|
-
async loadImageAt(entry) {
|
|
41264
|
-
const start = entry.ByteOffset;
|
|
41265
|
-
const end = entry.ByteOffset + entry.ByteLength - 1;
|
|
41266
|
-
const response = await fetch(this.archiveUrl, { headers: { Range: `bytes=${start}-${end}` } });
|
|
41267
|
-
const buffer = await response.arrayBuffer();
|
|
41268
|
-
const objectUrl = URL.createObjectURL(new Blob([buffer], { type: "image/png" }));
|
|
41269
|
-
try {
|
|
41270
|
-
return await loadImage(objectUrl);
|
|
41271
|
-
}
|
|
41272
|
-
finally {
|
|
41273
|
-
URL.revokeObjectURL(objectUrl);
|
|
41274
|
-
}
|
|
41275
|
-
}
|
|
41276
|
-
/*
|
|
41277
|
-
* Puts a static raster through the same resample the frames get.
|
|
41278
|
-
*/
|
|
41279
|
-
remap(image) {
|
|
41280
|
-
if (!image) {
|
|
41281
|
-
return null;
|
|
41282
|
-
}
|
|
41283
|
-
const rect = this.sourceRect({ width: image.width, height: image.height });
|
|
41284
|
-
if (!rect) {
|
|
41285
|
-
return image;
|
|
41286
|
-
}
|
|
41287
|
-
const from = document.createElement("canvas");
|
|
41288
|
-
from.width = image.width;
|
|
41289
|
-
from.height = image.height;
|
|
41290
|
-
from.getContext("2d").putImageData(image, 0, 0);
|
|
41291
|
-
const to = document.createElement("canvas");
|
|
41292
|
-
to.width = image.width;
|
|
41293
|
-
to.height = image.height;
|
|
41294
|
-
const ctx = to.getContext("2d");
|
|
41295
|
-
ctx.imageSmoothingEnabled = false;
|
|
41296
|
-
ctx.clearRect(0, 0, image.width, image.height);
|
|
41297
|
-
ctx.drawImage(from, rect.x, rect.y, rect.width, rect.height, 0, 0, image.width, image.height);
|
|
41298
|
-
return ctx.getImageData(0, 0, image.width, image.height);
|
|
41299
|
-
}
|
|
41300
|
-
/*
|
|
41301
|
-
* Range GETs one entry out of the blob and decodes it to pixels.
|
|
41302
|
-
*/
|
|
41303
|
-
async loadImageDataAt(entry) {
|
|
41304
|
-
const start = entry.ByteOffset;
|
|
41305
|
-
const end = entry.ByteOffset + entry.ByteLength - 1;
|
|
41306
|
-
const response = await fetch(this.archiveUrl, { headers: { Range: `bytes=${start}-${end}` } });
|
|
41307
|
-
const buffer = await response.arrayBuffer();
|
|
41308
|
-
const blob = new Blob([buffer], { type: "image/png" });
|
|
41309
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
41310
|
-
let image;
|
|
41311
|
-
try {
|
|
41312
|
-
image = await loadImage(objectUrl);
|
|
41313
|
-
}
|
|
41314
|
-
finally {
|
|
41315
|
-
URL.revokeObjectURL(objectUrl);
|
|
41316
|
-
}
|
|
41317
|
-
const canvas = document.createElement("canvas");
|
|
41318
|
-
canvas.width = image.width;
|
|
41319
|
-
canvas.height = image.height;
|
|
41320
|
-
const ctx = canvas.getContext("2d");
|
|
41321
|
-
ctx.drawImage(image, 0, 0);
|
|
41322
|
-
return ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
41323
|
-
}
|
|
41324
41336
|
/**
|
|
41325
41337
|
* Fetches and decodes the archive's static baseline mask, at most once.
|
|
41326
41338
|
*/
|
|
@@ -41515,6 +41527,52 @@ var TextureValueLabels;
|
|
|
41515
41527
|
return out;
|
|
41516
41528
|
}
|
|
41517
41529
|
TextureValueLabels.ClipOutline = ClipOutline;
|
|
41530
|
+
/**
|
|
41531
|
+
* One cell's numbers as a label should print them, or null where the texture has no data there.
|
|
41532
|
+
* @param params at is the index of the cell's red channel. sourceMap is derived from the metadata
|
|
41533
|
+
* when omitted, which a caller reading many cells should hoist rather than repeat.
|
|
41534
|
+
*/
|
|
41535
|
+
function ReadingAt(params) {
|
|
41536
|
+
const { metadata, source, floor, ceiling, at } = params;
|
|
41537
|
+
if (source.data[at + 3] < 128) {
|
|
41538
|
+
return null;
|
|
41539
|
+
}
|
|
41540
|
+
const lo = metadata && typeof metadata.ValueMin === "number" ? metadata.ValueMin : 0;
|
|
41541
|
+
const hi = metadata && typeof metadata.ValueMax === "number" ? metadata.ValueMax : 1;
|
|
41542
|
+
const normalised = TextureFrameSeriesAnimator.NormalisedAt(metadata, source.data, at);
|
|
41543
|
+
const toSource = params.sourceMap !== undefined
|
|
41544
|
+
? params.sourceMap
|
|
41545
|
+
: TextureFrameSeriesAnimator.SourceMap(metadata);
|
|
41546
|
+
const inSource = (value) => TextureFrameSeriesAnimator.ToSource(toSource, value);
|
|
41547
|
+
const reading = { value: inSource(lo + normalised * (hi - lo)) };
|
|
41548
|
+
if (TextureFrameSeriesAnimator.IsTransformed(metadata)) {
|
|
41549
|
+
return reading;
|
|
41550
|
+
}
|
|
41551
|
+
const eLo = metadata && metadata.ExtremesValueMin;
|
|
41552
|
+
const eHi = metadata && metadata.ExtremesValueMax;
|
|
41553
|
+
if (typeof eLo === "number" && typeof eHi === "number") {
|
|
41554
|
+
if (floor) {
|
|
41555
|
+
reading.floor = inSource(eLo + decode16(floor.data, at) * (eHi - eLo));
|
|
41556
|
+
}
|
|
41557
|
+
if (ceiling) {
|
|
41558
|
+
reading.ceiling = inSource(eLo + decode16(ceiling.data, at) * (eHi - eLo));
|
|
41559
|
+
}
|
|
41560
|
+
}
|
|
41561
|
+
return reading;
|
|
41562
|
+
}
|
|
41563
|
+
TextureValueLabels.ReadingAt = ReadingAt;
|
|
41564
|
+
/**
|
|
41565
|
+
* The unit a label's value line should name, or undefined when the archive states none.
|
|
41566
|
+
* @param metadata the archive's Data.generation
|
|
41567
|
+
*/
|
|
41568
|
+
function LabelUnits(metadata) {
|
|
41569
|
+
if (!metadata) {
|
|
41570
|
+
return undefined;
|
|
41571
|
+
}
|
|
41572
|
+
const recovered = TextureFrameSeriesAnimator.SourceMap(metadata);
|
|
41573
|
+
return (recovered && metadata.SourceUnits) || metadata.Units;
|
|
41574
|
+
}
|
|
41575
|
+
TextureValueLabels.LabelUnits = LabelUnits;
|
|
41518
41576
|
/**
|
|
41519
41577
|
* How many cells apart labels should sit, as a power of two.
|
|
41520
41578
|
* @param options cellPixels is one cell's size on screen, held is the stride already in use
|
|
@@ -41541,6 +41599,7 @@ var TextureValueLabels;
|
|
|
41541
41599
|
TextureValueLabels.ChooseLabelStride = ChooseLabelStride;
|
|
41542
41600
|
class Labels {
|
|
41543
41601
|
constructor(options) {
|
|
41602
|
+
this.sourceMap = null;
|
|
41544
41603
|
this.source = null;
|
|
41545
41604
|
this.painted = null;
|
|
41546
41605
|
this.floor = null;
|
|
@@ -41552,6 +41611,9 @@ var TextureValueLabels;
|
|
|
41552
41611
|
this.extent = options.extent;
|
|
41553
41612
|
this.settings = options.settings || {};
|
|
41554
41613
|
this.metadata = options.metadata;
|
|
41614
|
+
// Once per overlay rather than once per cell: a label pass probes thousands of texels
|
|
41615
|
+
// looking for one worth labelling, and the map cannot change while the metadata does not.
|
|
41616
|
+
this.sourceMap = TextureFrameSeriesAnimator.SourceMap(options.metadata);
|
|
41555
41617
|
this.tiles = options.tiles;
|
|
41556
41618
|
this.clipRing = options.clipRing;
|
|
41557
41619
|
this.canvas = document.createElement("canvas");
|
|
@@ -41967,13 +42029,14 @@ var TextureValueLabels;
|
|
|
41967
42029
|
widestLabel(parts) {
|
|
41968
42030
|
const sample = [];
|
|
41969
42031
|
if (parts.indexOf("value") >= 0) {
|
|
41970
|
-
sample.push("-000.00");
|
|
42032
|
+
sample.push(valueLine("-000.00", LabelUnits(this.metadata)));
|
|
41971
42033
|
}
|
|
41972
42034
|
const range = [];
|
|
41973
|
-
|
|
42035
|
+
const showsRange = !TextureFrameSeriesAnimator.IsTransformed(this.metadata);
|
|
42036
|
+
if (showsRange && parts.indexOf("floor") >= 0) {
|
|
41974
42037
|
range.push("min: -000.00");
|
|
41975
42038
|
}
|
|
41976
|
-
if (parts.indexOf("ceiling") >= 0) {
|
|
42039
|
+
if (showsRange && parts.indexOf("ceiling") >= 0) {
|
|
41977
42040
|
range.push("max: -000.00");
|
|
41978
42041
|
}
|
|
41979
42042
|
if (range.length) {
|
|
@@ -42007,7 +42070,7 @@ var TextureValueLabels;
|
|
|
42007
42070
|
const dp = (_a = this.settings.decimals) !== null && _a !== void 0 ? _a : (Math.abs(reading.value) < 10 ? 2 : 1);
|
|
42008
42071
|
const lines = [];
|
|
42009
42072
|
if (parts.indexOf("value") >= 0) {
|
|
42010
|
-
lines.push(reading.value.toFixed(dp));
|
|
42073
|
+
lines.push(valueLine(reading.value.toFixed(dp), LabelUnits(this.metadata)));
|
|
42011
42074
|
}
|
|
42012
42075
|
// Named rather than a bare pair: two numbers under a third say nothing about which is
|
|
42013
42076
|
// the series low and which is its high.
|
|
@@ -42081,29 +42144,17 @@ var TextureValueLabels;
|
|
|
42081
42144
|
}
|
|
42082
42145
|
// Decodes one cell, skipping anything the texture marks as having no data.
|
|
42083
42146
|
readAt(col, row, cols) {
|
|
42084
|
-
|
|
42085
|
-
const i = (row * cols + col) * 4;
|
|
42086
|
-
if (!this.source || this.source.data[i + 3] < 128) {
|
|
42147
|
+
if (!this.source) {
|
|
42087
42148
|
return null;
|
|
42088
42149
|
}
|
|
42089
|
-
|
|
42090
|
-
|
|
42091
|
-
|
|
42092
|
-
|
|
42093
|
-
|
|
42094
|
-
|
|
42095
|
-
|
|
42096
|
-
|
|
42097
|
-
// An anomaly archive's frames are already floor-relative, so the reading a user
|
|
42098
|
-
// wants is the absolute one. This is the whole reason the floor is published.
|
|
42099
|
-
if (TextureFrameSeriesAnimator.IsAnomalyMeasure(this.metadata)) {
|
|
42100
|
-
reading.value += reading.floor;
|
|
42101
|
-
}
|
|
42102
|
-
}
|
|
42103
|
-
if (this.ceiling && typeof eLo === "number" && typeof eHi === "number") {
|
|
42104
|
-
reading.ceiling = eLo + decode16(this.ceiling.data, i) * (eHi - eLo);
|
|
42105
|
-
}
|
|
42106
|
-
return reading;
|
|
42150
|
+
return ReadingAt({
|
|
42151
|
+
metadata: this.metadata,
|
|
42152
|
+
source: this.source,
|
|
42153
|
+
floor: this.floor,
|
|
42154
|
+
ceiling: this.ceiling,
|
|
42155
|
+
at: (row * cols + col) * 4,
|
|
42156
|
+
sourceMap: this.sourceMap
|
|
42157
|
+
});
|
|
42107
42158
|
}
|
|
42108
42159
|
lonAt(col, cols) {
|
|
42109
42160
|
return this.extent.West + ((col + 0.5) / cols) * (this.extent.East - this.extent.West);
|
|
@@ -42142,6 +42193,13 @@ var TextureValueLabels;
|
|
|
42142
42193
|
}
|
|
42143
42194
|
}
|
|
42144
42195
|
TextureValueLabels.Labels = Labels;
|
|
42196
|
+
/*
|
|
42197
|
+
* The value line. Units go on it alone: repeating them on the range underneath doubles the widest
|
|
42198
|
+
* label to say nothing, and the two lines are plainly the same quantity.
|
|
42199
|
+
*/
|
|
42200
|
+
function valueLine(value, units) {
|
|
42201
|
+
return units ? `${value} (${units})` : value;
|
|
42202
|
+
}
|
|
42145
42203
|
function decode16(data, i) {
|
|
42146
42204
|
return (data[i] * 256 + data[i + 1]) / 65535;
|
|
42147
42205
|
}
|
|
@@ -42167,11 +42225,6 @@ var DisplacedSurfacePrimitive;
|
|
|
42167
42225
|
const SKIRT_FRACTION = 0.015;
|
|
42168
42226
|
// Alpha below which a texel counts as no-data and is not drawn at all.
|
|
42169
42227
|
const COVERAGE_CUTOFF = 0.35;
|
|
42170
|
-
// With no exaggeration stated, the full value range is drawn as this fraction of the extent's shorter side.
|
|
42171
|
-
const AUTO_RELIEF_FRACTION = 0.02;
|
|
42172
|
-
// Ceiling on the derived relief. Sizing purely off the extent is fine for a parcel and absurd for
|
|
42173
|
-
// a whole estuary: 4 m of water over an 82 km extent came out 1.6 km tall.
|
|
42174
|
-
const AUTO_MAX_RELIEF_METRES = 250.0;
|
|
42175
42228
|
// Terrain is sampled on this grid and interpolated between samples.
|
|
42176
42229
|
// Per-texel sampling would be hundreds of thousands of lookups for a surface whose own data is far coarser than that.
|
|
42177
42230
|
const GROUND_SAMPLES_PER_SIDE = 64;
|
|
@@ -42192,6 +42245,7 @@ in float skirt;
|
|
|
42192
42245
|
|
|
42193
42246
|
uniform sampler2D u_valueTexture;
|
|
42194
42247
|
uniform sampler2D u_groundTexture;
|
|
42248
|
+
uniform float u_valuePacked;
|
|
42195
42249
|
uniform float u_valueMin;
|
|
42196
42250
|
uniform float u_valueRange;
|
|
42197
42251
|
uniform float u_exaggeration;
|
|
@@ -42229,18 +42283,37 @@ float sampleGround(vec2 uv) {
|
|
|
42229
42283
|
return mix(mix(h00, h10, f.x), mix(h01, h11, f.x), f.y);
|
|
42230
42284
|
}
|
|
42231
42285
|
|
|
42286
|
+
/*
|
|
42287
|
+
* The texel's normalised value, whichever way the archive packed it.
|
|
42288
|
+
*
|
|
42289
|
+
* A packed frame keeps the high byte in R, so reading R alone would quantise the whole range to 255
|
|
42290
|
+
* steps and draw a plausible wrong surface rather than an obviously broken one.
|
|
42291
|
+
*
|
|
42292
|
+
* Each channel is scaled and then added, rather than reassembled to a 0..65535 integer and divided.
|
|
42293
|
+
* That integer is outside the range mediump guarantees, and a fragment shader only gets highp where
|
|
42294
|
+
* the device offers it, so the obvious form loses the low byte on exactly the older mobile hardware
|
|
42295
|
+
* that Cesium falls back to mediump for.
|
|
42296
|
+
*/
|
|
42297
|
+
float decodeValue(vec4 texel) {
|
|
42298
|
+
float packed16 = texel.r * (255.0 * 256.0 / 65535.0) + texel.g * (255.0 / 65535.0);
|
|
42299
|
+
return mix(texel.r, packed16, u_valuePacked);
|
|
42300
|
+
}
|
|
42301
|
+
|
|
42232
42302
|
void main() {
|
|
42233
42303
|
vec4 texel = texture(u_valueTexture, st);
|
|
42234
42304
|
v_st = st;
|
|
42235
|
-
v_value = texel
|
|
42305
|
+
v_value = decodeValue(texel);
|
|
42236
42306
|
v_coverage = texel.a;
|
|
42237
42307
|
|
|
42238
|
-
|
|
42308
|
+
// Exaggeration stretches the span above the archive's minimum rather than the height itself. On an
|
|
42309
|
+
// elevation the height is measured from the ellipsoid, tens of metres from any of the data, so
|
|
42310
|
+
// scaling that instead translates the whole sheet underground rather than spreading it out.
|
|
42311
|
+
float metres = u_valueMin + v_value * u_valueRange * u_exaggeration;
|
|
42239
42312
|
|
|
42240
42313
|
// Value zero sits at the polygon's own altitude, plus the terrain underneath when the polygon
|
|
42241
42314
|
// is following the ground rather than absolutely positioned.
|
|
42242
42315
|
float ground = sampleGround(st) * u_groundWeight;
|
|
42243
|
-
float displacement = u_baseHeight + ground + metres *
|
|
42316
|
+
float displacement = u_baseHeight + ground + metres * texel.a - skirt * u_skirtDepth;
|
|
42244
42317
|
|
|
42245
42318
|
// Added to the LOW half of the encoded position: a metre-scale offset added to the high half
|
|
42246
42319
|
// would be lost to float32 rounding at an earth radius.
|
|
@@ -42253,6 +42326,7 @@ uniform sampler2D u_valueTexture;
|
|
|
42253
42326
|
uniform sampler2D u_rampTexture;
|
|
42254
42327
|
uniform float u_coverageCutoff;
|
|
42255
42328
|
uniform vec2 u_texelSize;
|
|
42329
|
+
uniform float u_valuePacked;
|
|
42256
42330
|
uniform float u_valueRange;
|
|
42257
42331
|
uniform float u_exaggeration;
|
|
42258
42332
|
uniform float u_metresPerTexel;
|
|
@@ -42261,6 +42335,16 @@ in vec2 v_st;
|
|
|
42261
42335
|
in float v_value;
|
|
42262
42336
|
in float v_coverage;
|
|
42263
42337
|
|
|
42338
|
+
/*
|
|
42339
|
+
* Scaled per channel for the same reason the vertex shader's decode is: reassembling the pair reaches
|
|
42340
|
+
* 65535, which mediump does not have to represent, and this is the shader that may not get highp.
|
|
42341
|
+
*/
|
|
42342
|
+
float valueAt(vec2 uv) {
|
|
42343
|
+
vec4 texel = texture(u_valueTexture, uv);
|
|
42344
|
+
float packed16 = texel.r * (255.0 * 256.0 / 65535.0) + texel.g * (255.0 / 65535.0);
|
|
42345
|
+
return mix(texel.r, packed16, u_valuePacked);
|
|
42346
|
+
}
|
|
42347
|
+
|
|
42264
42348
|
void main() {
|
|
42265
42349
|
if (v_coverage < u_coverageCutoff) {
|
|
42266
42350
|
discard;
|
|
@@ -42275,10 +42359,10 @@ void main() {
|
|
|
42275
42359
|
|
|
42276
42360
|
// Relief shading from the value gradient, so the displacement reads at a distance without
|
|
42277
42361
|
// recomputing vertex normals every time the texture changes.
|
|
42278
|
-
float left =
|
|
42279
|
-
float right =
|
|
42280
|
-
float down =
|
|
42281
|
-
float up =
|
|
42362
|
+
float left = valueAt(v_st - vec2(u_texelSize.x, 0.0));
|
|
42363
|
+
float right = valueAt(v_st + vec2(u_texelSize.x, 0.0));
|
|
42364
|
+
float down = valueAt(v_st - vec2(0.0, u_texelSize.y));
|
|
42365
|
+
float up = valueAt(v_st + vec2(0.0, u_texelSize.y));
|
|
42282
42366
|
float scale = u_valueRange * u_exaggeration;
|
|
42283
42367
|
vec3 n = normalize(vec3((left - right) * scale, (down - up) * scale, 2.0 * u_metresPerTexel));
|
|
42284
42368
|
float lambert = clamp(dot(n, normalize(vec3(-0.5, -0.6, 0.62))), 0.0, 1.0);
|
|
@@ -42488,8 +42572,9 @@ void main() {
|
|
|
42488
42572
|
this.source = options.source || null;
|
|
42489
42573
|
this.valueMin = (_a = options.valueMin) !== null && _a !== void 0 ? _a : 0;
|
|
42490
42574
|
this.valueMax = (_b = options.valueMax) !== null && _b !== void 0 ? _b : 1;
|
|
42491
|
-
this.exaggeration = (_c = options.exaggeration) !== null && _c !== void 0 ? _c :
|
|
42575
|
+
this.exaggeration = (_c = options.exaggeration) !== null && _c !== void 0 ? _c : 1;
|
|
42492
42576
|
this.baseHeight = (_d = options.baseHeight) !== null && _d !== void 0 ? _d : 0;
|
|
42577
|
+
this.packedValue = Boolean(options.packedValue);
|
|
42493
42578
|
this.pixelPlacement = options.pixelPlacement;
|
|
42494
42579
|
this.tileSkirts = Boolean(options.tileSkirts);
|
|
42495
42580
|
this.rampPixels = RampLookup(options.rampStops || null, options.lowColor || DEFAULT_LOW_COLOR, options.highColor || DEFAULT_HIGH_COLOR);
|
|
@@ -42713,6 +42798,14 @@ void main() {
|
|
|
42713
42798
|
if (this.texture) {
|
|
42714
42799
|
this.texture.destroy();
|
|
42715
42800
|
}
|
|
42801
|
+
// Nearest for a packed value, because filtering would blend the two bytes of the
|
|
42802
|
+
// packing rather than the values they encode, the same trap sampleGround avoids.
|
|
42803
|
+
const minification = this.packedValue
|
|
42804
|
+
? TextureMinificationFilter.NEAREST
|
|
42805
|
+
: TextureMinificationFilter.LINEAR;
|
|
42806
|
+
const magnification = this.packedValue
|
|
42807
|
+
? TextureMagnificationFilter.NEAREST
|
|
42808
|
+
: TextureMagnificationFilter.LINEAR;
|
|
42716
42809
|
this.texture = new Texture({
|
|
42717
42810
|
context,
|
|
42718
42811
|
source: this.source,
|
|
@@ -42722,8 +42815,8 @@ void main() {
|
|
|
42722
42815
|
sampler: new Sampler({
|
|
42723
42816
|
wrapS: TextureWrap.CLAMP_TO_EDGE,
|
|
42724
42817
|
wrapT: TextureWrap.CLAMP_TO_EDGE,
|
|
42725
|
-
minificationFilter:
|
|
42726
|
-
magnificationFilter:
|
|
42818
|
+
minificationFilter: minification,
|
|
42819
|
+
magnificationFilter: magnification
|
|
42727
42820
|
})
|
|
42728
42821
|
});
|
|
42729
42822
|
this.textureDirty = false;
|
|
@@ -42824,6 +42917,7 @@ void main() {
|
|
|
42824
42917
|
uniformMap: {
|
|
42825
42918
|
u_valueTexture: () => self.texture,
|
|
42826
42919
|
u_groundTexture: () => self.groundTexture,
|
|
42920
|
+
u_valuePacked: () => (self.packedValue ? 1 : 0),
|
|
42827
42921
|
u_groundWeight: () => (self.followGround && self.groundPixels ? 1 : 0),
|
|
42828
42922
|
u_groundRange: () => new Cartesian2(GROUND_MIN_METRES, GROUND_MAX_METRES),
|
|
42829
42923
|
u_groundSize: () => new Cartesian2(self.groundPixels ? GROUND_SAMPLES_PER_SIDE : 1, self.groundPixels ? GROUND_SAMPLES_PER_SIDE : 1),
|
|
@@ -42876,31 +42970,6 @@ void main() {
|
|
|
42876
42970
|
}
|
|
42877
42971
|
return tiles;
|
|
42878
42972
|
}
|
|
42879
|
-
/**
|
|
42880
|
-
* Exaggeration that makes the full value range stand AUTO_RELIEF_FRACTION of the extent tall.
|
|
42881
|
-
*
|
|
42882
|
-
* Derived from the whole extent rather than per tile: scaling each tile to its own size would
|
|
42883
|
-
* make neighbours disagree along their shared edge and tear the surface apart.
|
|
42884
|
-
* @param extent
|
|
42885
|
-
* @param valueMin
|
|
42886
|
-
* @param valueMax
|
|
42887
|
-
*/
|
|
42888
|
-
function autoExaggeration(extent, valueMin, valueMax) {
|
|
42889
|
-
const range = Math.abs(valueMax - valueMin);
|
|
42890
|
-
if (!(range > 0)) {
|
|
42891
|
-
return 1;
|
|
42892
|
-
}
|
|
42893
|
-
const southWest = Cartesian3.fromDegrees(extent.West, extent.South, 0);
|
|
42894
|
-
const southEast = Cartesian3.fromDegrees(extent.East, extent.South, 0);
|
|
42895
|
-
const northWest = Cartesian3.fromDegrees(extent.West, extent.North, 0);
|
|
42896
|
-
const shorterSide = Math.min(Cartesian3.distance(southWest, southEast), Cartesian3.distance(southWest, northWest));
|
|
42897
|
-
if (!(shorterSide > 0)) {
|
|
42898
|
-
return 1;
|
|
42899
|
-
}
|
|
42900
|
-
const relief = Math.min(shorterSide * AUTO_RELIEF_FRACTION, AUTO_MAX_RELIEF_METRES);
|
|
42901
|
-
return relief / range;
|
|
42902
|
-
}
|
|
42903
|
-
DisplacedSurfacePrimitive.autoExaggeration = autoExaggeration;
|
|
42904
42973
|
function now() {
|
|
42905
42974
|
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
42906
42975
|
}
|
|
@@ -43639,12 +43708,12 @@ function syncDisplacedSurface(params) {
|
|
|
43639
43708
|
&& existingAnimator.GetArchiveUrl() === extrusionArchive.url
|
|
43640
43709
|
&& existingSurface
|
|
43641
43710
|
&& !existingSurface.isDestroyed();
|
|
43642
|
-
const placement = surfacePlacement(entity, heightRef);
|
|
43711
|
+
const placement = surfacePlacement(entity, heightRef, extrusionArchive && TextureFrameSeriesAnimator.IsDatumHeight(extrusionArchive.metadata));
|
|
43643
43712
|
// Whether the surface follows terrain is baked into its ground sampling, so a change there has
|
|
43644
43713
|
// to rebuild rather than update in place.
|
|
43645
43714
|
if (reusable && existingSurface.GetFollowsGround() === placement.followGround) {
|
|
43646
43715
|
existingSurface.SetBaseHeight(placement.baseHeight);
|
|
43647
|
-
existingSurface.SetExaggeration(exaggerationFor(style
|
|
43716
|
+
existingSurface.SetExaggeration(exaggerationFor(style));
|
|
43648
43717
|
return;
|
|
43649
43718
|
}
|
|
43650
43719
|
disposeDisplacedSurface(cEntity, viewer);
|
|
@@ -43668,8 +43737,6 @@ function syncDisplacedSurface(params) {
|
|
|
43668
43737
|
produceValueCanvas: true,
|
|
43669
43738
|
metadata: extrusionArchive.metadata,
|
|
43670
43739
|
cellTexels: 1,
|
|
43671
|
-
baselineMask: extrusionArchive.metadata.BaselineMask,
|
|
43672
|
-
// Off-type for the same reason as the fill path: the pinned bruce-models predates the field.
|
|
43673
43740
|
maskBaseline: style.maskTextureBaseline
|
|
43674
43741
|
});
|
|
43675
43742
|
cEntity[EXTRUSION_ANIMATOR_KEY] = animator;
|
|
@@ -43684,12 +43751,13 @@ function syncDisplacedSurface(params) {
|
|
|
43684
43751
|
terrainProvider: viewer && viewer.terrainProvider,
|
|
43685
43752
|
valueMin: extrusionArchive.metadata.ValueMin,
|
|
43686
43753
|
valueMax: extrusionArchive.metadata.ValueMax,
|
|
43687
|
-
|
|
43754
|
+
packedValue: TextureFrameSeriesAnimator.IsPackedValue(extrusionArchive.metadata),
|
|
43755
|
+
exaggeration: exaggerationFor(style),
|
|
43688
43756
|
lowColor: mask ? Color$1.ColorFromStr(mask.minColor) : null,
|
|
43689
43757
|
highColor: mask ? Color$1.ColorFromStr(mask.maxColor) : null,
|
|
43690
43758
|
// Normalised the same way the animator normalises them, so the surface and the flat drape
|
|
43691
43759
|
// agree about which values the style hides.
|
|
43692
|
-
rampStops: (mask && mask.points || []).map((stop) => ({
|
|
43760
|
+
rampStops: ((mask && mask.points) || []).map((stop) => ({
|
|
43693
43761
|
position: TextureFrameSeriesAnimator.NormalisePosition(extrusionArchive.metadata, stop.position),
|
|
43694
43762
|
color: Color$1.ColorFromStr(stop.color)
|
|
43695
43763
|
})).filter((stop) => Boolean(stop.color))
|
|
@@ -43705,7 +43773,7 @@ function syncDisplacedSurface(params) {
|
|
|
43705
43773
|
* @param entity
|
|
43706
43774
|
* @param heightRef
|
|
43707
43775
|
*/
|
|
43708
|
-
function surfacePlacement(entity, heightRef) {
|
|
43776
|
+
function surfacePlacement(entity, heightRef, datumHeight) {
|
|
43709
43777
|
const rawAltitude = Entity$1.GetValue({
|
|
43710
43778
|
entity,
|
|
43711
43779
|
path: ["Bruce", "Location", "altitude"]
|
|
@@ -43717,32 +43785,18 @@ function surfacePlacement(entity, heightRef) {
|
|
|
43717
43785
|
if (heightRef === HeightReference.RELATIVE_TO_GROUND) {
|
|
43718
43786
|
return { baseHeight: altitude, followGround: true };
|
|
43719
43787
|
}
|
|
43720
|
-
|
|
43788
|
+
// Values that ARE heights against a datum already say where they belong, so adding the entity's
|
|
43789
|
+
// altitude on top would move a measured surface off the datum it was measured against.
|
|
43790
|
+
return { baseHeight: datumHeight ? 0 : altitude, followGround: false };
|
|
43721
43791
|
}
|
|
43722
|
-
/**
|
|
43723
|
-
* The archive's own extent when it recorded one, otherwise the polygon's own bounds so archives
|
|
43724
|
-
* generated before the extent was written still render somewhere sensible.
|
|
43725
|
-
* @param metadata
|
|
43726
|
-
* @param posses
|
|
43727
|
-
*/
|
|
43728
43792
|
/*
|
|
43729
|
-
* The factor a displaced surface should use,
|
|
43730
|
-
*
|
|
43731
|
-
* An elevation is a real height against a datum, so scaling it is not a display choice: it lifts the
|
|
43732
|
-
* surface off the datum it belongs to. Only a thickness is safe to exaggerate, which is why an
|
|
43733
|
-
* elevation archive defaults to 1 rather than to a derived factor.
|
|
43793
|
+
* The factor a displaced surface should use, which is the style's or nothing.
|
|
43734
43794
|
*/
|
|
43735
|
-
function exaggerationFor(style
|
|
43795
|
+
function exaggerationFor(style) {
|
|
43736
43796
|
if (style.extrusionExaggeration != null) {
|
|
43737
43797
|
return style.extrusionExaggeration;
|
|
43738
43798
|
}
|
|
43739
|
-
|
|
43740
|
-
return 1;
|
|
43741
|
-
}
|
|
43742
|
-
if (!extent) {
|
|
43743
|
-
return undefined;
|
|
43744
|
-
}
|
|
43745
|
-
return DisplacedSurfacePrimitive.autoExaggeration(extent, metadata.ValueMin, metadata.ValueMax);
|
|
43799
|
+
return 1;
|
|
43746
43800
|
}
|
|
43747
43801
|
/*
|
|
43748
43802
|
* The lon/lat bounding rectangle of a ring, which is the frame Cesium drapes an image material in.
|
|
@@ -43843,7 +43897,6 @@ function syncTextureFrameArchive(cEntity, frameArchive, viewer, textureColorMask
|
|
|
43843
43897
|
metadata: frameArchive.metadata,
|
|
43844
43898
|
cellBorder,
|
|
43845
43899
|
cellTexels,
|
|
43846
|
-
baselineMask: frameArchive.metadata.BaselineMask,
|
|
43847
43900
|
maskBaseline: maskTextureBaseline,
|
|
43848
43901
|
produceValueCanvas,
|
|
43849
43902
|
drapeExtent
|
|
@@ -43904,20 +43957,19 @@ function syncTextureValueLabels(params) {
|
|
|
43904
43957
|
}
|
|
43905
43958
|
const labels = new TextureValueLabels.Labels({
|
|
43906
43959
|
viewer, extent, settings, metadata,
|
|
43907
|
-
tiles: TextureFrameSeriesAnimator.
|
|
43908
|
-
|
|
43909
|
-
|
|
43910
|
-
|
|
43911
|
-
}))
|
|
43912
|
-
: undefined,
|
|
43960
|
+
tiles: TextureFrameSeriesAnimator.TilesOf(metadata).map((tile) => ({
|
|
43961
|
+
West: tile.West, East: tile.East, South: tile.South, North: tile.North,
|
|
43962
|
+
ResolutionX: tile.ResolutionX, ResolutionY: tile.ResolutionY
|
|
43963
|
+
})),
|
|
43913
43964
|
clipRing: params.clipRing
|
|
43914
43965
|
});
|
|
43915
43966
|
let lastVersion = -1;
|
|
43916
43967
|
let appliedFloor = null;
|
|
43917
43968
|
let appliedCeiling = null;
|
|
43918
|
-
//
|
|
43919
|
-
|
|
43920
|
-
|
|
43969
|
+
// Two extra Range GETs, and worth it only because a label draws the cell's own range from them.
|
|
43970
|
+
if (!TextureFrameSeriesAnimator.IsTransformed(metadata)) {
|
|
43971
|
+
animator.EnsureExtremes();
|
|
43972
|
+
}
|
|
43921
43973
|
const remove = viewer.scene.preRender.addEventListener(() => {
|
|
43922
43974
|
if (animator.IsDisposed()) {
|
|
43923
43975
|
return;
|
|
@@ -44043,10 +44095,14 @@ async function resolveTextureValue(params) {
|
|
|
44043
44095
|
url = clientFile.URL;
|
|
44044
44096
|
const clientFileData = clientFile.Data;
|
|
44045
44097
|
if (TextureFrameSeriesAnimator.IsFrameArchiveMetadata(clientFileData)) {
|
|
44098
|
+
const adapted = TextureFrameSeriesAnimator.Adapt(clientFileData.generation);
|
|
44099
|
+
if (!adapted) {
|
|
44100
|
+
return { dataUri: null, effective: textureTrace.effective };
|
|
44101
|
+
}
|
|
44046
44102
|
return {
|
|
44047
44103
|
dataUri: null,
|
|
44048
44104
|
effective: textureTrace.effective,
|
|
44049
|
-
frameArchive: { url, metadata:
|
|
44105
|
+
frameArchive: { url, metadata: adapted }
|
|
44050
44106
|
};
|
|
44051
44107
|
}
|
|
44052
44108
|
}
|
|
@@ -44075,7 +44131,11 @@ async function resolveTextureCondition(params) {
|
|
|
44075
44131
|
const url = clientFile.URL;
|
|
44076
44132
|
const clientFileData = clientFile.Data;
|
|
44077
44133
|
if (TextureFrameSeriesAnimator.IsFrameArchiveMetadata(clientFileData)) {
|
|
44078
|
-
|
|
44134
|
+
const adapted = TextureFrameSeriesAnimator.Adapt(clientFileData.generation);
|
|
44135
|
+
if (adapted) {
|
|
44136
|
+
return { dataUri: null, effective: null, frameArchive: { url, metadata: adapted } };
|
|
44137
|
+
}
|
|
44138
|
+
return { dataUri: null, effective: null };
|
|
44079
44139
|
}
|
|
44080
44140
|
const cacheKey = "texture-" + url + "-none";
|
|
44081
44141
|
let prom = _textureCache.Get(cacheKey);
|
|
@@ -45559,7 +45619,7 @@ var StyleUtils;
|
|
|
45559
45619
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
45560
45620
|
})(StyleUtils || (StyleUtils = {}));
|
|
45561
45621
|
|
|
45562
|
-
const VERSION = "7.2.
|
|
45622
|
+
const VERSION = "7.2.4";
|
|
45563
45623
|
/**
|
|
45564
45624
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
45565
45625
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|
|
@@ -45576,5 +45636,5 @@ const getENVIRONMENT = () => {
|
|
|
45576
45636
|
return ENVIRONMENT;
|
|
45577
45637
|
};
|
|
45578
45638
|
|
|
45579
|
-
export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, TextureValueLabels, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, DEFAULT_BRIGHTNESS_SHIFT, DEFAULT_LIGHT_INTENSITY, LIGHTING_SETTINGS_VERSION, LIGHT_INTENSITY_COMPENSATION, MAX_COMPENSATED_LIGHT_INTENSITY, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
|
|
45639
|
+
export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, DisplacedSurfacePrimitive, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, TextureFrameSeriesAnimator, TextureValueLabels, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, DEFAULT_BRIGHTNESS_SHIFT, DEFAULT_LIGHT_INTENSITY, LIGHTING_SETTINGS_VERSION, LIGHT_INTENSITY_COMPENSATION, MAX_COMPENSATED_LIGHT_INTENSITY, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
|
|
45580
45640
|
//# sourceMappingURL=bruce-cesium.es5.js.map
|