bruce-cesium 7.2.4 → 7.2.5
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 +326 -34
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +324 -32
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/internal/cesium-utils.js +32 -1
- package/dist/lib/internal/cesium-utils.js.map +1 -1
- package/dist/lib/rendering/entity-gatherer.js +111 -0
- package/dist/lib/rendering/entity-gatherer.js.map +1 -1
- package/dist/lib/rendering/menu-item-manager.js +1 -0
- package/dist/lib/rendering/menu-item-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/historic-utils.js +91 -24
- package/dist/lib/rendering/render-managers/common/historic-utils.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js +1 -0
- package/dist/lib/rendering/render-managers/entities/entities-ids-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/entities/entities-render-manager.js +1 -0
- package/dist/lib/rendering/render-managers/entities/entities-render-manager.js.map +1 -1
- package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js +61 -3
- package/dist/lib/rendering/render-managers/tilesets/tileset-entities-render-manager.js.map +1 -1
- package/dist/lib/rendering/texture-frame-series-animator.js +20 -3
- package/dist/lib/rendering/texture-frame-series-animator.js.map +1 -1
- package/dist/lib/rendering/tileset-styler.js +10 -1
- package/dist/lib/rendering/tileset-styler.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/internal/cesium-utils.d.ts +9 -0
- package/dist/types/rendering/entity-gatherer.d.ts +23 -0
- package/dist/types/rendering/render-managers/common/historic-utils.d.ts +30 -5
- package/dist/types/rendering/render-managers/tilesets/tileset-entities-render-manager.d.ts +5 -0
- package/dist/types/rendering/texture-frame-series-animator.d.ts +1 -0
- package/dist/types/rendering/tileset-styler.d.ts +3 -0
- package/package.json +1 -1
package/dist/bruce-cesium.umd.js
CHANGED
|
@@ -2883,6 +2883,36 @@
|
|
|
2883
2883
|
function ColorToCColor(color) {
|
|
2884
2884
|
return new Cesium.Color(color.red ? color.red / 255 : 0, color.green ? color.green / 255 : 0, color.blue ? color.blue / 255 : 0, color.alpha);
|
|
2885
2885
|
}
|
|
2886
|
+
const degreesCache = new WeakMap();
|
|
2887
|
+
/**
|
|
2888
|
+
* Returns a world position's latitude and longitude in degrees, or null when it has none.
|
|
2889
|
+
* @param pos
|
|
2890
|
+
*/
|
|
2891
|
+
function CartesianToDegrees(pos) {
|
|
2892
|
+
if (!pos) {
|
|
2893
|
+
return null;
|
|
2894
|
+
}
|
|
2895
|
+
const cached = degreesCache.get(pos);
|
|
2896
|
+
if (cached) {
|
|
2897
|
+
return cached;
|
|
2898
|
+
}
|
|
2899
|
+
let carto;
|
|
2900
|
+
try {
|
|
2901
|
+
carto = Cesium.Cartographic.fromCartesian(pos);
|
|
2902
|
+
}
|
|
2903
|
+
catch {
|
|
2904
|
+
return null;
|
|
2905
|
+
}
|
|
2906
|
+
if (!carto) {
|
|
2907
|
+
return null;
|
|
2908
|
+
}
|
|
2909
|
+
const degrees = {
|
|
2910
|
+
lat: Cesium.Math.toDegrees(carto.latitude),
|
|
2911
|
+
lon: Cesium.Math.toDegrees(carto.longitude)
|
|
2912
|
+
};
|
|
2913
|
+
degreesCache.set(pos, degrees);
|
|
2914
|
+
return degrees;
|
|
2915
|
+
}
|
|
2886
2916
|
/**
|
|
2887
2917
|
* Removes duplicate points in a row and returns a new array.
|
|
2888
2918
|
* Passed array is not mutated.
|
|
@@ -10737,41 +10767,107 @@
|
|
|
10737
10767
|
return Math.round(minMs + ((maxMs - minMs) * progress));
|
|
10738
10768
|
}
|
|
10739
10769
|
HistoricFetchOrder.IntervalFor = IntervalFor;
|
|
10770
|
+
// Upper bounds in metres for the distance bands, nearest first.
|
|
10771
|
+
HistoricFetchOrder.DEFAULT_BANDS = [500, 2000, 10000, 50000];
|
|
10740
10772
|
/**
|
|
10741
|
-
*
|
|
10742
|
-
*
|
|
10743
|
-
* Bands rather than a true sort, so a small camera move does not reshuffle the whole queue and
|
|
10744
|
-
* restart it. What the user is looking at resolves first either way.
|
|
10773
|
+
* Resolves what to order by from the view monitor, falling back to the camera itself.
|
|
10745
10774
|
*/
|
|
10746
|
-
function
|
|
10775
|
+
function FocusFrom(params) {
|
|
10747
10776
|
var _a;
|
|
10748
|
-
const { viewer,
|
|
10749
|
-
|
|
10750
|
-
|
|
10777
|
+
const { viewer, monitor } = params;
|
|
10778
|
+
let origin = null;
|
|
10779
|
+
let bounds = null;
|
|
10780
|
+
try {
|
|
10781
|
+
// Null whenever the view has no ground intersection, eg. a camera aimed at the sky.
|
|
10782
|
+
const target = monitor === null || monitor === void 0 ? void 0 : monitor.GetTarget();
|
|
10783
|
+
if (target && isFinite(target.latitude) && isFinite(target.longitude)) {
|
|
10784
|
+
origin = Cesium.Cartesian3.fromDegrees(target.longitude, target.latitude);
|
|
10785
|
+
}
|
|
10786
|
+
bounds = (monitor === null || monitor === void 0 ? void 0 : monitor.GetBounds()) || null;
|
|
10787
|
+
}
|
|
10788
|
+
catch {
|
|
10789
|
+
origin = null;
|
|
10790
|
+
bounds = null;
|
|
10791
|
+
}
|
|
10792
|
+
if (!origin) {
|
|
10793
|
+
origin = (_a = viewer === null || viewer === void 0 ? void 0 : viewer.camera) === null || _a === void 0 ? void 0 : _a.position;
|
|
10794
|
+
}
|
|
10795
|
+
if (!origin) {
|
|
10796
|
+
return null;
|
|
10797
|
+
}
|
|
10798
|
+
return bounds ? { origin, bounds } : { origin };
|
|
10799
|
+
}
|
|
10800
|
+
HistoricFetchOrder.FocusFrom = FocusFrom;
|
|
10801
|
+
/**
|
|
10802
|
+
* Returns the Entities grouped nearest first, on screen ahead of off screen.
|
|
10803
|
+
*/
|
|
10804
|
+
function ByCameraDistance(params) {
|
|
10805
|
+
const { viewer, entities, monitor } = params;
|
|
10806
|
+
return ByCameraDistanceOf({
|
|
10807
|
+
focus: FocusFrom({ viewer, monitor }),
|
|
10808
|
+
items: entities,
|
|
10809
|
+
posOf: (entity) => SafePos(entity, viewer),
|
|
10810
|
+
bands: params.bands
|
|
10811
|
+
});
|
|
10812
|
+
}
|
|
10813
|
+
HistoricFetchOrder.ByCameraDistance = ByCameraDistance;
|
|
10814
|
+
/**
|
|
10815
|
+
* Bands anything that can name its own world position, on the same bounds as the Entity form.
|
|
10816
|
+
*/
|
|
10817
|
+
function ByCameraDistanceOf(params) {
|
|
10818
|
+
const { focus, items, posOf } = params;
|
|
10819
|
+
const bands = params.bands || HistoricFetchOrder.DEFAULT_BANDS;
|
|
10820
|
+
if (!(items === null || items === void 0 ? void 0 : items.length)) {
|
|
10751
10821
|
return [];
|
|
10752
10822
|
}
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
10823
|
+
if (!(focus === null || focus === void 0 ? void 0 : focus.origin)) {
|
|
10824
|
+
return [items];
|
|
10825
|
+
}
|
|
10826
|
+
// One band past the named bounds, for everything beyond the last of them. Then the same
|
|
10827
|
+
// again for what is off screen, so nothing visible waits behind something that is not.
|
|
10828
|
+
const perTier = bands.length + 1;
|
|
10829
|
+
const offScreenTier = focus.bounds ? perTier : 0;
|
|
10830
|
+
const placeless = offScreenTier + perTier;
|
|
10831
|
+
const grouped = [];
|
|
10832
|
+
for (let i = 0; i <= placeless; i++) {
|
|
10833
|
+
grouped.push([]);
|
|
10756
10834
|
}
|
|
10757
|
-
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
const pos = SafePos(entity, viewer);
|
|
10835
|
+
for (const item of items) {
|
|
10836
|
+
// An item with no position falls to the last group rather than blocking the near ones.
|
|
10837
|
+
const pos = posOf(item);
|
|
10761
10838
|
if (!pos) {
|
|
10762
|
-
|
|
10839
|
+
grouped[placeless].push(item);
|
|
10763
10840
|
continue;
|
|
10764
10841
|
}
|
|
10765
|
-
const distance = Cesium.Cartesian3.distance(
|
|
10766
|
-
let
|
|
10767
|
-
if (
|
|
10768
|
-
|
|
10842
|
+
const distance = Cesium.Cartesian3.distance(focus.origin, pos);
|
|
10843
|
+
let band = bands.findIndex(bound => distance <= bound);
|
|
10844
|
+
if (band < 0) {
|
|
10845
|
+
band = bands.length;
|
|
10769
10846
|
}
|
|
10770
|
-
|
|
10847
|
+
grouped[(focus.bounds && !InBounds(pos, focus.bounds)) ? offScreenTier + band : band].push(item);
|
|
10771
10848
|
}
|
|
10772
|
-
return
|
|
10849
|
+
return grouped.filter(group => group.length > 0);
|
|
10773
10850
|
}
|
|
10774
|
-
HistoricFetchOrder.
|
|
10851
|
+
HistoricFetchOrder.ByCameraDistanceOf = ByCameraDistanceOf;
|
|
10852
|
+
/*
|
|
10853
|
+
* Returns whether a world position sits inside a ground rectangle given in degrees.
|
|
10854
|
+
*/
|
|
10855
|
+
function InBounds(pos, bounds) {
|
|
10856
|
+
const degrees = CartesianToDegrees(pos);
|
|
10857
|
+
if (!degrees) {
|
|
10858
|
+
return false;
|
|
10859
|
+
}
|
|
10860
|
+
const { lat, lon } = degrees;
|
|
10861
|
+
if (lat < bounds.south || lat > bounds.north) {
|
|
10862
|
+
return false;
|
|
10863
|
+
}
|
|
10864
|
+
// A view straddling the antimeridian reports west east of east, so the span is the outside.
|
|
10865
|
+
if (bounds.west > bounds.east) {
|
|
10866
|
+
return lon >= bounds.west || lon <= bounds.east;
|
|
10867
|
+
}
|
|
10868
|
+
return lon >= bounds.west && lon <= bounds.east;
|
|
10869
|
+
}
|
|
10870
|
+
HistoricFetchOrder.InBounds = InBounds;
|
|
10775
10871
|
/*
|
|
10776
10872
|
* Returns an Entity's world position, or null when it has none to place it by.
|
|
10777
10873
|
*/
|
|
@@ -11089,7 +11185,7 @@
|
|
|
11089
11185
|
}
|
|
11090
11186
|
if (plan.detail) {
|
|
11091
11187
|
const bands = entities.length > HistoricFetchOrder.SMALL_SET
|
|
11092
|
-
? HistoricFetchOrder.ByCameraDistance({ viewer, entities })
|
|
11188
|
+
? HistoricFetchOrder.ByCameraDistance({ viewer, entities, monitor: this.params.monitor })
|
|
11093
11189
|
: [entities];
|
|
11094
11190
|
for (const range of this.cache.MissingRanges(plan.detail.start, plan.detail.stop)) {
|
|
11095
11191
|
if (this.disposed) {
|
|
@@ -11253,6 +11349,7 @@
|
|
|
11253
11349
|
this.onSeriesDiscovered = onSeriesDiscovered;
|
|
11254
11350
|
this.historicGatherer = new HistoricGatherer({
|
|
11255
11351
|
viewer: this.viewer,
|
|
11352
|
+
monitor: this.monitor,
|
|
11256
11353
|
getApi: () => this.apiGetter.getApi(),
|
|
11257
11354
|
getAttrKey: () => { var _a; return (_a = this.item.BruceEntity) === null || _a === void 0 ? void 0 : _a.historicAttrKey; },
|
|
11258
11355
|
// A second either side, to take in records sitting exactly on the boundary.
|
|
@@ -13358,6 +13455,7 @@
|
|
|
13358
13455
|
this.visualsManager = visualsManager;
|
|
13359
13456
|
this.historicGatherer = new HistoricGatherer({
|
|
13360
13457
|
viewer: this.viewer,
|
|
13458
|
+
monitor: this.monitor,
|
|
13361
13459
|
getApi: () => this.apiGetter.getApi(),
|
|
13362
13460
|
getAttrKey: () => { var _a; return (_a = this.item.BruceEntity) === null || _a === void 0 ? void 0 : _a.historicAttrKey; },
|
|
13363
13461
|
// Padding either side of a requested range, for clock desync between us and the server.
|
|
@@ -13992,6 +14090,16 @@
|
|
|
13992
14090
|
this.lastFoundDateTimes = new Map();
|
|
13993
14091
|
// ID of Entity IDs that need to be requested.
|
|
13994
14092
|
this.eIdQueue = [];
|
|
14093
|
+
// Resolves where an Entity sits without reading its record, when the caller can say.
|
|
14094
|
+
// Unset leaves the queue in insertion order, which is what sources that bake no coordinates get.
|
|
14095
|
+
this.positionOf = null;
|
|
14096
|
+
// How many IDs at the front of the queue were explicitly asked for first.
|
|
14097
|
+
// Camera ordering leaves those alone, since an explicit re-render outranks proximity.
|
|
14098
|
+
this.priorityCount = 0;
|
|
14099
|
+
// View focus the queue was last banded from.
|
|
14100
|
+
this.lastOrderFocus = null;
|
|
14101
|
+
// Reports what the camera is aimed at, rather than only where it sits.
|
|
14102
|
+
this.monitor = null;
|
|
13995
14103
|
// All IDs that have ever been queued.
|
|
13996
14104
|
// When nothing is in queue, we'll re-request the existing IDs based on timeline changes.
|
|
13997
14105
|
this.allEIds = new Set();
|
|
@@ -14091,6 +14199,8 @@
|
|
|
14091
14199
|
return;
|
|
14092
14200
|
}
|
|
14093
14201
|
this.eIdQueue = [];
|
|
14202
|
+
this.priorityCount = 0;
|
|
14203
|
+
this.lastOrderFocus = null;
|
|
14094
14204
|
this.allEIds.clear();
|
|
14095
14205
|
this.lastFoundDateTimes.clear();
|
|
14096
14206
|
this.lastDateTime = null;
|
|
@@ -14100,6 +14210,89 @@
|
|
|
14100
14210
|
return;
|
|
14101
14211
|
}
|
|
14102
14212
|
this.eIdQueue = Array.from(this.allEIds);
|
|
14213
|
+
this.priorityCount = 0;
|
|
14214
|
+
this.lastOrderFocus = null;
|
|
14215
|
+
}
|
|
14216
|
+
/**
|
|
14217
|
+
* Supplies a lookup from Entity ID to world position, letting the queue resolve what the camera
|
|
14218
|
+
* is nearest first. Sources that cannot answer should not call this, and are served in order.
|
|
14219
|
+
*/
|
|
14220
|
+
SetPositionSource(positionOf) {
|
|
14221
|
+
this.positionOf = positionOf;
|
|
14222
|
+
this.lastOrderFocus = null;
|
|
14223
|
+
}
|
|
14224
|
+
/**
|
|
14225
|
+
* Supplies the view monitor, so the order follows the ground the camera is aimed at and prefers
|
|
14226
|
+
* what is on screen. Without one the ordering falls back to distance from the camera itself.
|
|
14227
|
+
*/
|
|
14228
|
+
SetViewMonitor(monitor) {
|
|
14229
|
+
this.monitor = monitor;
|
|
14230
|
+
this.lastOrderFocus = null;
|
|
14231
|
+
}
|
|
14232
|
+
/**
|
|
14233
|
+
* Re-bands the pending queue so the nearest Entities are requested first.
|
|
14234
|
+
*/
|
|
14235
|
+
orderQueueByCamera() {
|
|
14236
|
+
if (!this.positionOf || this.eIdQueue.length < EntityGatherer.MIN_ORDER_QUEUE) {
|
|
14237
|
+
return;
|
|
14238
|
+
}
|
|
14239
|
+
const focus = HistoricFetchOrder.FocusFrom({ viewer: this.viewer, monitor: this.monitor });
|
|
14240
|
+
if (!focus) {
|
|
14241
|
+
return;
|
|
14242
|
+
}
|
|
14243
|
+
// Re-banding on every batch would cost a full pass per request for no change in the answer.
|
|
14244
|
+
// Measured on the focus, so panning across the ground counts even when the eye barely moves.
|
|
14245
|
+
if (this.lastOrderFocus && !EntityGatherer.boundsChanged(this.lastOrderFocus, focus) &&
|
|
14246
|
+
Cesium.Cartesian3.distance(this.lastOrderFocus.origin, focus.origin) < EntityGatherer.REORDER_MOVE_METRES) {
|
|
14247
|
+
return;
|
|
14248
|
+
}
|
|
14249
|
+
this.lastOrderFocus = focus;
|
|
14250
|
+
const priority = this.priorityCount > 0 ? this.eIdQueue.slice(0, this.priorityCount) : [];
|
|
14251
|
+
const rest = this.priorityCount > 0 ? this.eIdQueue.slice(this.priorityCount) : this.eIdQueue;
|
|
14252
|
+
if (!rest.length) {
|
|
14253
|
+
return;
|
|
14254
|
+
}
|
|
14255
|
+
this.eIdQueue = priority.concat(this.bandIds(rest, focus));
|
|
14256
|
+
}
|
|
14257
|
+
/*
|
|
14258
|
+
* Returns whether the visible rectangle differs enough to change what counts as on screen.
|
|
14259
|
+
*/
|
|
14260
|
+
static boundsChanged(a, b) {
|
|
14261
|
+
if (!a.bounds || !b.bounds) {
|
|
14262
|
+
return Boolean(a.bounds) !== Boolean(b.bounds);
|
|
14263
|
+
}
|
|
14264
|
+
return (a.bounds.north !== b.bounds.north ||
|
|
14265
|
+
a.bounds.south !== b.bounds.south ||
|
|
14266
|
+
a.bounds.east !== b.bounds.east ||
|
|
14267
|
+
a.bounds.west !== b.bounds.west);
|
|
14268
|
+
}
|
|
14269
|
+
/*
|
|
14270
|
+
* Returns the IDs reordered nearest band first, or unchanged when there is nothing to order by.
|
|
14271
|
+
*/
|
|
14272
|
+
bandIds(entityIds, focus) {
|
|
14273
|
+
const from = focus || HistoricFetchOrder.FocusFrom({ viewer: this.viewer, monitor: this.monitor });
|
|
14274
|
+
if (!this.positionOf || !from || !entityIds.length) {
|
|
14275
|
+
return entityIds;
|
|
14276
|
+
}
|
|
14277
|
+
const banded = HistoricFetchOrder.ByCameraDistanceOf({
|
|
14278
|
+
focus: from,
|
|
14279
|
+
items: entityIds,
|
|
14280
|
+
posOf: (entityId) => {
|
|
14281
|
+
try {
|
|
14282
|
+
return this.positionOf(entityId);
|
|
14283
|
+
}
|
|
14284
|
+
catch {
|
|
14285
|
+
return null;
|
|
14286
|
+
}
|
|
14287
|
+
}
|
|
14288
|
+
});
|
|
14289
|
+
const ordered = [];
|
|
14290
|
+
for (const band of banded) {
|
|
14291
|
+
for (const entityId of band) {
|
|
14292
|
+
ordered.push(entityId);
|
|
14293
|
+
}
|
|
14294
|
+
}
|
|
14295
|
+
return ordered;
|
|
14103
14296
|
}
|
|
14104
14297
|
Queue(entityIds, topOfQueue = false) {
|
|
14105
14298
|
if (this.disposed || !(entityIds === null || entityIds === void 0 ? void 0 : entityIds.length)) {
|
|
@@ -14113,8 +14306,12 @@
|
|
|
14113
14306
|
// If we want it to be at the top of the queue, remove it from the queue first.
|
|
14114
14307
|
if (index !== -1) {
|
|
14115
14308
|
this.eIdQueue.splice(index, 1);
|
|
14309
|
+
if (index < this.priorityCount) {
|
|
14310
|
+
this.priorityCount -= 1;
|
|
14311
|
+
}
|
|
14116
14312
|
}
|
|
14117
14313
|
this.eIdQueue.unshift(eId);
|
|
14314
|
+
this.priorityCount += 1;
|
|
14118
14315
|
changes += 1;
|
|
14119
14316
|
}
|
|
14120
14317
|
else if (index === -1) {
|
|
@@ -14265,7 +14462,9 @@
|
|
|
14265
14462
|
if (this.historic && this.lastDateTime !== rTime) {
|
|
14266
14463
|
break;
|
|
14267
14464
|
}
|
|
14465
|
+
this.orderQueueByCamera();
|
|
14268
14466
|
const batch = this.eIdQueue.splice(0, QUEUE_BATCH_SIZE);
|
|
14467
|
+
this.priorityCount = Math.max(0, this.priorityCount - batch.length);
|
|
14269
14468
|
const { entities } = await BModels.Entity.GetListByIds({
|
|
14270
14469
|
entityIds: batch,
|
|
14271
14470
|
historicPoint: this.historic ? rTime : null,
|
|
@@ -14298,6 +14497,9 @@
|
|
|
14298
14497
|
allEIds = allEIds.filter((eId) => requestedIds.indexOf(eId) === -1);
|
|
14299
14498
|
}
|
|
14300
14499
|
if (allEIds.length) {
|
|
14500
|
+
// A historic tick re-reads the whole set, so the near ones are worth resolving
|
|
14501
|
+
// first here even more than in the queue above.
|
|
14502
|
+
allEIds = this.bandIds(allEIds);
|
|
14301
14503
|
while (allEIds.length && !this.disposed && !this.eIdQueue.length) {
|
|
14302
14504
|
if (this.historic && this.lastDateTime !== rTime) {
|
|
14303
14505
|
break;
|
|
@@ -14331,6 +14533,11 @@
|
|
|
14331
14533
|
})();
|
|
14332
14534
|
}
|
|
14333
14535
|
}
|
|
14536
|
+
// Below this the whole queue clears in one or two requests, so ordering it buys nothing.
|
|
14537
|
+
EntityGatherer.MIN_ORDER_QUEUE = 500;
|
|
14538
|
+
// How far the point being looked at has to move before the queue is worth re-banding, in metres.
|
|
14539
|
+
// Under the nearest band's width, so a move that could change what is nearest still triggers one.
|
|
14540
|
+
EntityGatherer.REORDER_MOVE_METRES = 250;
|
|
14334
14541
|
|
|
14335
14542
|
// ND-1641. BOOKMARKS - (DEMO) View does not match bookmark.
|
|
14336
14543
|
// We have some evil hard-coded style mappings that need to be fixed.
|
|
@@ -14454,7 +14661,8 @@
|
|
|
14454
14661
|
}
|
|
14455
14662
|
Init(params) {
|
|
14456
14663
|
var _a, _b;
|
|
14457
|
-
let { viewer, api, cTileset, fallbackStyleId, styleMapping, expandSources, menuItemId, register, scenario, historic, applyStyles } = params;
|
|
14664
|
+
let { viewer, api, cTileset, fallbackStyleId, styleMapping, expandSources, menuItemId, register, scenario, historic, applyStyles, monitor } = params;
|
|
14665
|
+
this.monitor = monitor;
|
|
14458
14666
|
this.viewer = viewer;
|
|
14459
14667
|
this.api = api;
|
|
14460
14668
|
this.cTileset = cTileset;
|
|
@@ -14510,6 +14718,14 @@
|
|
|
14510
14718
|
}
|
|
14511
14719
|
}
|
|
14512
14720
|
});
|
|
14721
|
+
// Only Entities Sets bake coordinates into their features, so for any other source this
|
|
14722
|
+
// resolves nothing and the gather stays in insertion order.
|
|
14723
|
+
this.entityGatherer.SetViewMonitor(this.monitor);
|
|
14724
|
+
this.entityGatherer.SetPositionSource((entityId) => {
|
|
14725
|
+
var _a;
|
|
14726
|
+
const visual = (_a = this.getEntityRego(entityId)) === null || _a === void 0 ? void 0 : _a.visual;
|
|
14727
|
+
return (visual === null || visual === void 0 ? void 0 : visual._bakedPos) || null;
|
|
14728
|
+
});
|
|
14513
14729
|
this.loaded = true;
|
|
14514
14730
|
this.loadStyles();
|
|
14515
14731
|
const feed = (_b = this.api) === null || _b === void 0 ? void 0 : _b.RecordChangeFeed;
|
|
@@ -19721,7 +19937,8 @@
|
|
|
19721
19937
|
// Saves having to do a case-insensitive lookup every time.
|
|
19722
19938
|
this.featurePropCache = new Map();
|
|
19723
19939
|
this.featurePropsChecked = 0;
|
|
19724
|
-
const { viewer, register: visualsManager, getters: apiGetter, item, initQueue } = params;
|
|
19940
|
+
const { viewer, register: visualsManager, getters: apiGetter, item, initQueue, monitor } = params;
|
|
19941
|
+
this.monitor = monitor;
|
|
19725
19942
|
this.viewer = viewer;
|
|
19726
19943
|
this.getters = apiGetter;
|
|
19727
19944
|
this.item = item;
|
|
@@ -19830,7 +20047,8 @@
|
|
|
19830
20047
|
menuItemId: this.item.id,
|
|
19831
20048
|
register: this.visualsManager,
|
|
19832
20049
|
historic: Manager.IsHistoric(this.item),
|
|
19833
|
-
applyStyles: Boolean(this.item.ApplyStyles)
|
|
20050
|
+
applyStyles: Boolean(this.item.ApplyStyles),
|
|
20051
|
+
monitor: this.monitor
|
|
19834
20052
|
});
|
|
19835
20053
|
}
|
|
19836
20054
|
this.onCTilesetLoad();
|
|
@@ -19990,6 +20208,16 @@
|
|
|
19990
20208
|
else if (lowered === "internalid") {
|
|
19991
20209
|
this.featurePropCache.set("internalId", prop);
|
|
19992
20210
|
}
|
|
20211
|
+
else if (lowered === "latitude") {
|
|
20212
|
+
this.featurePropCache.set("latitude", prop);
|
|
20213
|
+
}
|
|
20214
|
+
else if (lowered === "longitude") {
|
|
20215
|
+
this.featurePropCache.set("longitude", prop);
|
|
20216
|
+
}
|
|
20217
|
+
// b3dm names the baked height TerrainHeight, the glTF metadata table calls it Altitude.
|
|
20218
|
+
else if (lowered === "terrainheight" || lowered === "altitude") {
|
|
20219
|
+
this.featurePropCache.set("height", prop);
|
|
20220
|
+
}
|
|
19993
20221
|
}
|
|
19994
20222
|
}
|
|
19995
20223
|
Dispose() {
|
|
@@ -20144,7 +20372,8 @@
|
|
|
20144
20372
|
menuItemId: this.item.id,
|
|
20145
20373
|
register: this.visualsManager,
|
|
20146
20374
|
historic: Manager.IsHistoric(this.item),
|
|
20147
|
-
applyStyles: Boolean(this.item.ApplyStyles)
|
|
20375
|
+
applyStyles: Boolean(this.item.ApplyStyles),
|
|
20376
|
+
monitor: this.monitor
|
|
20148
20377
|
});
|
|
20149
20378
|
this.queueHandoffRestyle(this.visualsManager.GetRegos({ menuItemId: this.item.id }));
|
|
20150
20379
|
}
|
|
@@ -20187,6 +20416,45 @@
|
|
|
20187
20416
|
}
|
|
20188
20417
|
}, 10);
|
|
20189
20418
|
}
|
|
20419
|
+
/*
|
|
20420
|
+
* Reads a numeric feature property, returning null for anything that is not one.
|
|
20421
|
+
*/
|
|
20422
|
+
static readNumber(feature, prop) {
|
|
20423
|
+
const raw = feature.getProperty(prop);
|
|
20424
|
+
// Coercing straight to a number would turn null, undefined and "" into a valid zero,
|
|
20425
|
+
// which for a coordinate is a real place off the coast of Africa.
|
|
20426
|
+
if (raw == null || raw === "" || typeof raw === "boolean") {
|
|
20427
|
+
return null;
|
|
20428
|
+
}
|
|
20429
|
+
const value = +raw;
|
|
20430
|
+
return isFinite(value) ? value : null;
|
|
20431
|
+
}
|
|
20432
|
+
/*
|
|
20433
|
+
* Returns the world position an Entities Set bakes into each feature, or null when it has none.
|
|
20434
|
+
*/
|
|
20435
|
+
readBakedPos(feature) {
|
|
20436
|
+
const latProp = this.featurePropCache.get("latitude");
|
|
20437
|
+
const lonProp = this.featurePropCache.get("longitude");
|
|
20438
|
+
if (!latProp || !lonProp) {
|
|
20439
|
+
return null;
|
|
20440
|
+
}
|
|
20441
|
+
try {
|
|
20442
|
+
const lat = Manager.readNumber(feature, latProp);
|
|
20443
|
+
const lon = Manager.readNumber(feature, lonProp);
|
|
20444
|
+
// Degrees, per the batch table the generator writes. The range check doubles as a
|
|
20445
|
+
// guard against a source that bakes radians, which would otherwise read as valid.
|
|
20446
|
+
if (lat == null || lon == null || Math.abs(lat) > 90 || Math.abs(lon) > 180) {
|
|
20447
|
+
return null;
|
|
20448
|
+
}
|
|
20449
|
+
// A height that will not read is worth losing, the position it belongs to is not.
|
|
20450
|
+
const heightProp = this.featurePropCache.get("height");
|
|
20451
|
+
const height = heightProp ? Manager.readNumber(feature, heightProp) : 0;
|
|
20452
|
+
return Cesium.Cartesian3.fromDegrees(lon, lat, height !== null && height !== void 0 ? height : 0);
|
|
20453
|
+
}
|
|
20454
|
+
catch {
|
|
20455
|
+
return null;
|
|
20456
|
+
}
|
|
20457
|
+
}
|
|
20190
20458
|
mapTilesetFeature(feature) {
|
|
20191
20459
|
var _a, _b, _c;
|
|
20192
20460
|
this.evaluateFeatureProps(feature);
|
|
@@ -20267,6 +20535,12 @@
|
|
|
20267
20535
|
rego.internalId = parsed;
|
|
20268
20536
|
}
|
|
20269
20537
|
}
|
|
20538
|
+
// Stamped on the feature the properties came from, so a sibling keeps its own position
|
|
20539
|
+
// and nothing has to be cleaned up when the tile unloads.
|
|
20540
|
+
const bakedPos = this.readBakedPos(feature);
|
|
20541
|
+
if (bakedPos) {
|
|
20542
|
+
feature._bakedPos = bakedPos;
|
|
20543
|
+
}
|
|
20270
20544
|
this.loadedCesiumEntities[rego.entityId] = rego;
|
|
20271
20545
|
this.visualsManager.AddRego({
|
|
20272
20546
|
rego,
|
|
@@ -24131,6 +24405,7 @@
|
|
|
24131
24405
|
viewer: this.viewer,
|
|
24132
24406
|
register: this.visualsRegister,
|
|
24133
24407
|
getters: this.getters,
|
|
24408
|
+
monitor: this.sharedMonitor,
|
|
24134
24409
|
item: params.item,
|
|
24135
24410
|
initQueue: this.tilesetInitQueue
|
|
24136
24411
|
});
|
|
@@ -40886,9 +41161,11 @@
|
|
|
40886
41161
|
return;
|
|
40887
41162
|
}
|
|
40888
41163
|
let next = -1;
|
|
41164
|
+
let isTarget = false;
|
|
40889
41165
|
if (this.pendingIndex !== -1) {
|
|
40890
41166
|
next = this.pendingIndex;
|
|
40891
41167
|
this.pendingIndex = -1;
|
|
41168
|
+
isTarget = true;
|
|
40892
41169
|
}
|
|
40893
41170
|
else {
|
|
40894
41171
|
next = this.nearestUncachedFrame();
|
|
@@ -40897,7 +41174,7 @@
|
|
|
40897
41174
|
return;
|
|
40898
41175
|
}
|
|
40899
41176
|
this.inFlightIndex = next;
|
|
40900
|
-
this.fetchAndTint(next)
|
|
41177
|
+
this.fetchAndTint(next, isTarget)
|
|
40901
41178
|
.catch(() => {
|
|
40902
41179
|
// Eating it.
|
|
40903
41180
|
})
|
|
@@ -40908,7 +41185,7 @@
|
|
|
40908
41185
|
}
|
|
40909
41186
|
});
|
|
40910
41187
|
}
|
|
40911
|
-
async fetchAndTint(idx) {
|
|
41188
|
+
async fetchAndTint(idx, isTarget = true) {
|
|
40912
41189
|
const tiles = this.tiles;
|
|
40913
41190
|
// Every tile's frame for one timestep sits contiguously, because the generator writes
|
|
40914
41191
|
// frame major. So a tiled frame is still ONE range request, not one per tile.
|
|
@@ -40940,10 +41217,25 @@
|
|
|
40940
41217
|
this.frameCache[idx] = decoded.pixels;
|
|
40941
41218
|
this.frameDims[idx] = { width: decoded.width, height: decoded.height };
|
|
40942
41219
|
this.valueCache[idx] = decoded.valuePixels || null;
|
|
40943
|
-
if (idx
|
|
41220
|
+
if (this.shouldPresent(idx, isTarget)) {
|
|
40944
41221
|
this.beginCrossfadeTo(idx);
|
|
40945
41222
|
}
|
|
40946
41223
|
}
|
|
41224
|
+
/*
|
|
41225
|
+
* Whether a frame that has just decoded is worth putting on screen.
|
|
41226
|
+
*/
|
|
41227
|
+
shouldPresent(idx, isTarget) {
|
|
41228
|
+
if (idx === this.currentFrameIndex) {
|
|
41229
|
+
return true;
|
|
41230
|
+
}
|
|
41231
|
+
// A prefetch is for a frame nobody asked to see, so it stays in the cache.
|
|
41232
|
+
if (!isTarget) {
|
|
41233
|
+
return false;
|
|
41234
|
+
}
|
|
41235
|
+
// Dragging the timeline retargets faster than a frame can be fetched, so the frame that
|
|
41236
|
+
// lands is rarely the one now under the playhead.
|
|
41237
|
+
return !this.frameCache[this.currentFrameIndex];
|
|
41238
|
+
}
|
|
40947
41239
|
/*
|
|
40948
41240
|
* Draws every tile of one frame into a single raster covering the drape extent.
|
|
40949
41241
|
*/
|
|
@@ -45481,7 +45773,7 @@ void main() {
|
|
|
45481
45773
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
45482
45774
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
45483
45775
|
|
|
45484
|
-
const VERSION = "7.2.
|
|
45776
|
+
const VERSION = "7.2.5";
|
|
45485
45777
|
/**
|
|
45486
45778
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
45487
45779
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|