bruce-cesium 7.3.8 → 7.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bruce-cesium.es5.js +315 -26
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +313 -24
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/entity-gatherer.js +249 -16
- package/dist/lib/rendering/entity-gatherer.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/historic-utils.js +64 -7
- package/dist/lib/rendering/render-managers/common/historic-utils.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/entity-gatherer.d.ts +27 -4
- package/dist/types/rendering/render-managers/common/historic-utils.d.ts +12 -4
- package/package.json +1 -1
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, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator,
|
|
2
|
+
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ShaderSource, Cartesian3, Math as Math$1, Ellipsoid, Transforms, Matrix4, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, JulianDate, Quaternion, HeadingPitchRoll, HeightReference, ColorBlendMode, ShadowMode, ClassificationType, Model, HorizontalOrigin, VerticalOrigin, ConstantPositionProperty, ArcType, CornerType, DistanceDisplayCondition, SceneTransforms, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, NearFarScalar, Matrix3, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, HeadingPitchRange, Ion, IonResource, Cesium3DTileColorBlendMode, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, OrthographicFrustum, EasingFunction, Intersect, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, PolygonPipeline, CustomDataSource, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, ScreenSpaceEventHandler, ScreenSpaceEventType, GeometryInstance, Fullscreen, CzmlDataSource } from 'cesium';
|
|
3
|
+
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Api, Carto, Geometry as Geometry$1, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, AccountConcept, EntityRelation, BruceApi, RecordChangeFeed, EntitySource, ProgramKey, ProjectViewLegacyTile, Camera, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType, EntityHistoricData } from 'bruce-models';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Ensures a number is returned from a given value.
|
|
@@ -11048,10 +11048,6 @@ class PointClustering {
|
|
|
11048
11048
|
|
|
11049
11049
|
/**
|
|
11050
11050
|
* How often a historic refresh is worth running, and which Entities it should ask about first.
|
|
11051
|
-
*
|
|
11052
|
-
* A handful of tracked vehicles can afford to re-read on almost every clock tick. Thousands of
|
|
11053
|
-
* parcels cannot, and refreshing them that often was never buying anything since the answer barely
|
|
11054
|
-
* changes between ticks.
|
|
11055
11051
|
*/
|
|
11056
11052
|
var HistoricFetchOrder;
|
|
11057
11053
|
(function (HistoricFetchOrder) {
|
|
@@ -11096,6 +11092,13 @@ var HistoricFetchOrder;
|
|
|
11096
11092
|
HistoricFetchOrder.IntervalForClock = IntervalForClock;
|
|
11097
11093
|
// Upper bounds in metres for the distance bands, nearest first.
|
|
11098
11094
|
HistoricFetchOrder.DEFAULT_BANDS = [500, 2000, 10000, 50000];
|
|
11095
|
+
// How far outside the visible rectangle something still counts as worth re-reading, share of the view itself.
|
|
11096
|
+
HistoricFetchOrder.REFRESH_MARGIN_FRACTION = 0.5;
|
|
11097
|
+
// A close view still gets a usable buffer, and a distant one does not reach half the account.
|
|
11098
|
+
HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES = 250;
|
|
11099
|
+
HistoricFetchOrder.MAX_REFRESH_MARGIN_METRES = 2000;
|
|
11100
|
+
const METRES_PER_DEGREE_LAT = 111320;
|
|
11101
|
+
const MIN_LAT_COSINE = 0.01;
|
|
11099
11102
|
/**
|
|
11100
11103
|
* Resolves what to order by from the view monitor, falling back to the camera itself.
|
|
11101
11104
|
*/
|
|
@@ -11176,6 +11179,55 @@ var HistoricFetchOrder;
|
|
|
11176
11179
|
return grouped.filter(group => group.length > 0);
|
|
11177
11180
|
}
|
|
11178
11181
|
HistoricFetchOrder.ByCameraDistanceOf = ByCameraDistanceOf;
|
|
11182
|
+
/**
|
|
11183
|
+
* Returns how far past a visible rectangle a refresh should still reach, in metres.
|
|
11184
|
+
*/
|
|
11185
|
+
function RefreshMarginFor(bounds) {
|
|
11186
|
+
if (!bounds) {
|
|
11187
|
+
return HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES;
|
|
11188
|
+
}
|
|
11189
|
+
const latSpan = Math.abs(bounds.north - bounds.south) * METRES_PER_DEGREE_LAT;
|
|
11190
|
+
const cosine = Math.max(MIN_LAT_COSINE, Math.cos(Math$1.toRadians((bounds.north + bounds.south) / 2)));
|
|
11191
|
+
const lonDegrees = bounds.west > bounds.east
|
|
11192
|
+
? (bounds.east + 360) - bounds.west
|
|
11193
|
+
: bounds.east - bounds.west;
|
|
11194
|
+
const lonSpan = Math.abs(lonDegrees) * METRES_PER_DEGREE_LAT * cosine;
|
|
11195
|
+
const span = Math.min(latSpan, lonSpan);
|
|
11196
|
+
if (!(span > 0)) {
|
|
11197
|
+
return HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES;
|
|
11198
|
+
}
|
|
11199
|
+
return Math.min(HistoricFetchOrder.MAX_REFRESH_MARGIN_METRES, Math.max(HistoricFetchOrder.MIN_REFRESH_MARGIN_METRES, span * HistoricFetchOrder.REFRESH_MARGIN_FRACTION));
|
|
11200
|
+
}
|
|
11201
|
+
HistoricFetchOrder.RefreshMarginFor = RefreshMarginFor;
|
|
11202
|
+
/**
|
|
11203
|
+
* Returns the rectangle grown outwards by a margin in metres.
|
|
11204
|
+
*/
|
|
11205
|
+
function GrowBounds(bounds, metres) {
|
|
11206
|
+
if (!bounds || !(metres > 0)) {
|
|
11207
|
+
return bounds;
|
|
11208
|
+
}
|
|
11209
|
+
const dLat = metres / METRES_PER_DEGREE_LAT;
|
|
11210
|
+
const north = Math.min(90, bounds.north + dLat);
|
|
11211
|
+
const south = Math.max(-90, bounds.south - dLat);
|
|
11212
|
+
const cosine = Math.cos(Math$1.toRadians((bounds.north + bounds.south) / 2));
|
|
11213
|
+
if (cosine < MIN_LAT_COSINE) {
|
|
11214
|
+
return { north, south, west: -180, east: 180 };
|
|
11215
|
+
}
|
|
11216
|
+
const dLon = metres / (METRES_PER_DEGREE_LAT * cosine);
|
|
11217
|
+
const straddles = bounds.west > bounds.east;
|
|
11218
|
+
const gap = straddles ? bounds.west - bounds.east : 360 - (bounds.east - bounds.west);
|
|
11219
|
+
if (gap <= dLon * 2) {
|
|
11220
|
+
return { north, south, west: -180, east: 180 };
|
|
11221
|
+
}
|
|
11222
|
+
return { north, south, west: wrapLongitude(bounds.west - dLon), east: wrapLongitude(bounds.east + dLon) };
|
|
11223
|
+
}
|
|
11224
|
+
HistoricFetchOrder.GrowBounds = GrowBounds;
|
|
11225
|
+
/*
|
|
11226
|
+
* Returns a longitude folded back into the range the bounds are expressed in.
|
|
11227
|
+
*/
|
|
11228
|
+
function wrapLongitude(lon) {
|
|
11229
|
+
return (((lon + 180) % 360) + 360) % 360 - 180;
|
|
11230
|
+
}
|
|
11179
11231
|
/*
|
|
11180
11232
|
* Returns whether a world position sits inside a ground rectangle given in degrees.
|
|
11181
11233
|
*/
|
|
@@ -11184,17 +11236,22 @@ var HistoricFetchOrder;
|
|
|
11184
11236
|
if (!degrees) {
|
|
11185
11237
|
return false;
|
|
11186
11238
|
}
|
|
11187
|
-
|
|
11239
|
+
return InDegreeBounds(degrees.lat, degrees.lon, bounds);
|
|
11240
|
+
}
|
|
11241
|
+
HistoricFetchOrder.InBounds = InBounds;
|
|
11242
|
+
/*
|
|
11243
|
+
* The same test for a caller that already holds the degrees and should not pay to resolve them from a world position again.
|
|
11244
|
+
*/
|
|
11245
|
+
function InDegreeBounds(lat, lon, bounds) {
|
|
11188
11246
|
if (lat < bounds.south || lat > bounds.north) {
|
|
11189
11247
|
return false;
|
|
11190
11248
|
}
|
|
11191
|
-
// A view straddling the antimeridian reports west east of east, so the span is the outside.
|
|
11192
11249
|
if (bounds.west > bounds.east) {
|
|
11193
11250
|
return lon >= bounds.west || lon <= bounds.east;
|
|
11194
11251
|
}
|
|
11195
11252
|
return lon >= bounds.west && lon <= bounds.east;
|
|
11196
11253
|
}
|
|
11197
|
-
HistoricFetchOrder.
|
|
11254
|
+
HistoricFetchOrder.InDegreeBounds = InDegreeBounds;
|
|
11198
11255
|
/*
|
|
11199
11256
|
* Returns an Entity's world position, or null when it has none to place it by.
|
|
11200
11257
|
*/
|
|
@@ -14600,6 +14657,19 @@ class EntityGatherer {
|
|
|
14600
14657
|
// All IDs that have ever been queued.
|
|
14601
14658
|
// When nothing is in queue, we'll re-request the existing IDs based on timeline changes.
|
|
14602
14659
|
this.allEIds = new Set();
|
|
14660
|
+
// IDs a historic read has actually answered with a record, rather than falling back to a stub.
|
|
14661
|
+
// A refresh serves these before the ones that have never produced anything.
|
|
14662
|
+
this.everFound = new Set();
|
|
14663
|
+
// Every known Entity bucketed by the ground cell its position falls in, so a refresh can ask
|
|
14664
|
+
// what the view reaches instead of walking the whole set. Built as IDs arrive.
|
|
14665
|
+
this.cells = new Map();
|
|
14666
|
+
// IDs the position source could not place yet. They are always refreshed.
|
|
14667
|
+
this.unplaced = new Set();
|
|
14668
|
+
// The IDs the last decision found inside the view, so a camera move can queue the difference
|
|
14669
|
+
// rather than re-requesting everything it already asked about.
|
|
14670
|
+
this.lastInView = new Set();
|
|
14671
|
+
// Unsubscribes the view monitor listener that queues what the camera has moved onto.
|
|
14672
|
+
this.monitorRemoval = null;
|
|
14603
14673
|
// Indicates a tick is active.
|
|
14604
14674
|
// When true, we won't bother calling onTick again.
|
|
14605
14675
|
this.runningTick = false;
|
|
@@ -14650,6 +14720,16 @@ class EntityGatherer {
|
|
|
14650
14720
|
}
|
|
14651
14721
|
this.historic = historic;
|
|
14652
14722
|
this.expandSources = expandSources;
|
|
14723
|
+
if (this.historic) {
|
|
14724
|
+
// Anything already known was taken in before the index was being built, so it is filed
|
|
14725
|
+
// a bounded number at a time from here rather than in one pass now.
|
|
14726
|
+
for (const entityId of this.allEIds) {
|
|
14727
|
+
this.unplaced.add(entityId);
|
|
14728
|
+
}
|
|
14729
|
+
}
|
|
14730
|
+
else {
|
|
14731
|
+
this.clearIndex();
|
|
14732
|
+
}
|
|
14653
14733
|
if (this.historic) {
|
|
14654
14734
|
// 4 ticks per second.
|
|
14655
14735
|
// The fastest data we are working with is 5 times per second.
|
|
@@ -14701,6 +14781,8 @@ class EntityGatherer {
|
|
|
14701
14781
|
this.lastOrderFocus = null;
|
|
14702
14782
|
this.allEIds.clear();
|
|
14703
14783
|
this.lastFoundDateTimes.clear();
|
|
14784
|
+
this.everFound.clear();
|
|
14785
|
+
this.clearIndex();
|
|
14704
14786
|
this.lastDateTime = null;
|
|
14705
14787
|
}
|
|
14706
14788
|
ReQueueAll() {
|
|
@@ -14711,22 +14793,193 @@ class EntityGatherer {
|
|
|
14711
14793
|
this.eIdQueued = new Set(this.eIdQueue);
|
|
14712
14794
|
this.priorityCount = 0;
|
|
14713
14795
|
this.lastOrderFocus = null;
|
|
14796
|
+
this.clearIndex();
|
|
14714
14797
|
}
|
|
14715
14798
|
/**
|
|
14716
|
-
* Supplies a lookup from Entity ID to world position, letting the queue resolve what the camera
|
|
14717
|
-
*
|
|
14799
|
+
* Supplies a lookup from Entity ID to world position, letting the queue resolve what the camera is nearest first.
|
|
14800
|
+
* Sources that cannot answer should not call this, and are served in order.
|
|
14718
14801
|
*/
|
|
14719
14802
|
SetPositionSource(positionOf) {
|
|
14720
14803
|
this.positionOf = positionOf;
|
|
14721
14804
|
this.lastOrderFocus = null;
|
|
14805
|
+
this.cells.clear();
|
|
14806
|
+
this.lastInView.clear();
|
|
14807
|
+
for (const entityId of this.allEIds) {
|
|
14808
|
+
this.unplaced.add(entityId);
|
|
14809
|
+
}
|
|
14722
14810
|
}
|
|
14723
14811
|
/**
|
|
14724
|
-
* Supplies the view monitor, so the order follows the ground the camera is aimed at and prefers
|
|
14725
|
-
*
|
|
14812
|
+
* Supplies the view monitor, so the order follows the ground the camera is aimed at and prefers what is on screen.
|
|
14813
|
+
* Without one the ordering falls back to distance from the camera itself.
|
|
14726
14814
|
*/
|
|
14727
14815
|
SetViewMonitor(monitor) {
|
|
14816
|
+
var _a;
|
|
14817
|
+
(_a = this.monitorRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
14818
|
+
this.monitorRemoval = null;
|
|
14728
14819
|
this.monitor = monitor;
|
|
14729
14820
|
this.lastOrderFocus = null;
|
|
14821
|
+
if (!monitor) {
|
|
14822
|
+
return;
|
|
14823
|
+
}
|
|
14824
|
+
this.monitorRemoval = monitor.Updated().Subscribe(() => {
|
|
14825
|
+
this.admitNewlyInView();
|
|
14826
|
+
});
|
|
14827
|
+
}
|
|
14828
|
+
/*
|
|
14829
|
+
* Queues whatever the camera has moved onto since the last decision.
|
|
14830
|
+
*/
|
|
14831
|
+
admitNewlyInView() {
|
|
14832
|
+
if (this.disposed || !this.historic) {
|
|
14833
|
+
return;
|
|
14834
|
+
}
|
|
14835
|
+
const inView = this.decideInView();
|
|
14836
|
+
if (!inView) {
|
|
14837
|
+
return;
|
|
14838
|
+
}
|
|
14839
|
+
const admit = [];
|
|
14840
|
+
for (const entityId of inView) {
|
|
14841
|
+
if (!this.lastInView.has(entityId)) {
|
|
14842
|
+
admit.push(entityId);
|
|
14843
|
+
}
|
|
14844
|
+
}
|
|
14845
|
+
this.lastInView = new Set(inView);
|
|
14846
|
+
if (admit.length) {
|
|
14847
|
+
this.Queue(admit);
|
|
14848
|
+
}
|
|
14849
|
+
}
|
|
14850
|
+
/*
|
|
14851
|
+
* Returns the IDs a refresh should ask about, or null when the view cannot say and the answer has to be everything.
|
|
14852
|
+
*/
|
|
14853
|
+
decideInView() {
|
|
14854
|
+
if (!this.historic || !this.positionOf || !this.monitor) {
|
|
14855
|
+
return null;
|
|
14856
|
+
}
|
|
14857
|
+
const area = this.refreshArea();
|
|
14858
|
+
if (!area) {
|
|
14859
|
+
return null;
|
|
14860
|
+
}
|
|
14861
|
+
const inView = [];
|
|
14862
|
+
for (const key of this.candidateCellKeys(area)) {
|
|
14863
|
+
const cell = this.cells.get(key);
|
|
14864
|
+
if (!cell) {
|
|
14865
|
+
continue;
|
|
14866
|
+
}
|
|
14867
|
+
for (let i = 0; i < cell.ids.length; i++) {
|
|
14868
|
+
if (HistoricFetchOrder.InDegreeBounds(cell.lats[i], cell.lons[i], area)) {
|
|
14869
|
+
inView.push(cell.ids[i]);
|
|
14870
|
+
}
|
|
14871
|
+
}
|
|
14872
|
+
}
|
|
14873
|
+
// Anything the source cannot place yet is asked about rather than quietly dropped.
|
|
14874
|
+
for (const entityId of this.unplaced) {
|
|
14875
|
+
inView.push(entityId);
|
|
14876
|
+
}
|
|
14877
|
+
return inView;
|
|
14878
|
+
}
|
|
14879
|
+
/*
|
|
14880
|
+
* Returns the cell keys a rectangle can reach.
|
|
14881
|
+
*/
|
|
14882
|
+
candidateCellKeys(area) {
|
|
14883
|
+
const size = EntityGatherer.CELL_DEGREES;
|
|
14884
|
+
const southCell = Math.floor(area.south / size);
|
|
14885
|
+
const northCell = Math.floor(area.north / size);
|
|
14886
|
+
const spans = (area.west > area.east ? [
|
|
14887
|
+
{
|
|
14888
|
+
from: Math.floor(area.west / size),
|
|
14889
|
+
to: Math.floor(180 / size)
|
|
14890
|
+
},
|
|
14891
|
+
{
|
|
14892
|
+
from: Math.floor(-180 / size),
|
|
14893
|
+
to: Math.floor(area.east / size)
|
|
14894
|
+
}
|
|
14895
|
+
] :
|
|
14896
|
+
[{
|
|
14897
|
+
from: Math.floor(area.west / size),
|
|
14898
|
+
to: Math.floor(area.east / size)
|
|
14899
|
+
}]);
|
|
14900
|
+
let width = 0;
|
|
14901
|
+
for (const span of spans) {
|
|
14902
|
+
width += (span.to - span.from) + 1;
|
|
14903
|
+
}
|
|
14904
|
+
const wanted = ((northCell - southCell) + 1) * width;
|
|
14905
|
+
if (!(wanted > 0) || wanted > this.cells.size) {
|
|
14906
|
+
return Array.from(this.cells.keys());
|
|
14907
|
+
}
|
|
14908
|
+
const keys = [];
|
|
14909
|
+
for (let lat = southCell; lat <= northCell; lat++) {
|
|
14910
|
+
for (const span of spans) {
|
|
14911
|
+
for (let lon = span.from; lon <= span.to; lon++) {
|
|
14912
|
+
keys.push(lat + ":" + lon);
|
|
14913
|
+
}
|
|
14914
|
+
}
|
|
14915
|
+
}
|
|
14916
|
+
return keys;
|
|
14917
|
+
}
|
|
14918
|
+
/*
|
|
14919
|
+
* Files an Entity in the cell its position falls in.
|
|
14920
|
+
*/
|
|
14921
|
+
place(entityId) {
|
|
14922
|
+
const degrees = this.degreesOf(entityId);
|
|
14923
|
+
if (!degrees) {
|
|
14924
|
+
this.unplaced.add(entityId);
|
|
14925
|
+
return;
|
|
14926
|
+
}
|
|
14927
|
+
const size = EntityGatherer.CELL_DEGREES;
|
|
14928
|
+
const key = Math.floor(degrees.lat / size) + ":" + Math.floor(degrees.lon / size);
|
|
14929
|
+
let cell = this.cells.get(key);
|
|
14930
|
+
if (!cell) {
|
|
14931
|
+
cell = { ids: [], lats: [], lons: [] };
|
|
14932
|
+
this.cells.set(key, cell);
|
|
14933
|
+
}
|
|
14934
|
+
cell.ids.push(entityId);
|
|
14935
|
+
cell.lats.push(degrees.lat);
|
|
14936
|
+
cell.lons.push(degrees.lon);
|
|
14937
|
+
this.unplaced.delete(entityId);
|
|
14938
|
+
}
|
|
14939
|
+
/*
|
|
14940
|
+
* Retries a bounded number of the Entities the source could not place before, so a late baked
|
|
14941
|
+
* position joins the index without any one tick paying for all of them.
|
|
14942
|
+
*/
|
|
14943
|
+
placeStragglers() {
|
|
14944
|
+
if (!this.unplaced.size || !this.positionOf) {
|
|
14945
|
+
return;
|
|
14946
|
+
}
|
|
14947
|
+
let budget = EntityGatherer.PLACE_BATCH;
|
|
14948
|
+
for (const entityId of this.unplaced) {
|
|
14949
|
+
if (budget-- <= 0) {
|
|
14950
|
+
return;
|
|
14951
|
+
}
|
|
14952
|
+
this.place(entityId);
|
|
14953
|
+
}
|
|
14954
|
+
}
|
|
14955
|
+
clearIndex() {
|
|
14956
|
+
this.cells.clear();
|
|
14957
|
+
this.unplaced.clear();
|
|
14958
|
+
this.lastInView.clear();
|
|
14959
|
+
}
|
|
14960
|
+
/*
|
|
14961
|
+
* Returns where an Entity sits in degrees, or null when the source cannot place it.
|
|
14962
|
+
*/
|
|
14963
|
+
degreesOf(entityId) {
|
|
14964
|
+
let pos = null;
|
|
14965
|
+
try {
|
|
14966
|
+
pos = this.positionOf ? this.positionOf(entityId) : null;
|
|
14967
|
+
}
|
|
14968
|
+
catch {
|
|
14969
|
+
pos = null;
|
|
14970
|
+
}
|
|
14971
|
+
return pos ? CartesianToDegrees(pos) : null;
|
|
14972
|
+
}
|
|
14973
|
+
/*
|
|
14974
|
+
* Returns the visible rectangle plus the margin a refresh still reaches into,
|
|
14975
|
+
* or null when the view cannot say, which is what leaves every Entity in.
|
|
14976
|
+
*/
|
|
14977
|
+
refreshArea() {
|
|
14978
|
+
const focus = HistoricFetchOrder.FocusFrom({ viewer: this.viewer, monitor: this.monitor });
|
|
14979
|
+
if (!(focus === null || focus === void 0 ? void 0 : focus.bounds)) {
|
|
14980
|
+
return null;
|
|
14981
|
+
}
|
|
14982
|
+
return HistoricFetchOrder.GrowBounds(focus.bounds, HistoricFetchOrder.RefreshMarginFor(focus.bounds));
|
|
14730
14983
|
}
|
|
14731
14984
|
/**
|
|
14732
14985
|
* Re-bands the pending queue so the nearest Entities are requested first.
|
|
@@ -14739,8 +14992,6 @@ class EntityGatherer {
|
|
|
14739
14992
|
if (!focus) {
|
|
14740
14993
|
return;
|
|
14741
14994
|
}
|
|
14742
|
-
// Re-banding on every batch would cost a full pass per request for no change in the answer.
|
|
14743
|
-
// Measured on the focus, so panning across the ground counts even when the eye barely moves.
|
|
14744
14995
|
if (this.lastOrderFocus && !EntityGatherer.boundsChanged(this.lastOrderFocus, focus) &&
|
|
14745
14996
|
Cartesian3.distance(this.lastOrderFocus.origin, focus.origin) < EntityGatherer.REORDER_MOVE_METRES) {
|
|
14746
14997
|
return;
|
|
@@ -14787,26 +15038,47 @@ class EntityGatherer {
|
|
|
14787
15038
|
});
|
|
14788
15039
|
const ordered = [];
|
|
14789
15040
|
for (const band of banded) {
|
|
15041
|
+
// Within a band, the ones a read has answered for go first.
|
|
15042
|
+
// A building that has never produced a record is the one least likely to start now, so it waits.
|
|
15043
|
+
const withData = [];
|
|
15044
|
+
const withoutData = [];
|
|
14790
15045
|
for (const entityId of band) {
|
|
15046
|
+
(this.everFound.has(entityId) ? withData : withoutData).push(entityId);
|
|
15047
|
+
}
|
|
15048
|
+
for (const entityId of withData) {
|
|
15049
|
+
ordered.push(entityId);
|
|
15050
|
+
}
|
|
15051
|
+
for (const entityId of withoutData) {
|
|
14791
15052
|
ordered.push(entityId);
|
|
14792
15053
|
}
|
|
14793
15054
|
}
|
|
14794
15055
|
return ordered;
|
|
14795
15056
|
}
|
|
15057
|
+
/*
|
|
15058
|
+
* Takes an ID into the known set, filing it in the index the first time it is seen.
|
|
15059
|
+
*/
|
|
15060
|
+
remember(entityId) {
|
|
15061
|
+
if (this.allEIds.has(entityId)) {
|
|
15062
|
+
return;
|
|
15063
|
+
}
|
|
15064
|
+
this.allEIds.add(entityId);
|
|
15065
|
+
// Only a historic refresh reads the index, so nothing else pays to build it.
|
|
15066
|
+
if (this.historic) {
|
|
15067
|
+
this.place(entityId);
|
|
15068
|
+
}
|
|
15069
|
+
}
|
|
14796
15070
|
Queue(entityIds, topOfQueue = false) {
|
|
14797
15071
|
if (this.disposed || !(entityIds === null || entityIds === void 0 ? void 0 : entityIds.length)) {
|
|
14798
15072
|
return;
|
|
14799
15073
|
}
|
|
14800
15074
|
let changes = 0;
|
|
14801
15075
|
if (topOfQueue) {
|
|
14802
|
-
// Walked back to front so a repeated ID keeps the position of its last occurrence, then
|
|
14803
|
-
// laid down in that order, which is where inserting one at a time leaves them.
|
|
14804
15076
|
const toFront = [];
|
|
14805
15077
|
const promoting = new Set();
|
|
14806
15078
|
let anyAlreadyQueued = false;
|
|
14807
15079
|
for (let i = entityIds.length - 1; i >= 0; i--) {
|
|
14808
15080
|
const eId = entityIds[i];
|
|
14809
|
-
this.
|
|
15081
|
+
this.remember(eId);
|
|
14810
15082
|
if (promoting.has(eId)) {
|
|
14811
15083
|
continue;
|
|
14812
15084
|
}
|
|
@@ -14842,7 +15114,7 @@ class EntityGatherer {
|
|
|
14842
15114
|
else {
|
|
14843
15115
|
for (let i = 0; i < entityIds.length; i++) {
|
|
14844
15116
|
const eId = entityIds[i];
|
|
14845
|
-
this.
|
|
15117
|
+
this.remember(eId);
|
|
14846
15118
|
if (this.eIdQueued.has(eId)) {
|
|
14847
15119
|
continue;
|
|
14848
15120
|
}
|
|
@@ -14857,19 +15129,22 @@ class EntityGatherer {
|
|
|
14857
15129
|
this.onTick(false);
|
|
14858
15130
|
}
|
|
14859
15131
|
Dispose() {
|
|
15132
|
+
var _a;
|
|
14860
15133
|
if (this.disposed) {
|
|
14861
15134
|
return;
|
|
14862
15135
|
}
|
|
14863
15136
|
this.disposed = true;
|
|
15137
|
+
(_a = this.monitorRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
15138
|
+
this.monitorRemoval = null;
|
|
14864
15139
|
this.hDisposals.forEach((d) => d());
|
|
14865
15140
|
this.hDisposals = [];
|
|
14866
|
-
// A tick still awaiting a response resumes after this, and anything left here would have it
|
|
14867
|
-
// ask for the whole set again on the way out.
|
|
14868
15141
|
this.eIdQueue = [];
|
|
14869
15142
|
this.eIdQueued.clear();
|
|
14870
15143
|
this.priorityCount = 0;
|
|
14871
15144
|
this.allEIds.clear();
|
|
14872
15145
|
this.lastFoundDateTimes.clear();
|
|
15146
|
+
this.everFound.clear();
|
|
15147
|
+
this.clearIndex();
|
|
14873
15148
|
this.entityDataOverrides.clear();
|
|
14874
15149
|
}
|
|
14875
15150
|
checkRange(force) {
|
|
@@ -14893,6 +15168,7 @@ class EntityGatherer {
|
|
|
14893
15168
|
this.lastDateTime = rTime;
|
|
14894
15169
|
(async () => {
|
|
14895
15170
|
this.runningTick = true;
|
|
15171
|
+
this.placeStragglers();
|
|
14896
15172
|
let rerun = false;
|
|
14897
15173
|
try {
|
|
14898
15174
|
const handleResponse = async (requestedBatch, entities) => {
|
|
@@ -14905,6 +15181,13 @@ class EntityGatherer {
|
|
|
14905
15181
|
foundById.set(entityId, entity);
|
|
14906
15182
|
}
|
|
14907
15183
|
}
|
|
15184
|
+
if (this.historic) {
|
|
15185
|
+
for (const entityId of requestedBatch || []) {
|
|
15186
|
+
if (foundById.has(entityId)) {
|
|
15187
|
+
this.everFound.add(entityId);
|
|
15188
|
+
}
|
|
15189
|
+
}
|
|
15190
|
+
}
|
|
14908
15191
|
for (const entityId of requestedBatch || []) {
|
|
14909
15192
|
const override = this.entityDataOverrides.get(entityId);
|
|
14910
15193
|
if (override) {
|
|
@@ -15033,15 +15316,16 @@ class EntityGatherer {
|
|
|
15033
15316
|
this._onQueueProgress.Trigger(100);
|
|
15034
15317
|
}
|
|
15035
15318
|
}
|
|
15036
|
-
// Now run through
|
|
15319
|
+
// Now run through the IDs we've seen that the view still reaches, and request them.
|
|
15037
15320
|
// We'll skip those that we just requested.
|
|
15038
|
-
|
|
15321
|
+
const inView = this.decideInView();
|
|
15322
|
+
this.lastInView = inView ? new Set(inView) : new Set();
|
|
15323
|
+
let allEIds = inView || Array.from(this.allEIds);
|
|
15039
15324
|
if (requestedIds.size) {
|
|
15040
15325
|
allEIds = allEIds.filter((eId) => !requestedIds.has(eId));
|
|
15041
15326
|
}
|
|
15042
15327
|
if (allEIds.length) {
|
|
15043
|
-
//
|
|
15044
|
-
// first here even more than in the queue above.
|
|
15328
|
+
// The near ones are resolved first out of whatever the view still reaches.
|
|
15045
15329
|
allEIds = this.bandIds(allEIds);
|
|
15046
15330
|
while (allEIds.length && !this.disposed && !this.eIdQueue.length) {
|
|
15047
15331
|
if (this.historic && this.lastDateTime !== rTime) {
|
|
@@ -15080,6 +15364,11 @@ class EntityGatherer {
|
|
|
15080
15364
|
}
|
|
15081
15365
|
// Below this the whole queue clears in one or two requests, so ordering it buys nothing.
|
|
15082
15366
|
EntityGatherer.MIN_ORDER_QUEUE = 500;
|
|
15367
|
+
// Side of the ground cells Entities are bucketed into, in degrees.
|
|
15368
|
+
// About a kilometre, so a view covers a handful of them rather than hundreds.
|
|
15369
|
+
EntityGatherer.CELL_DEGREES = 0.01;
|
|
15370
|
+
// How many Entities one tick will try to place in the index.
|
|
15371
|
+
EntityGatherer.PLACE_BATCH = 20000;
|
|
15083
15372
|
// How far the point being looked at has to move before the queue is worth re-banding, in metres.
|
|
15084
15373
|
// Under the nearest band's width, so a move that could change what is nearest still triggers one.
|
|
15085
15374
|
EntityGatherer.REORDER_MOVE_METRES = 250;
|
|
@@ -47923,7 +48212,7 @@ var StyleUtils;
|
|
|
47923
48212
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
47924
48213
|
})(StyleUtils || (StyleUtils = {}));
|
|
47925
48214
|
|
|
47926
|
-
const VERSION = "7.3.
|
|
48215
|
+
const VERSION = "7.3.9";
|
|
47927
48216
|
/**
|
|
47928
48217
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
47929
48218
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|