bruce-cesium 7.2.1 → 7.2.3

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.
@@ -1,4 +1,4 @@
1
- import { Style } from "bruce-models";
1
+ import { Calculator, Style } from "bruce-models";
2
2
  import * as Cesium from "cesium";
3
3
  export declare namespace TextureFrameSeriesAnimator {
4
4
  /**
@@ -23,35 +23,263 @@ export declare namespace TextureFrameSeriesAnimator {
23
23
  ResolutionX?: number;
24
24
  ResolutionY?: number;
25
25
  PixelPlacement?: string;
26
- BaselineFaces?: number;
26
+ ExtremesValueMin?: number;
27
+ ExtremesValueMax?: number;
28
+ Times?: string[];
29
+ Tiles?: ITileEntry[];
30
+ Format?: string;
31
+ Encoding?: string;
32
+ Units?: string;
33
+ SourceVerticalDatum?: string;
34
+ Transform?: string;
35
+ SourceUnits?: string;
36
+ SourceValueMin?: number;
37
+ SourceValueMax?: number;
38
+ }
39
+ /**
40
+ * One tile of an adaptive pyramid.
41
+ *
42
+ * TexelMetres is the ground size of one of its texels, which is what lets a viewer see where the
43
+ * model actually has detail rather than presenting one resolution as if it were uniform.
44
+ */
45
+ interface ITileEntry {
46
+ Level: number;
47
+ X: number;
48
+ Y: number;
49
+ West: number;
50
+ East: number;
51
+ South: number;
52
+ North: number;
53
+ TexelMetres: number;
54
+ ResolutionX: number;
55
+ ResolutionY: number;
56
+ Frames: IFrameEntry[];
57
+ Floor?: {
58
+ ByteOffset: number;
59
+ ByteLength: number;
60
+ };
61
+ Ceiling?: {
62
+ ByteOffset: number;
63
+ ByteLength: number;
64
+ };
27
65
  BaselineMask?: {
28
66
  ByteOffset: number;
29
67
  ByteLength: number;
30
68
  };
31
- BaselineValueMin?: number;
32
- BaselineValueMax?: number;
33
69
  }
70
+ const LAYOUT_TILES = "tiles";
71
+ const SUPPORTED_VERSION = 3;
72
+ /**
73
+ * A value map as the generator publishes it: what the numbers are, how they are packed, where
74
+ * they are, and which per-texel layers exist.
75
+ */
76
+ interface IValueMapMetadata {
77
+ Version?: number;
78
+ Identity?: {
79
+ BruceSourceID?: number;
80
+ EntityTypeSourceID?: number;
81
+ EntityTypeID?: string;
82
+ Attribute?: string;
83
+ Label?: string;
84
+ Dataset?: string;
85
+ Generated?: string;
86
+ Revision?: number;
87
+ };
88
+ Series?: {
89
+ Start?: string;
90
+ End?: string;
91
+ Increment?: string;
92
+ Requested?: number;
93
+ Written?: number;
94
+ Complete?: boolean;
95
+ Times?: string[];
96
+ };
97
+ Value?: {
98
+ Units?: string;
99
+ Encoding?: string;
100
+ Format?: string;
101
+ Min?: number;
102
+ Max?: number;
103
+ };
104
+ ValueSource?: {
105
+ Units?: string;
106
+ Min?: number;
107
+ Max?: number;
108
+ VerticalDatum?: string;
109
+ Transform?: string;
110
+ };
111
+ Layers?: {
112
+ Name: string;
113
+ Format?: string;
114
+ PerTime?: boolean;
115
+ Min?: number;
116
+ Max?: number;
117
+ }[];
118
+ Geometry?: {
119
+ CRS?: string;
120
+ SourceCRS?: string;
121
+ West?: number;
122
+ East?: number;
123
+ South?: number;
124
+ North?: number;
125
+ PixelPlacement?: string;
126
+ ExtentCovers?: string;
127
+ Layout?: string;
128
+ TileTexels?: number;
129
+ ResolutionX?: number;
130
+ ResolutionY?: number;
131
+ };
132
+ Stats?: {
133
+ MovingRangeMax?: number;
134
+ BaselineCells?: number;
135
+ Baseline?: {
136
+ Min?: number;
137
+ Max?: number;
138
+ };
139
+ };
140
+ Hints?: {
141
+ ColorBarMin?: number;
142
+ ColorBarMax?: number;
143
+ };
144
+ Tiles?: IValueMapTile[];
145
+ }
146
+ interface IValueMapTile {
147
+ Level: number;
148
+ X: number;
149
+ Y: number;
150
+ West: number;
151
+ East: number;
152
+ South: number;
153
+ North: number;
154
+ TexelMetres: number;
155
+ ResolutionX: number;
156
+ ResolutionY: number;
157
+ Layers?: {
158
+ [name: string]: {
159
+ Bytes: IByteRange;
160
+ } | {
161
+ Bytes: IByteRange;
162
+ }[];
163
+ };
164
+ }
165
+ interface IByteRange {
166
+ Offset: number;
167
+ Length: number;
168
+ }
169
+ const FORMAT_U8 = "u8";
170
+ const FORMAT_RG16 = "rg16";
171
+ const ENCODING_ABSOLUTE = "absolute";
172
+ const LAYER_VALUE = "Value";
173
+ const LAYER_VALUE_MIN = "ValueMin";
174
+ const LAYER_VALUE_MAX = "ValueMax";
175
+ const LAYER_BASELINE = "Baseline";
176
+ const LAYER_VALUE_SHIFT = "ValueShift";
177
+ /**
178
+ * Turns a published value map into the flat shape this renderer works in, or null when it cannot be drawn.
179
+ * @param published the archive's Data.generation
180
+ */
181
+ function Adapt(published: IValueMapMetadata | undefined): IFrameArchiveMetadata | null;
182
+ /**
183
+ * How to turn a delivered value into the number the source published, or null when the archive
184
+ * does not say enough to do it.
185
+ * @param metadata the archive's Data.generation
186
+ */
187
+ function SourceMap(metadata: IFrameArchiveMetadata | undefined): {
188
+ scale: number;
189
+ offset: number;
190
+ } | null;
191
+ /**
192
+ * A delivered value in the source's own terms, or unchanged when it cannot be turned back.
193
+ * @param map from SourceMap(), null when the archive does not say enough
194
+ */
195
+ function ToSource(map: {
196
+ scale: number;
197
+ offset: number;
198
+ } | null, value: number): number;
199
+ /**
200
+ * Whether the archive's frames carry a 16 bit value packed across R and G.
201
+ *
202
+ * Every consumer that reads a texel has to ask: taking R alone from a packed frame yields a
203
+ * plausible surface quantised to 255 steps of the full range rather than an obvious failure.
204
+ * @param metadata the archive's Data.generation
205
+ */
206
+ function IsPackedValue(metadata: IFrameArchiveMetadata | undefined): boolean;
207
+ /**
208
+ * The normalised 0 to 1 value at a texel, from whichever format the archive packed it in.
209
+ * @param metadata the archive's Data.generation
210
+ * @param pixels untinted RGBA value pixels
211
+ * @param at index of the texel's red channel
212
+ */
213
+ function NormalisedAt(metadata: IFrameArchiveMetadata | undefined, pixels: Uint8ClampedArray, at: number): number;
214
+ const DATUM_ELLIPSOIDAL = "WGS84";
215
+ /**
216
+ * Whether the values are heights against a vertical datum rather than a thickness.
217
+ *
218
+ * A thickness rises from wherever the polygon sits and a height already knows where it belongs, so
219
+ * this is what decides whether the polygon's own altitude may be added underneath it.
220
+ * @param metadata the archive's Data.generation
221
+ */
222
+ function IsDatumHeight(metadata: IFrameArchiveMetadata | undefined): boolean;
223
+ /**
224
+ * The archive's tiles, which Adapt() guarantees are present.
225
+ * @param metadata the archive's Data.generation
226
+ */
227
+ function TilesOf(metadata: IFrameArchiveMetadata | undefined): ITileEntry[];
228
+ /**
229
+ * Turns a value in the attribute's own units into the 0 to 1 position the ramp is indexed by.
230
+ *
231
+ * Stops are authored in real units, since "hide anything under 0.1 m" is the sentence a user
232
+ * actually has, and the archive's own published range is what makes that expressible.
233
+ * @param metadata the archive's Data.generation
234
+ * @param value in the attribute's units
235
+ */
236
+ function NormalisePosition(metadata: IFrameArchiveMetadata | undefined, value: number): number;
34
237
  /**
35
238
  * Detects whether a ClientFile's `Data.generation` metadata describes a frame archive rather than a single static image,
36
239
  * so a caller can decide whether to construct an Animator or fall back to the existing static-texture path.
37
- * @param data ClientFile.Data (the `IFile.Data` field), as returned by ClientFile.Get().
240
+ * @param data ClientFile.Data
38
241
  */
39
242
  function IsFrameArchiveMetadata(data: any): data is {
40
- generation: IFrameArchiveMetadata;
243
+ generation: IValueMapMetadata;
41
244
  };
245
+ /**
246
+ * Structural copies of the style shapes this consumes.
247
+ */
248
+ interface IExtent {
249
+ West: number;
250
+ East: number;
251
+ South: number;
252
+ North: number;
253
+ }
254
+ interface ICellBorder {
255
+ color: Calculator.IField[];
256
+ width: Calculator.IField[];
257
+ }
258
+ interface IRampPoint {
259
+ position: number;
260
+ color: string;
261
+ }
262
+ function AppearanceSignature(options: {
263
+ valueCanvas?: boolean;
264
+ drape?: IExtent;
265
+ textureColorMask?: Style.ITextureColorMask;
266
+ cellBorder?: ICellBorder;
267
+ cellTexels?: number;
268
+ maskBaseline?: boolean;
269
+ }): string;
42
270
  interface IOptions {
43
271
  viewer: Cesium.Viewer;
44
272
  entity: Cesium.Entity;
45
273
  archiveUrl: string;
46
274
  frames: IFrameEntry[];
47
275
  textureColorMask?: Style.ITextureColorMask;
276
+ cellBorder?: ICellBorder;
277
+ cellTexels?: number;
278
+ metadata?: IFrameArchiveMetadata;
48
279
  crossfadeMs?: number;
49
280
  driveMaterial?: boolean;
50
281
  produceValueCanvas?: boolean;
51
- baselineMask?: {
52
- ByteOffset: number;
53
- ByteLength: number;
54
- };
282
+ drapeExtent?: IExtent;
55
283
  maskBaseline?: boolean;
56
284
  }
57
285
  class Animator {
@@ -88,11 +316,20 @@ export declare namespace TextureFrameSeriesAnimator {
88
316
  private readonly pool;
89
317
  private poolIdx;
90
318
  private readonly imageProperty;
319
+ private readonly appearance;
320
+ private readonly rampStops;
321
+ private readonly cellBorder;
91
322
  private readonly driveMaterial;
92
323
  private readonly produceValueCanvas;
324
+ private readonly metadata?;
325
+ private readonly drapeExtent?;
326
+ private readonly tiles;
93
327
  private readonly valueCanvas;
94
328
  private valueDims;
95
329
  private presentVersion;
330
+ private extremesLoad;
331
+ private floorPixels;
332
+ private ceilingPixels;
96
333
  constructor(options: IOptions);
97
334
  /**
98
335
  * Explicit teardown: stops driving the entity's material, abandons any in-flight/pending fetch (results are simply ignored when they land),
@@ -100,6 +337,7 @@ export declare namespace TextureFrameSeriesAnimator {
100
337
  */
101
338
  Dispose(): void;
102
339
  IsDisposed(): boolean;
340
+ GetAppearanceSignature(): string;
103
341
  /**
104
342
  * The archive URL this instance was constructed with,
105
343
  * lets a caller re-rendering the same entity tell whether an existing instance is already correct, without reaching into private state.
@@ -110,6 +348,13 @@ export declare namespace TextureFrameSeriesAnimator {
110
348
  * material (eg: re-tinting for opacity/selection) without detaching the animation.
111
349
  */
112
350
  GetImageProperty(): Cesium.CallbackProperty;
351
+ /**
352
+ * The presented frame's TINTED pixels, where alpha is what the ramp actually painted.
353
+ *
354
+ * Distinct from the value canvas, whose alpha only says a texel has data. A cell can hold a
355
+ * reading and still be painted nothing, which is exactly what a hidden floor band does.
356
+ */
357
+ GetDisplayedPixels(): Uint8ClampedArray | null;
113
358
  /**
114
359
  * The untinted canvas carrying the presented frame's value in RGB and its coverage in alpha,
115
360
  * or null unless the instance was constructed with produceValueCanvas.
@@ -127,15 +372,36 @@ export declare namespace TextureFrameSeriesAnimator {
127
372
  private nearestUncachedFrame;
128
373
  private pumpFetchQueue;
129
374
  private fetchAndTint;
130
- /**
131
- * Decodes one frame's raw PNG bytes (as returned by a Range GET) and applies the grayscale color mask.
132
- */
133
- protected decodeAndTint(buffer: ArrayBuffer): Promise<{
375
+ protected composeTiles(tiles: ITileEntry[], idx: number, buffer: ArrayBuffer, spanStart: number): Promise<{
134
376
  pixels: Uint8ClampedArray;
135
377
  width: number;
136
378
  height: number;
137
379
  valuePixels?: Uint8ClampedArray;
138
380
  }>;
381
+ private compositeExtent;
382
+ private compositeSize;
383
+ protected tint(imageData: ImageData): {
384
+ pixels: Uint8ClampedArray;
385
+ width: number;
386
+ height: number;
387
+ valuePixels?: Uint8ClampedArray;
388
+ };
389
+ private writeInto;
390
+ /**
391
+ * The archive's per-cell floor and ceiling rasters, once EnsureExtremes has resolved.
392
+ */
393
+ GetExtremes(): {
394
+ floor: ImageData | null;
395
+ ceiling: ImageData | null;
396
+ };
397
+ /**
398
+ * Fetches and decodes the floor and ceiling rasters, at most once.
399
+ */
400
+ EnsureExtremes(): Promise<void>;
401
+ private loadTiledBaselineMask;
402
+ private loadTiledExtremes;
403
+ private tileRect;
404
+ private decodeSlices;
139
405
  /**
140
406
  * Fetches and decodes the archive's static baseline mask, at most once.
141
407
  */
@@ -0,0 +1,161 @@
1
+ import * as Cesium from "cesium";
2
+ import { TextureFrameSeriesAnimator } from "./texture-frame-series-animator";
3
+ /**
4
+ * Prints a value texture's own numbers over the cells they belong to.
5
+ */
6
+ export declare namespace TextureValueLabels {
7
+ /**
8
+ * A structural copy of the style shape, for the same reason the animator keeps one: a host app
9
+ * may be on an older published bruce-models than the one that introduced it.
10
+ */
11
+ interface ISettings {
12
+ minCellPixels?: number;
13
+ minSpacingPixels?: number;
14
+ maxLabels?: number;
15
+ decimals?: number;
16
+ parts?: ("value" | "floor" | "ceiling")[];
17
+ gridColor?: string;
18
+ gridWidthPixels?: number;
19
+ minGridCellPixels?: number;
20
+ }
21
+ /**
22
+ * One tile's footprint and cell count, for drawing a grid at the tile's own resolution.
23
+ */
24
+ interface ITileGrid {
25
+ West: number;
26
+ East: number;
27
+ South: number;
28
+ North: number;
29
+ ResolutionX: number;
30
+ ResolutionY: number;
31
+ }
32
+ interface IExtent {
33
+ West: number;
34
+ East: number;
35
+ South: number;
36
+ North: number;
37
+ }
38
+ interface IOptions {
39
+ viewer: Cesium.Viewer;
40
+ extent: IExtent;
41
+ settings?: ISettings;
42
+ metadata?: TextureFrameSeriesAnimator.IFrameArchiveMetadata;
43
+ tiles?: ITileGrid[];
44
+ clipRing?: {
45
+ lon: number;
46
+ lat: number;
47
+ }[];
48
+ }
49
+ /**
50
+ * One cell's numbers, in the attribute's own units.
51
+ */
52
+ interface IReading {
53
+ value: number;
54
+ floor?: number;
55
+ ceiling?: number;
56
+ }
57
+ /**
58
+ * A clip outline from a projected ring, or null when the ring cannot be drawn.
59
+ * @param projected one entry per ring vertex, null where the vertex has no window coordinate
60
+ */
61
+ function ClipOutline(projected: ({
62
+ x: number;
63
+ y: number;
64
+ } | null)[]): {
65
+ x: number;
66
+ y: number;
67
+ }[] | null;
68
+ /**
69
+ * One cell's numbers as a label should print them, or null where the texture has no data there.
70
+ * @param params at is the index of the cell's red channel. sourceMap is derived from the metadata
71
+ * when omitted, which a caller reading many cells should hoist rather than repeat.
72
+ */
73
+ function ReadingAt(params: {
74
+ metadata?: TextureFrameSeriesAnimator.IFrameArchiveMetadata;
75
+ source: ImageData;
76
+ floor?: ImageData | null;
77
+ ceiling?: ImageData | null;
78
+ at: number;
79
+ sourceMap?: {
80
+ scale: number;
81
+ offset: number;
82
+ } | null;
83
+ }): IReading | null;
84
+ /**
85
+ * The unit a label's value line should name, or undefined when the archive states none.
86
+ * @param metadata the archive's Data.generation
87
+ */
88
+ function LabelUnits(metadata?: TextureFrameSeriesAnimator.IFrameArchiveMetadata): string | undefined;
89
+ /**
90
+ * How many cells apart labels should sit, as a power of two.
91
+ * @param options cellPixels is one cell's size on screen, held is the stride already in use
92
+ */
93
+ function ChooseLabelStride(options: {
94
+ cellPixels: number;
95
+ visibleCols: number;
96
+ visibleRows: number;
97
+ maxLabels: number;
98
+ minSpacingPixels: number;
99
+ held?: number;
100
+ }): number;
101
+ class Labels {
102
+ private readonly viewer;
103
+ private readonly canvas;
104
+ private readonly ctx;
105
+ private readonly settings;
106
+ private extent;
107
+ private metadata?;
108
+ private sourceMap;
109
+ private tiles?;
110
+ private clipRing?;
111
+ private source;
112
+ private painted;
113
+ private floor;
114
+ private ceiling;
115
+ private disposed;
116
+ private drawn;
117
+ private stride;
118
+ constructor(options: IOptions);
119
+ SetExtent(extent: IExtent): void;
120
+ /**
121
+ * The current frame's decoded values, as the animator's value canvas already provides them.
122
+ * @param source value pixels, one texel per cell
123
+ */
124
+ SetSource(source: ImageData | null): void;
125
+ /**
126
+ * The tinted pixels of the same frame, so the grid can skip cells the ramp painted nothing in.
127
+ * @param painted RGBA of the presented frame, or null to fall back to coverage alone
128
+ */
129
+ SetPainted(painted: Uint8ClampedArray | null): void;
130
+ /**
131
+ * The archive's per-cell extremes, when it publishes them. Without these a label can still
132
+ * print the current reading, just not the range behind it.
133
+ */
134
+ SetExtremes(floor: ImageData | null, ceiling: ImageData | null): void;
135
+ GetDrawnCount(): number;
136
+ Clear(): void;
137
+ Dispose(): void;
138
+ /**
139
+ * Redraws every visible label. Cheap enough to call per rendered frame, because the cell
140
+ * count it considers is bounded by the view rather than by the texture.
141
+ */
142
+ Render(): void;
143
+ private drawGrid;
144
+ private applyRingClip;
145
+ private tileCellOutline;
146
+ private drawTileGrid;
147
+ private groundAtScreenCentre;
148
+ private coveredAt;
149
+ private isCovered;
150
+ private widestLabel;
151
+ private cellOutline;
152
+ private drawLabel;
153
+ private readNear;
154
+ private paintedAt;
155
+ private readAt;
156
+ private lonAt;
157
+ private latAt;
158
+ private visibleTexels;
159
+ private project;
160
+ }
161
+ }
@@ -438,6 +438,7 @@ export declare namespace VisualsRegister {
438
438
  requestRender?: boolean;
439
439
  source?: EUpdateSource;
440
440
  lazy?: boolean;
441
+ keepVisual?: Visual;
441
442
  onComplete?: () => void;
442
443
  }): void;
443
444
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bruce-cesium",
3
- "version": "7.2.1",
3
+ "version": "7.2.3",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "main": "dist/bruce-cesium.umd.js",
@@ -83,7 +83,7 @@
83
83
  "typescript": "^5.0.4"
84
84
  },
85
85
  "dependencies": {
86
- "bruce-models": "^7.1.75",
86
+ "bruce-models": "^7.1.80",
87
87
  "tslib": "^2.4.1"
88
88
  }
89
89
  }