@inweb/viewer-three 26.12.6 → 27.1.0

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.
Files changed (43) hide show
  1. package/dist/extensions/loaders/GLTFFileLoader.js +1 -1
  2. package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -1
  3. package/dist/extensions/loaders/GLTFFileLoader.min.js +1 -1
  4. package/dist/extensions/loaders/GLTFFileLoader.module.js +1 -1
  5. package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -1
  6. package/dist/extensions/loaders/IFCXLoader.js +2 -2
  7. package/dist/extensions/loaders/IFCXLoader.js.map +1 -1
  8. package/dist/extensions/loaders/IFCXLoader.min.js +1 -1
  9. package/dist/extensions/loaders/IFCXLoader.module.js +2 -2
  10. package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -1
  11. package/dist/viewer-three.js +466 -170
  12. package/dist/viewer-three.js.map +1 -1
  13. package/dist/viewer-three.min.js +2 -2
  14. package/dist/viewer-three.module.js +464 -168
  15. package/dist/viewer-three.module.js.map +1 -1
  16. package/extensions/loaders/GLTFFileLoader.ts +1 -1
  17. package/extensions/loaders/IFCX/IFCXCloudLoader.ts +1 -1
  18. package/extensions/loaders/IFCX/IFCXFileLoader.ts +1 -1
  19. package/lib/Viewer/Viewer.d.ts +2 -1
  20. package/lib/Viewer/components/ExtentsComponent.d.ts +1 -1
  21. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +3 -3
  22. package/lib/Viewer/measurement/Snapper.d.ts +1 -0
  23. package/lib/Viewer/measurement/UnitConverter.d.ts +20 -13
  24. package/lib/Viewer/models/IModelImpl.d.ts +2 -6
  25. package/lib/Viewer/models/ModelImpl.d.ts +4 -6
  26. package/package.json +5 -5
  27. package/src/Viewer/Viewer.ts +25 -15
  28. package/src/Viewer/commands/GetSelected2.ts +2 -2
  29. package/src/Viewer/commands/ZoomTo.ts +3 -3
  30. package/src/Viewer/components/CameraComponent.ts +4 -4
  31. package/src/Viewer/components/ExtentsComponent.ts +3 -3
  32. package/src/Viewer/components/HighlighterComponent.ts +11 -17
  33. package/src/Viewer/components/SelectionComponent.ts +14 -13
  34. package/src/Viewer/draggers/MeasureLineDragger.ts +1 -0
  35. package/src/Viewer/draggers/OrbitDragger.ts +2 -0
  36. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +287 -22
  37. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +94 -18
  38. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +1 -1
  39. package/src/Viewer/measurement/Snapper.ts +6 -3
  40. package/src/Viewer/measurement/UnitConverter.ts +19 -12
  41. package/src/Viewer/measurement/UnitFormatter.ts +2 -2
  42. package/src/Viewer/models/IModelImpl.ts +2 -10
  43. package/src/Viewer/models/ModelImpl.ts +111 -61
