bruce-cesium 7.4.1 → 7.4.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.
- package/dist/bruce-cesium.es5.js +295 -159
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +293 -157
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/entity-gatherer.js +50 -51
- package/dist/lib/rendering/entity-gatherer.js.map +1 -1
- package/dist/lib/rendering/entity-render-engine.js +56 -26
- package/dist/lib/rendering/entity-render-engine.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label.js +185 -78
- package/dist/lib/rendering/render-managers/common/entity-label.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/entity-gatherer.d.ts +2 -1
- package/dist/types/rendering/entity-render-engine.d.ts +1 -0
- package/dist/types/rendering/render-managers/common/entity-label.d.ts +4 -1
- 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, HeightReference, DistanceDisplayCondition,
|
|
3
|
-
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style,
|
|
2
|
+
import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, ConstantPositionProperty, HeightReference, DistanceDisplayCondition, ColorBlendMode, HeadingPitchRoll, Math as Math$1, Transforms, ShadowMode, Cartesian3, ClassificationType, Model, JulianDate, Quaternion, Matrix4, ShaderSource, Ellipsoid, Geometry, GeometryAttribute, ComponentDatatype, PrimitiveType, BoundingSphere, GeometryPipeline, Cartesian2, Cartesian4, sampleTerrain, Texture, PixelFormat, Sampler, TextureWrap, TextureMinificationFilter, TextureMagnificationFilter, VertexArray, BufferUsage, ShaderProgram, RenderState, BlendingState, DrawCommand, Pass, ArcType, CornerType, HorizontalOrigin, VerticalOrigin, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Rectangle, SceneTransforms, FeatureDetection, NearFarScalar, Matrix3, KmlDataSource, SceneMode, GeoJsonDataSource, 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, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, CesiumInspector, ClockRange, DynamicEnvironmentMapManager, GeometryInstance, CustomDataSource, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
|
|
3
|
+
import { Cartes, LRUCache, ProjectViewTile, ENVIRONMENT, Calculator, ClientFile, Entity as Entity$1, EntityLod, EntityTag, EntityType, ObjectUtils, Style, Carto, Geometry as Geometry$1, Api, Bounds, ClientFileValueMap, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, DataLab, BruceEvent, EntityCoords, AccountConcept, DelayQueue, BruceApi, EntityRelation, 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.
|
|
@@ -5399,7 +5399,14 @@ var EntityLabel;
|
|
|
5399
5399
|
(function (EntityLabel) {
|
|
5400
5400
|
const ICON_BACKGROUND_BLEND = 0.8;
|
|
5401
5401
|
const ICON_BACKGROUND_ALPHA = 0.45;
|
|
5402
|
+
// Under this much difference between the glyph's width and height the chip is squared off,
|
|
5403
|
+
// so a row of labels reads as one size rather than a set of differently shaped pills.
|
|
5404
|
+
const ICON_BACKGROUND_UNIFORM_TOLERANCE = 0.3;
|
|
5402
5405
|
const TEXT_MAX_WIDTH = 200;
|
|
5406
|
+
// How far an angled leader runs sideways before the label starts.
|
|
5407
|
+
const ANGLED_LEADER_RUN = 28;
|
|
5408
|
+
// One per tinted icon, since an SVG mask is addressed by id across the whole document.
|
|
5409
|
+
let tintCounter = 0;
|
|
5403
5410
|
// Key where the label instance is stored within the cesium entity.
|
|
5404
5411
|
// Eg: rego[ATTACH_KEY] = new EntityLabel(...);
|
|
5405
5412
|
EntityLabel.ATTACH_KEY = "nextspace-navigator-entity-label";
|
|
@@ -5498,7 +5505,7 @@ var EntityLabel;
|
|
|
5498
5505
|
this.nextOrder = 0;
|
|
5499
5506
|
}
|
|
5500
5507
|
Resolve(frames) {
|
|
5501
|
-
var _a, _b;
|
|
5508
|
+
var _a, _b, _c;
|
|
5502
5509
|
const live = new Set(frames.map(frame => frame.id));
|
|
5503
5510
|
const moved = (frame) => {
|
|
5504
5511
|
var _a;
|
|
@@ -5525,10 +5532,17 @@ var EntityLabel;
|
|
|
5525
5532
|
const placed = new Map();
|
|
5526
5533
|
const next = new Map();
|
|
5527
5534
|
const candidate = (frame, side) => {
|
|
5528
|
-
var _a;
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5535
|
+
var _a, _b;
|
|
5536
|
+
if (!frame.canFlip) {
|
|
5537
|
+
return frame;
|
|
5538
|
+
}
|
|
5539
|
+
if (frame.leaderRun != null) {
|
|
5540
|
+
const x = side === "left" ? frame.anchorX - frame.leaderRun - frame.width : frame.anchorX + frame.leaderRun;
|
|
5541
|
+
return { ...frame, x: Math.max(0, Math.min(x, ((_a = frame.viewportWidth) !== null && _a !== void 0 ? _a : Infinity) - frame.width)) };
|
|
5542
|
+
}
|
|
5543
|
+
return (side === "left" ?
|
|
5544
|
+
{ ...frame, x: Math.max(0, Math.min(frame.anchorX - frame.width, ((_b = frame.viewportWidth) !== null && _b !== void 0 ? _b : Infinity) - frame.width)) }
|
|
5545
|
+
: frame);
|
|
5532
5546
|
};
|
|
5533
5547
|
const score = (frame, padding = 0) => {
|
|
5534
5548
|
const box = {
|
|
@@ -5544,7 +5558,7 @@ var EntityLabel;
|
|
|
5544
5558
|
};
|
|
5545
5559
|
for (const frame of ordered) {
|
|
5546
5560
|
const old = this.previous.get(frame.id);
|
|
5547
|
-
let side = frame.canFlip ? (_a = old === null || old === void 0 ? void 0 : old.side) !== null && _a !== void 0 ? _a : "right" : "right";
|
|
5561
|
+
let side = frame.canFlip ? (_b = (_a = old === null || old === void 0 ? void 0 : old.side) !== null && _a !== void 0 ? _a : frame.leaderSide) !== null && _b !== void 0 ? _b : "right" : "right";
|
|
5548
5562
|
let chosen = candidate(frame, side);
|
|
5549
5563
|
if (!fixed(frame) && frame.canFlip) {
|
|
5550
5564
|
const otherSide = side === "left" ? "right" : "left";
|
|
@@ -5556,7 +5570,7 @@ var EntityLabel;
|
|
|
5556
5570
|
}
|
|
5557
5571
|
}
|
|
5558
5572
|
placed.set(frame.id, { frame: chosen, side });
|
|
5559
|
-
next.set(frame.id, { frame: fixed(frame) ? old.frame : { ...frame }, side, order: (
|
|
5573
|
+
next.set(frame.id, { frame: fixed(frame) ? old.frame : { ...frame }, side, order: (_c = old === null || old === void 0 ? void 0 : old.order) !== null && _c !== void 0 ? _c : this.nextOrder++ });
|
|
5560
5574
|
text.Add(chosen);
|
|
5561
5575
|
const stem = leaderBounds(chosen);
|
|
5562
5576
|
if (stem) {
|
|
@@ -5576,7 +5590,7 @@ var EntityLabel;
|
|
|
5576
5590
|
* Resolves clustering and stable text placement before depth fading; highlighted labels receive priority.
|
|
5577
5591
|
*/
|
|
5578
5592
|
function Layout(input, memory = new PlacementMemory()) {
|
|
5579
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
5593
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
5580
5594
|
const frames = input.filter(frame => [frame.x, frame.y, frame.width, frame.height, frame.depth].every(Number.isFinite))
|
|
5581
5595
|
.sort((a, b) => (b.priority || 0) - (a.priority || 0) || a.depth - b.depth || a.id.localeCompare(b.id));
|
|
5582
5596
|
const result = new Map();
|
|
@@ -5642,17 +5656,13 @@ var EntityLabel;
|
|
|
5642
5656
|
}
|
|
5643
5657
|
}
|
|
5644
5658
|
if (values.size > 1) {
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
if (values.size > 2)
|
|
5653
|
-
rows.push(`+${values.size - 2} more…`);
|
|
5654
|
-
representative.text = rows.join("\n");
|
|
5655
|
-
}
|
|
5659
|
+
// A value long enough to wrap fills the box on its own, so only one is listed.
|
|
5660
|
+
const wrapped = stableMembers.some(member => { var _a, _b; return member.textWrapped && ((_b = (member.text || ((_a = member.options) === null || _a === void 0 ? void 0 : _a.text))) === null || _b === void 0 ? void 0 : _b.trim()); });
|
|
5661
|
+
const limit = wrapped ? 1 : 2;
|
|
5662
|
+
const rows = Array.from(values).slice(0, limit);
|
|
5663
|
+
if (values.size > limit)
|
|
5664
|
+
rows.push(`+${values.size - limit} more…`);
|
|
5665
|
+
representative.text = rows.join("\n");
|
|
5656
5666
|
}
|
|
5657
5667
|
}
|
|
5658
5668
|
for (const frame of cluster.members) {
|
|
@@ -5676,7 +5686,7 @@ var EntityLabel;
|
|
|
5676
5686
|
const box = { ...frame, x: frame.x + .01, y: frame.y + .01, width: Math.max(0, frame.width - .02), height: Math.max(0, frame.height - .02) };
|
|
5677
5687
|
const overlap = foreground.HasOverlap(box) || foregroundLeaders.HasOverlap(box) || Boolean(stem && foreground.HasOverlap(stem));
|
|
5678
5688
|
if (overlap) {
|
|
5679
|
-
placement.opacity *= Math.max(0, Math.min(1, (
|
|
5689
|
+
placement.opacity *= Math.max(0, Math.min(1, (_g = (_f = frame.options) === null || _f === void 0 ? void 0 : _f.overlapOpacity) !== null && _g !== void 0 ? _g : 0.25));
|
|
5680
5690
|
}
|
|
5681
5691
|
placement.zIndex = zIndex--;
|
|
5682
5692
|
foreground.Add(frame);
|
|
@@ -5998,6 +6008,8 @@ var EntityLabel;
|
|
|
5998
6008
|
this.loadTimeout = null;
|
|
5999
6009
|
this.loadedName = false;
|
|
6000
6010
|
this.line = null;
|
|
6011
|
+
// The sideways half of an angled leader; the rise is drawn by line.
|
|
6012
|
+
this.leaderRun = null;
|
|
6001
6013
|
this.anchor = null;
|
|
6002
6014
|
// Null = not attempted to load.
|
|
6003
6015
|
this.additionalTexts = null;
|
|
@@ -6394,6 +6406,7 @@ var EntityLabel;
|
|
|
6394
6406
|
}
|
|
6395
6407
|
};
|
|
6396
6408
|
const normalLeader = (_k = this.options.leader) !== null && _k !== void 0 ? _k : presentation === "text";
|
|
6409
|
+
const angled = this.options.leaderStyle === "angled";
|
|
6397
6410
|
let leader = normalLeader;
|
|
6398
6411
|
const content = document.createElement("span");
|
|
6399
6412
|
const originalText = (_l = this.options.text) !== null && _l !== void 0 ? _l : [text, ...additionalTexts].join("\n");
|
|
@@ -6402,6 +6415,7 @@ var EntityLabel;
|
|
|
6402
6415
|
let sourceNaturalText;
|
|
6403
6416
|
let iconElement;
|
|
6404
6417
|
let iconContainer;
|
|
6418
|
+
let fitIconBackground;
|
|
6405
6419
|
content.className = "entity-label-content";
|
|
6406
6420
|
content.style.cssText = "display:flex;align-items:center;gap:6px;";
|
|
6407
6421
|
if (presentation === "icon-text-above") {
|
|
@@ -6424,34 +6438,49 @@ var EntityLabel;
|
|
|
6424
6438
|
image.alt = this.options.icon || "";
|
|
6425
6439
|
const scale = (_o = this.options.iconScale) !== null && _o !== void 0 ? _o : 1;
|
|
6426
6440
|
const size = this.options.iconSize;
|
|
6427
|
-
const
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
mask
|
|
6434
|
-
mask.
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
}
|
|
6441
|
+
const svgNs = "http://www.w3.org/2000/svg";
|
|
6442
|
+
const tint = iconColor ? document.createElementNS(svgNs, "svg") : null;
|
|
6443
|
+
const painted = tint ? document.createElementNS(svgNs, "image") : null;
|
|
6444
|
+
const inked = tint ? document.createElementNS(svgNs, "rect") : null;
|
|
6445
|
+
if (tint) {
|
|
6446
|
+
const maskId = `entity-label-tint-${++tintCounter}`;
|
|
6447
|
+
const mask = document.createElementNS(svgNs, "mask");
|
|
6448
|
+
mask.setAttribute("id", maskId);
|
|
6449
|
+
mask.setAttribute("maskUnits", "userSpaceOnUse");
|
|
6450
|
+
painted.setAttribute("href", this.options.iconUrl);
|
|
6451
|
+
painted.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
6452
|
+
mask.appendChild(painted);
|
|
6453
|
+
inked.setAttribute("fill", iconColor);
|
|
6454
|
+
inked.setAttribute("mask", `url(#${maskId})`);
|
|
6455
|
+
tint.append(mask, inked);
|
|
6456
|
+
tint.style.display = "block";
|
|
6457
|
+
icon.style.display = "inline-flex";
|
|
6458
|
+
icon.appendChild(tint);
|
|
6441
6459
|
}
|
|
6442
6460
|
const resize = () => {
|
|
6443
6461
|
if (this.disposed || this.counter !== counter) {
|
|
6444
6462
|
return;
|
|
6445
6463
|
}
|
|
6446
6464
|
const intrinsic = this.options.iconScale != null && size == null;
|
|
6447
|
-
|
|
6448
|
-
|
|
6465
|
+
const width = (intrinsic ? image.naturalWidth || 24 : size || 24) * scale;
|
|
6466
|
+
const height = (intrinsic ? image.naturalHeight || 24 : size || 24) * scale;
|
|
6467
|
+
if (tint) {
|
|
6468
|
+
tint.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
6469
|
+
for (const node of [tint, painted, inked]) {
|
|
6470
|
+
node.setAttribute("width", String(width));
|
|
6471
|
+
node.setAttribute("height", String(height));
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
else {
|
|
6475
|
+
image.style.width = `${width}px`;
|
|
6476
|
+
image.style.height = `${height}px`;
|
|
6477
|
+
}
|
|
6449
6478
|
this.viewer.scene.requestRender();
|
|
6450
6479
|
};
|
|
6451
6480
|
image.onload = resize;
|
|
6452
6481
|
resize();
|
|
6453
6482
|
image.src = this.options.iconUrl;
|
|
6454
|
-
if (!
|
|
6483
|
+
if (!tint) {
|
|
6455
6484
|
icon.appendChild(image);
|
|
6456
6485
|
}
|
|
6457
6486
|
}
|
|
@@ -6476,6 +6505,27 @@ var EntityLabel;
|
|
|
6476
6505
|
icon.style.minWidth = `${size}px`;
|
|
6477
6506
|
icon.style.minHeight = `${size}px`;
|
|
6478
6507
|
icon.style.boxSizing = "content-box";
|
|
6508
|
+
let fitted = false;
|
|
6509
|
+
fitIconBackground = () => {
|
|
6510
|
+
if (fitted) {
|
|
6511
|
+
return;
|
|
6512
|
+
}
|
|
6513
|
+
const padding = size / 3;
|
|
6514
|
+
const width = icon.offsetWidth - padding * 2;
|
|
6515
|
+
const height = icon.offsetHeight - padding * 2;
|
|
6516
|
+
if (width <= 0 || height <= 0) {
|
|
6517
|
+
return;
|
|
6518
|
+
}
|
|
6519
|
+
fitted = true;
|
|
6520
|
+
const longest = Math.max(width, height);
|
|
6521
|
+
const difference = (longest - Math.min(width, height)) / longest;
|
|
6522
|
+
if (difference > ICON_BACKGROUND_UNIFORM_TOLERANCE) {
|
|
6523
|
+
return;
|
|
6524
|
+
}
|
|
6525
|
+
icon.style.minWidth = `${longest}px`;
|
|
6526
|
+
icon.style.minHeight = `${longest}px`;
|
|
6527
|
+
this.viewer.scene.requestRender();
|
|
6528
|
+
};
|
|
6479
6529
|
}
|
|
6480
6530
|
if (this.options.iconScale === 0) {
|
|
6481
6531
|
icon.style.display = "none";
|
|
@@ -6514,8 +6564,10 @@ var EntityLabel;
|
|
|
6514
6564
|
const countElement = document.createElement("span");
|
|
6515
6565
|
countElement.className = "entity-label-count";
|
|
6516
6566
|
countElement.style.cssText = "flex:none;align-self:center;white-space:nowrap;background:#fff;color:#000;text-shadow:none;border-radius:8px;padding:0 3px;display:none;";
|
|
6567
|
+
// Text above the icon would have the badge land in it, so the free corner is the lower one.
|
|
6568
|
+
const badgeBelow = presentation === "icon-text-above";
|
|
6517
6569
|
if (iconContainer) {
|
|
6518
|
-
countElement.style.cssText +=
|
|
6570
|
+
countElement.style.cssText += `position:absolute;left:100%;top:${badgeBelow ? "100%" : "0"};transform:translate(-50%,-50%);`;
|
|
6519
6571
|
iconContainer.appendChild(countElement);
|
|
6520
6572
|
}
|
|
6521
6573
|
if (!layers.has(this.viewer)) {
|
|
@@ -6524,6 +6576,7 @@ var EntityLabel;
|
|
|
6524
6576
|
const layer = layers.get(this.viewer);
|
|
6525
6577
|
let ele = null;
|
|
6526
6578
|
let lineEle = null;
|
|
6579
|
+
let runEle = null;
|
|
6527
6580
|
if (this.label) {
|
|
6528
6581
|
ele = this.label;
|
|
6529
6582
|
}
|
|
@@ -6560,6 +6613,7 @@ var EntityLabel;
|
|
|
6560
6613
|
}
|
|
6561
6614
|
if (this.line) {
|
|
6562
6615
|
lineEle = this.line;
|
|
6616
|
+
runEle = this.leaderRun;
|
|
6563
6617
|
}
|
|
6564
6618
|
else {
|
|
6565
6619
|
lineEle = document.createElement("div");
|
|
@@ -6603,6 +6657,14 @@ var EntityLabel;
|
|
|
6603
6657
|
layer.element.appendChild(lineEleNode);
|
|
6604
6658
|
layer.element.appendChild(lineEle);
|
|
6605
6659
|
}
|
|
6660
|
+
// Built here rather than beside the stem, since the style can change on a label that is reused.
|
|
6661
|
+
if (angled && !runEle) {
|
|
6662
|
+
runEle = lineEle.cloneNode(false);
|
|
6663
|
+
runEle.className = "entity-label-leader-run";
|
|
6664
|
+
runEle.style.display = "none";
|
|
6665
|
+
this.leaderRun = runEle;
|
|
6666
|
+
layer.element.appendChild(runEle);
|
|
6667
|
+
}
|
|
6606
6668
|
let MAX_DISTANCE = Math.max(15000, sizeInM * 35);
|
|
6607
6669
|
if (visual && visual instanceof Entity) {
|
|
6608
6670
|
// Consistent sized things.
|
|
@@ -6622,6 +6684,25 @@ var EntityLabel;
|
|
|
6622
6684
|
y: upwards ? endY - height : endY, endY
|
|
6623
6685
|
};
|
|
6624
6686
|
};
|
|
6687
|
+
/*
|
|
6688
|
+
* An angled leader parks the label beside the anchor instead of over it,
|
|
6689
|
+
* so the stem rises to the label's middle and then runs out to whichever side has the room.
|
|
6690
|
+
*/
|
|
6691
|
+
const fitAngledLeader = (anchorX, anchorY, desired, width, height, radius = 0) => {
|
|
6692
|
+
const canvas = this.viewer.canvas;
|
|
6693
|
+
const above = Math.max(0, anchorY - height / 2);
|
|
6694
|
+
const below = Math.max(0, canvas.clientHeight - anchorY - height / 2);
|
|
6695
|
+
const upwards = above >= Math.max(radius ? radius + 4 : 0, Math.min(8, desired)) || above >= below;
|
|
6696
|
+
const length = Math.min(desired, upwards ? above : below);
|
|
6697
|
+
const endY = anchorY + (upwards ? -length : length);
|
|
6698
|
+
const run = Math.max(ANGLED_LEADER_RUN, radius + 4);
|
|
6699
|
+
const rightwards = anchorX + run + width <= canvas.clientWidth || anchorX - run - width < 0;
|
|
6700
|
+
return {
|
|
6701
|
+
x: Math.max(0, Math.min(rightwards ? anchorX + run : anchorX - run - width, canvas.clientWidth - width)),
|
|
6702
|
+
y: Math.max(0, Math.min(endY - height / 2, canvas.clientHeight - height)), endY,
|
|
6703
|
+
run, side: (rightwards ? "right" : "left")
|
|
6704
|
+
};
|
|
6705
|
+
};
|
|
6625
6706
|
let cursorMotion = this.cursorMotion;
|
|
6626
6707
|
const project = () => {
|
|
6627
6708
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
@@ -6759,7 +6840,14 @@ var EntityLabel;
|
|
|
6759
6840
|
y -= height / 2;
|
|
6760
6841
|
}
|
|
6761
6842
|
// Membership uses the unclamped source footprint, never the summary's changing dimensions.
|
|
6762
|
-
|
|
6843
|
+
let leaderRun;
|
|
6844
|
+
let leaderSide;
|
|
6845
|
+
if (leader && angled) {
|
|
6846
|
+
const fit = fitAngledLeader(anchorX, anchorY, leaderLength, width, height);
|
|
6847
|
+
({ x, y } = fit);
|
|
6848
|
+
({ run: leaderRun, side: leaderSide } = fit);
|
|
6849
|
+
}
|
|
6850
|
+
else if (leader)
|
|
6763
6851
|
({ x, y } = fitLeader(anchorX, anchorY, leaderLength, width, height));
|
|
6764
6852
|
const bounds = clusterBounds || { x, y, width, height };
|
|
6765
6853
|
if (!leader && (bounds.x + bounds.width < 0 || bounds.y + bounds.height < 0 || bounds.x > this.viewer.canvas.clientWidth || bounds.y > this.viewer.canvas.clientHeight)) {
|
|
@@ -6774,20 +6862,21 @@ var EntityLabel;
|
|
|
6774
6862
|
extendedGeometry: visual instanceof Entity && Boolean(visual.polygon || visual.polyline || visual.corridor),
|
|
6775
6863
|
viewportWidth: this.viewer.canvas.clientWidth,
|
|
6776
6864
|
id: this.id, entityKey: ((_s = this.rego) === null || _s === void 0 ? void 0 : _s.entityId) ? JSON.stringify([this.rego.entityId, this.rego.menuItemId || "", this.Transient && !this.Persistent ? "hover" : ""]) : undefined,
|
|
6777
|
-
entityId: (_t = this.rego) === null || _t === void 0 ? void 0 : _t.entityId, group: this.groupId, x, y, width, height, anchorX, anchorY, depth, leaderLength, distance,
|
|
6865
|
+
entityId: (_t = this.rego) === null || _t === void 0 ? void 0 : _t.entityId, group: this.groupId, x, y, width, height, anchorX, anchorY, depth, leaderLength, leaderRun, leaderSide, distance,
|
|
6778
6866
|
// Priority shows the hovered member individually without dragging its cluster along.
|
|
6779
6867
|
opacity, priority: hover || cursorAmount > 0 || (state === null || state === void 0 ? void 0 : state.highlighted) ? 1 : 0, options: this.options, text: originalText, clusterBounds
|
|
6780
6868
|
};
|
|
6781
6869
|
};
|
|
6782
6870
|
let displacement = { x: 0, y: 0 };
|
|
6783
|
-
let displayedSummaryMore = false;
|
|
6784
6871
|
let nudge = { x: 0, y: 0, fromX: 0, fromY: 0, targetX: 0, targetY: 0, start: 0 };
|
|
6785
6872
|
const apply = (placement) => {
|
|
6786
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
6873
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
6787
6874
|
const show = (placement === null || placement === void 0 ? void 0 : placement.visible) && placement.opacity > 0;
|
|
6788
6875
|
clickEntityIds = show ? placement.entityIds : [];
|
|
6789
6876
|
ele.style.visibility = show ? "visible" : "hidden";
|
|
6790
6877
|
lineEle.style.display = show && leader ? "block" : "none";
|
|
6878
|
+
if (runEle)
|
|
6879
|
+
runEle.style.display = show && leader ? "block" : "none";
|
|
6791
6880
|
this.anchor.style.display = show && leader ? "block" : "none";
|
|
6792
6881
|
if (!show) {
|
|
6793
6882
|
displacement = { x: 0, y: 0 };
|
|
@@ -6798,17 +6887,8 @@ var EntityLabel;
|
|
|
6798
6887
|
return;
|
|
6799
6888
|
}
|
|
6800
6889
|
const displayText = (_a = placement.text) !== null && _a !== void 0 ? _a : originalText;
|
|
6801
|
-
|
|
6802
|
-
if (textElement && (textElement.textContent !== displayText + (summaryMore ? "\n…" : "") || displayedSummaryMore !== summaryMore)) {
|
|
6890
|
+
if (textElement && textElement.textContent !== displayText) {
|
|
6803
6891
|
textElement.textContent = displayText;
|
|
6804
|
-
if (summaryMore) {
|
|
6805
|
-
const more = document.createElement("span");
|
|
6806
|
-
more.className = "entity-label-more";
|
|
6807
|
-
more.style.opacity = "0.65";
|
|
6808
|
-
more.textContent = "\n…";
|
|
6809
|
-
textElement.appendChild(more);
|
|
6810
|
-
}
|
|
6811
|
-
displayedSummaryMore = summaryMore;
|
|
6812
6892
|
// Measure the summary's footprint next frame without replacing each member's source text.
|
|
6813
6893
|
this.viewer.scene.requestRender();
|
|
6814
6894
|
}
|
|
@@ -6826,6 +6906,7 @@ var EntityLabel;
|
|
|
6826
6906
|
// The badge participates in layout, so its new width needs another measurement.
|
|
6827
6907
|
this.viewer.scene.requestRender();
|
|
6828
6908
|
}
|
|
6909
|
+
fitIconBackground === null || fitIconBackground === void 0 ? void 0 : fitIconBackground();
|
|
6829
6910
|
if (iconContainer) {
|
|
6830
6911
|
const badgeWidth = countElement.offsetWidth;
|
|
6831
6912
|
const iconWidth = iconElement.offsetWidth;
|
|
@@ -6833,7 +6914,9 @@ var EntityLabel;
|
|
|
6833
6914
|
const clearance = badgeWidth ? (narrow ? badgeWidth / 2 + 2 : Math.max(0, badgeWidth / 2 - iconWidth / 4)) : 0;
|
|
6834
6915
|
countElement.style.left = `calc(100% + ${clearance}px)`;
|
|
6835
6916
|
// Reserve the badge overhang so adjacent text and viewport edges remain clear.
|
|
6836
|
-
|
|
6917
|
+
const overhang = countElement.offsetHeight / 2;
|
|
6918
|
+
iconContainer.style.marginTop = badgeBelow ? "0px" : `${overhang}px`;
|
|
6919
|
+
iconContainer.style.marginBottom = badgeBelow ? `${overhang}px` : "0px";
|
|
6837
6920
|
iconContainer.style.marginRight = `${badgeWidth / 2 + clearance}px`;
|
|
6838
6921
|
}
|
|
6839
6922
|
// Summary and badge changes must fit on their first visible frame, including after resize.
|
|
@@ -6876,19 +6959,26 @@ var EntityLabel;
|
|
|
6876
6959
|
sharedRing.animation = ringAnimation;
|
|
6877
6960
|
}
|
|
6878
6961
|
const radius = ringAnimation.inner > 0 ? ringAnimation.outer : 0;
|
|
6879
|
-
const stem = (leader ? fitLeader(frame.anchorX, frame.anchorY, Math.max(frame.leaderLength, radius ? radius + 4 : 0), ele.offsetWidth / coordinates.scaleX, ele.offsetHeight / coordinates.scaleY, radius) : undefined);
|
|
6962
|
+
const stem = (leader ? (angled ? fitAngledLeader : fitLeader)(frame.anchorX, frame.anchorY, Math.max(frame.leaderLength, radius ? radius + 4 : 0), ele.offsetWidth / coordinates.scaleX, ele.offsetHeight / coordinates.scaleY, radius) : undefined);
|
|
6880
6963
|
const position = { x: (stem || frame).x, y: (stem || frame).y };
|
|
6881
6964
|
const width = ele.offsetWidth / coordinates.scaleX;
|
|
6882
6965
|
const height = ele.offsetHeight / coordinates.scaleY;
|
|
6883
|
-
if (leader &&
|
|
6966
|
+
if (leader && angled) {
|
|
6967
|
+
// The declutter owns the side; the fit only says which one had the room to begin with.
|
|
6968
|
+
const run = Math.max(ANGLED_LEADER_RUN, radius + 4);
|
|
6969
|
+
const side = (_l = (_k = placement.textSide) !== null && _k !== void 0 ? _k : frame.leaderSide) !== null && _l !== void 0 ? _l : "right";
|
|
6970
|
+
const beside = side === "left" ? frame.anchorX - run - width : frame.anchorX + run;
|
|
6971
|
+
position.x = Math.max(0, Math.min(beside, this.viewer.canvas.clientWidth - width));
|
|
6972
|
+
}
|
|
6973
|
+
else if (leader && placement.textSide === "left") {
|
|
6884
6974
|
position.x = Math.max(0, Math.min(frame.anchorX - width, this.viewer.canvas.clientWidth - width));
|
|
6885
6975
|
}
|
|
6886
|
-
const gap = (
|
|
6976
|
+
const gap = (_o = (_m = this.options.pointerAvoidance) === null || _m === void 0 ? void 0 : _m.gap) !== null && _o !== void 0 ? _o : 12;
|
|
6887
6977
|
const containsPointer = (x, y, margin) => {
|
|
6888
6978
|
return pointer && pointer.x >= x - margin && pointer.x <= x + width + margin && pointer.y >= y - margin && pointer.y <= y + height + margin;
|
|
6889
6979
|
};
|
|
6890
6980
|
const passive = !selectOnClick || !this.visualRegister;
|
|
6891
|
-
if (passive && ((
|
|
6981
|
+
if (passive && ((_p = this.options.pointerAvoidance) === null || _p === void 0 ? void 0 : _p.enabled) !== false && pointer &&
|
|
6892
6982
|
(containsPointer(position.x, position.y, gap) || containsPointer(position.x + displacement.x, position.y + displacement.y, gap))) {
|
|
6893
6983
|
if (containsPointer(position.x + displacement.x, position.y + displacement.y, 0)) {
|
|
6894
6984
|
// Choose against the original box and retain the offset until the pointer leaves both boxes.
|
|
@@ -6906,7 +6996,7 @@ var EntityLabel;
|
|
|
6906
6996
|
else {
|
|
6907
6997
|
displacement = { x: 0, y: 0 };
|
|
6908
6998
|
}
|
|
6909
|
-
const nudgeDuration = (
|
|
6999
|
+
const nudgeDuration = (_r = (_q = this.options.pointerAvoidance) === null || _q === void 0 ? void 0 : _q.transitionDuration) !== null && _r !== void 0 ? _r : 200;
|
|
6910
7000
|
const animateNudge = () => {
|
|
6911
7001
|
const progress = now < nudge.start ? 0 : nudgeDuration > 0 ? Math.min(1, (now - nudge.start) / nudgeDuration) : 1;
|
|
6912
7002
|
const eased = progress * progress * (3 - 2 * progress);
|
|
@@ -6922,7 +7012,7 @@ var EntityLabel;
|
|
|
6922
7012
|
fromY: nudge.y,
|
|
6923
7013
|
targetX: displacement.x,
|
|
6924
7014
|
targetY: displacement.y,
|
|
6925
|
-
start: now + ((
|
|
7015
|
+
start: now + ((_t = (_s = this.options.pointerAvoidance) === null || _s === void 0 ? void 0 : _s.delay) !== null && _t !== void 0 ? _t : 180)
|
|
6926
7016
|
};
|
|
6927
7017
|
}
|
|
6928
7018
|
if (animateNudge() < 1 && (nudge.fromX !== nudge.targetX || nudge.fromY !== nudge.targetY)) {
|
|
@@ -6934,7 +7024,7 @@ var EntityLabel;
|
|
|
6934
7024
|
ele.style.top = `${coordinates.y + position.y * coordinates.scaleY}px`;
|
|
6935
7025
|
const clickTarget = content.querySelector('[role="button"]');
|
|
6936
7026
|
if (clickTarget) {
|
|
6937
|
-
clickTarget.setAttribute("aria-label", placement.members.length ? `Select ${placement.entityIds.length} entities` : `Select ${(
|
|
7027
|
+
clickTarget.setAttribute("aria-label", placement.members.length ? `Select ${placement.entityIds.length} entities` : `Select ${(_v = (_u = this.options.text) !== null && _u !== void 0 ? _u : text) !== null && _v !== void 0 ? _v : (_w = this.rego) === null || _w === void 0 ? void 0 : _w.entityId}`);
|
|
6938
7028
|
}
|
|
6939
7029
|
if (leader) {
|
|
6940
7030
|
const nodeRadius = ringAnimation.outer;
|
|
@@ -6957,8 +7047,13 @@ var EntityLabel;
|
|
|
6957
7047
|
anchor.style.opacity = String(opacity * (normalLeader ? 1 : cursorMotion.amount));
|
|
6958
7048
|
anchor.style.zIndex = String(placement.zIndex);
|
|
6959
7049
|
// The stem starts at the rim, never across the transparent centre, even after passive displacement.
|
|
6960
|
-
const
|
|
6961
|
-
const
|
|
7050
|
+
const straightX = Math.max(position.x, Math.min(frame.anchorX, position.x + width));
|
|
7051
|
+
const straightY = frame.anchorY < position.y ? position.y : frame.anchorY > position.y + height ? position.y + height : frame.anchorY;
|
|
7052
|
+
const beside = angled && (frame.anchorX < position.x || frame.anchorX > position.x + width);
|
|
7053
|
+
const elbowY = position.y + height / 2;
|
|
7054
|
+
const endX = beside ? frame.anchorX : straightX;
|
|
7055
|
+
const endY = beside ? elbowY : straightY;
|
|
7056
|
+
const runToX = frame.anchorX < position.x ? position.x : position.x + width;
|
|
6962
7057
|
const dx = endX - frame.anchorX, dy = endY - frame.anchorY;
|
|
6963
7058
|
const length = Math.hypot(dx, dy);
|
|
6964
7059
|
const leaderAngle = Math.atan2(dy, dx);
|
|
@@ -6969,13 +7064,13 @@ var EntityLabel;
|
|
|
6969
7064
|
// Keep the stem inside the 126-degree arc, away from antialiased endpoints.
|
|
6970
7065
|
const arcFraction = 0.35;
|
|
6971
7066
|
const rotationLimit = Math.PI * arcFraction - Math.PI / 30;
|
|
6972
|
-
const targetOffset = hovered ? Math.max(-rotationLimit, Math.min(rotationLimit, wrappedAngle)) : ((
|
|
7067
|
+
const targetOffset = hovered ? Math.max(-rotationLimit, Math.min(rotationLimit, wrappedAngle)) : ((_x = ringAnimation.arcOffset) !== null && _x !== void 0 ? _x : 0);
|
|
6973
7068
|
const targetOpen = cursorMotion.target || (hovered && (ring === null || ring === void 0 ? void 0 : ring.enabled) !== false && targetRadius > 0) ? 1 : 0;
|
|
6974
|
-
const elapsed = Math.min(32, Math.max(0, now - ((
|
|
7069
|
+
const elapsed = Math.min(32, Math.max(0, now - ((_y = ringAnimation.arcTime) !== null && _y !== void 0 ? _y : now)));
|
|
6975
7070
|
const blend = duration > 0 ? 1 - Math.exp(-elapsed / (duration / 3)) : 1;
|
|
6976
7071
|
const approach = (value, target) => Math.abs(value - target) < 0.001 ? target : value + (target - value) * blend;
|
|
6977
|
-
ringAnimation.arcOffset = approach((
|
|
6978
|
-
ringAnimation.arcOpen = approach((
|
|
7072
|
+
ringAnimation.arcOffset = approach((_z = ringAnimation.arcOffset) !== null && _z !== void 0 ? _z : 0, targetOffset);
|
|
7073
|
+
ringAnimation.arcOpen = approach((_0 = ringAnimation.arcOpen) !== null && _0 !== void 0 ? _0 : 0, targetOpen);
|
|
6979
7074
|
ringAnimation.arcTime = now;
|
|
6980
7075
|
if (ringAnimation.arcOffset !== targetOffset || ringAnimation.arcOpen !== targetOpen) {
|
|
6981
7076
|
this.viewer.scene.requestRender();
|
|
@@ -6987,17 +7082,27 @@ var EntityLabel;
|
|
|
6987
7082
|
const cut = Math.min(radius, length);
|
|
6988
7083
|
const startX = frame.anchorX + (length ? dx / length * cut : 0);
|
|
6989
7084
|
const startY = frame.anchorY + (length ? dy / length * cut : 0);
|
|
6990
|
-
const
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7085
|
+
const draw = (element, fromX, fromY, toX, toY) => {
|
|
7086
|
+
const screenDx = (toX - fromX) * coordinates.scaleX;
|
|
7087
|
+
const screenDy = (toY - fromY) * coordinates.scaleY;
|
|
7088
|
+
element.style.width = `${2 * coordinates.scaleX}px`;
|
|
7089
|
+
element.style.left = `${coordinates.x + (fromX - 1) * coordinates.scaleX}px`;
|
|
7090
|
+
element.style.top = `${coordinates.y + fromY * coordinates.scaleY}px`;
|
|
7091
|
+
element.style.height = `${Math.hypot(screenDx, screenDy)}px`;
|
|
7092
|
+
element.style.transform = `rotate(${Math.atan2(screenDy, screenDx) - Math.PI / 2}rad)`;
|
|
7093
|
+
element.style.boxShadow = radius ? "none" : "0 0 5px rgba(0, 0, 0, 0.3)";
|
|
7094
|
+
element.style.transformOrigin = "top center";
|
|
7095
|
+
element.style.opacity = String(opacity * (normalLeader ? 1 : cursorMotion.amount));
|
|
7096
|
+
element.style.zIndex = String(placement.zIndex);
|
|
7097
|
+
};
|
|
7098
|
+
draw(lineEle, startX, startY, endX, endY);
|
|
7099
|
+
if (runEle) {
|
|
7100
|
+
// Overlap the corner by the stem's own width so the elbow has no notch in it.
|
|
7101
|
+
const overlap = frame.anchorX < runToX ? -1 : 1;
|
|
7102
|
+
runEle.style.display = beside ? "block" : "none";
|
|
7103
|
+
if (beside)
|
|
7104
|
+
draw(runEle, endX + overlap, endY, runToX, endY);
|
|
7105
|
+
}
|
|
7001
7106
|
}
|
|
7002
7107
|
};
|
|
7003
7108
|
ele.style.display = "flex";
|
|
@@ -7022,7 +7127,7 @@ var EntityLabel;
|
|
|
7022
7127
|
* Removes label from the viewer and unsubscribes from events.
|
|
7023
7128
|
*/
|
|
7024
7129
|
removeLabel() {
|
|
7025
|
-
var _a;
|
|
7130
|
+
var _a, _b;
|
|
7026
7131
|
(_a = this.anchor) === null || _a === void 0 ? void 0 : _a.remove();
|
|
7027
7132
|
this.anchor = null;
|
|
7028
7133
|
if (this.label &&
|
|
@@ -7034,6 +7139,8 @@ var EntityLabel;
|
|
|
7034
7139
|
this.line.parentElement.removeChild(this.line);
|
|
7035
7140
|
this.line = null;
|
|
7036
7141
|
}
|
|
7142
|
+
(_b = this.leaderRun) === null || _b === void 0 ? void 0 : _b.remove();
|
|
7143
|
+
this.leaderRun = null;
|
|
7037
7144
|
if (this.renderRemoval) {
|
|
7038
7145
|
this.renderRemoval();
|
|
7039
7146
|
this.renderRemoval = null;
|
|
@@ -16689,9 +16796,6 @@ class EntityGatherer {
|
|
|
16689
16796
|
// Last date-time range taken from the clock.
|
|
16690
16797
|
this.lastDateTimeMin = null;
|
|
16691
16798
|
this.lastDateTimeMax = null;
|
|
16692
|
-
// Entity ID -> last resolved date time.
|
|
16693
|
-
// Helps determine if a slow resolved request can still be applied while we wait for the next one.
|
|
16694
|
-
this.lastFoundDateTimes = new Map();
|
|
16695
16799
|
// ID of Entity IDs that need to be requested.
|
|
16696
16800
|
this.eIdQueue = [];
|
|
16697
16801
|
// Membership mirror of eIdQueue for quick checks.
|
|
@@ -16723,8 +16827,12 @@ class EntityGatherer {
|
|
|
16723
16827
|
// Unsubscribes the view monitor listener that queues what the camera has moved onto.
|
|
16724
16828
|
this.monitorRemoval = null;
|
|
16725
16829
|
// Indicates a tick is active.
|
|
16726
|
-
// When true,
|
|
16830
|
+
// When true, a new tick is not started; it is noted in pendingTick and run once this one ends.
|
|
16727
16831
|
this.runningTick = false;
|
|
16832
|
+
// A tick was asked for while one was running, so another is owed once it finishes.
|
|
16833
|
+
this.pendingTick = false;
|
|
16834
|
+
// The debounce every clock change goes through, kept so a tick owed after a running one does too.
|
|
16835
|
+
this.tickDelay = null;
|
|
16728
16836
|
// Entity ID -> Entity blob.
|
|
16729
16837
|
// This is a tool that lets developers set their own JSON blobs instead of requesting data from API.
|
|
16730
16838
|
this.entityDataOverrides = new Map();
|
|
@@ -16788,11 +16896,13 @@ class EntityGatherer {
|
|
|
16788
16896
|
let tickDelay = new DelayQueue(() => {
|
|
16789
16897
|
this.onTick(false);
|
|
16790
16898
|
}, 250, true);
|
|
16899
|
+
this.tickDelay = tickDelay;
|
|
16791
16900
|
this.hDisposals.push(() => {
|
|
16792
16901
|
if (tickDelay) {
|
|
16793
16902
|
tickDelay.Dispose();
|
|
16794
16903
|
}
|
|
16795
16904
|
tickDelay = null;
|
|
16905
|
+
this.tickDelay = null;
|
|
16796
16906
|
});
|
|
16797
16907
|
// React to clock changes and request new Entities.
|
|
16798
16908
|
let prevTime = null;
|
|
@@ -16832,7 +16942,6 @@ class EntityGatherer {
|
|
|
16832
16942
|
this.priorityCount = 0;
|
|
16833
16943
|
this.lastOrderFocus = null;
|
|
16834
16944
|
this.allEIds.clear();
|
|
16835
|
-
this.lastFoundDateTimes.clear();
|
|
16836
16945
|
this.everFound.clear();
|
|
16837
16946
|
this.clearIndex();
|
|
16838
16947
|
this.lastDateTime = null;
|
|
@@ -17194,7 +17303,6 @@ class EntityGatherer {
|
|
|
17194
17303
|
this.eIdQueued.clear();
|
|
17195
17304
|
this.priorityCount = 0;
|
|
17196
17305
|
this.allEIds.clear();
|
|
17197
|
-
this.lastFoundDateTimes.clear();
|
|
17198
17306
|
this.everFound.clear();
|
|
17199
17307
|
this.clearIndex();
|
|
17200
17308
|
this.entityDataOverrides.clear();
|
|
@@ -17210,7 +17318,13 @@ class EntityGatherer {
|
|
|
17210
17318
|
}
|
|
17211
17319
|
}
|
|
17212
17320
|
onTick(force) {
|
|
17213
|
-
if (this.
|
|
17321
|
+
if (this.disposed) {
|
|
17322
|
+
return;
|
|
17323
|
+
}
|
|
17324
|
+
if (this.runningTick) {
|
|
17325
|
+
if (this.historic) {
|
|
17326
|
+
this.pendingTick = true;
|
|
17327
|
+
}
|
|
17214
17328
|
return;
|
|
17215
17329
|
}
|
|
17216
17330
|
const rTime = this.viewer.clock.currentTime.toString();
|
|
@@ -17218,10 +17332,16 @@ class EntityGatherer {
|
|
|
17218
17332
|
return;
|
|
17219
17333
|
}
|
|
17220
17334
|
this.lastDateTime = rTime;
|
|
17335
|
+
// Whether the clock has left the moment this tick is reading.
|
|
17336
|
+
const movedOn = () => this.historic && this.viewer.clock.currentTime.toString() !== rTime;
|
|
17221
17337
|
(async () => {
|
|
17222
17338
|
this.runningTick = true;
|
|
17339
|
+
this.pendingTick = false;
|
|
17223
17340
|
this.placeStragglers();
|
|
17224
17341
|
let rerun = false;
|
|
17342
|
+
let interrupted = false;
|
|
17343
|
+
// Batch's answer is applied while the next batch is being read.
|
|
17344
|
+
const applying = [];
|
|
17225
17345
|
try {
|
|
17226
17346
|
const handleResponse = async (requestedBatch, entities) => {
|
|
17227
17347
|
var _a, _b, _c, _d;
|
|
@@ -17285,45 +17405,7 @@ class EntityGatherer {
|
|
|
17285
17405
|
api: this.api
|
|
17286
17406
|
})).tags;
|
|
17287
17407
|
}
|
|
17288
|
-
|
|
17289
|
-
// 1 = rTime is in the future.
|
|
17290
|
-
// -1 = rTime is in the past.
|
|
17291
|
-
let changeDir = 0;
|
|
17292
|
-
if (this.lastDateTime !== this.viewer.clock.currentTime.toString()) {
|
|
17293
|
-
changeDir = this.lastDateTime < this.viewer.clock.currentTime.toString() ? 1 : -1;
|
|
17294
|
-
}
|
|
17295
|
-
let toEmit;
|
|
17296
|
-
if (this.historic) {
|
|
17297
|
-
// We can emit Entities if the last resolved time (per Entity) isn't newer than rTime.
|
|
17298
|
-
// We compare using the changeDir to determine if we should emit or not.
|
|
17299
|
-
toEmit = resolvedEntities.filter((e) => {
|
|
17300
|
-
var _a;
|
|
17301
|
-
const entityId = ((_a = e === null || e === void 0 ? void 0 : e.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || (e === null || e === void 0 ? void 0 : e.id);
|
|
17302
|
-
const lastFoundDateTime = this.lastFoundDateTimes.get(entityId);
|
|
17303
|
-
if (lastFoundDateTime) {
|
|
17304
|
-
if (changeDir === 1) {
|
|
17305
|
-
return lastFoundDateTime <= rTime;
|
|
17306
|
-
}
|
|
17307
|
-
else if (changeDir === -1) {
|
|
17308
|
-
return lastFoundDateTime >= rTime;
|
|
17309
|
-
}
|
|
17310
|
-
}
|
|
17311
|
-
return true;
|
|
17312
|
-
});
|
|
17313
|
-
// Update the last found date times for the filtered Entities.
|
|
17314
|
-
toEmit.forEach((e) => {
|
|
17315
|
-
var _a;
|
|
17316
|
-
const entityId = ((_a = e === null || e === void 0 ? void 0 : e.Bruce) === null || _a === void 0 ? void 0 : _a.ID) || (e === null || e === void 0 ? void 0 : e.id);
|
|
17317
|
-
if (entityId) {
|
|
17318
|
-
this.lastFoundDateTimes.set(entityId, rTime);
|
|
17319
|
-
}
|
|
17320
|
-
});
|
|
17321
|
-
}
|
|
17322
|
-
else {
|
|
17323
|
-
// If we're not historic, we can just emit everything.
|
|
17324
|
-
toEmit = resolvedEntities;
|
|
17325
|
-
}
|
|
17326
|
-
this.emitEntities(toEmit, tags);
|
|
17408
|
+
this.emitEntities(resolvedEntities, tags);
|
|
17327
17409
|
};
|
|
17328
17410
|
const QUEUE_BATCH_SIZE = 500;
|
|
17329
17411
|
const requestedIds = new Set();
|
|
@@ -17332,7 +17414,8 @@ class EntityGatherer {
|
|
|
17332
17414
|
const total = this.eIdQueue.length;
|
|
17333
17415
|
let done = 0;
|
|
17334
17416
|
while (this.eIdQueue.length && !this.disposed) {
|
|
17335
|
-
if (
|
|
17417
|
+
if (movedOn()) {
|
|
17418
|
+
interrupted = true;
|
|
17336
17419
|
break;
|
|
17337
17420
|
}
|
|
17338
17421
|
this.orderQueueByCamera();
|
|
@@ -17348,7 +17431,7 @@ class EntityGatherer {
|
|
|
17348
17431
|
api: this.api,
|
|
17349
17432
|
maxSearchTimeSec: 60 * 2
|
|
17350
17433
|
});
|
|
17351
|
-
handleResponse(batch, entities);
|
|
17434
|
+
applying.push(handleResponse(batch, entities));
|
|
17352
17435
|
for (let i = 0; i < batch.length; i++) {
|
|
17353
17436
|
requestedIds.add(batch[i]);
|
|
17354
17437
|
}
|
|
@@ -17380,7 +17463,8 @@ class EntityGatherer {
|
|
|
17380
17463
|
// The near ones are resolved first out of whatever the view still reaches.
|
|
17381
17464
|
allEIds = this.bandIds(allEIds);
|
|
17382
17465
|
while (allEIds.length && !this.disposed && !this.eIdQueue.length) {
|
|
17383
|
-
if (
|
|
17466
|
+
if (movedOn()) {
|
|
17467
|
+
interrupted = true;
|
|
17384
17468
|
break;
|
|
17385
17469
|
}
|
|
17386
17470
|
const batch = allEIds.splice(0, QUEUE_BATCH_SIZE);
|
|
@@ -17391,7 +17475,7 @@ class EntityGatherer {
|
|
|
17391
17475
|
api: this.api,
|
|
17392
17476
|
maxSearchTimeSec: 60 * 2
|
|
17393
17477
|
});
|
|
17394
|
-
handleResponse(batch, entities);
|
|
17478
|
+
applying.push(handleResponse(batch, entities));
|
|
17395
17479
|
for (let i = 0; i < batch.length; i++) {
|
|
17396
17480
|
requestedIds.add(batch[i]);
|
|
17397
17481
|
}
|
|
@@ -17406,10 +17490,32 @@ class EntityGatherer {
|
|
|
17406
17490
|
console.error(e);
|
|
17407
17491
|
}
|
|
17408
17492
|
finally {
|
|
17493
|
+
// Only a historic answer can be overtaken by a newer moment, so nothing else waits.
|
|
17494
|
+
if (this.historic && applying.length) {
|
|
17495
|
+
await Promise.all(applying.map((pending) => pending.catch((e) => console.error(e))));
|
|
17496
|
+
}
|
|
17409
17497
|
this.runningTick = false;
|
|
17410
17498
|
}
|
|
17411
|
-
|
|
17499
|
+
// A moment read only in part is forgotten, so coming back to it reads it again in full.
|
|
17500
|
+
if (interrupted && this.lastDateTime === rTime) {
|
|
17501
|
+
this.lastDateTime = null;
|
|
17502
|
+
}
|
|
17503
|
+
if (this.disposed) {
|
|
17504
|
+
return;
|
|
17505
|
+
}
|
|
17506
|
+
// Leftovers at the same moment carry straight on, as they always have.
|
|
17507
|
+
if (rerun && !interrupted) {
|
|
17412
17508
|
this.onTick(true);
|
|
17509
|
+
return;
|
|
17510
|
+
}
|
|
17511
|
+
if (interrupted || this.pendingTick || movedOn()) {
|
|
17512
|
+
this.pendingTick = false;
|
|
17513
|
+
if (this.tickDelay) {
|
|
17514
|
+
this.tickDelay.Call();
|
|
17515
|
+
}
|
|
17516
|
+
else {
|
|
17517
|
+
this.onTick(false);
|
|
17518
|
+
}
|
|
17413
17519
|
}
|
|
17414
17520
|
})();
|
|
17415
17521
|
}
|
|
@@ -49099,7 +49205,7 @@ var EntityRenderEngine;
|
|
|
49099
49205
|
}
|
|
49100
49206
|
EntityRenderEngine.GetGraphicShapeId = GetGraphicShapeId;
|
|
49101
49207
|
async function Render(params) {
|
|
49102
|
-
var _a, _b, _c;
|
|
49208
|
+
var _a, _b, _c, _d, _e;
|
|
49103
49209
|
const groupRenderParams = {
|
|
49104
49210
|
apiGetter: params.apiGetter,
|
|
49105
49211
|
viewer: params.viewer,
|
|
@@ -49276,10 +49382,20 @@ var EntityRenderEngine;
|
|
|
49276
49382
|
polygons.push(entity);
|
|
49277
49383
|
continue;
|
|
49278
49384
|
}
|
|
49385
|
+
// Present when the gate above chose to reuse this entity's graphic.
|
|
49386
|
+
const existingRoot = cEntities.get(entity.Bruce.ID);
|
|
49387
|
+
const existingParts = new Map();
|
|
49388
|
+
(_d = existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) === null || _d === void 0 ? void 0 : _d.forEach((part) => {
|
|
49389
|
+
if (part._multiPartIndex != null) {
|
|
49390
|
+
existingParts.set(part._multiPartIndex, part);
|
|
49391
|
+
}
|
|
49392
|
+
});
|
|
49393
|
+
const partRendered = new Map();
|
|
49394
|
+
const partIndexes = new Map();
|
|
49279
49395
|
const pParams = {
|
|
49280
49396
|
...groupRenderParams,
|
|
49281
49397
|
entities: [],
|
|
49282
|
-
rendered:
|
|
49398
|
+
rendered: partRendered
|
|
49283
49399
|
};
|
|
49284
49400
|
pParams.entitiesHistoric = params.entitiesHistoric;
|
|
49285
49401
|
const zoomItem = pParams.zoomItems[entity.Bruce.ID];
|
|
@@ -49295,39 +49411,59 @@ var EntityRenderEngine;
|
|
|
49295
49411
|
};
|
|
49296
49412
|
pParams.zoomItems[subEntity.Bruce.ID] = zoomItem;
|
|
49297
49413
|
pParams.entities.push(subEntity);
|
|
49298
|
-
|
|
49299
|
-
|
|
49300
|
-
|
|
49301
|
-
|
|
49302
|
-
|
|
49303
|
-
|
|
49304
|
-
|
|
49305
|
-
|
|
49306
|
-
|
|
49307
|
-
|
|
49308
|
-
|
|
49414
|
+
partIndexes.set(subEntity.Bruce.ID, j);
|
|
49415
|
+
const existingPart = existingParts.get(j);
|
|
49416
|
+
if (existingPart) {
|
|
49417
|
+
// An engine preparing a reused graphic gathers everything connected to it, so a part still
|
|
49418
|
+
// attached to its root would have every other part evicted from the scene.
|
|
49419
|
+
existingPart._parentEntity = null;
|
|
49420
|
+
partRendered.set(subEntity.Bruce.ID, existingPart);
|
|
49421
|
+
}
|
|
49422
|
+
}
|
|
49423
|
+
const rendered = [];
|
|
49424
|
+
const collect = (results) => {
|
|
49425
|
+
results.forEach((cEntity, key) => {
|
|
49426
|
+
if (!cEntity) {
|
|
49427
|
+
return;
|
|
49428
|
+
}
|
|
49429
|
+
cEntity._multiPartIndex = partIndexes.get(key);
|
|
49430
|
+
rendered.push(cEntity);
|
|
49309
49431
|
pParams.entities = pParams.entities.filter((e) => e.Bruce.ID != key);
|
|
49310
|
-
}
|
|
49311
|
-
}
|
|
49312
|
-
|
|
49432
|
+
});
|
|
49433
|
+
};
|
|
49434
|
+
collect(await Polygon.RenderGroup(pParams));
|
|
49435
|
+
collect(await Polyline.RenderGroup(pParams));
|
|
49313
49436
|
// We'll only render points when there's no other geometry.
|
|
49314
49437
|
// Generally speaking when polygons/polylines are drawn, points are only drawn because of invalid data.
|
|
49315
49438
|
if (!rendered.length) {
|
|
49316
|
-
|
|
49317
|
-
rendered = rendered.concat(Array.from(cPoints.values()));
|
|
49439
|
+
collect(await Point.RenderGroup(pParams));
|
|
49318
49440
|
}
|
|
49319
|
-
rendered = rendered.filter(x => x != null);
|
|
49320
49441
|
if (rendered.length) {
|
|
49321
|
-
const
|
|
49322
|
-
|
|
49323
|
-
|
|
49324
|
-
|
|
49442
|
+
const sameParts = ((_e = existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) === null || _e === void 0 ? void 0 : _e.length) == rendered.length &&
|
|
49443
|
+
rendered.every((part) => existingRoot._siblingGraphics.includes(part));
|
|
49444
|
+
let rootEntity;
|
|
49445
|
+
if (sameParts) {
|
|
49446
|
+
rootEntity = existingRoot;
|
|
49447
|
+
}
|
|
49448
|
+
else {
|
|
49449
|
+
if (existingRoot === null || existingRoot === void 0 ? void 0 : existingRoot._siblingGraphics) {
|
|
49450
|
+
// Retiring the old root removes its parts, and the ones carried over belong to the new root now.
|
|
49451
|
+
existingRoot._siblingGraphics = existingRoot._siblingGraphics.filter((part) => !rendered.includes(part));
|
|
49452
|
+
}
|
|
49453
|
+
rootEntity = new Entity({
|
|
49454
|
+
id: ObjectUtils.UId(15)
|
|
49455
|
+
});
|
|
49456
|
+
}
|
|
49457
|
+
rootEntity._siblingGraphics = rendered;
|
|
49325
49458
|
rootEntity._renderGroup = GetRenderGroupId(zoomItem);
|
|
49326
|
-
|
|
49459
|
+
// The skip gate compares the rego's style against the zoom item's, and the rego takes it from here.
|
|
49460
|
+
rootEntity.styleId = (zoomItem === null || zoomItem === void 0 ? void 0 : zoomItem.StyleID) == -1 ? -1 : (+(zoomItem === null || zoomItem === void 0 ? void 0 : zoomItem.StyleID) || null);
|
|
49461
|
+
rootEntity.styleEffective = rendered[0].styleEffective;
|
|
49327
49462
|
cEntities.set(entity.Bruce.ID, rootEntity);
|
|
49328
|
-
const
|
|
49329
|
-
|
|
49330
|
-
|
|
49463
|
+
const newPosition = GetCValue(params.viewer, rendered[0].position);
|
|
49464
|
+
const oldPosition = GetCValue(params.viewer, rootEntity.position);
|
|
49465
|
+
if (newPosition && (!oldPosition || !Cartes.IsEqualCartes3(oldPosition, newPosition))) {
|
|
49466
|
+
rootEntity.position = new ConstantPositionProperty(newPosition);
|
|
49331
49467
|
}
|
|
49332
49468
|
rendered.forEach((child) => {
|
|
49333
49469
|
child._parentEntity = rootEntity;
|
|
@@ -50264,7 +50400,7 @@ var StyleUtils;
|
|
|
50264
50400
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
50265
50401
|
})(StyleUtils || (StyleUtils = {}));
|
|
50266
50402
|
|
|
50267
|
-
const VERSION = "7.4.
|
|
50403
|
+
const VERSION = "7.4.3";
|
|
50268
50404
|
/**
|
|
50269
50405
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
50270
50406
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|