bruce-cesium 7.6.3 → 7.6.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/README.md +2 -27
- package/dist/bruce-cesium.es5.js +684 -43
- package/dist/bruce-cesium.es5.js.map +1 -1
- package/dist/bruce-cesium.umd.js +682 -41
- package/dist/bruce-cesium.umd.js.map +1 -1
- package/dist/lib/bruce-cesium.js +1 -1
- package/dist/lib/rendering/entity-render-engine-point-orientation.js +422 -0
- package/dist/lib/rendering/entity-render-engine-point-orientation.js.map +1 -0
- package/dist/lib/rendering/entity-render-engine-point.js +43 -3
- package/dist/lib/rendering/entity-render-engine-point.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label-group.js +53 -17
- package/dist/lib/rendering/render-managers/common/entity-label-group.js.map +1 -1
- package/dist/lib/rendering/render-managers/common/entity-label.js +51 -3
- package/dist/lib/rendering/render-managers/common/entity-label.js.map +1 -1
- package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js +3 -1
- package/dist/lib/rendering/render-managers/tilesets/tileset-cad-render-manager.js.map +1 -1
- package/dist/lib/rendering/view-render-engine.js +2 -2
- package/dist/lib/rendering/view-render-engine.js.map +1 -1
- package/dist/lib/utils/entity-utils.js +96 -0
- package/dist/lib/utils/entity-utils.js.map +1 -1
- package/dist/lib/viewer/viewer-utils.js +23 -15
- package/dist/lib/viewer/viewer-utils.js.map +1 -1
- package/dist/types/bruce-cesium.d.ts +1 -1
- package/dist/types/rendering/entity-render-engine-point-orientation.d.ts +59 -0
- package/dist/types/rendering/render-managers/common/entity-label-group.d.ts +2 -0
- package/dist/types/rendering/render-managers/common/entity-label.d.ts +3 -0
- package/dist/types/utils/entity-utils.d.ts +29 -0
- package/package.json +4 -3
package/dist/bruce-cesium.umd.js
CHANGED
|
@@ -7668,6 +7668,8 @@
|
|
|
7668
7668
|
this.modelBox = null;
|
|
7669
7669
|
this.boxMorph = { value: 0, from: 0, target: 0, start: 0, anchor: undefined, group: undefined,
|
|
7670
7670
|
shift: { x: 0, y: 0, start: 0 } };
|
|
7671
|
+
// A CAD part's record and its tileset, so the label stays on the part wherever the tileset is drawn now.
|
|
7672
|
+
this.tilesetPart = null;
|
|
7671
7673
|
// Counter to help differentiate between createLabel calls.
|
|
7672
7674
|
this.counter = 0;
|
|
7673
7675
|
// Whether this label has asked its group for a default image, which it does once on screen.
|
|
@@ -7977,6 +7979,9 @@
|
|
|
7977
7979
|
return;
|
|
7978
7980
|
}
|
|
7979
7981
|
this._pos3d = pos3d;
|
|
7982
|
+
if (!this.prePositioned && visual instanceof Cesium.Cesium3DTileFeature) {
|
|
7983
|
+
this.followTilesetPart(visual, counter);
|
|
7984
|
+
}
|
|
7980
7985
|
let text = "Unknown Entity";
|
|
7981
7986
|
const additionalTexts = this.additionalTexts ? this.additionalTexts : [];
|
|
7982
7987
|
if (this.rego) {
|
|
@@ -8438,13 +8443,12 @@
|
|
|
8438
8443
|
// Past the wait a slow record no longer holds the label back; a box that comes later eases in.
|
|
8439
8444
|
setTimeout(settle, MODEL_BOX_WAIT);
|
|
8440
8445
|
this.modelBox.load.then(corners => {
|
|
8441
|
-
var _a, _b;
|
|
8442
8446
|
if (!corners || this.disposed || this.counter !== counter) {
|
|
8443
8447
|
return;
|
|
8444
8448
|
}
|
|
8445
8449
|
// A record that disagrees with where the model was found describes another placement, such as a moved tileset.
|
|
8446
8450
|
// A part known to have moved from its record, eg. a joint turning, is judged where it has moved to.
|
|
8447
|
-
const motion =
|
|
8451
|
+
const motion = this.motionAt(this.viewer.clock.currentTime);
|
|
8448
8452
|
const centre = Cesium.Cartesian3.midpoint(corners[0], corners[7], new Cesium.Cartesian3());
|
|
8449
8453
|
if (motion) {
|
|
8450
8454
|
Cesium.Matrix4.multiplyByPoint(motion, centre, centre);
|
|
@@ -8456,7 +8460,8 @@
|
|
|
8456
8460
|
// Let go a little further out than it is taken, so a camera resting at the limit does not flip it.
|
|
8457
8461
|
let near = false;
|
|
8458
8462
|
layer.modelBoxes.Set(this.id, corners, rego.entityId, {
|
|
8459
|
-
|
|
8463
|
+
// Asked each frame, since a CAD part's tileset may only be known once its record is read.
|
|
8464
|
+
motion: () => this.motionAt(this.viewer.clock.currentTime),
|
|
8460
8465
|
selected: () => { var _a, _b; return Boolean((_b = (_a = this.visualRegister) === null || _a === void 0 ? void 0 : _a.GetState({ entityId: rego.entityId, menuItemId: rego.menuItemId })) === null || _b === void 0 ? void 0 : _b.selected); },
|
|
8461
8466
|
hovered: () => { var _a, _b; return Boolean((_b = (_a = this.visualRegister) === null || _a === void 0 ? void 0 : _a.IsLabelHovered) === null || _b === void 0 ? void 0 : _b.call(_a, rego.entityId, rego.menuItemId)); },
|
|
8462
8467
|
near: () => {
|
|
@@ -8490,6 +8495,12 @@
|
|
|
8490
8495
|
desiredHeightRef: Cesium.HeightReference.NONE, heightRef, pos3d: position, viewer: this.viewer
|
|
8491
8496
|
});
|
|
8492
8497
|
}
|
|
8498
|
+
// A CAD part sits where its tileset is drawn this frame.
|
|
8499
|
+
else if (!this.prePositioned && this.tilesetPart) {
|
|
8500
|
+
const { tileset, entity } = this.tilesetPart;
|
|
8501
|
+
const rootFrame = exports.EntityUtils.GetTilesetRootFrame(tileset);
|
|
8502
|
+
this._pos3d = (rootFrame && exports.EntityUtils.GetAssemblyPartPos3d({ viewer: this.viewer, entity, rootFrame })) || this._pos3d;
|
|
8503
|
+
}
|
|
8493
8504
|
if (!Number.isFinite((_b = this._pos3d) === null || _b === void 0 ? void 0 : _b.x)) {
|
|
8494
8505
|
return null;
|
|
8495
8506
|
}
|
|
@@ -9223,6 +9234,43 @@
|
|
|
9223
9234
|
};
|
|
9224
9235
|
step();
|
|
9225
9236
|
}
|
|
9237
|
+
/*
|
|
9238
|
+
* Keeps a label on a CAD Assembly part where its tileset is drawn, which a record cannot know as it moves.
|
|
9239
|
+
*/
|
|
9240
|
+
async followTilesetPart(feature, counter) {
|
|
9241
|
+
var _a, _b, _c;
|
|
9242
|
+
const known = (_c = (_b = (_a = this.visualRegister) === null || _a === void 0 ? void 0 : _a.GetLabelGroupFor(this.rego.entityId, this.rego.menuItemId)) === null || _b === void 0 ? void 0 : _b.item) === null || _c === void 0 ? void 0 : _c.entity;
|
|
9243
|
+
let entity = exports.EntityUtils.IsAssemblyPart(known) ? known : null;
|
|
9244
|
+
if (!entity && this.api) {
|
|
9245
|
+
try {
|
|
9246
|
+
entity = (await BModels.Entity.Get({ api: this.api, entityId: this.rego.entityId, expandLocation: true, migrated: true })).entity;
|
|
9247
|
+
}
|
|
9248
|
+
// Expanding location fails for entities outside an assembly, which keep the position already found.
|
|
9249
|
+
catch {
|
|
9250
|
+
return;
|
|
9251
|
+
}
|
|
9252
|
+
}
|
|
9253
|
+
const record = exports.EntityUtils.GetAssemblyRecordFrame(entity);
|
|
9254
|
+
if (!record || this.disposed || this.counter !== counter || !feature.tileset) {
|
|
9255
|
+
return;
|
|
9256
|
+
}
|
|
9257
|
+
this.tilesetPart = { tileset: feature.tileset, entity, record };
|
|
9258
|
+
this.viewer.scene.requestRender();
|
|
9259
|
+
}
|
|
9260
|
+
/*
|
|
9261
|
+
* Rigid motion from where the record places this Entity to where it is drawn, see IVisualRego.motion.
|
|
9262
|
+
* A CAD part has none of its own, so it moves with its tileset.
|
|
9263
|
+
*/
|
|
9264
|
+
motionAt(time) {
|
|
9265
|
+
var _a, _b;
|
|
9266
|
+
const own = (_b = (_a = this.rego) === null || _a === void 0 ? void 0 : _a.motion) === null || _b === void 0 ? void 0 : _b.call(_a, time);
|
|
9267
|
+
if (own || !this.tilesetPart) {
|
|
9268
|
+
return own !== null && own !== void 0 ? own : null;
|
|
9269
|
+
}
|
|
9270
|
+
const drawn = exports.EntityUtils.GetTilesetRootFrame(this.tilesetPart.tileset);
|
|
9271
|
+
const inverse = Cesium.Matrix4.inverseTransformation(this.tilesetPart.record, new Cesium.Matrix4());
|
|
9272
|
+
return drawn ? Cesium.Matrix4.multiply(drawn, inverse, inverse) : null;
|
|
9273
|
+
}
|
|
9226
9274
|
/*
|
|
9227
9275
|
* Reads the record's geometry box, preferring an entity a label group already hydrated.
|
|
9228
9276
|
*/
|
|
@@ -9395,21 +9443,17 @@
|
|
|
9395
9443
|
(function (EntityLabelGroup) {
|
|
9396
9444
|
/*
|
|
9397
9445
|
* Keeps the query response useful even when the Entity has no loaded visual yet.
|
|
9446
|
+
* An Assembly part is placed from its record when shown (Manager.RefreshEntity); Location is its fallback.
|
|
9398
9447
|
*/
|
|
9399
9448
|
function FromEntity(entity) {
|
|
9400
|
-
var _a, _b, _c
|
|
9449
|
+
var _a, _b, _c;
|
|
9401
9450
|
const location = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.Location;
|
|
9402
|
-
const pivot = (_b = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _b === void 0 ? void 0 : _b.GeometryWorldPivot;
|
|
9403
|
-
let cartographic;
|
|
9404
|
-
if ((pivot === null || pivot === void 0 ? void 0 : pivot.length) >= 3 && pivot.every(Number.isFinite)) {
|
|
9405
|
-
cartographic = Cesium.Cartographic.fromCartesian(Cesium.Cartesian3.fromArray(pivot));
|
|
9406
|
-
}
|
|
9407
9451
|
return {
|
|
9408
|
-
entityId: (
|
|
9409
|
-
text: (
|
|
9410
|
-
longitude:
|
|
9411
|
-
latitude:
|
|
9412
|
-
altitude:
|
|
9452
|
+
entityId: (_b = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _b === void 0 ? void 0 : _b.ID,
|
|
9453
|
+
text: (_c = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _c === void 0 ? void 0 : _c.Name,
|
|
9454
|
+
longitude: location === null || location === void 0 ? void 0 : location.longitude,
|
|
9455
|
+
latitude: location === null || location === void 0 ? void 0 : location.latitude,
|
|
9456
|
+
altitude: location === null || location === void 0 ? void 0 : location.altitude,
|
|
9413
9457
|
entity
|
|
9414
9458
|
};
|
|
9415
9459
|
}
|
|
@@ -9522,7 +9566,8 @@
|
|
|
9522
9566
|
const response = await BModels.DataLab.Run({ api, query, skip: offset, load: limit, migrated: true, req: { noCache: true, abortSignal: signal } });
|
|
9523
9567
|
const entities = response.entities || response.items || [];
|
|
9524
9568
|
return {
|
|
9525
|
-
|
|
9569
|
+
// A simulated stand-in or patch wins over what the query read, as it does for hand-picked groups.
|
|
9570
|
+
items: entities.map(entity => { var _a, _b; return FromEntity((_b = simulation === null || simulation === void 0 ? void 0 : simulation.Resolve((_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID, entity)) !== null && _b !== void 0 ? _b : entity); }),
|
|
9526
9571
|
hasMore: response.totalCount != null ? offset + entities.length < response.totalCount : entities.length === limit
|
|
9527
9572
|
};
|
|
9528
9573
|
};
|
|
@@ -9875,7 +9920,7 @@
|
|
|
9875
9920
|
}
|
|
9876
9921
|
}
|
|
9877
9922
|
RefreshEntity(entityId) {
|
|
9878
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
9923
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
9879
9924
|
const match = this.Resolve(entityId);
|
|
9880
9925
|
const registered = this.register.GetRego({ entityId });
|
|
9881
9926
|
if (!registered && match && this.standalone.has(entityId) && this.standaloneItems.get(entityId) === match.item) {
|
|
@@ -9892,19 +9937,22 @@
|
|
|
9892
9937
|
return;
|
|
9893
9938
|
}
|
|
9894
9939
|
const item = match.item;
|
|
9895
|
-
|
|
9940
|
+
const position = (_d = this.assemblyPosition(item.entity)) !== null && _d !== void 0 ? _d : ([item.longitude, item.latitude, (_e = item.altitude) !== null && _e !== void 0 ? _e : 0].every(Number.isFinite) && Math.abs(item.latitude) <= 90
|
|
9941
|
+
? Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, item.altitude || 0)
|
|
9942
|
+
: null);
|
|
9943
|
+
if (!position) {
|
|
9896
9944
|
return;
|
|
9897
9945
|
}
|
|
9898
9946
|
const visual = new Cesium.Entity({
|
|
9899
|
-
position:
|
|
9947
|
+
position: position,
|
|
9900
9948
|
point: { heightReference: Cesium.HeightReference.NONE, pixelSize: 0 }
|
|
9901
9949
|
});
|
|
9902
9950
|
this.standalone.set(entityId, new exports.EntityLabel.Label({
|
|
9903
9951
|
viewer: this.register.Viewer,
|
|
9904
9952
|
visualRegister: this.register,
|
|
9905
|
-
api: (
|
|
9953
|
+
api: (_f = this.register.ApiGetters) === null || _f === void 0 ? void 0 : _f.GetBruceApi(),
|
|
9906
9954
|
rego: { entityId, visual, name: item.text || entityId, priority: 0 },
|
|
9907
|
-
options: { ...match.options, text: (
|
|
9955
|
+
options: { ...match.options, text: (_h = (_g = match.options.text) !== null && _g !== void 0 ? _g : item.text) !== null && _h !== void 0 ? _h : entityId },
|
|
9908
9956
|
groupId: match.groupId,
|
|
9909
9957
|
visible: () => {
|
|
9910
9958
|
const state = this.register.GetState({ entityId });
|
|
@@ -9913,6 +9961,41 @@
|
|
|
9913
9961
|
}));
|
|
9914
9962
|
this.standaloneItems.set(entityId, item);
|
|
9915
9963
|
}
|
|
9964
|
+
/*
|
|
9965
|
+
* Places an undrawn Assembly part where its Assembly is now: model-space, history and simulation included.
|
|
9966
|
+
* Returns null for anything else, which keeps its record's Location.
|
|
9967
|
+
*/
|
|
9968
|
+
assemblyPosition(entity) {
|
|
9969
|
+
const viewer = this.register.Viewer;
|
|
9970
|
+
if (!exports.EntityUtils.GetAssemblyPartPos3d({ viewer, entity })) {
|
|
9971
|
+
return null;
|
|
9972
|
+
}
|
|
9973
|
+
let last = null;
|
|
9974
|
+
return new Cesium.CallbackProperty((time) => {
|
|
9975
|
+
var _a, _b, _c;
|
|
9976
|
+
const at = Cesium.JulianDate.toDate(time !== null && time !== void 0 ? time : viewer.clock.currentTime).getTime();
|
|
9977
|
+
const simulated = (_b = (_a = exports.EntitySimulation.Get(viewer)) === null || _a === void 0 ? void 0 : _a.ApplyAt(entity, at)) !== null && _b !== void 0 ? _b : entity;
|
|
9978
|
+
last = (_c = exports.EntityUtils.GetAssemblyPartPos3d({ viewer, entity: simulated, rootFrame: this.drawnFrame(entity) })) !== null && _c !== void 0 ? _c : last;
|
|
9979
|
+
return last;
|
|
9980
|
+
}, false);
|
|
9981
|
+
}
|
|
9982
|
+
/*
|
|
9983
|
+
* The frame of a CAD tileset drawn at this Assembly's root, which moves with its history and simulation.
|
|
9984
|
+
*/
|
|
9985
|
+
drawnFrame(entity) {
|
|
9986
|
+
var _a, _b;
|
|
9987
|
+
const root = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.AssemblyRootLocation;
|
|
9988
|
+
for (const { tileset } of this.register.GetTilesets()) {
|
|
9989
|
+
const at = (_b = tileset._bruceCoords) === null || _b === void 0 ? void 0 : _b.location;
|
|
9990
|
+
if (at && root &&
|
|
9991
|
+
Math.abs(+at.latitude - +root.latitude) < 1e-7 &&
|
|
9992
|
+
Math.abs(+at.longitude - +root.longitude) < 1e-7 &&
|
|
9993
|
+
Math.abs((+at.altitude || 0) - (+root.altitude || 0)) < 0.01) {
|
|
9994
|
+
return exports.EntityUtils.GetTilesetRootFrame(tileset);
|
|
9995
|
+
}
|
|
9996
|
+
}
|
|
9997
|
+
return null;
|
|
9998
|
+
}
|
|
9916
9999
|
Remove(id) {
|
|
9917
10000
|
var _a;
|
|
9918
10001
|
const known = this.definitions.delete(id);
|
|
@@ -23471,7 +23554,9 @@
|
|
|
23471
23554
|
ucs: coords === null || coords === void 0 ? void 0 : coords.ucs,
|
|
23472
23555
|
location: (coords === null || coords === void 0 ? void 0 : coords.location) == null ? settings.location : coords.location,
|
|
23473
23556
|
transform: (coords === null || coords === void 0 ? void 0 : coords.transform) == null ? settings.transform : coords.transform
|
|
23474
|
-
}
|
|
23557
|
+
},
|
|
23558
|
+
// Placed as first drawn, or a model-space tileset jumps to its site on a history or simulation update.
|
|
23559
|
+
modelSpace: this.modelSpace
|
|
23475
23560
|
});
|
|
23476
23561
|
this.viewer.scene.requestRender();
|
|
23477
23562
|
}
|
|
@@ -38170,7 +38255,7 @@
|
|
|
38170
38255
|
if (!bookmark) {
|
|
38171
38256
|
let bookmarkId = params.bookmarkId;
|
|
38172
38257
|
if (!bookmarkId) {
|
|
38173
|
-
bookmarkId = view.
|
|
38258
|
+
bookmarkId = view["Default.UISlide.ID"];
|
|
38174
38259
|
}
|
|
38175
38260
|
bookmark = bookmarkId ? (await BModels.ProjectViewBookmark.Get({
|
|
38176
38261
|
api,
|
|
@@ -38231,7 +38316,7 @@
|
|
|
38231
38316
|
if (!bookmark) {
|
|
38232
38317
|
let bookmarkId = params.bookmarkId;
|
|
38233
38318
|
if (!bookmarkId) {
|
|
38234
|
-
bookmarkId = view.
|
|
38319
|
+
bookmarkId = view["Default.UISlide.ID"];
|
|
38235
38320
|
}
|
|
38236
38321
|
bookmark = bookmarkId ? (await BModels.ProjectViewBookmark.Get({
|
|
38237
38322
|
api,
|
|
@@ -44005,37 +44090,46 @@
|
|
|
44005
44090
|
|
|
44006
44091
|
const CESIUM_VIEWER_MANAGER_KEY = "_cesiumViewerManager";
|
|
44007
44092
|
const CESIUM_VIEWER_EVENT_TRACKER_KEY = "_cesiumViewerEventTracker";
|
|
44008
|
-
/**
|
|
44009
|
-
* Bug related to entities not being visible after they were added then a render was requested.
|
|
44010
|
-
* It was 4 point entities in York. They would not appear until a request render was recalled.
|
|
44011
|
-
* Adding this slow render loop as a band-aid fix.
|
|
44012
|
-
*/
|
|
44013
44093
|
const BACKGROUND_RENDERING_KEY = "_backgroundRendering";
|
|
44094
|
+
// How long after the scene last drew it is drawn once more.
|
|
44095
|
+
const FOLLOW_UP_RENDER_MS = 3000;
|
|
44096
|
+
/*
|
|
44097
|
+
* Draws once more a few seconds after the scene last drew, for graphics not ready by the render that asked for them.
|
|
44098
|
+
*/
|
|
44014
44099
|
function backgroundRendering(viewer) {
|
|
44015
44100
|
if (viewer[BACKGROUND_RENDERING_KEY]) {
|
|
44016
44101
|
return;
|
|
44017
44102
|
}
|
|
44018
44103
|
viewer[BACKGROUND_RENDERING_KEY] = true;
|
|
44104
|
+
// Wall time, since scene.lastRenderTime is the scene clock's and stands still while the clock is paused.
|
|
44105
|
+
let lastRenderAt = performance.now();
|
|
44106
|
+
// Whether the last render was the follow up, so a still scene is drawn once more rather than forever.
|
|
44107
|
+
let followedUp = false;
|
|
44108
|
+
let requested = false;
|
|
44109
|
+
const removeListener = viewer.scene.postRender.addEventListener(() => {
|
|
44110
|
+
lastRenderAt = performance.now();
|
|
44111
|
+
followedUp = requested;
|
|
44112
|
+
requested = false;
|
|
44113
|
+
});
|
|
44019
44114
|
const interval = setInterval(() => {
|
|
44020
44115
|
var _a;
|
|
44021
44116
|
if (!(viewer === null || viewer === void 0 ? void 0 : viewer.cesiumWidget) || !(viewer === null || viewer === void 0 ? void 0 : viewer.scene) || viewer.isDestroyed()) {
|
|
44022
44117
|
clearInterval(interval);
|
|
44118
|
+
removeListener();
|
|
44023
44119
|
return;
|
|
44024
44120
|
}
|
|
44025
44121
|
// We'll ignore the call if the viewer container is not visible.
|
|
44026
44122
|
if (!viewer.container || ((_a = viewer.container.style) === null || _a === void 0 ? void 0 : _a.display) == "none") {
|
|
44027
44123
|
return;
|
|
44028
44124
|
}
|
|
44125
|
+
if (followedUp || requested || performance.now() - lastRenderAt < FOLLOW_UP_RENDER_MS) {
|
|
44126
|
+
return;
|
|
44127
|
+
}
|
|
44029
44128
|
try {
|
|
44030
|
-
//
|
|
44031
|
-
|
|
44032
|
-
|
|
44033
|
-
|
|
44034
|
-
// Check if window is active/in focus.
|
|
44035
|
-
// TODO: Should render the moment it is in focus as well.
|
|
44036
|
-
if (document.hasFocus()) {
|
|
44037
|
-
viewer.scene.requestRender();
|
|
44038
|
-
}
|
|
44129
|
+
// Only while the window has focus. TODO: should render the moment it regains focus as well.
|
|
44130
|
+
if (document.hasFocus()) {
|
|
44131
|
+
requested = true;
|
|
44132
|
+
viewer.scene.requestRender();
|
|
44039
44133
|
}
|
|
44040
44134
|
}
|
|
44041
44135
|
catch (e) {
|
|
@@ -44435,6 +44529,47 @@
|
|
|
44435
44529
|
}
|
|
44436
44530
|
return Cesium.Matrix4.multiplyByPoint(enuFrame, new Cesium.Cartesian3(tx, ty, tz), new Cesium.Cartesian3());
|
|
44437
44531
|
}
|
|
44532
|
+
/*
|
|
44533
|
+
* Reads a row-major 4x4 from a record, or null when it is missing or malformed.
|
|
44534
|
+
*/
|
|
44535
|
+
function matrixFromRows(rows) {
|
|
44536
|
+
if (!Array.isArray(rows) || rows.length !== 4) {
|
|
44537
|
+
return null;
|
|
44538
|
+
}
|
|
44539
|
+
const values = [].concat(...rows).map(Number);
|
|
44540
|
+
return values.length === 16 && values.every(Number.isFinite) ? Cesium.Matrix4.fromRowMajorArray(values) : null;
|
|
44541
|
+
}
|
|
44542
|
+
/*
|
|
44543
|
+
* An Assembly part's geometry centre in its root's frame, via its parent so a simulated AssemblyPosition counts.
|
|
44544
|
+
*/
|
|
44545
|
+
function calcAssemblyPartOffset(entity) {
|
|
44546
|
+
const bruce = entity === null || entity === void 0 ? void 0 : entity.Bruce;
|
|
44547
|
+
const pivot = Array.isArray(bruce === null || bruce === void 0 ? void 0 : bruce.GeometryPivot) && bruce.GeometryPivot.length >= 3 ? bruce.GeometryPivot.slice(0, 3).map(Number) : null;
|
|
44548
|
+
const parent = matrixFromRows(bruce === null || bruce === void 0 ? void 0 : bruce.AssemblyParentWorldPosition);
|
|
44549
|
+
const local = matrixFromRows(bruce === null || bruce === void 0 ? void 0 : bruce.AssemblyPosition);
|
|
44550
|
+
const world = parent && local ? Cesium.Matrix4.multiply(parent, local, new Cesium.Matrix4()) : matrixFromRows(bruce === null || bruce === void 0 ? void 0 : bruce.AssemblyWorldPosition);
|
|
44551
|
+
if (world && (!pivot || pivot.every(Number.isFinite))) {
|
|
44552
|
+
return Cesium.Matrix4.multiplyByPoint(world, pivot ? Cesium.Cartesian3.fromArray(pivot) : Cesium.Cartesian3.ZERO, new Cesium.Cartesian3());
|
|
44553
|
+
}
|
|
44554
|
+
const worldPivot = Array.isArray(bruce === null || bruce === void 0 ? void 0 : bruce.GeometryWorldPivot) ? bruce.GeometryWorldPivot.slice(0, 3).map(Number) : [];
|
|
44555
|
+
return worldPivot.length === 3 && worldPivot.every(Number.isFinite) ? Cesium.Cartesian3.fromArray(worldPivot) : null;
|
|
44556
|
+
}
|
|
44557
|
+
/*
|
|
44558
|
+
* The frame a part's record places it in, as the API's Location: the root (0,0 in model-space), then its transform.
|
|
44559
|
+
*/
|
|
44560
|
+
function calcAssemblyRootFrame(entity, modelSpace) {
|
|
44561
|
+
var _a, _b, _c;
|
|
44562
|
+
const root = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.AssemblyRootLocation;
|
|
44563
|
+
if (!root && !modelSpace) {
|
|
44564
|
+
return null;
|
|
44565
|
+
}
|
|
44566
|
+
const origin = modelSpace ? Cesium.Cartesian3.fromDegrees(0, 0, 0) : Cesium.Cartesian3.fromDegrees(EnsureNumber(root.longitude), EnsureNumber(root.latitude), EnsureNumber(root.altitude));
|
|
44567
|
+
const transform = (_c = (_b = entity.Bruce) === null || _b === void 0 ? void 0 : _b.AssemblyWorldTransform) !== null && _c !== void 0 ? _c : {};
|
|
44568
|
+
const frame = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
|
|
44569
|
+
Cesium.Matrix4.multiply(frame, Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(EnsureNumber(transform.x), EnsureNumber(transform.y), EnsureNumber(transform.z))), frame);
|
|
44570
|
+
const hpr = Cesium.HeadingPitchRoll.fromDegrees(EnsureNumber(transform.heading), EnsureNumber(transform.pitch), EnsureNumber(transform.roll));
|
|
44571
|
+
return Cesium.Matrix4.multiply(frame, Cesium.Matrix4.fromRotation(Cesium.Matrix3.fromHeadingPitchRoll(hpr)), frame);
|
|
44572
|
+
}
|
|
44438
44573
|
// Records created within about this long ago are the ones the oversized GeometryRadius bug could have written.
|
|
44439
44574
|
const GEOMETRY_RADIUS_SUSPECT_AGE_MS = 1000 * 60 * 60 * 24 * 183;
|
|
44440
44575
|
// Above this a recent record's radius is treated as that bug rather than a real size.
|
|
@@ -44479,6 +44614,61 @@
|
|
|
44479
44614
|
// +90° rotation around Z: aligns GLTF Y-up forward with Cesium ENU North.
|
|
44480
44615
|
const _assemblyAxisShift = new Cesium.Quaternion(0, 0, -Math.SQRT1_2, Math.SQRT1_2);
|
|
44481
44616
|
(function (EntityUtils) {
|
|
44617
|
+
/**
|
|
44618
|
+
* Returns where an Assembly part's geometry centre is, without asking the API or the scene.
|
|
44619
|
+
* Bruce.Location only holds where the API last placed it, so this composes from the root's frame instead.
|
|
44620
|
+
* @param params.rootFrame the frame its Assembly is drawn in now, eg. GetTilesetRootFrame of its CAD tileset.
|
|
44621
|
+
* Default: the frame its record describes, at 0,0 in model-space.
|
|
44622
|
+
* @returns null when the record is not an Assembly part or lacks its matrices.
|
|
44623
|
+
*/
|
|
44624
|
+
function GetAssemblyPartPos3d(params) {
|
|
44625
|
+
var _a;
|
|
44626
|
+
const { viewer, entity } = params;
|
|
44627
|
+
if (!IsAssemblyPart(entity)) {
|
|
44628
|
+
return null;
|
|
44629
|
+
}
|
|
44630
|
+
const offset = calcAssemblyPartOffset(entity);
|
|
44631
|
+
const frame = (_a = params.rootFrame) !== null && _a !== void 0 ? _a : calcAssemblyRootFrame(entity, exports.ViewUtils.GetModelSpace(viewer));
|
|
44632
|
+
return offset && frame ? Cesium.Matrix4.multiplyByPoint(frame, offset, new Cesium.Cartesian3()) : null;
|
|
44633
|
+
}
|
|
44634
|
+
EntityUtils.GetAssemblyPartPos3d = GetAssemblyPartPos3d;
|
|
44635
|
+
/**
|
|
44636
|
+
* Returns the geospatial frame a part's record assumes for its root, the one the API works Location out in.
|
|
44637
|
+
* Comparing it with where the Assembly is drawn gives how far the drawing has moved from the record.
|
|
44638
|
+
* @param entity
|
|
44639
|
+
*/
|
|
44640
|
+
function GetAssemblyRecordFrame(entity) {
|
|
44641
|
+
return IsAssemblyPart(entity) ? calcAssemblyRootFrame(entity, false) : null;
|
|
44642
|
+
}
|
|
44643
|
+
EntityUtils.GetAssemblyRecordFrame = GetAssemblyRecordFrame;
|
|
44644
|
+
/**
|
|
44645
|
+
* Returns whether a record is an Assembly part, ie. placed through its root rather than its own Location.
|
|
44646
|
+
* @param entity
|
|
44647
|
+
*/
|
|
44648
|
+
function IsAssemblyPart(entity) {
|
|
44649
|
+
const bruce = entity === null || entity === void 0 ? void 0 : entity.Bruce;
|
|
44650
|
+
return ((bruce === null || bruce === void 0 ? void 0 : bruce.AssemblyRootLocation) != null &&
|
|
44651
|
+
(bruce.AssemblyWorldPosition != null || bruce.AssemblyPosition != null || bruce.GeometryWorldPivot != null));
|
|
44652
|
+
}
|
|
44653
|
+
EntityUtils.IsAssemblyPart = IsAssemblyPart;
|
|
44654
|
+
/**
|
|
44655
|
+
* Returns the frame a tileset is drawn in now, without its scale, so Assembly offsets in metres apply to it.
|
|
44656
|
+
* It follows whatever moved the tileset: history, a simulated root, or model-space.
|
|
44657
|
+
* @param tileset
|
|
44658
|
+
*/
|
|
44659
|
+
function GetTilesetRootFrame(tileset) {
|
|
44660
|
+
var _a, _b;
|
|
44661
|
+
const transform = (_a = tileset === null || tileset === void 0 ? void 0 : tileset.root) === null || _a === void 0 ? void 0 : _a.transform;
|
|
44662
|
+
if (!transform || ((_b = tileset.isDestroyed) === null || _b === void 0 ? void 0 : _b.call(tileset))) {
|
|
44663
|
+
return null;
|
|
44664
|
+
}
|
|
44665
|
+
const scale = Cesium.Matrix4.getScale(transform, new Cesium.Cartesian3());
|
|
44666
|
+
if (!(scale.x > 0)) {
|
|
44667
|
+
return null;
|
|
44668
|
+
}
|
|
44669
|
+
return Cesium.Matrix4.multiplyByUniformScale(transform, 1 / scale.x, new Cesium.Matrix4());
|
|
44670
|
+
}
|
|
44671
|
+
EntityUtils.GetTilesetRootFrame = GetTilesetRootFrame;
|
|
44482
44672
|
/**
|
|
44483
44673
|
* Returns the location for given entity or entities.
|
|
44484
44674
|
* If available it will also compute a rectangle.
|
|
@@ -46340,6 +46530,418 @@
|
|
|
46340
46530
|
}
|
|
46341
46531
|
}
|
|
46342
46532
|
|
|
46533
|
+
/**
|
|
46534
|
+
* Draws the orientation effect a point style can ask for, an open ring whose pointer shows which way the Entity faces.
|
|
46535
|
+
*/
|
|
46536
|
+
var EntityRenderEnginePointOrientation;
|
|
46537
|
+
(function (EntityRenderEnginePointOrientation) {
|
|
46538
|
+
// Compared as the wire string, since an older bruce-models in the host has no EPointEffectType at runtime.
|
|
46539
|
+
EntityRenderEnginePointOrientation.ORIENTATION_EFFECT = "ORIENTATION";
|
|
46540
|
+
// Clearance between the glyph and the ring, and the smallest ring, matching entity-label.ts's icon ring.
|
|
46541
|
+
EntityRenderEnginePointOrientation.RING_PADDING = 4;
|
|
46542
|
+
EntityRenderEnginePointOrientation.RING_MIN = 10;
|
|
46543
|
+
const RING_STROKE = 2;
|
|
46544
|
+
const RING_CSS = "rgba(255, 255, 255, 0.8)";
|
|
46545
|
+
const RING_GLOW_CSS = "rgba(0, 0, 0, 0.3)";
|
|
46546
|
+
const RING_GLOW_BLUR = 5;
|
|
46547
|
+
// The pointer reaches TIP_BASE + TIP_GROWTH * sqrt(radius) px past the ring, so it grows slower than the ring.
|
|
46548
|
+
const TIP_BASE = 3;
|
|
46549
|
+
const TIP_GROWTH = 2.2;
|
|
46550
|
+
// Share of the circle kept around the heading. Label rings keep 0.35, but the pointer uses most of it.
|
|
46551
|
+
const ARC_FRACTION = 0.5;
|
|
46552
|
+
// The arc always runs at least this far past where the pointer leaves it, so it still reads as a ring.
|
|
46553
|
+
const ARC_TAIL = Math.PI / 30;
|
|
46554
|
+
const ARC_STEPS = 12;
|
|
46555
|
+
// Copies of the cap outline nested toward its centre, enough for 2 px strokes to read as a fill.
|
|
46556
|
+
const CAP_FILL_LOOPS = 4;
|
|
46557
|
+
// Canvas oversampling so the stroke stays crisp on high density screens.
|
|
46558
|
+
const RING_DPR = 2;
|
|
46559
|
+
const _ringCache = new BModels.LRUCache(50);
|
|
46560
|
+
/*
|
|
46561
|
+
* Whether a point style asks for the orientation effect.
|
|
46562
|
+
*/
|
|
46563
|
+
function IsEnabled(style) {
|
|
46564
|
+
var _a;
|
|
46565
|
+
return ((_a = style === null || style === void 0 ? void 0 : style.effect) === null || _a === void 0 ? void 0 : _a.type) === EntityRenderEnginePointOrientation.ORIENTATION_EFFECT;
|
|
46566
|
+
}
|
|
46567
|
+
EntityRenderEnginePointOrientation.IsEnabled = IsEnabled;
|
|
46568
|
+
/*
|
|
46569
|
+
* The Entity's orientation from Bruce.Transform, or null when it has no usable heading to show.
|
|
46570
|
+
*/
|
|
46571
|
+
function GetOrientation(entity) {
|
|
46572
|
+
var _a;
|
|
46573
|
+
const transform = (_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.Transform;
|
|
46574
|
+
const raw = transform === null || transform === void 0 ? void 0 : transform.heading;
|
|
46575
|
+
if (raw == null ||
|
|
46576
|
+
(typeof raw == "string" && !raw.trim())) {
|
|
46577
|
+
return null;
|
|
46578
|
+
}
|
|
46579
|
+
const heading = Number(raw);
|
|
46580
|
+
if (!isFinite(heading)) {
|
|
46581
|
+
return null;
|
|
46582
|
+
}
|
|
46583
|
+
const pitch = Number(transform.pitch);
|
|
46584
|
+
const roll = Number(transform.roll);
|
|
46585
|
+
return {
|
|
46586
|
+
heading,
|
|
46587
|
+
pitch: isFinite(pitch) ? pitch : 0,
|
|
46588
|
+
roll: isFinite(roll) ? roll : 0
|
|
46589
|
+
};
|
|
46590
|
+
}
|
|
46591
|
+
EntityRenderEnginePointOrientation.GetOrientation = GetOrientation;
|
|
46592
|
+
/*
|
|
46593
|
+
* Ring radius in px for a glyph of the given radius.
|
|
46594
|
+
*/
|
|
46595
|
+
function GetRingRadius(glyphRadius) {
|
|
46596
|
+
const radius = Number(glyphRadius);
|
|
46597
|
+
return Math.max(EntityRenderEnginePointOrientation.RING_MIN, (isFinite(radius) ? radius : 0) + EntityRenderEnginePointOrientation.RING_PADDING);
|
|
46598
|
+
}
|
|
46599
|
+
EntityRenderEnginePointOrientation.GetRingRadius = GetRingRadius;
|
|
46600
|
+
/*
|
|
46601
|
+
* How far the pointer's tip sits from the centre, as a multiple of the ring radius.
|
|
46602
|
+
*/
|
|
46603
|
+
function GetTipRatio(ringRadius) {
|
|
46604
|
+
return 1 + (TIP_BASE + TIP_GROWTH * Math.sqrt(ringRadius)) / ringRadius;
|
|
46605
|
+
}
|
|
46606
|
+
EntityRenderEnginePointOrientation.GetTipRatio = GetTipRatio;
|
|
46607
|
+
/*
|
|
46608
|
+
* The open ring in a unit frame, u forward and v right: arc tail, tangent to the tip, tangent back, arc tail.
|
|
46609
|
+
* The pointer's sides are tangents to the circle, so the arc runs into the tip with no visible joint.
|
|
46610
|
+
*/
|
|
46611
|
+
function GetOutline(tipRatio) {
|
|
46612
|
+
const touch = Math.acos(1 / tipRatio);
|
|
46613
|
+
const half = Math.max(Math.PI * ARC_FRACTION, touch + ARC_TAIL);
|
|
46614
|
+
const points = [];
|
|
46615
|
+
for (let i = 0; i <= ARC_STEPS; i++) {
|
|
46616
|
+
const phi = -half + (half - touch) * i / ARC_STEPS;
|
|
46617
|
+
points.push([Math.cos(phi), Math.sin(phi)]);
|
|
46618
|
+
}
|
|
46619
|
+
points.push([tipRatio, 0]);
|
|
46620
|
+
for (let i = 0; i <= ARC_STEPS; i++) {
|
|
46621
|
+
const phi = touch + (half - touch) * i / ARC_STEPS;
|
|
46622
|
+
points.push([Math.cos(phi), Math.sin(phi)]);
|
|
46623
|
+
}
|
|
46624
|
+
return points;
|
|
46625
|
+
}
|
|
46626
|
+
EntityRenderEnginePointOrientation.GetOutline = GetOutline;
|
|
46627
|
+
/*
|
|
46628
|
+
* The filled cap between the pointer's sides and the circle, in the same unit frame as GetOutline.
|
|
46629
|
+
*/
|
|
46630
|
+
function GetCap(tipRatio) {
|
|
46631
|
+
const touch = Math.acos(1 / tipRatio);
|
|
46632
|
+
const points = [[tipRatio, 0]];
|
|
46633
|
+
for (let i = 0; i <= ARC_STEPS; i++) {
|
|
46634
|
+
const phi = touch - 2 * touch * i / ARC_STEPS;
|
|
46635
|
+
points.push([Math.cos(phi), Math.sin(phi)]);
|
|
46636
|
+
}
|
|
46637
|
+
return points;
|
|
46638
|
+
}
|
|
46639
|
+
EntityRenderEnginePointOrientation.GetCap = GetCap;
|
|
46640
|
+
/*
|
|
46641
|
+
* The outline as one path with its cap filled by nested copies of the cap's outline, for a polyline that cannot fill.
|
|
46642
|
+
* Back and forth strokes would need sharp reversals, which Cesium mitres into spikes; nested loops only turn at the
|
|
46643
|
+
* cap's own corners. Like GetOutline it starts and ends on the arc tails.
|
|
46644
|
+
*/
|
|
46645
|
+
function GetFilledOutline(tipRatio) {
|
|
46646
|
+
const outline = GetOutline(tipRatio);
|
|
46647
|
+
const tipIndex = outline.findIndex(([u, v]) => u === tipRatio && v === 0);
|
|
46648
|
+
const cap = GetCap(tipRatio);
|
|
46649
|
+
const cu = cap.reduce((sum, [u]) => sum + u, 0) / cap.length;
|
|
46650
|
+
const cv = cap.reduce((sum, [, v]) => sum + v, 0) / cap.length;
|
|
46651
|
+
const loops = [];
|
|
46652
|
+
for (let i = 0; i < CAP_FILL_LOOPS; i++) {
|
|
46653
|
+
const k = 1 - i / CAP_FILL_LOOPS;
|
|
46654
|
+
for (const [u, v] of cap) {
|
|
46655
|
+
loops.push([cu + (u - cu) * k, cv + (v - cv) * k]);
|
|
46656
|
+
}
|
|
46657
|
+
}
|
|
46658
|
+
loops.push([tipRatio, 0]);
|
|
46659
|
+
return [...outline.slice(0, tipIndex + 1), ...loops, ...outline.slice(tipIndex + 1)];
|
|
46660
|
+
}
|
|
46661
|
+
EntityRenderEnginePointOrientation.GetFilledOutline = GetFilledOutline;
|
|
46662
|
+
/*
|
|
46663
|
+
* Draws the ring for a glyph as a billboard image pointing up, or null where there is no canvas to draw on.
|
|
46664
|
+
*/
|
|
46665
|
+
function CreateRingBillboard(glyphRadius) {
|
|
46666
|
+
var _a;
|
|
46667
|
+
const radius = GetRingRadius(glyphRadius);
|
|
46668
|
+
const key = radius.toFixed(1);
|
|
46669
|
+
const cached = _ringCache.Get(key);
|
|
46670
|
+
if (cached) {
|
|
46671
|
+
return cached;
|
|
46672
|
+
}
|
|
46673
|
+
const tipRatio = GetTipRatio(radius);
|
|
46674
|
+
const size = Math.ceil((radius * tipRatio + RING_STROKE + RING_GLOW_BLUR) * 2);
|
|
46675
|
+
const canvas = document.createElement("canvas");
|
|
46676
|
+
canvas.width = size * RING_DPR;
|
|
46677
|
+
canvas.height = size * RING_DPR;
|
|
46678
|
+
const context = (_a = canvas.getContext) === null || _a === void 0 ? void 0 : _a.call(canvas, "2d");
|
|
46679
|
+
if (!context) {
|
|
46680
|
+
return null;
|
|
46681
|
+
}
|
|
46682
|
+
context.scale(RING_DPR, RING_DPR);
|
|
46683
|
+
// Forward is up the image, right is to the right.
|
|
46684
|
+
const toCanvas = ([u, v]) => [size / 2 + v * radius, size / 2 - u * radius];
|
|
46685
|
+
const trace = (points, close) => {
|
|
46686
|
+
context.beginPath();
|
|
46687
|
+
points.map(toCanvas).forEach(([x, y], i) => i ? context.lineTo(x, y) : context.moveTo(x, y));
|
|
46688
|
+
if (close) {
|
|
46689
|
+
context.closePath();
|
|
46690
|
+
}
|
|
46691
|
+
};
|
|
46692
|
+
context.shadowColor = RING_GLOW_CSS;
|
|
46693
|
+
context.shadowBlur = RING_GLOW_BLUR;
|
|
46694
|
+
context.fillStyle = RING_CSS;
|
|
46695
|
+
trace(GetCap(tipRatio), true);
|
|
46696
|
+
context.fill();
|
|
46697
|
+
context.strokeStyle = RING_CSS;
|
|
46698
|
+
context.lineWidth = RING_STROKE;
|
|
46699
|
+
context.lineJoin = "round";
|
|
46700
|
+
context.lineCap = "round";
|
|
46701
|
+
trace(GetOutline(tipRatio), false);
|
|
46702
|
+
context.stroke();
|
|
46703
|
+
const ring = {
|
|
46704
|
+
canvasDataUri: canvas.toDataURL("image/png"),
|
|
46705
|
+
size
|
|
46706
|
+
};
|
|
46707
|
+
_ringCache.Set(key, ring);
|
|
46708
|
+
return ring;
|
|
46709
|
+
}
|
|
46710
|
+
EntityRenderEnginePointOrientation.CreateRingBillboard = CreateRingBillboard;
|
|
46711
|
+
/*
|
|
46712
|
+
* World space unit vector along the local horizon at a heading in degrees clockwise from north.
|
|
46713
|
+
*/
|
|
46714
|
+
function GetHeadingAxis(pos3d, heading) {
|
|
46715
|
+
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(pos3d);
|
|
46716
|
+
const rad = Cesium.Math.toRadians(heading);
|
|
46717
|
+
const local = new Cesium.Cartesian3(Math.sin(rad), Math.cos(rad), 0);
|
|
46718
|
+
const world = Cesium.Matrix4.multiplyByPointAsVector(enu, local, new Cesium.Cartesian3());
|
|
46719
|
+
return Cesium.Cartesian3.normalize(world, world);
|
|
46720
|
+
}
|
|
46721
|
+
EntityRenderEnginePointOrientation.GetHeadingAxis = GetHeadingAxis;
|
|
46722
|
+
/*
|
|
46723
|
+
* World space forward and right unit vectors for a full orientation, which span the plane the 3D ring lies in.
|
|
46724
|
+
*/
|
|
46725
|
+
function GetBasis(pos3d, orientation) {
|
|
46726
|
+
const h = Cesium.Math.toRadians(orientation.heading);
|
|
46727
|
+
const p = Cesium.Math.toRadians(orientation.pitch);
|
|
46728
|
+
const r = Cesium.Math.toRadians(orientation.roll);
|
|
46729
|
+
const forward = new Cesium.Cartesian3(Math.sin(h) * Math.cos(p), Math.cos(h) * Math.cos(p), Math.sin(p));
|
|
46730
|
+
const level = new Cesium.Cartesian3(Math.cos(h), -Math.sin(h), 0);
|
|
46731
|
+
const up = Cesium.Cartesian3.cross(level, forward, new Cesium.Cartesian3());
|
|
46732
|
+
// Positive roll lowers the right side.
|
|
46733
|
+
const right = Cesium.Cartesian3.add(Cesium.Cartesian3.multiplyByScalar(level, Math.cos(r), new Cesium.Cartesian3()), Cesium.Cartesian3.multiplyByScalar(up, -Math.sin(r), new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
|
46734
|
+
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(pos3d);
|
|
46735
|
+
const toWorld = (local) => {
|
|
46736
|
+
const world = Cesium.Matrix4.multiplyByPointAsVector(enu, local, new Cesium.Cartesian3());
|
|
46737
|
+
return Cesium.Cartesian3.normalize(world, world);
|
|
46738
|
+
};
|
|
46739
|
+
return { forward: toWorld(forward), right: toWorld(right) };
|
|
46740
|
+
}
|
|
46741
|
+
EntityRenderEnginePointOrientation.GetBasis = GetBasis;
|
|
46742
|
+
/*
|
|
46743
|
+
* Counter-clockwise billboard rotation that turns its up edge along a world direction as the camera sees it.
|
|
46744
|
+
* Cesium's alignedAxis squares its angle and drops perspective, up to 160 degrees out when side on.
|
|
46745
|
+
*/
|
|
46746
|
+
function GetScreenRotation(viewer, pos3d, axis) {
|
|
46747
|
+
const transforms = Cesium.SceneTransforms;
|
|
46748
|
+
const project = transforms.wgs84ToWindowCoordinates || transforms.worldToWindowCoordinates;
|
|
46749
|
+
const camera = viewer.camera.positionWC || viewer.camera.position;
|
|
46750
|
+
// A step proportional to distance keeps the two projections a few pixels apart at any zoom.
|
|
46751
|
+
const step = Math.max(0.01, Cesium.Cartesian3.distance(camera, pos3d) * 0.01);
|
|
46752
|
+
const ahead = Cesium.Cartesian3.add(pos3d, Cesium.Cartesian3.multiplyByScalar(axis, step, new Cesium.Cartesian3()), new Cesium.Cartesian3());
|
|
46753
|
+
const from = project(viewer.scene, pos3d, new Cesium.Cartesian2());
|
|
46754
|
+
const to = project(viewer.scene, ahead, new Cesium.Cartesian2());
|
|
46755
|
+
if (!from || !to) {
|
|
46756
|
+
return null;
|
|
46757
|
+
}
|
|
46758
|
+
const dx = to.x - from.x;
|
|
46759
|
+
const dy = to.y - from.y;
|
|
46760
|
+
if (Math.abs(dx) + Math.abs(dy) < 1e-6) {
|
|
46761
|
+
return null;
|
|
46762
|
+
}
|
|
46763
|
+
return Math.atan2(-dx, -dy);
|
|
46764
|
+
}
|
|
46765
|
+
EntityRenderEnginePointOrientation.GetScreenRotation = GetScreenRotation;
|
|
46766
|
+
/*
|
|
46767
|
+
* Metres one CSS pixel covers at a position, since billboard sizes and polyline widths are CSS pixels.
|
|
46768
|
+
*/
|
|
46769
|
+
function getMetresPerPixel(viewer, pos3d) {
|
|
46770
|
+
const scene = viewer.scene;
|
|
46771
|
+
const sphere = new Cesium.BoundingSphere(pos3d, 0);
|
|
46772
|
+
const perBufferPixel = viewer.camera.getPixelSize(sphere, scene.drawingBufferWidth, scene.drawingBufferHeight);
|
|
46773
|
+
return perBufferPixel * (scene.pixelRatio || 1);
|
|
46774
|
+
}
|
|
46775
|
+
/*
|
|
46776
|
+
* Where the parent is drawn this frame, as an absolute position, or null while its ground is not known yet.
|
|
46777
|
+
*/
|
|
46778
|
+
function getDrawnPos3d(viewer, parent, heightRef) {
|
|
46779
|
+
const pos3d = GetCValue(viewer, parent.position);
|
|
46780
|
+
if (!pos3d) {
|
|
46781
|
+
return null;
|
|
46782
|
+
}
|
|
46783
|
+
return exports.DrawingUtils.GetDrawnPos3d({
|
|
46784
|
+
viewer,
|
|
46785
|
+
heightRef,
|
|
46786
|
+
pos3d,
|
|
46787
|
+
terrainId: exports.ViewUtils.GetTerrainCacheId(viewer)
|
|
46788
|
+
});
|
|
46789
|
+
}
|
|
46790
|
+
/*
|
|
46791
|
+
* Creates or updates the ring for a point, or returns null when it cannot be drawn.
|
|
46792
|
+
* Clamped to ground it shows only the heading as a billboard, otherwise the full 3D orientation.
|
|
46793
|
+
*/
|
|
46794
|
+
function Render(params) {
|
|
46795
|
+
const { viewer, parent, orientation, heightRef } = params;
|
|
46796
|
+
if (!viewer || !parent || !orientation) {
|
|
46797
|
+
return null;
|
|
46798
|
+
}
|
|
46799
|
+
const clamped = heightRef == Cesium.HeightReference.CLAMP_TO_GROUND;
|
|
46800
|
+
const ring = clamped ? renderBillboard(params) : renderPolyline(params);
|
|
46801
|
+
if (ring) {
|
|
46802
|
+
ring._orientationRing = true;
|
|
46803
|
+
ring._noEdit = true;
|
|
46804
|
+
ring._parentEntity = parent;
|
|
46805
|
+
}
|
|
46806
|
+
return ring;
|
|
46807
|
+
}
|
|
46808
|
+
EntityRenderEnginePointOrientation.Render = Render;
|
|
46809
|
+
/*
|
|
46810
|
+
* The ring among a point's sibling graphics, if it has one.
|
|
46811
|
+
*/
|
|
46812
|
+
function FindRing(siblings) {
|
|
46813
|
+
return (siblings === null || siblings === void 0 ? void 0 : siblings.find(x => x === null || x === void 0 ? void 0 : x._orientationRing)) || null;
|
|
46814
|
+
}
|
|
46815
|
+
EntityRenderEnginePointOrientation.FindRing = FindRing;
|
|
46816
|
+
/*
|
|
46817
|
+
* The heading only ring, a billboard turned every frame to point along the ground.
|
|
46818
|
+
*/
|
|
46819
|
+
function renderBillboard(params) {
|
|
46820
|
+
var _a;
|
|
46821
|
+
const { viewer, parent, orientation, heightRef } = params;
|
|
46822
|
+
const image = CreateRingBillboard(params.glyphRadius);
|
|
46823
|
+
if (!image) {
|
|
46824
|
+
return null;
|
|
46825
|
+
}
|
|
46826
|
+
let rotation = 0;
|
|
46827
|
+
const rotationProp = new Cesium.CallbackProperty(() => {
|
|
46828
|
+
const drawn = getDrawnPos3d(viewer, parent, heightRef);
|
|
46829
|
+
if (drawn) {
|
|
46830
|
+
const next = GetScreenRotation(viewer, drawn, GetHeadingAxis(drawn, orientation.heading));
|
|
46831
|
+
if (next != null) {
|
|
46832
|
+
rotation = next;
|
|
46833
|
+
}
|
|
46834
|
+
}
|
|
46835
|
+
return rotation;
|
|
46836
|
+
}, false);
|
|
46837
|
+
const position = new Cesium.CallbackProperty(() => GetCValue(viewer, parent.position), false);
|
|
46838
|
+
const displayCondition = exports.EntityRenderEngine.GetDisplayCondition(params.minDistance, params.maxDistance);
|
|
46839
|
+
const pixelOffset = new Cesium.Cartesian2(0, -(params.glyphOffsetY || 0));
|
|
46840
|
+
let ring = ((_a = params.existing) === null || _a === void 0 ? void 0 : _a.billboard) ? params.existing : null;
|
|
46841
|
+
if (!ring) {
|
|
46842
|
+
ring = new Cesium.Entity({
|
|
46843
|
+
id: BModels.ObjectUtils.UId(15),
|
|
46844
|
+
billboard: {
|
|
46845
|
+
image: image.canvasDataUri,
|
|
46846
|
+
width: image.size,
|
|
46847
|
+
height: image.size,
|
|
46848
|
+
rotation: rotationProp,
|
|
46849
|
+
heightReference: heightRef,
|
|
46850
|
+
pixelOffset,
|
|
46851
|
+
distanceDisplayCondition: displayCondition
|
|
46852
|
+
},
|
|
46853
|
+
position,
|
|
46854
|
+
show: true
|
|
46855
|
+
});
|
|
46856
|
+
}
|
|
46857
|
+
else {
|
|
46858
|
+
ring.billboard.image = new Cesium.ConstantProperty(image.canvasDataUri);
|
|
46859
|
+
ring.billboard.width = new Cesium.ConstantProperty(image.size);
|
|
46860
|
+
ring.billboard.height = new Cesium.ConstantProperty(image.size);
|
|
46861
|
+
ring.billboard.rotation = rotationProp;
|
|
46862
|
+
ring.billboard.heightReference = new Cesium.ConstantProperty(heightRef);
|
|
46863
|
+
ring.billboard.pixelOffset = new Cesium.ConstantProperty(pixelOffset);
|
|
46864
|
+
ring.billboard.distanceDisplayCondition = new Cesium.ConstantProperty(displayCondition);
|
|
46865
|
+
ring.position = position;
|
|
46866
|
+
ring.show = true;
|
|
46867
|
+
}
|
|
46868
|
+
exports.CesiumEntityStyler.BakeDefaultColor({
|
|
46869
|
+
entity: ring,
|
|
46870
|
+
viewer,
|
|
46871
|
+
colors: {
|
|
46872
|
+
"billboard": Cesium.Color.WHITE
|
|
46873
|
+
},
|
|
46874
|
+
refresh: false
|
|
46875
|
+
});
|
|
46876
|
+
return ring;
|
|
46877
|
+
}
|
|
46878
|
+
/*
|
|
46879
|
+
* The full orientation ring, a polyline in the orientation's plane, resized each frame to hold its screen size.
|
|
46880
|
+
*/
|
|
46881
|
+
function renderPolyline(params) {
|
|
46882
|
+
var _a;
|
|
46883
|
+
const { viewer, parent, orientation, heightRef } = params;
|
|
46884
|
+
const radiusPx = GetRingRadius(params.glyphRadius);
|
|
46885
|
+
const outline = GetFilledOutline(GetTipRatio(radiusPx));
|
|
46886
|
+
const color = Cesium.Color.fromCssColorString(RING_CSS);
|
|
46887
|
+
let last = [];
|
|
46888
|
+
let basisAt = null;
|
|
46889
|
+
let basis = null;
|
|
46890
|
+
const positions = new Cesium.CallbackProperty(() => {
|
|
46891
|
+
const drawn = getDrawnPos3d(viewer, parent, heightRef);
|
|
46892
|
+
if (!drawn) {
|
|
46893
|
+
return last;
|
|
46894
|
+
}
|
|
46895
|
+
// The local frame only changes when the point moves.
|
|
46896
|
+
if (!basisAt || !Cesium.Cartesian3.equals(basisAt, drawn)) {
|
|
46897
|
+
basis = GetBasis(drawn, orientation);
|
|
46898
|
+
basisAt = Cesium.Cartesian3.clone(drawn);
|
|
46899
|
+
}
|
|
46900
|
+
const scale = radiusPx * getMetresPerPixel(viewer, drawn);
|
|
46901
|
+
if (!isFinite(scale) || scale <= 0) {
|
|
46902
|
+
return last;
|
|
46903
|
+
}
|
|
46904
|
+
last = outline.map(([u, v]) => {
|
|
46905
|
+
const point = Cesium.Cartesian3.multiplyByScalar(basis.forward, u * scale, new Cesium.Cartesian3());
|
|
46906
|
+
Cesium.Cartesian3.add(point, Cesium.Cartesian3.multiplyByScalar(basis.right, v * scale, new Cesium.Cartesian3()), point);
|
|
46907
|
+
return Cesium.Cartesian3.add(point, drawn, point);
|
|
46908
|
+
});
|
|
46909
|
+
return last;
|
|
46910
|
+
}, false);
|
|
46911
|
+
const displayCondition = exports.EntityRenderEngine.GetDisplayCondition(params.minDistance, params.maxDistance);
|
|
46912
|
+
let ring = ((_a = params.existing) === null || _a === void 0 ? void 0 : _a.polyline) ? params.existing : null;
|
|
46913
|
+
if (!ring) {
|
|
46914
|
+
ring = new Cesium.Entity({
|
|
46915
|
+
id: BModels.ObjectUtils.UId(15),
|
|
46916
|
+
polyline: {
|
|
46917
|
+
positions,
|
|
46918
|
+
width: RING_STROKE,
|
|
46919
|
+
material: color,
|
|
46920
|
+
arcType: Cesium.ArcType.NONE,
|
|
46921
|
+
// The positions are already absolute. Unset reads as clamped to the culler, which then grounds the ring.
|
|
46922
|
+
clampToGround: false,
|
|
46923
|
+
distanceDisplayCondition: displayCondition
|
|
46924
|
+
},
|
|
46925
|
+
position: new Cesium.CallbackProperty(() => GetCValue(viewer, parent.position), false),
|
|
46926
|
+
show: true
|
|
46927
|
+
});
|
|
46928
|
+
}
|
|
46929
|
+
else {
|
|
46930
|
+
ring.polyline.positions = positions;
|
|
46931
|
+
ring.polyline.distanceDisplayCondition = new Cesium.ConstantProperty(displayCondition);
|
|
46932
|
+
ring.show = true;
|
|
46933
|
+
}
|
|
46934
|
+
exports.CesiumEntityStyler.SetDefaultColor({
|
|
46935
|
+
color,
|
|
46936
|
+
entity: ring,
|
|
46937
|
+
viewer,
|
|
46938
|
+
override: true,
|
|
46939
|
+
requestRender: false
|
|
46940
|
+
});
|
|
46941
|
+
return ring;
|
|
46942
|
+
}
|
|
46943
|
+
})(EntityRenderEnginePointOrientation || (EntityRenderEnginePointOrientation = {}));
|
|
46944
|
+
|
|
46343
46945
|
(function (EntityRenderEnginePoint) {
|
|
46344
46946
|
/**
|
|
46345
46947
|
* Creates a circle billboard (canvas) for a point.
|
|
@@ -46377,14 +46979,21 @@
|
|
|
46377
46979
|
let animatePosition = null;
|
|
46378
46980
|
let shouldShowTrack = false;
|
|
46379
46981
|
let trackStyle = null;
|
|
46982
|
+
// The drawn glyph's half size and how far its centre sits above the anchor, for sizing the orientation ring.
|
|
46983
|
+
let glyph = null;
|
|
46984
|
+
// The orientation ring a previous render left, which the effect decides to keep or remove at the end.
|
|
46985
|
+
let existingRing = null;
|
|
46380
46986
|
const prepareExistingGraphic = (cEntity, maxSiblings = 0) => {
|
|
46381
46987
|
// Gather entity in case previous version had sibling graphics we no longer need.
|
|
46382
46988
|
const parts = exports.EntityUtils.GatherEntity({
|
|
46383
46989
|
entity: cEntity,
|
|
46384
46990
|
});
|
|
46385
46991
|
if (parts.length > 1) {
|
|
46992
|
+
// The ring is held apart so the sibling count below only ever trims the track.
|
|
46993
|
+
existingRing = EntityRenderEnginePointOrientation.FindRing(cEntity._siblingGraphics);
|
|
46994
|
+
const others = (cEntity._siblingGraphics || []).filter(x => x !== existingRing);
|
|
46386
46995
|
// We'll cull all except the allowed number of siblings.
|
|
46387
|
-
cEntity._siblingGraphics =
|
|
46996
|
+
cEntity._siblingGraphics = others.slice(0, maxSiblings).concat(existingRing ? [existingRing] : []);
|
|
46388
46997
|
// We'll remove all that aren't in the allowed (direct) list.
|
|
46389
46998
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
46390
46999
|
const part = parts[i];
|
|
@@ -46396,7 +47005,7 @@
|
|
|
46396
47005
|
console.warn("Point.Render: Parent entity was not null. This should not happen.");
|
|
46397
47006
|
}
|
|
46398
47007
|
}
|
|
46399
|
-
siblings = cEntity._siblingGraphics;
|
|
47008
|
+
siblings = (cEntity._siblingGraphics || []).filter(x => x !== existingRing);
|
|
46400
47009
|
cEntity._siblingGraphics = [];
|
|
46401
47010
|
};
|
|
46402
47011
|
const updateShouldShowTrack = () => {
|
|
@@ -46649,6 +47258,11 @@
|
|
|
46649
47258
|
}
|
|
46650
47259
|
cEntity.billboard._billboardSize = image.height;
|
|
46651
47260
|
cEntity.billboard._billboardImgKey = imageKey;
|
|
47261
|
+
// Icons hang from their bottom edge, so the glyph's centre sits half its height up.
|
|
47262
|
+
glyph = {
|
|
47263
|
+
radius: Math.max(image.width || image.height, image.height) * iconScale / 2,
|
|
47264
|
+
offsetY: image.height * iconScale / 2
|
|
47265
|
+
};
|
|
46652
47266
|
}
|
|
46653
47267
|
}
|
|
46654
47268
|
}
|
|
@@ -47022,6 +47636,7 @@
|
|
|
47022
47636
|
cEntity.billboard._billboardImgKey = imgKey;
|
|
47023
47637
|
}
|
|
47024
47638
|
cEntity.billboard._billboardSize = Math.ceil(circleBillboard.height / 2);
|
|
47639
|
+
glyph = { radius: size / 2, offsetY: 0 };
|
|
47025
47640
|
}
|
|
47026
47641
|
// Generate a polyline 'track' for the historic data.
|
|
47027
47642
|
// We do this for historic data that exists and is moving.
|
|
@@ -47071,6 +47686,31 @@
|
|
|
47071
47686
|
}
|
|
47072
47687
|
trackEntity._parentEntity = cEntity;
|
|
47073
47688
|
}
|
|
47689
|
+
// Cylinders set no glyph, so a style switching to one drops its ring.
|
|
47690
|
+
const orientation = glyph && cEntity && EntityRenderEnginePointOrientation.IsEnabled(style)
|
|
47691
|
+
? EntityRenderEnginePointOrientation.GetOrientation(entity)
|
|
47692
|
+
: null;
|
|
47693
|
+
const ring = orientation ? EntityRenderEnginePointOrientation.Render({
|
|
47694
|
+
viewer: params.viewer,
|
|
47695
|
+
parent: cEntity,
|
|
47696
|
+
existing: existingRing,
|
|
47697
|
+
orientation,
|
|
47698
|
+
heightRef,
|
|
47699
|
+
glyphRadius: glyph.radius,
|
|
47700
|
+
glyphOffsetY: glyph.offsetY,
|
|
47701
|
+
minDistance: params.minDistance,
|
|
47702
|
+
maxDistance: params.maxDistance
|
|
47703
|
+
}) : null;
|
|
47704
|
+
if (existingRing && existingRing !== ring) {
|
|
47705
|
+
RemoveCEntityFromScene(params.viewer, existingRing);
|
|
47706
|
+
}
|
|
47707
|
+
if (ring) {
|
|
47708
|
+
siblings.push(ring);
|
|
47709
|
+
// A new graphic on an existing visual needs a full refresh to be added, as the track does.
|
|
47710
|
+
if (ring !== existingRing && params.rego) {
|
|
47711
|
+
params.rego.stale = true;
|
|
47712
|
+
}
|
|
47713
|
+
}
|
|
47074
47714
|
cEntity._siblingGraphics = siblings;
|
|
47075
47715
|
cEntity.styleEffective = exports.StyleEffective.Combine(styleTraceParts);
|
|
47076
47716
|
return cEntity;
|
|
@@ -47205,7 +47845,8 @@
|
|
|
47205
47845
|
canvas.getContext("2d").drawImage(image, 0, 0);
|
|
47206
47846
|
return {
|
|
47207
47847
|
canvasDataUri: canvas.toDataURL("image/png"),
|
|
47208
|
-
height: image.height
|
|
47848
|
+
height: image.height,
|
|
47849
|
+
width: image.width
|
|
47209
47850
|
};
|
|
47210
47851
|
});
|
|
47211
47852
|
_billboardCache$1.Set(cacheKey, prom);
|
|
@@ -55436,7 +56077,7 @@ void main() {
|
|
|
55436
56077
|
StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
|
|
55437
56078
|
})(exports.StyleUtils || (exports.StyleUtils = {}));
|
|
55438
56079
|
|
|
55439
|
-
const VERSION = "7.6.
|
|
56080
|
+
const VERSION = "7.6.5";
|
|
55440
56081
|
/**
|
|
55441
56082
|
* Updates the environment instance used by bruce-cesium to one specified.
|
|
55442
56083
|
* This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
|