@@ -33829,6 +33829,7 @@ void main() {
33829
33829
  this.changed = false;
33830
33830
  this.viewer = viewer;
33831
33831
  this.viewer.addEventListener("databasechunk", this.updateControls);
33832
+ this.viewer.addEventListener("clear", this.updateControls);
33832
33833
  this.viewer.on("viewposition", this.updateControls);
33833
33834
  this.viewer.addEventListener("zoom", this.updateControls);
33834
33835
  this.viewer.addEventListener("drawviewpoint", this.updateControls);
@@ -33840,6 +33841,7 @@ void main() {
33840
33841
  initialize() { }
33841
33842
  dispose() {
33842
33843
  this.viewer.removeEventListener("databasechunk", this.updateControls);
33844
+ this.viewer.removeEventListener("clear", this.updateControls);
33843
33845
  this.viewer.off("viewposition", this.updateControls);
33844
33846
  this.viewer.removeEventListener("zoom", this.updateControls);
33845
33847
  this.viewer.removeEventListener("drawviewpoint", this.updateControls);
@@ -33937,20 +33939,25 @@ void main() {
33937
33939
  }
33938
33940
  }
33939
33941
 
33942
+ const DisplayUnits = {
33943
+ Meters: { name: "Meters", symbol: "m", scale: 1.0 },
33944
+ Centimeters: { name: "Centimeters", symbol: "cm", scale: 0.01 },
33945
+ Millimeters: { name: "Millimeters", symbol: "mm", scale: 0.001 },
33946
+ Feet: { name: "Feet", symbol: "ft", scale: 0.3048 },
33947
+ Inches: { name: "Inches", symbol: "in", scale: 0.0254 },
33948
+ Yards: { name: "Yards", symbol: "yd", scale: 0.9144 },
33949
+ Kilometers: { name: "Kilometers", symbol: "km", scale: 1000.0 },
33950
+ Miles: { name: "Miles", symbol: "mi", scale: 1609.344 },
33951
+ Micrometers: { name: "Micrometers", symbol: "µm", scale: 0.000001 },
33952
+ Mils: { name: "Mils", symbol: "mil", scale: 0.0000254 },
33953
+ MicroInches: { name: "Micro-inches", symbol: "µin", scale: 0.0000000254 },
33954
+ Default: { name: "File units", symbol: "", scale: 1.0 },
33955
+ };
33940
33956
  const ModelUnits = {
33941
- Meters: { name: "Meters", type: "m", scale: 1.0 },
33942
- Centimeters: { name: "Centimeters", type: "cm", scale: 0.01 },
33943
- Millimeters: { name: "Millimeters", type: "mm", scale: 0.001 },
33944
- Feet: { name: "Feet", type: "ft", scale: 0.3048 },
33945
- Inches: { name: "Inches", type: "in", scale: 0.0254 },
33946
- Yards: { name: "Yards", type: "yd", scale: 0.9144 },
33947
- Kilometers: { name: "Kilometers", type: "km", scale: 1000.0 },
33948
- Miles: { name: "Miles", type: "mi", scale: 1609.344 },
33949
- Micrometers: { name: "Micrometers", type: "µm", scale: 0.000001 },
33950
- Mils: { name: "Mils", type: "mil", scale: 0.0000254 },
33951
- MicroInches: { name: "Micro-inches", type: "µin", scale: 0.0000000254 },
33952
- Default: { name: "File units", type: "unit", scale: 1.0 },
33957
+ Default: { name: "", symbol: "", scale: 1.0 },
33953
33958
  };
33959
+ Object.keys(DisplayUnits).forEach((key) => (ModelUnits[key] = DisplayUnits[key]));
33960
+ Object.keys(DisplayUnits).forEach((key) => (ModelUnits[DisplayUnits[key].symbol] = DisplayUnits[key]));
33954
33961
  function convertUnits(fromUnits, toUnits, distance) {
33955
33962
  const fromFactor = 1 / (ModelUnits[fromUnits] || ModelUnits.Default).scale;
33956
33963
  const toFactor = (ModelUnits[toUnits] || ModelUnits.Default).scale || 1;
@@ -33958,7 +33965,7 @@ void main() {
33958
33965
  }
33959
33966
 
33960
33967
  function getDisplayUnit(units) {
33961
- return (ModelUnits[units] || ModelUnits.Default).type;
33968
+ return (ModelUnits[units] || ModelUnits.Default).symbol;
33962
33969
  }
33963
33970
  function calculatePrecision(value) {
33964
33971
  const distance = Math.abs(value);
@@ -33995,7 +34002,7 @@ void main() {
33995
34002
  else if (digits > 10)
33996
34003
  digits = 10;
33997
34004
  if (ModelUnits[units]) {
33998
- return formatNumber(distance, digits, precision) + " " + ModelUnits[units].type;
34005
+ return formatNumber(distance, digits, precision) + " " + ModelUnits[units].symbol;
33999
34006
  }
34000
34007
  else if (units) {
34001
34008
  return formatNumber(distance, digits, precision) + " " + units;
@@ -34018,6 +34025,7 @@ void main() {
34018
34025
  this.camera = camera;
34019
34026
  this.renderer = renderer;
34020
34027
  this.canvas = canvas;
34028
+ this.threshold = 0.0001;
34021
34029
  this.raycaster = new Raycaster();
34022
34030
  this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
34023
34031
  this.edgesCache = new WeakMap();
@@ -34038,10 +34046,10 @@ void main() {
34038
34046
  this.raycaster.setFromCamera(coords, this.camera);
34039
34047
  this.raycaster.params = {
34040
34048
  Mesh: {},
34041
- Line: { threshold: 0.05 },
34042
- Line2: { threshold: 0.05 },
34049
+ Line: { threshold: this.threshold },
34050
+ Line2: { threshold: this.threshold },
34043
34051
  LOD: {},
34044
- Points: { threshold: 0.01 },
34052
+ Points: { threshold: this.threshold },
34045
34053
  Sprite: {},
34046
34054
  };
34047
34055
  let intersects = this.raycaster.intersectObjects(objects, false);
@@ -34210,6 +34218,7 @@ void main() {
34210
34218
  this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
34211
34219
  this.overlay.addLine(this.line);
34212
34220
  this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
34221
+ this.snapper.threshold = viewer.extents.getSize(new Vector3()).length() / 10000;
34213
34222
  this.objects = [];
34214
34223
  this.updateObjects();
34215
34224
  this.updateUnits();
@@ -35213,7 +35222,7 @@ void main() {
35213
35222
  const boxCenter = box.getCenter(new Vector3());
35214
35223
  const boxSize = box.getBoundingSphere(new Sphere()).radius;
35215
35224
  const rendererSize = viewer.renderer.getSize(new Vector2());
35216
- const aspect = rendererSize.x / rendererSize.y;
35225
+ const aspectRatio = rendererSize.x / rendererSize.y;
35217
35226
  const camera = viewer.camera;
35218
35227
  if (camera.isPerspectiveCamera) {
35219
35228
  const offset = new Vector3(0, 0, 1)
@@ -35225,8 +35234,8 @@ void main() {
35225
35234
  if (camera.isOrthographicCamera) {
35226
35235
  camera.top = boxSize;
35227
35236
  camera.bottom = -boxSize;
35228
- camera.left = camera.bottom * aspect;
35229
- camera.right = camera.top * aspect;
35237
+ camera.left = camera.bottom * aspectRatio;
35238
+ camera.right = camera.top * aspectRatio;
35230
35239
  camera.zoom = 1;
35231
35240
  camera.updateProjectionMatrix();
35232
35241
  const offset = new Vector3(0, 0, 1)
@@ -35287,9 +35296,9 @@ void main() {
35287
35296
  function getSelected2(viewer) {
35288
35297
  const handles2 = [];
35289
35298
  viewer.models.forEach((model) => {
35290
- handles2.push(...model.getHandlesByObjects(viewer.selected));
35299
+ handles2.push(model.getHandlesByObjects(viewer.selected));
35291
35300
  });
35292
- return handles2;
35301
+ return handles2.flat();
35293
35302
  }
35294
35303
 
35295
35304
  function hideSelected(viewer) {
@@ -35513,15 +35522,15 @@ void main() {
35513
35522
  switchCamera(camera) {
35514
35523
  const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius * 2 || 1;
35515
35524
  const rendererSize = this.viewer.renderer.getSize(new Vector2());
35516
- const aspect = rendererSize.x / rendererSize.y;
35525
+ const aspectRatio = rendererSize.x / rendererSize.y;
35517
35526
  if (camera.isPerspectiveCamera) {
35518
- camera.aspect = aspect;
35527
+ camera.aspect = aspectRatio;
35519
35528
  camera.near = extentsSize / 1000;
35520
35529
  camera.far = extentsSize * 1000;
35521
35530
  }
35522
35531
  if (camera.isOrthographicCamera) {
35523
- camera.left = camera.bottom * aspect;
35524
- camera.right = camera.top * aspect;
35532
+ camera.left = camera.bottom * aspectRatio;
35533
+ camera.right = camera.top * aspectRatio;
35525
35534
  camera.near = 0;
35526
35535
  camera.far = extentsSize * 1000;
35527
35536
  }
@@ -35569,10 +35578,12 @@ void main() {
35569
35578
 
35570
35579
  class ExtentsComponent {
35571
35580
  constructor(viewer) {
35572
- this.syncExtents = () => {
35581
+ this.syncExtents = (event) => {
35573
35582
  const extents = new Box3();
35574
35583
  this.viewer.models.forEach((model) => model.getExtents(extents));
35575
35584
  this.viewer.extents.copy(extents);
35585
+ if (event.type !== "databasechunk" && event.target !== "clear")
35586
+ return;
35576
35587
  if (this.viewer.models.length > 1)
35577
35588
  return;
35578
35589
  this.viewer.extents.getCenter(this.viewer.target);
@@ -36578,12 +36589,12 @@ void main() {
36578
36589
  const { edgesVisibility } = this.viewer.options;
36579
36590
  if (!Array.isArray(objects))
36580
36591
  objects = [objects];
36581
- if (!objects.length)
36592
+ if (objects.length === 0)
36582
36593
  return;
36583
36594
  objects
36584
36595
  .filter((object) => !object.userData.isEdge)
36585
36596
  .forEach((object) => {
36586
- if (object.isHighlighted)
36597
+ if (object.userData.isHighlighted)
36587
36598
  return;
36588
36599
  if (object.isLine || object.isLineSegments) {
36589
36600
  const positions = object.geometry.attributes.position.array;
@@ -36592,43 +36603,39 @@ void main() {
36592
36603
  ? HighlighterUtils.fromIndexedLine(positions, indices)
36593
36604
  : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
36594
36605
  const wireframe = new Wireframe(lineGeometry, this.lineGlowMaterial);
36595
- wireframe.position.copy(object.position);
36596
- wireframe.rotation.copy(object.rotation);
36597
- wireframe.scale.copy(object.scale);
36598
36606
  wireframe.visible = edgesVisibility;
36599
- object.parent.add(wireframe);
36607
+ wireframe.userData.isHighlightWireframe = true;
36608
+ object.add(wireframe);
36600
36609
  object.userData.highlightWireframe = wireframe;
36601
36610
  object.userData.originalMaterial = object.material;
36602
36611
  object.material = this.lineMaterial;
36603
- object.isHighlighted = true;
36612
+ object.userData.isHighlighted = true;
36604
36613
  }
36605
36614
  else if (object.isMesh) {
36606
36615
  const edgesGeometry = new EdgesGeometry(object.geometry, 89);
36607
36616
  const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
36608
36617
  const wireframe = new Wireframe(lineGeometry, this.edgesMaterial);
36609
- wireframe.position.copy(object.position);
36610
- wireframe.rotation.copy(object.rotation);
36611
- wireframe.scale.copy(object.scale);
36612
36618
  wireframe.visible = edgesVisibility;
36613
- object.parent.add(wireframe);
36619
+ wireframe.userData.isHighlightWireframe = true;
36620
+ object.add(wireframe);
36614
36621
  object.userData.highlightWireframe = wireframe;
36615
36622
  object.userData.originalMaterial = object.material;
36616
36623
  object.material = this.facesMaterial;
36617
- object.isHighlighted = true;
36624
+ object.userData.isHighlighted = true;
36618
36625
  }
36619
36626
  });
36620
36627
  }
36621
36628
  unhighlight(objects) {
36622
36629
  if (!Array.isArray(objects))
36623
36630
  objects = [objects];
36624
- if (!objects.length)
36631
+ if (objects.length === 0)
36625
36632
  return;
36626
36633
  objects.forEach((object) => {
36627
- if (!object.isHighlighted)
36634
+ if (!object.userData.isHighlighted)
36628
36635
  return;
36629
- object.isHighlighted = false;
36630
36636
  object.material = object.userData.originalMaterial;
36631
36637
  object.userData.highlightWireframe.removeFromParent();
36638
+ delete object.userData.isHighlighted;
36632
36639
  delete object.userData.originalMaterial;
36633
36640
  delete object.userData.highlightWireframe;
36634
36641
  });
@@ -36676,6 +36683,7 @@ void main() {
36676
36683
  if (upPosition.distanceTo(this.downPosition) !== 0)
36677
36684
  return;
36678
36685
  const snapper = new Snapper(this.viewer.camera, this.viewer.renderer, this.viewer.canvas);
36686
+ snapper.threshold = this.viewer.extents.getSize(new Vector3()).length() / 10000;
36679
36687
  let intersections = [];
36680
36688
  this.viewer.models.forEach((model) => {
36681
36689
  const objects = model.getVisibleObjects();
@@ -36730,12 +36738,12 @@ void main() {
36730
36738
  }
36731
36739
  if (!Array.isArray(objects))
36732
36740
  objects = [objects];
36733
- if (!objects.length)
36741
+ if (objects.length === 0)
36734
36742
  return;
36735
- model.showOriginalObjects(objects);
36743
+ model.highlightObjects(objects);
36736
36744
  this.highlighter.highlight(objects);
36737
36745
  objects.forEach((object) => this.viewer.selected.push(object));
36738
- objects.forEach((object) => (object.isSelected = true));
36746
+ objects.forEach((object) => (object.userData.isSelected = true));
36739
36747
  }
36740
36748
  deselect(objects, model) {
36741
36749
  if (!model) {
@@ -36744,29 +36752,29 @@ void main() {
36744
36752
  }
36745
36753
  if (!Array.isArray(objects))
36746
36754
  objects = [objects];
36747
- if (!objects.length)
36755
+ if (objects.length === 0)
36748
36756
  return;
36757
+ model.unhighlightObjects(objects);
36749
36758
  this.highlighter.unhighlight(objects);
36750
- model.hideOriginalObjects(objects);
36751
36759
  this.viewer.selected = this.viewer.selected.filter((x) => !objects.includes(x));
36752
- objects.forEach((object) => (object.isSelected = false));
36760
+ objects.forEach((object) => (object.userData.isSelected = false));
36753
36761
  }
36754
36762
  toggleSelection(objects, model) {
36755
36763
  if (!Array.isArray(objects))
36756
36764
  objects = [objects];
36757
- if (!objects.length)
36765
+ if (objects.length === 0)
36758
36766
  return;
36759
- if (objects[0].isSelected)
36767
+ if (objects[0].userData.isSelected)
36760
36768
  this.deselect(objects, model);
36761
36769
  else
36762
36770
  this.select(objects, model);
36763
36771
  }
36764
36772
  clearSelection() {
36765
- if (!this.viewer.selected.length)
36773
+ if (this.viewer.selected.length === 0)
36766
36774
  return;
36775
+ this.viewer.models.forEach((model) => model.unhighlightObjects(this.viewer.selected));
36767
36776
  this.highlighter.unhighlight(this.viewer.selected);
36768
- this.viewer.models.forEach((model) => model.hideOriginalObjects(this.viewer.selected));
36769
- this.viewer.selected.forEach((object) => (object.isSelected = false));
36777
+ this.viewer.selected.forEach((object) => (object.userData.isSelected = false));
36770
36778
  this.viewer.selected.length = 0;
36771
36779
  }
36772
36780
  }
@@ -36928,6 +36936,20 @@ void main() {
36928
36936
  class ModelImpl {
36929
36937
  constructor(scene) {
36930
36938
  this.scene = scene;
36939
+ this.handleToObjects = new Map();
36940
+ this.originalObjects = new Set();
36941
+ this.scene.traverse((object) => {
36942
+ this.originalObjects.add(object);
36943
+ const handle = object.userData.handle;
36944
+ if (!handle)
36945
+ return;
36946
+ let objects = this.handleToObjects.get(handle);
36947
+ if (!objects) {
36948
+ objects = new Set();
36949
+ this.handleToObjects.set(handle, objects);
36950
+ }
36951
+ objects.add(object);
36952
+ });
36931
36953
  }
36932
36954
  dispose() {
36933
36955
  function disposeMaterial(material) {
@@ -36943,6 +36965,8 @@ void main() {
36943
36965
  if (object.material)
36944
36966
  disposeMaterials(object.material);
36945
36967
  }
36968
+ this.handleToObjects = undefined;
36969
+ this.originalObjects = undefined;
36946
36970
  this.scene.traverse(disposeObject);
36947
36971
  this.scene.clear();
36948
36972
  }
@@ -37085,67 +37109,56 @@ void main() {
37085
37109
  return info;
37086
37110
  }
37087
37111
  getExtents(target) {
37088
- this.scene.traverseVisible((object) => !object.children.length && target.expandByObject(object));
37112
+ this.scene.traverseVisible((object) => target.expandByObject(object));
37089
37113
  return target;
37090
37114
  }
37091
37115
  getObjects() {
37092
- const objects = [];
37093
- this.scene.traverse((object) => objects.push(object));
37094
- return objects;
37116
+ return Array.from(this.originalObjects);
37095
37117
  }
37096
37118
  getVisibleObjects() {
37097
37119
  const objects = [];
37098
37120
  this.scene.traverseVisible((object) => objects.push(object));
37099
- return objects;
37121
+ return objects.filter((object) => object.userData.handle);
37100
37122
  }
37101
- hasObject(object) {
37102
- while (object) {
37103
- if (object === this.scene)
37104
- return true;
37105
- object = object.parent;
37106
- }
37107
- return false;
37108
- }
37109
- hasHandle(handle) {
37110
- return !handle.includes(":") || handle.split(":", 1)[0] === this.id + "";
37111
- }
37112
- getOwnObjects(objects) {
37113
- if (!Array.isArray(objects))
37114
- objects = [objects];
37115
- return objects.filter((object) => this.hasObject(object));
37116
- }
37117
- getOwnHandles(handles) {
37123
+ getObjectsByHandles(handles) {
37118
37124
  if (!Array.isArray(handles))
37119
37125
  handles = [handles];
37120
- return handles.filter((handle) => this.hasHandle(handle));
37121
- }
37122
- getObjectsByHandles(handles) {
37123
- const ownHandles = this.getOwnHandles(handles);
37124
- if (ownHandles.length === 0)
37125
- return [];
37126
- const handleSet = new Set(ownHandles.map((handle) => handle.slice(handle.indexOf(":") + 1)));
37126
+ const ownHandles = [];
37127
+ handles.forEach((handle) => {
37128
+ const index = handle.indexOf(":");
37129
+ if (index !== -1) {
37130
+ if (handle.slice(0, index) !== this.id)
37131
+ return;
37132
+ handle = handle.slice(index + 1);
37133
+ }
37134
+ ownHandles.push(handle);
37135
+ });
37136
+ const handlesSet = new Set(ownHandles);
37127
37137
  const objects = [];
37128
- this.scene.traverse((object) => {
37129
- const handle = object.userData.handle;
37130
- if (handle && handleSet.has(handle))
37131
- objects.push(object);
37138
+ handlesSet.forEach((handle) => {
37139
+ objects.push(Array.from(this.handleToObjects.get(handle) || []));
37132
37140
  });
37133
- return objects;
37141
+ return objects.flat();
37134
37142
  }
37135
37143
  getHandlesByObjects(objects) {
37136
- const ownObjects = this.getOwnObjects(objects);
37137
- if (ownObjects.length === 0)
37138
- return [];
37144
+ if (!Array.isArray(objects))
37145
+ objects = [objects];
37139
37146
  const handleSet = new Set();
37140
- ownObjects.forEach((object) => {
37141
- const handle = object.userData.handle;
37142
- if (handle)
37143
- handleSet.add(`${this.id}:${handle}`);
37147
+ objects
37148
+ .filter((object) => this.originalObjects.has(object))
37149
+ .forEach((object) => {
37150
+ handleSet.add(`${this.id}:${object.userData.handle}`);
37144
37151
  });
37145
37152
  return Array.from(handleSet);
37146
37153
  }
37147
37154
  hideObjects(objects) {
37148
- this.getOwnObjects(objects).forEach((object) => (object.visible = false));
37155
+ if (!Array.isArray(objects))
37156
+ objects = [objects];
37157
+ objects
37158
+ .filter((object) => this.originalObjects.has(object))
37159
+ .forEach((object) => {
37160
+ object.visible = false;
37161
+ });
37149
37162
  return this;
37150
37163
  }
37151
37164
  hideAllObjects() {
@@ -37155,12 +37168,20 @@ void main() {
37155
37168
  if (!Array.isArray(objects))
37156
37169
  objects = [objects];
37157
37170
  const visibleSet = new Set(objects);
37158
- this.getOwnObjects(objects).forEach((object) => object.traverseAncestors((parent) => visibleSet.add(parent)));
37171
+ objects
37172
+ .filter((object) => this.originalObjects.has(object))
37173
+ .forEach((object) => {
37174
+ object.traverseAncestors((parent) => visibleSet.add(parent));
37175
+ });
37159
37176
  this.scene.traverse((object) => (object.visible = visibleSet.has(object)));
37160
37177
  return this;
37161
37178
  }
37162
37179
  showObjects(objects) {
37163
- this.getOwnObjects(objects).forEach((object) => {
37180
+ if (!Array.isArray(objects))
37181
+ objects = [objects];
37182
+ objects
37183
+ .filter((object) => this.originalObjects.has(object))
37184
+ .forEach((object) => {
37164
37185
  object.visible = true;
37165
37186
  object.traverseAncestors((parent) => (parent.visible = true));
37166
37187
  });
@@ -37170,36 +37191,55 @@ void main() {
37170
37191
  this.scene.traverse((object) => (object.visible = true));
37171
37192
  return this;
37172
37193
  }
37173
- showOriginalObjects(objects) {
37194
+ highlightObjects(objects) {
37174
37195
  return this;
37175
37196
  }
37176
- hideOriginalObjects(objects) {
37197
+ unhighlightObjects(objects) {
37177
37198
  return this;
37178
37199
  }
37179
37200
  explode(scale = 0, coeff = 4) {
37201
+ const centers = new Map();
37202
+ const getObjectCenter = (object, target) => {
37203
+ const extents = new Box3().setFromObject(object);
37204
+ const handle = object.userData.handle;
37205
+ if (!handle)
37206
+ return extents.getCenter(target);
37207
+ const center = centers.get(handle);
37208
+ if (center)
37209
+ return target.copy(center);
37210
+ const objects = this.getObjectsByHandles(handle);
37211
+ objects.forEach((x) => extents.expandByObject(x));
37212
+ extents.getCenter(target);
37213
+ centers.set(handle, target.clone());
37214
+ return target;
37215
+ };
37180
37216
  function calcExplodeDepth(object, depth) {
37181
- let res = depth;
37217
+ let result = depth;
37182
37218
  object.children.forEach((x) => {
37183
37219
  const objectDepth = calcExplodeDepth(x, depth + 1);
37184
- if (res < objectDepth)
37185
- res = objectDepth;
37220
+ if (result < objectDepth)
37221
+ result = objectDepth;
37186
37222
  });
37187
37223
  object.userData.originalPosition = object.position.clone();
37188
- object.userData.originalCenter = new Box3().setFromObject(object).getCenter(new Vector3());
37189
- object.userData.isExplodeLocked = depth > 2 && object.children.length === 0;
37190
- return res;
37191
- }
37192
- scale /= 100;
37193
- if (!this.scene.userData.explodeDepth)
37194
- this.scene.userData.explodeDepth = calcExplodeDepth(this.scene, 1);
37195
- const maxDepth = this.scene.userData.explodeDepth;
37196
- const scaledExplodeDepth = scale * maxDepth + 1;
37224
+ object.userData.originalCenter = getObjectCenter(object, new Vector3());
37225
+ return result;
37226
+ }
37227
+ const explodeScale = scale / 100;
37228
+ const explodeRoot = this.scene;
37229
+ if (!explodeRoot.userData.explodeDepth)
37230
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
37231
+ const maxDepth = explodeRoot.userData.explodeDepth;
37232
+ const scaledExplodeDepth = explodeScale * maxDepth + 1;
37197
37233
  const explodeDepth = 0 | scaledExplodeDepth;
37198
37234
  const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
37199
37235
  function explodeObject(object, depth) {
37236
+ if (object.isCamera)
37237
+ return;
37238
+ if (object.userData.isHighlightWireframe)
37239
+ return;
37200
37240
  object.position.copy(object.userData.originalPosition);
37201
- if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
37202
- let objectScale = scale * coeff;
37241
+ if (depth > 0 && depth <= explodeDepth) {
37242
+ let objectScale = explodeScale * coeff;
37203
37243
  if (depth === explodeDepth)
37204
37244
  objectScale *= currentSegmentFraction;
37205
37245
  const parentCenter = object.parent.userData.originalCenter;
@@ -37209,7 +37249,7 @@ void main() {
37209
37249
  }
37210
37250
  object.children.forEach((x) => explodeObject(x, depth + 1));
37211
37251
  }
37212
- explodeObject(this.scene, 0);
37252
+ explodeObject(explodeRoot, 0);
37213
37253
  this.scene.updateMatrixWorld();
37214
37254
  return this;
37215
37255
  }
@@ -37247,29 +37287,24 @@ void main() {
37247
37287
  getVisibleObjects() {
37248
37288
  return this.gltfLoader.getOriginalObjectForSelect();
37249
37289
  }
37250
- hasObject(object) {
37251
- return this.gltfLoader.originalObjects.has(object);
37252
- }
37253
37290
  getObjectsByHandles(handles) {
37254
- const ownHandles = this.getOwnHandles(handles);
37255
- if (ownHandles.length === 0)
37256
- return [];
37257
- const handlesSet = new Set(ownHandles);
37291
+ if (!Array.isArray(handles))
37292
+ handles = [handles];
37293
+ const handlesSet = new Set(handles);
37258
37294
  const objects = [];
37259
37295
  handlesSet.forEach((handle) => {
37260
- objects.push(...this.gltfLoader.getObjectsByHandle(handle));
37296
+ objects.push(this.gltfLoader.getObjectsByHandle(handle));
37261
37297
  });
37262
- return objects;
37298
+ return objects.flat();
37263
37299
  }
37264
37300
  getHandlesByObjects(objects) {
37265
- const ownObjects = this.getOwnObjects(objects);
37266
- if (ownObjects.length === 0)
37267
- return [];
37301
+ if (!Array.isArray(objects))
37302
+ objects = [objects];
37268
37303
  const handleSet = new Set();
37269
- ownObjects.forEach((object) => {
37270
- const handle = object.userData.handle;
37271
- if (handle)
37272
- handleSet.add(handle);
37304
+ objects
37305
+ .filter((object) => this.gltfLoader.originalObjects.has(object))
37306
+ .forEach((object) => {
37307
+ handleSet.add(object.userData.handle);
37273
37308
  });
37274
37309
  return Array.from(handleSet);
37275
37310
  }
@@ -37292,14 +37327,78 @@ void main() {
37292
37327
  this.gltfLoader.showAllHiddenObjects();
37293
37328
  return this;
37294
37329
  }
37295
- showOriginalObjects(objects) {
37330
+ highlightObjects(objects) {
37296
37331
  this.gltfLoader.showOriginalObjects(objects);
37297
37332
  return this;
37298
37333
  }
37299
- hideOriginalObjects(objects) {
37334
+ unhighlightObjects(objects) {
37300
37335
  this.gltfLoader.hideOriginalObjects(objects);
37301
37336
  return this;
37302
37337
  }
37338
+ explode(scale = 0, coeff = 4) {
37339
+ const centers = new Map();
37340
+ const calcObjectCenter = (object, target) => {
37341
+ const extents = new Box3().setFromObject(object);
37342
+ const handle = object.userData.handle;
37343
+ if (!handle)
37344
+ return extents.getCenter(target);
37345
+ const center = centers.get(handle);
37346
+ if (center)
37347
+ return target.copy(center);
37348
+ const objects = this.getObjectsByHandles(handle);
37349
+ objects.forEach((x) => extents.expandByObject(x));
37350
+ extents.getCenter(target);
37351
+ centers.set(handle, target.clone());
37352
+ return target;
37353
+ };
37354
+ function calcExplodeDepth(object, depth) {
37355
+ let result = depth;
37356
+ object.children
37357
+ .filter((x) => !x.userData.isOptimized)
37358
+ .forEach((x) => {
37359
+ const objectDepth = calcExplodeDepth(x, depth + 1);
37360
+ if (result < objectDepth)
37361
+ result = objectDepth;
37362
+ });
37363
+ object.userData.originalPosition = object.position.clone();
37364
+ object.userData.originalCenter = calcObjectCenter(object, new Vector3());
37365
+ return result;
37366
+ }
37367
+ const explodeScale = scale / 100;
37368
+ const explodeRoot = this.scene.children[0];
37369
+ if (!explodeRoot.userData.explodeDepth)
37370
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
37371
+ const maxDepth = explodeRoot.userData.explodeDepth;
37372
+ const scaledExplodeDepth = explodeScale * maxDepth + 1;
37373
+ const explodeDepth = 0 | scaledExplodeDepth;
37374
+ const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
37375
+ const transformMap = new Map();
37376
+ function explodeObject(object, depth) {
37377
+ if (object.isCamera)
37378
+ return;
37379
+ if (object.userData.isHighlightWireframe)
37380
+ return;
37381
+ object.position.copy(object.userData.originalPosition);
37382
+ if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
37383
+ let objectScale = explodeScale * coeff;
37384
+ if (depth === explodeDepth)
37385
+ objectScale *= currentSegmentFraction;
37386
+ const parentCenter = object.parent.userData.originalCenter;
37387
+ const objectCenter = object.userData.originalCenter;
37388
+ const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
37389
+ object.position.add(objectOffset);
37390
+ const matrix = new Matrix4().makeTranslation(objectOffset.x, objectOffset.y, objectOffset.z);
37391
+ transformMap.set(object, matrix);
37392
+ }
37393
+ object.children
37394
+ .filter((x) => !x.userData.isOptimized)
37395
+ .forEach((x) => explodeObject(x, depth + 1));
37396
+ }
37397
+ explodeObject(explodeRoot, 0);
37398
+ this.scene.updateMatrixWorld();
37399
+ this.gltfLoader.applyObjectTransforms(transformMap);
37400
+ return this;
37401
+ }
37303
37402
  }
37304
37403
 
37305
37404
  const GL_COMPONENT_TYPES = {
@@ -37348,7 +37447,7 @@ void main() {
37348
37447
  this.textureCache = new Map();
37349
37448
  this.materialCache = new Map();
37350
37449
  this.uri = "";
37351
- this._nextObjectId = 0;
37450
+ this._nextObjectId = 1;
37352
37451
  this.loadingAborted = false;
37353
37452
  this.criticalError = null;
37354
37453
  }
@@ -37998,8 +38097,6 @@ void main() {
37998
38097
  this.frameDelay = 0;
37999
38098
  this.graphicsObjectLimit = 10000;
38000
38099
  this.totalLoadedObjects = 0;
38001
- this.lastUpdateTime = 0;
38002
- this.updateInterval = 1000;
38003
38100
  this.handleToObjects = new Map();
38004
38101
  this.originalObjects = new Set();
38005
38102
  this.originalObjectsToSelection = new Set();
@@ -38016,6 +38113,8 @@ void main() {
38016
38113
  this.hiddenHandles = new Set();
38017
38114
  this.newOptimizedObjects = new Set();
38018
38115
  this.oldOptimizeObjects = new Set();
38116
+ this.objectTransforms = new Map();
38117
+ this.transformedGeometries = new Map();
38019
38118
  this.activeChunkLoads = 0;
38020
38119
  this.chunkQueue = [];
38021
38120
  this.objectIdToIndex = new Map();
@@ -38673,11 +38772,7 @@ void main() {
38673
38772
  loaded: loadedCount,
38674
38773
  total: totalNodes,
38675
38774
  });
38676
- const currentTime = Date.now();
38677
- if (currentTime - this.lastUpdateTime >= this.updateInterval) {
38678
- this.dispatchEvent("update");
38679
- this.lastUpdateTime = currentTime;
38680
- }
38775
+ this.dispatchEvent("update");
38681
38776
  await new Promise((resolve) => {
38682
38777
  setTimeout(resolve, 0);
38683
38778
  });
@@ -38777,14 +38872,32 @@ void main() {
38777
38872
  if (!node.geometryExtents) continue;
38778
38873
  if (node.object && this.hiddenHandles.has(node.object.userData.handle)) continue;
38779
38874
  const transformedBox = node.geometryExtents.clone();
38780
- if (node.group && node.group.matrix) {
38781
- transformedBox.applyMatrix4(node.group.matrix);
38782
- if (node.group.parent && node.group.parent.matrix) {
38783
- transformedBox.applyMatrix4(node.group.parent.matrix);
38875
+ const structureRoot = node.structure ? this.structureRoots.get(node.structure.id) : null;
38876
+ if (node.group) {
38877
+ const matrices = [];
38878
+ let currentGroup = node.group;
38879
+ while (currentGroup && currentGroup !== structureRoot) {
38880
+ if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
38881
+ matrices.unshift(currentGroup.matrix);
38882
+ }
38883
+ currentGroup = currentGroup.parent;
38884
+ }
38885
+ for (const matrix of matrices) {
38886
+ transformedBox.applyMatrix4(matrix);
38784
38887
  }
38785
38888
  }
38889
+ if (structureRoot && structureRoot.matrix) {
38890
+ transformedBox.applyMatrix4(structureRoot.matrix);
38891
+ }
38892
+ const transform = this.objectTransforms.get(node.object);
38893
+ if (transform) {
38894
+ transformedBox.applyMatrix4(transform);
38895
+ }
38786
38896
  totalExtent.union(transformedBox);
38787
38897
  }
38898
+ if (this.scene && this.scene.matrix && !totalExtent.isEmpty()) {
38899
+ totalExtent.applyMatrix4(this.scene.matrix);
38900
+ }
38788
38901
  return totalExtent;
38789
38902
  }
38790
38903
  loadCamera(structure, cameraIndex, nodeDef) {
@@ -38860,7 +38973,6 @@ void main() {
38860
38973
  for (let i = 0; i < this.maxObjectId; i++) {
38861
38974
  this.objectVisibility[i] = 1.0;
38862
38975
  }
38863
- console.log(`Initialized object visibility array: ${this.maxObjectId} objects`);
38864
38976
  }
38865
38977
  }
38866
38978
  createVisibilityMaterial(material) {
@@ -38997,8 +39109,9 @@ void main() {
38997
39109
  this.newOptimizedObjects.clear();
38998
39110
  this.oldOptimizeObjects.clear();
38999
39111
  this.isolatedObjects = [];
39112
+ this.objectTransforms.clear();
39113
+ this.transformedGeometries.clear();
39000
39114
  this.totalLoadedObjects = 0;
39001
- this.lastUpdateTime = 0;
39002
39115
  this.currentMemoryUsage = 0;
39003
39116
  this.loadedGeometrySize = 0;
39004
39117
  this.abortController = new AbortController();
@@ -39109,9 +39222,7 @@ void main() {
39109
39222
  }
39110
39223
  yieldToUI() {
39111
39224
  return new Promise((resolve) => {
39112
- requestAnimationFrame(() => {
39113
- setTimeout(resolve, 0);
39114
- });
39225
+ setTimeout(resolve, 0);
39115
39226
  });
39116
39227
  }
39117
39228
  async optimizeScene() {
@@ -39694,6 +39805,171 @@ void main() {
39694
39805
  mergedObject.geometry.attributes.visibility.needsUpdate = true;
39695
39806
  }
39696
39807
  }
39808
+ applyObjectTransforms(objectTransformMap) {
39809
+ if (this.mergedObjectMap.size === 0) {
39810
+ console.warn("No merged objects to transform");
39811
+ return;
39812
+ }
39813
+ this.objectTransforms = new Map(objectTransformMap);
39814
+ for (const mesh of this.mergedMesh) {
39815
+ this._applyTransformToMergedObject(mesh);
39816
+ }
39817
+ for (const line of this.mergedLines) {
39818
+ this._applyTransformToMergedObject(line);
39819
+ }
39820
+ for (const lineSegment of this.mergedLineSegments) {
39821
+ this._applyTransformToMergedObject(lineSegment);
39822
+ }
39823
+ for (const point of this.mergedPoints) {
39824
+ this._applyTransformToMergedObject(point);
39825
+ }
39826
+ }
39827
+ createExplodeTransforms(objects = null, explodeCenter = null, explodeFactor = 1.5) {
39828
+ const transformMap = new Map();
39829
+ if (!explodeCenter) {
39830
+ explodeCenter = new Vector3();
39831
+ const extent = this.getTotalGeometryExtent();
39832
+ if (!extent.isEmpty()) {
39833
+ extent.getCenter(explodeCenter);
39834
+ }
39835
+ }
39836
+ const objectsArray = objects
39837
+ ? Array.isArray(objects)
39838
+ ? objects
39839
+ : Array.from(objects)
39840
+ : Array.from(this.originalObjects);
39841
+ for (const obj of objectsArray) {
39842
+ if (!obj.geometry || !obj.geometry.attributes.position) continue;
39843
+ const boundingBox = new Box3().setFromBufferAttribute(obj.geometry.attributes.position);
39844
+ if (obj.matrixWorld) {
39845
+ boundingBox.applyMatrix4(obj.matrixWorld);
39846
+ }
39847
+ if (boundingBox.isEmpty()) continue;
39848
+ const objectCenter = new Vector3();
39849
+ boundingBox.getCenter(objectCenter);
39850
+ const direction = objectCenter.clone().sub(explodeCenter);
39851
+ const distance = direction.length();
39852
+ if (distance > 0) {
39853
+ direction.normalize();
39854
+ const offset = direction.multiplyScalar(distance * (explodeFactor - 1.0));
39855
+ const matrix = new Matrix4().makeTranslation(offset.x, offset.y, offset.z);
39856
+ transformMap.set(obj, matrix);
39857
+ }
39858
+ }
39859
+ return transformMap;
39860
+ }
39861
+ clearTransforms() {
39862
+ this.objectTransforms.clear();
39863
+ for (const mesh of this.mergedMesh) {
39864
+ this._restoreOriginalGeometry(mesh);
39865
+ }
39866
+ for (const line of this.mergedLines) {
39867
+ this._restoreOriginalGeometry(line);
39868
+ }
39869
+ for (const lineSegment of this.mergedLineSegments) {
39870
+ this._restoreOriginalGeometry(lineSegment);
39871
+ }
39872
+ for (const point of this.mergedPoints) {
39873
+ this._restoreOriginalGeometry(point);
39874
+ }
39875
+ }
39876
+ clearHandleTransforms() {
39877
+ this.clearTransforms();
39878
+ }
39879
+ _applyTransformToMergedObject(mergedObject) {
39880
+ const objectData = this.mergedObjectMap.get(mergedObject.uuid);
39881
+ if (!objectData || !objectData.objectMapping) return;
39882
+ const geometry = mergedObject.geometry;
39883
+ if (!geometry || !geometry.attributes.position) return;
39884
+ const positionAttr = geometry.attributes.position;
39885
+ const positions = positionAttr.array;
39886
+ if (!this.transformedGeometries.has(mergedObject.uuid)) {
39887
+ this.transformedGeometries.set(mergedObject.uuid, new Float32Array(positions));
39888
+ }
39889
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
39890
+ const tempVector = new Vector3();
39891
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
39892
+ const transform = this.objectTransforms.get(originalMesh);
39893
+ if (!transform) {
39894
+ const startIdx = mappingData.startVertexIndex * 3;
39895
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
39896
+ for (let i = startIdx; i < endIdx; i++) {
39897
+ positions[i] = originalPositions[i];
39898
+ }
39899
+ continue;
39900
+ }
39901
+ const startVertex = mappingData.startVertexIndex;
39902
+ const vertexCount = mappingData.vertexCount;
39903
+ for (let i = 0; i < vertexCount; i++) {
39904
+ const idx = (startVertex + i) * 3;
39905
+ tempVector.set(originalPositions[idx], originalPositions[idx + 1], originalPositions[idx + 2]);
39906
+ tempVector.applyMatrix4(transform);
39907
+ positions[idx] = tempVector.x;
39908
+ positions[idx + 1] = tempVector.y;
39909
+ positions[idx + 2] = tempVector.z;
39910
+ }
39911
+ }
39912
+ if (geometry.attributes.normal) {
39913
+ this._updateNormalsForTransform(geometry, objectData, originalPositions);
39914
+ }
39915
+ positionAttr.needsUpdate = true;
39916
+ geometry.computeBoundingSphere();
39917
+ geometry.computeBoundingBox();
39918
+ }
39919
+ _updateNormalsForTransform(geometry, objectData, originalPositions) {
39920
+ const normalAttr = geometry.attributes.normal;
39921
+ if (!normalAttr) return;
39922
+ const normals = normalAttr.array;
39923
+ const tempVector = new Vector3();
39924
+ const normalMatrix = new Matrix4();
39925
+ const normalsKey = `${geometry.uuid}_normals`;
39926
+ if (!this.transformedGeometries.has(normalsKey)) {
39927
+ this.transformedGeometries.set(normalsKey, new Float32Array(normals));
39928
+ }
39929
+ const originalNormals = this.transformedGeometries.get(normalsKey);
39930
+ for (const [originalMesh, mappingData] of objectData.objectMapping) {
39931
+ const transform = this.objectTransforms.get(originalMesh);
39932
+ if (!transform) {
39933
+ const startIdx = mappingData.startVertexIndex * 3;
39934
+ const endIdx = (mappingData.startVertexIndex + mappingData.vertexCount) * 3;
39935
+ for (let i = startIdx; i < endIdx; i++) {
39936
+ normals[i] = originalNormals[i];
39937
+ }
39938
+ continue;
39939
+ }
39940
+ normalMatrix.copy(transform).invert().transpose();
39941
+ const startVertex = mappingData.startVertexIndex;
39942
+ const vertexCount = mappingData.vertexCount;
39943
+ for (let i = 0; i < vertexCount; i++) {
39944
+ const idx = (startVertex + i) * 3;
39945
+ tempVector.set(originalNormals[idx], originalNormals[idx + 1], originalNormals[idx + 2]);
39946
+ tempVector.applyMatrix4(normalMatrix).normalize();
39947
+ normals[idx] = tempVector.x;
39948
+ normals[idx + 1] = tempVector.y;
39949
+ normals[idx + 2] = tempVector.z;
39950
+ }
39951
+ }
39952
+ normalAttr.needsUpdate = true;
39953
+ }
39954
+ _restoreOriginalGeometry(mergedObject) {
39955
+ const geometry = mergedObject.geometry;
39956
+ if (!geometry || !geometry.attributes.position) return;
39957
+ const originalPositions = this.transformedGeometries.get(mergedObject.uuid);
39958
+ if (originalPositions) {
39959
+ const positions = geometry.attributes.position.array;
39960
+ positions.set(originalPositions);
39961
+ geometry.attributes.position.needsUpdate = true;
39962
+ }
39963
+ const normalsKey = `${geometry.uuid}_normals`;
39964
+ const originalNormals = this.transformedGeometries.get(normalsKey);
39965
+ if (originalNormals && geometry.attributes.normal) {
39966
+ const normals = geometry.attributes.normal.array;
39967
+ normals.set(originalNormals);
39968
+ geometry.attributes.normal.needsUpdate = true;
39969
+ }
39970
+ geometry.computeBoundingSphere();
39971
+ geometry.computeBoundingBox();
39972
+ }
39697
39973
  syncHiddenObjects() {
39698
39974
  if (this.mergedObjectMap.size === 0) {
39699
39975
  console.log("No merged objects to sync");
@@ -39725,19 +40001,33 @@ void main() {
39725
40001
  }
39726
40002
  getStructureGeometryExtent(structureId) {
39727
40003
  const extent = new Box3();
40004
+ const structureRoot = this.structureRoots.get(structureId);
39728
40005
  for (const [nodeId, node] of this.nodes.entries()) {
39729
40006
  if (!node.geometryExtents) continue;
39730
40007
  if (!nodeId.startsWith(structureId + "_")) continue;
39731
40008
  if (node.object && this.hiddenHandles && this.hiddenHandles.has(node.object.userData.handle)) continue;
39732
40009
  const transformedBox = node.geometryExtents.clone();
39733
- if (node.group && node.group.matrix) {
39734
- transformedBox.applyMatrix4(node.group.matrix);
39735
- if (node.group.parent && node.group.parent.matrix) {
39736
- transformedBox.applyMatrix4(node.group.parent.matrix);
40010
+ if (node.group) {
40011
+ const matrices = [];
40012
+ let currentGroup = node.group;
40013
+ while (currentGroup && currentGroup !== structureRoot) {
40014
+ if (currentGroup.matrix && currentGroup.matrixAutoUpdate === false) {
40015
+ matrices.unshift(currentGroup.matrix);
40016
+ }
40017
+ currentGroup = currentGroup.parent;
39737
40018
  }
40019
+ for (const matrix of matrices) {
40020
+ transformedBox.applyMatrix4(matrix);
40021
+ }
40022
+ }
40023
+ if (structureRoot && structureRoot.matrix) {
40024
+ transformedBox.applyMatrix4(structureRoot.matrix);
39738
40025
  }
39739
40026
  extent.union(transformedBox);
39740
40027
  }
40028
+ if (this.scene && this.scene.matrix && !extent.isEmpty()) {
40029
+ extent.applyMatrix4(this.scene.matrix);
40030
+ }
39741
40031
  return extent;
39742
40032
  }
39743
40033
  setMaxConcurrentChunks(maxChunks) {
@@ -54403,7 +54693,7 @@ js: import "konva/skia-backend";
54403
54693
  }
54404
54694
  getViewpoint(viewpoint) {
54405
54695
  if (!viewpoint)
54406
- viewpoint = {};
54696
+ viewpoint = { custom_fields: {} };
54407
54697
  viewpoint.lines = this.getMarkupLines();
54408
54698
  viewpoint.texts = this.getMarkupTexts();
54409
54699
  viewpoint.arrows = this.getMarkupArrows();
@@ -54411,8 +54701,8 @@ js: import "konva/skia-backend";
54411
54701
  viewpoint.ellipses = this.getMarkupEllipses();
54412
54702
  viewpoint.images = this.getMarkupImages();
54413
54703
  viewpoint.rectangles = this.getMarkupRectangles();
54414
- viewpoint.custom_fields = { markup_color: this.getMarkupColor() };
54415
54704
  viewpoint.snapshot = { data: this.combineMarkupWithDrawing() };
54705
+ viewpoint.custom_fields.markup_color = this.getMarkupColor();
54416
54706
  return viewpoint;
54417
54707
  }
54418
54708
  enableEditMode(mode) {
@@ -55100,6 +55390,7 @@ js: import "konva/skia-backend";
55100
55390
  this.target = new Vector3(0, 0, 0);
55101
55391
  this._activeDragger = null;
55102
55392
  this._components = [];
55393
+ this._updateDelay = 1000;
55103
55394
  this._renderNeeded = false;
55104
55395
  this._renderTime = 0;
55105
55396
  this.render = this.render.bind(this);
@@ -55123,8 +55414,8 @@ js: import "konva/skia-backend";
55123
55414
  const rect = canvas.parentElement.getBoundingClientRect();
55124
55415
  const width = rect.width || 1;
55125
55416
  const height = rect.height || 1;
55126
- const aspect = width / height;
55127
- this.camera = new PerspectiveCamera(45, aspect, 0.001, 1000);
55417
+ const aspectRatio = width / height;
55418
+ this.camera = new PerspectiveCamera(45, aspectRatio, 0.001, 1000);
55128
55419
  this.camera.up.set(0, 1, 0);
55129
55420
  this.camera.position.set(0, 0, 1);
55130
55421
  this.camera.lookAt(this.target);
@@ -55221,14 +55512,14 @@ js: import "konva/skia-backend";
55221
55512
  if (!this.renderer)
55222
55513
  return;
55223
55514
  const camera = this.camera;
55224
- const aspect = width / height;
55515
+ const aspectRatio = width / height;
55225
55516
  if (camera.isPerspectiveCamera) {
55226
- camera.aspect = aspect;
55517
+ camera.aspect = aspectRatio;
55227
55518
  camera.updateProjectionMatrix();
55228
55519
  }
55229
55520
  if (camera.isOrthographicCamera) {
55230
- camera.left = camera.bottom * aspect;
55231
- camera.right = camera.top * aspect;
55521
+ camera.left = camera.bottom * aspectRatio;
55522
+ camera.right = camera.top * aspectRatio;
55232
55523
  camera.updateProjectionMatrix();
55233
55524
  }
55234
55525
  this.renderer.setSize(width, height, updateStyle);
@@ -55237,16 +55528,18 @@ js: import "konva/skia-backend";
55237
55528
  this.emitEvent({ type: "resize", width, height });
55238
55529
  }
55239
55530
  update(force = false) {
55531
+ const time = performance.now();
55532
+ force = force || time - this._renderTime >= this._updateDelay;
55240
55533
  this._renderNeeded = true;
55241
55534
  if (force)
55242
- this.render();
55243
- this.emitEvent({ type: "update", data: force });
55535
+ this.render(time);
55536
+ this.emitEvent({ type: "update", force });
55244
55537
  }
55245
- render(time, force = false) {
55538
+ render(time) {
55246
55539
  var _a, _b;
55247
55540
  if (!this.renderer)
55248
55541
  return;
55249
- if (!this._renderNeeded && !force)
55542
+ if (!this._renderNeeded)
55250
55543
  return;
55251
55544
  if (!time)
55252
55545
  time = performance.now();
@@ -55455,12 +55748,12 @@ js: import "konva/skia-backend";
55455
55748
  if (orthogonal_camera) {
55456
55749
  const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
55457
55750
  const rendererSize = this.renderer.getSize(new Vector2());
55458
- const aspect = rendererSize.x / rendererSize.y;
55751
+ const aspectRatio = rendererSize.x / rendererSize.y;
55459
55752
  const camera = new OrthographicCamera();
55460
55753
  camera.top = orthogonal_camera.field_height / 2;
55461
55754
  camera.bottom = -orthogonal_camera.field_height / 2;
55462
- camera.left = camera.bottom * aspect;
55463
- camera.right = camera.top * aspect;
55755
+ camera.left = camera.bottom * aspectRatio;
55756
+ camera.right = camera.top * aspectRatio;
55464
55757
  camera.near = 0;
55465
55758
  camera.far = extentsSize * 1000;
55466
55759
  camera.zoom = orthogonal_camera.view_to_world_scale;
@@ -55473,6 +55766,7 @@ js: import "konva/skia-backend";
55473
55766
  this.renderPass.camera = camera;
55474
55767
  this.helpersPass.camera = camera;
55475
55768
  this.ssaaRenderPass.camera = camera;
55769
+ this.options.cameraMode = "orthographic";
55476
55770
  this.emitEvent({ type: "changecameramode", mode: "orthographic" });
55477
55771
  }
55478
55772
  };
@@ -55480,10 +55774,10 @@ js: import "konva/skia-backend";
55480
55774
  if (perspective_camera) {
55481
55775
  const extentsSize = this.extents.getBoundingSphere(new Sphere()).radius * 2;
55482
55776
  const rendererSize = this.renderer.getSize(new Vector2());
55483
- const aspect = rendererSize.x / rendererSize.y;
55777
+ const aspectRatio = rendererSize.x / rendererSize.y;
55484
55778
  const camera = new PerspectiveCamera();
55485
55779
  camera.fov = perspective_camera.field_of_view;
55486
- camera.aspect = aspect;
55780
+ camera.aspect = aspectRatio;
55487
55781
  camera.near = extentsSize / 1000;
55488
55782
  camera.far = extentsSize * 1000;
55489
55783
  camera.updateProjectionMatrix();
@@ -55495,6 +55789,7 @@ js: import "konva/skia-backend";
55495
55789
  this.renderPass.camera = camera;
55496
55790
  this.helpersPass.camera = camera;
55497
55791
  this.ssaaRenderPass.camera = camera;
55792
+ this.options.cameraMode = "perspective";
55498
55793
  this.emitEvent({ type: "changecameramode", mode: "perspective" });
55499
55794
  }
55500
55795
  };
@@ -55524,6 +55819,7 @@ js: import "konva/skia-backend";
55524
55819
  setSelection(((_b = viewpoint.custom_fields) === null || _b === void 0 ? void 0 : _b.selection2) || viewpoint.selection);
55525
55820
  this._markup.setViewpoint(viewpoint);
55526
55821
  this.target.copy(getVector3FromPoint3d((_d = (_c = viewpoint.custom_fields) === null || _c === void 0 ? void 0 : _c.camera_target) !== null && _d !== void 0 ? _d : this.target));
55822
+ this.syncOverlay();
55527
55823
  this.setActiveDragger(draggerName);
55528
55824
  this.emitEvent({ type: "drawviewpoint", data: viewpoint });
55529
55825
  this.update();