@inweb/viewer-three 26.10.6 → 26.11.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 (143) hide show
  1. package/README.md +7 -4
  2. package/dist/{plugins → extensions}/components/AxesHelperComponent.js +23 -1
  3. package/dist/extensions/components/AxesHelperComponent.js.map +1 -0
  4. package/dist/extensions/components/AxesHelperComponent.min.js +24 -0
  5. package/dist/{plugins → extensions}/components/AxesHelperComponent.module.js +24 -2
  6. package/dist/extensions/components/AxesHelperComponent.module.js.map +1 -0
  7. package/dist/{plugins → extensions}/components/ExtentsHelperComponent.js +18 -0
  8. package/dist/extensions/components/ExtentsHelperComponent.js.map +1 -0
  9. package/dist/{plugins/components/AxesHelperComponent.min.js → extensions/components/ExtentsHelperComponent.min.js} +1 -1
  10. package/dist/{plugins → extensions}/components/ExtentsHelperComponent.module.js +19 -1
  11. package/dist/extensions/components/ExtentsHelperComponent.module.js.map +1 -0
  12. package/dist/extensions/components/GridHelperComponent.js.map +1 -0
  13. package/dist/extensions/components/GridHelperComponent.module.js.map +1 -0
  14. package/dist/extensions/components/LightHelperComponent.js.map +1 -0
  15. package/dist/extensions/components/LightHelperComponent.module.js.map +1 -0
  16. package/dist/extensions/components/RoomEnvironmentComponent.js.map +1 -0
  17. package/dist/extensions/components/RoomEnvironmentComponent.module.js.map +1 -0
  18. package/dist/extensions/components/StatsPanelComponent.js.map +1 -0
  19. package/dist/extensions/components/StatsPanelComponent.module.js.map +1 -0
  20. package/dist/{plugins → extensions}/loaders/GLTFCloudLoader.js +2 -3
  21. package/dist/extensions/loaders/GLTFCloudLoader.js.map +1 -0
  22. package/dist/{plugins → extensions}/loaders/GLTFCloudLoader.min.js +1 -1
  23. package/dist/{plugins → extensions}/loaders/GLTFCloudLoader.module.js +2 -3
  24. package/dist/extensions/loaders/GLTFCloudLoader.module.js.map +1 -0
  25. package/dist/extensions/loaders/GLTFFileLoader.js +2499 -0
  26. package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -0
  27. package/dist/extensions/loaders/GLTFFileLoader.min.js +24 -0
  28. package/dist/extensions/loaders/GLTFFileLoader.module.js +74 -0
  29. package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -0
  30. package/dist/{plugins → extensions}/loaders/IFCXLoader.js +5 -7
  31. package/dist/extensions/loaders/IFCXLoader.js.map +1 -0
  32. package/dist/{plugins → extensions}/loaders/IFCXLoader.min.js +1 -1
  33. package/dist/{plugins → extensions}/loaders/IFCXLoader.module.js +5 -7
  34. package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -0
  35. package/dist/{plugins → extensions}/loaders/PotreeLoader.js +1 -2
  36. package/dist/extensions/loaders/PotreeLoader.js.map +1 -0
  37. package/dist/{plugins → extensions}/loaders/PotreeLoader.min.js +1 -1
  38. package/dist/{plugins → extensions}/loaders/PotreeLoader.module.js +1 -2
  39. package/dist/extensions/loaders/PotreeLoader.module.js.map +1 -0
  40. package/dist/viewer-three.js +1015 -2926
  41. package/dist/viewer-three.js.map +1 -1
  42. package/dist/viewer-three.min.js +3 -3
  43. package/dist/viewer-three.module.js +847 -356
  44. package/dist/viewer-three.module.js.map +1 -1
  45. package/{plugins → extensions}/components/AxesHelperComponent.ts +31 -2
  46. package/{plugins → extensions}/components/ExtentsHelperComponent.ts +25 -0
  47. package/{plugins → extensions}/loaders/GLTFCloudLoader.ts +2 -3
  48. package/{src/Viewer → extensions}/loaders/GLTFFileLoader.ts +21 -12
  49. package/{plugins → extensions}/loaders/IFCX/IFCXCloudLoader.ts +5 -5
  50. package/{plugins → extensions}/loaders/IFCX/IFCXFileLoader.ts +3 -4
  51. package/{plugins → extensions}/loaders/Potree/PotreeFileLoader.ts +3 -4
  52. package/lib/Viewer/Viewer.d.ts +27 -20
  53. package/lib/Viewer/commands/GetSelected2.d.ts +2 -0
  54. package/lib/Viewer/commands/SelectModel.d.ts +1 -1
  55. package/lib/Viewer/commands/SetSelected2.d.ts +2 -0
  56. package/lib/Viewer/components/SelectionComponent.d.ts +1 -3
  57. package/lib/Viewer/components/index.d.ts +6 -6
  58. package/lib/Viewer/draggers/MeasureLineDragger.d.ts +7 -1
  59. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +0 -1
  60. package/lib/Viewer/loaders/GLTFBinaryExtension.d.ts +5 -0
  61. package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +2 -2
  62. package/lib/Viewer/loaders/{GLTFFileLoader.d.ts → GLTFFileDynamicLoader.d.ts} +7 -1
  63. package/lib/Viewer/loaders/GLTFLoadingManager.d.ts +4 -3
  64. package/lib/Viewer/loaders/RangesLoader.d.ts +15 -0
  65. package/lib/Viewer/loaders/index.d.ts +22 -14
  66. package/lib/Viewer/measurement/Snapper.d.ts +15 -0
  67. package/lib/Viewer/measurement/UnitConverter.d.ts +63 -0
  68. package/lib/Viewer/measurement/UnitFormatter.d.ts +4 -0
  69. package/lib/Viewer/models/IModelImpl.d.ts +10 -8
  70. package/lib/Viewer/models/ModelImpl.d.ts +7 -5
  71. package/package.json +11 -11
  72. package/src/Viewer/Viewer.ts +120 -88
  73. package/src/Viewer/commands/ClearSelected.ts +3 -1
  74. package/src/Viewer/commands/GetModels.ts +1 -1
  75. package/src/Viewer/commands/GetSelected.ts +2 -2
  76. package/src/Viewer/commands/GetSelected2.ts +34 -0
  77. package/src/Viewer/commands/HideSelected.ts +3 -1
  78. package/src/Viewer/commands/SelectModel.ts +5 -5
  79. package/src/Viewer/commands/SetSelected.ts +9 -10
  80. package/src/Viewer/commands/SetSelected2.ts +42 -0
  81. package/src/Viewer/commands/ZoomToObjects.ts +5 -6
  82. package/src/Viewer/commands/ZoomToSelected.ts +3 -1
  83. package/src/Viewer/commands/index.ts +4 -0
  84. package/src/Viewer/components/CameraComponent.ts +6 -1
  85. package/src/Viewer/components/ExtentsComponent.ts +4 -1
  86. package/src/Viewer/components/SelectionComponent.ts +7 -30
  87. package/src/Viewer/components/index.ts +6 -6
  88. package/src/Viewer/draggers/MeasureLineDragger.ts +84 -226
  89. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +263 -34
  90. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +20 -10
  91. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +4 -1
  92. package/src/Viewer/loaders/GLTFBinaryExtension.ts +91 -0
  93. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +13 -19
  94. package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +145 -0
  95. package/src/Viewer/loaders/GLTFLoadingManager.ts +5 -4
  96. package/src/Viewer/loaders/RangesLoader.ts +95 -0
  97. package/src/Viewer/loaders/index.ts +24 -16
  98. package/src/Viewer/measurement/Snapper.ts +208 -0
  99. package/src/Viewer/measurement/UnitConverter.ts +47 -0
  100. package/src/Viewer/measurement/UnitFormatter.ts +95 -0
  101. package/src/Viewer/models/IModelImpl.ts +15 -8
  102. package/src/Viewer/models/ModelImpl.ts +48 -17
  103. package/src/index-umd.ts +1 -1
  104. package/dist/plugins/components/AxesHelperComponent.js.map +0 -1
  105. package/dist/plugins/components/AxesHelperComponent.module.js.map +0 -1
  106. package/dist/plugins/components/ExtentsHelperComponent.js.map +0 -1
  107. package/dist/plugins/components/ExtentsHelperComponent.min.js +0 -24
  108. package/dist/plugins/components/ExtentsHelperComponent.module.js.map +0 -1
  109. package/dist/plugins/components/GridHelperComponent.js.map +0 -1
  110. package/dist/plugins/components/GridHelperComponent.module.js.map +0 -1
  111. package/dist/plugins/components/LightHelperComponent.js.map +0 -1
  112. package/dist/plugins/components/LightHelperComponent.module.js.map +0 -1
  113. package/dist/plugins/components/RoomEnvironmentComponent.js.map +0 -1
  114. package/dist/plugins/components/RoomEnvironmentComponent.module.js.map +0 -1
  115. package/dist/plugins/components/StatsPanelComponent.js.map +0 -1
  116. package/dist/plugins/components/StatsPanelComponent.module.js.map +0 -1
  117. package/dist/plugins/loaders/GLTFCloudLoader.js.map +0 -1
  118. package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +0 -1
  119. package/dist/plugins/loaders/IFCXLoader.js.map +0 -1
  120. package/dist/plugins/loaders/IFCXLoader.module.js.map +0 -1
  121. package/dist/plugins/loaders/PotreeLoader.js.map +0 -1
  122. package/dist/plugins/loaders/PotreeLoader.module.js.map +0 -1
  123. /package/dist/{plugins → extensions}/components/GridHelperComponent.js +0 -0
  124. /package/dist/{plugins → extensions}/components/GridHelperComponent.min.js +0 -0
  125. /package/dist/{plugins → extensions}/components/GridHelperComponent.module.js +0 -0
  126. /package/dist/{plugins → extensions}/components/LightHelperComponent.js +0 -0
  127. /package/dist/{plugins → extensions}/components/LightHelperComponent.min.js +0 -0
  128. /package/dist/{plugins → extensions}/components/LightHelperComponent.module.js +0 -0
  129. /package/dist/{plugins → extensions}/components/RoomEnvironmentComponent.js +0 -0
  130. /package/dist/{plugins → extensions}/components/RoomEnvironmentComponent.min.js +0 -0
  131. /package/dist/{plugins → extensions}/components/RoomEnvironmentComponent.module.js +0 -0
  132. /package/dist/{plugins → extensions}/components/StatsPanelComponent.js +0 -0
  133. /package/dist/{plugins → extensions}/components/StatsPanelComponent.min.js +0 -0
  134. /package/dist/{plugins → extensions}/components/StatsPanelComponent.module.js +0 -0
  135. /package/{plugins → extensions}/components/GridHelperComponent.ts +0 -0
  136. /package/{plugins → extensions}/components/LightHelperComponent.ts +0 -0
  137. /package/{plugins → extensions}/components/RoomEnvironmentComponent.ts +0 -0
  138. /package/{plugins → extensions}/components/StatsPanelComponent.ts +0 -0
  139. /package/{plugins → extensions}/loaders/IFCX/IFCXLoader.ts +0 -0
  140. /package/{plugins → extensions}/loaders/IFCX/index.ts +0 -0
  141. /package/{plugins → extensions}/loaders/IFCX/render.js +0 -0
  142. /package/{plugins → extensions}/loaders/Potree/PotreeModelImpl.ts +0 -0
  143. /package/{plugins → extensions}/loaders/Potree/index.ts +0 -0
@@ -21,32 +21,24 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import {
25
- Camera,
26
- EdgesGeometry,
27
- Intersection,
28
- Line3,
29
- MathUtils,
30
- Matrix4,
31
- Object3D,
32
- Plane,
33
- Raycaster,
34
- Vector2,
35
- Vector3,
36
- Vector4,
37
- } from "three";
24
+ import { Camera, MathUtils, Matrix4, Object3D, Vector2, Vector3, Vector4 } from "three";
38
25
 
39
26
  import type { Viewer } from "../Viewer";
40
27
  import { OrbitDragger } from "./OrbitDragger";
28
+ import { convertUnits } from "../measurement/UnitConverter";
29
+ import { formatDistance } from "../measurement/UnitFormatter";
30
+ import { Snapper } from "../measurement/Snapper";
41
31
 
42
- const PRECISION = 0.01;
43
- const DESKTOP_SNAP_DISTANCE = 10;
44
- const MOBILE_SNAP_DISTANCE = 50;
32
+ const _downPoint = new Vector2();
45
33
 
46
34
  export class MeasureLineDragger extends OrbitDragger {
47
35
  private overlay: MeasureOverlay;
48
36
  private line: MeasureLine;
49
- private snapper: MeasureSnapper;
37
+ private snapper: Snapper;
38
+ private objects: Object3D[];
39
+ private scale = 1.0;
40
+ private units = "";
41
+ private precision: any = 2;
50
42
 
51
43
  constructor(viewer: Viewer) {
52
44
  super(viewer);
@@ -54,11 +46,15 @@ export class MeasureLineDragger extends OrbitDragger {
54
46
  this.overlay = new MeasureOverlay(viewer.camera, viewer.canvas);
55
47
  this.overlay.attach();
56
48
 
57
- this.line = new MeasureLine(this.overlay);
49
+ this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
58
50
  this.overlay.addLine(this.line);
59
51
 
60
- this.snapper = new MeasureSnapper(viewer.camera, viewer.canvas);
61
- this.updateSnapper();
52
+ this.snapper = new Snapper(viewer.camera, viewer.renderer, viewer.canvas);
53
+
54
+ this.objects = [];
55
+ this.updateObjects();
56
+
57
+ this.updateUnits();
62
58
 
63
59
  this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown);
64
60
  this.viewer.canvas.addEventListener("pointermove", this.onPointerMove);
@@ -67,11 +63,12 @@ export class MeasureLineDragger extends OrbitDragger {
67
63
  this.viewer.canvas.addEventListener("pointerleave", this.onPointerLeave);
68
64
 
69
65
  this.viewer.addEventListener("render", this.renderOverlay);
70
- this.viewer.addEventListener("hide", this.updateSnapper);
71
- this.viewer.addEventListener("isolate", this.updateSnapper);
72
- this.viewer.addEventListener("show", this.updateSnapper);
73
- this.viewer.addEventListener("showall", this.updateSnapper);
66
+ this.viewer.addEventListener("hide", this.updateObjects);
67
+ this.viewer.addEventListener("isolate", this.updateObjects);
68
+ this.viewer.addEventListener("show", this.updateObjects);
69
+ this.viewer.addEventListener("showall", this.updateObjects);
74
70
  this.viewer.addEventListener("changecameramode", this.updateSnapperCamera);
71
+ this.viewer.addEventListener("optionschange", this.updateUnits);
75
72
  }
76
73
 
77
74
  override dispose() {
@@ -82,13 +79,14 @@ export class MeasureLineDragger extends OrbitDragger {
82
79
  this.viewer.canvas.removeEventListener("pointerleave", this.onPointerLeave);
83
80
 
84
81
  this.viewer.removeEventListener("render", this.renderOverlay);
85
- this.viewer.removeEventListener("hide", this.updateSnapper);
86
- this.viewer.removeEventListener("isolate", this.updateSnapper);
87
- this.viewer.removeEventListener("show", this.updateSnapper);
88
- this.viewer.removeEventListener("showall", this.updateSnapper);
82
+ this.viewer.removeEventListener("hide", this.updateObjects);
83
+ this.viewer.removeEventListener("isolate", this.updateObjects);
84
+ this.viewer.removeEventListener("show", this.updateObjects);
85
+ this.viewer.removeEventListener("showall", this.updateObjects);
89
86
  this.viewer.removeEventListener("changecameramode", this.updateSnapperCamera);
87
+ this.viewer.removeEventListener("optionschange", this.updateUnits);
90
88
 
91
- this.snapper.dispose();
89
+ this.objects.length = 0;
92
90
 
93
91
  this.overlay.detach();
94
92
  this.overlay.dispose();
@@ -99,7 +97,8 @@ export class MeasureLineDragger extends OrbitDragger {
99
97
  onPointerDown = (event: PointerEvent) => {
100
98
  if (event.button !== 0) return;
101
99
 
102
- this.line.startPoint = this.snapper.getSnapPoint(event);
100
+ const mouse = this.snapper.getMousePosition(event, _downPoint);
101
+ this.line.startPoint = this.snapper.getSnapPoint(mouse, this.objects);
103
102
  this.line.render();
104
103
 
105
104
  this.viewer.canvas.setPointerCapture(event.pointerId);
@@ -109,7 +108,8 @@ export class MeasureLineDragger extends OrbitDragger {
109
108
  onPointerMove = (event: PointerEvent) => {
110
109
  if (this.orbit.enabled && this.orbit.state !== -1) return;
111
110
 
112
- const snapPoint = this.snapper.getSnapPoint(event);
111
+ const mouse = this.snapper.getMousePosition(event, _downPoint);
112
+ const snapPoint = this.snapper.getSnapPoint(mouse, this.objects);
113
113
  if (snapPoint && this.line.endPoint && snapPoint.equals(this.line.endPoint)) return;
114
114
 
115
115
  this.line.endPoint = snapPoint;
@@ -119,8 +119,8 @@ export class MeasureLineDragger extends OrbitDragger {
119
119
  };
120
120
 
121
121
  onPointerUp = (event: PointerEvent) => {
122
- if (this.line.startPoint && this.line.endPoint && this.line.getDistance() >= PRECISION) {
123
- this.line = new MeasureLine(this.overlay);
122
+ if (this.line.startPoint && this.line.endPoint && this.line.getDistance() > 0) {
123
+ this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
124
124
  this.overlay.addLine(this.line);
125
125
  } else {
126
126
  this.line.startPoint = undefined;
@@ -141,204 +141,50 @@ export class MeasureLineDragger extends OrbitDragger {
141
141
  this.line.render();
142
142
  };
143
143
 
144
+ clearOverlay = () => {
145
+ this.overlay.clear();
146
+
147
+ this.line = new MeasureLine(this.overlay, this.scale, this.units, this.precision);
148
+ this.overlay.addLine(this.line);
149
+ };
150
+
144
151
  renderOverlay = () => {
145
152
  this.overlay.render();
146
153
  };
147
154
 
148
- updateSnapper = () => {
149
- this.snapper.setFromViewer(this.viewer);
155
+ updateObjects = () => {
156
+ this.objects.length = 0;
157
+ this.viewer.models.forEach((model) => {
158
+ model.getVisibleObjects().forEach((object) => this.objects.push(object));
159
+ });
150
160
  };
151
161
 
152
162
  updateSnapperCamera = () => {
153
163
  this.snapper.camera = this.viewer.camera;
154
164
  this.overlay.camera = this.viewer.camera;
155
165
  };
156
- }
157
-
158
- const _vertex = new Vector3();
159
- const _start = new Vector3();
160
- const _end = new Vector3();
161
- const _line = new Line3();
162
- const _center = new Vector3();
163
- const _projection = new Vector3();
164
-
165
- class MeasureSnapper {
166
- public camera: Camera;
167
- private canvas: HTMLCanvasElement;
168
- private objects: Object3D[];
169
- private clippingPlanes: Plane[];
170
- private raycaster: Raycaster;
171
- private detectRadiusInPixels: number;
172
- private edgesCache: WeakMap<any, EdgesGeometry>;
173
-
174
- constructor(camera: Camera, canvas: HTMLCanvasElement) {
175
- this.camera = camera;
176
- this.canvas = canvas;
177
- this.objects = [];
178
- this.clippingPlanes = [];
179
- this.raycaster = new Raycaster();
180
- this.detectRadiusInPixels = this.isMobile() ? MOBILE_SNAP_DISTANCE : DESKTOP_SNAP_DISTANCE;
181
- this.edgesCache = new WeakMap();
182
- }
183
-
184
- dispose() {
185
- this.objects = [];
186
- }
187
-
188
- isMobile(): boolean {
189
- if (typeof navigator === "undefined") return false;
190
-
191
- // ===================== AI-CODE-START ======================
192
- // Source: Claude Sonnet 4
193
- // Date: 2025-09-09
194
- // Reviewer: roman.mochalov@opendesign.com
195
- // Issue: CLOUD-5799
196
-
197
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
198
-
199
- // ===================== AI-CODE-END ======================
200
- }
201
-
202
- getMousePosition(event: MouseEvent, target: Vector2): Vector2 {
203
- return target.set(event.clientX, event.clientY);
204
- }
205
-
206
- getPointerIntersects(mouse: Vector2): Array<Intersection<Object3D>> {
207
- const rect = this.canvas.getBoundingClientRect();
208
- const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
209
- const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
210
-
211
- const coords = new Vector2(x, y);
212
- this.raycaster.setFromCamera(coords, this.camera);
213
-
214
- this.raycaster.params = {
215
- Mesh: {},
216
- Line: { threshold: 0.05 },
217
- Line2: { threshold: 0.05 },
218
- LOD: {},
219
- Points: { threshold: 0.01 },
220
- Sprite: {},
221
- };
222
-
223
- let intersects = this.raycaster.intersectObjects(this.objects, false);
224
-
225
- this.clippingPlanes.forEach((plane) => {
226
- intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
227
- });
228
-
229
- return intersects;
230
- }
231
-
232
- getDetectRadius(point: Vector3): number {
233
- const camera: any = this.camera;
234
-
235
- // ===================== AI-CODE-START ======================
236
- // Source: Gemini 2.5 Pro
237
- // Date: 2025-08-27
238
- // Reviewer: roman.mochalov@opendesign.com
239
- // Issue: CLOUD-5799
240
- // Notes: Originally AI-generated, modified manually
241
166
 
242
- if (camera.isOrthographicCamera) {
243
- const fieldHeight = (camera.top - camera.bottom) / camera.zoom;
167
+ updateUnits = () => {
168
+ const model = this.viewer.models[0];
169
+ const units = this.viewer.options.rulerUnit ?? "Default";
170
+ const precision = this.viewer.options.rulerPrecision ?? "Default";
244
171
 
245
- const canvasHeight = this.canvas.height;
246
- const worldUnitsPerPixel = fieldHeight / canvasHeight;
247
-
248
- return this.detectRadiusInPixels * worldUnitsPerPixel;
249
- }
250
-
251
- if (camera.isPerspectiveCamera) {
252
- const distance = camera.position.distanceTo(point);
253
- const fieldHeight = 2 * Math.tan(MathUtils.degToRad(camera.fov * 0.5)) * distance;
254
-
255
- const canvasHeight = this.canvas.height;
256
- const worldUnitsPerPixel = fieldHeight / canvasHeight;
257
-
258
- return this.detectRadiusInPixels * worldUnitsPerPixel;
259
- }
260
-
261
- // ===================== AI-CODE-END ======================
262
-
263
- return 0.1;
264
- }
265
-
266
- getSnapPoint(event: PointerEvent): Vector3 {
267
- const mouse = this.getMousePosition(event, new Vector2());
268
-
269
- const intersections = this.getPointerIntersects(mouse);
270
- if (intersections.length === 0) return undefined;
271
-
272
- // ===================== AI-CODE-START ======================
273
- // Source: Gemini 2.5 Pro
274
- // Date: 2025-08-20
275
- // Reviewer: roman.mochalov@opendesign.com
276
- // Issue: CLOUD-5799
277
- // Notes: Originally AI-generated, modified manually
278
-
279
- const object: any = intersections[0].object;
280
- const intersectionPoint = intersections[0].point;
281
- const localPoint = object.worldToLocal(intersectionPoint.clone());
282
-
283
- let snapPoint: Vector3;
284
- let snapDistance = this.getDetectRadius(intersectionPoint);
285
-
286
- const geometry = object.geometry;
287
-
288
- const positions = geometry.attributes.position.array;
289
- for (let i = 0; i < positions.length; i += 3) {
290
- _vertex.set(positions[i], positions[i + 1], positions[i + 2]);
291
- const distance = _vertex.distanceTo(localPoint);
292
- if (distance < snapDistance) {
293
- snapDistance = distance;
294
- snapPoint = _vertex.clone();
295
- }
296
- }
297
- if (snapPoint) return object.localToWorld(snapPoint);
298
-
299
- let edges = this.edgesCache.get(geometry);
300
- if (!edges) {
301
- edges = new EdgesGeometry(geometry);
302
- this.edgesCache.set(geometry, edges);
172
+ if (units === "Default") {
173
+ this.scale = model.getUnitScale();
174
+ this.units = model.getUnitString();
175
+ } else {
176
+ this.scale = convertUnits(model.getUnits(), units, 1);
177
+ this.units = units;
303
178
  }
304
179
 
305
- const edgePositions = edges.attributes.position.array;
306
- for (let i = 0; i < edgePositions.length; i += 6) {
307
- _start.set(edgePositions[i], edgePositions[i + 1], edgePositions[i + 2]);
308
- _end.set(edgePositions[i + 3], edgePositions[i + 4], edgePositions[i + 5]);
309
- _line.set(_start, _end);
310
-
311
- _line.getCenter(_center);
312
- const centerDistance = _center.distanceTo(localPoint);
313
- if (centerDistance < snapDistance) {
314
- snapDistance = centerDistance;
315
- snapPoint = _center.clone();
316
- continue;
317
- }
318
-
319
- _line.closestPointToPoint(localPoint, true, _projection);
320
- const lineDistance = _projection.distanceTo(localPoint);
321
- if (lineDistance < snapDistance) {
322
- snapDistance = lineDistance;
323
- snapPoint = _projection.clone();
324
- }
180
+ if (precision === "Default") {
181
+ this.precision = model.getPrecision();
182
+ } else {
183
+ this.precision = precision;
325
184
  }
326
- if (snapPoint) return object.localToWorld(snapPoint);
327
-
328
- // ===================== AI-CODE-END ======================
329
185
 
330
- return intersectionPoint.clone();
331
- }
332
-
333
- setFromViewer(viewer: Viewer) {
334
- this.objects.length = 0;
335
- viewer.models.forEach((model) => {
336
- model.getVisibleObjects().forEach((object) => this.objects.push(object));
337
- });
338
-
339
- this.camera = viewer.camera;
340
- this.clippingPlanes = viewer.renderer.clippingPlanes || [];
341
- }
186
+ this.overlay.updateLineUnits(this.scale, this.units, this.precision);
187
+ };
342
188
  }
343
189
 
344
190
  class MeasureOverlay {
@@ -356,6 +202,10 @@ class MeasureOverlay {
356
202
  this.resizeObserver = new ResizeObserver(this.resizeContainer);
357
203
  }
358
204
 
205
+ dispose() {
206
+ this.clear();
207
+ }
208
+
359
209
  attach() {
360
210
  this.container = document.createElement("div");
361
211
  this.container.id = "measure-container";
@@ -370,10 +220,6 @@ class MeasureOverlay {
370
220
  this.resizeObserver.observe(this.canvas);
371
221
  }
372
222
 
373
- dispose() {
374
- this.clear();
375
- }
376
-
377
223
  detach() {
378
224
  this.resizeObserver.disconnect();
379
225
 
@@ -383,7 +229,7 @@ class MeasureOverlay {
383
229
 
384
230
  clear() {
385
231
  this.lines.forEach((line) => line.dispose());
386
- this.lines = [];
232
+ this.lines.length = 0;
387
233
  }
388
234
 
389
235
  render() {
@@ -403,6 +249,14 @@ class MeasureOverlay {
403
249
  this.lines = this.lines.filter((x) => x !== line);
404
250
  }
405
251
 
252
+ updateLineUnits(scale: number, units: string, precision: any) {
253
+ this.lines.forEach((line) => {
254
+ line.scale = scale;
255
+ line.units = units;
256
+ line.precision = precision;
257
+ });
258
+ }
259
+
406
260
  resizeContainer = () => {
407
261
  const { offsetLeft, offsetTop, offsetWidth, offsetHeight } = this.canvas;
408
262
 
@@ -430,8 +284,9 @@ class MeasureLine {
430
284
  public endPoint: Vector3;
431
285
 
432
286
  public id = MathUtils.generateUUID();
433
- public unit = "";
434
- public scale = 1.0;
287
+ public scale: number;
288
+ public units: string;
289
+ public precision: any;
435
290
  public size = 10.0;
436
291
  public lineWidth = 2;
437
292
 
@@ -443,8 +298,11 @@ class MeasureLine {
443
298
  font: "1rem system-ui",
444
299
  };
445
300
 
446
- constructor(overlay: MeasureOverlay) {
301
+ constructor(overlay: MeasureOverlay, scale: number, units: string, precision: any) {
447
302
  this.overlay = overlay;
303
+ this.scale = scale;
304
+ this.units = units;
305
+ this.precision = precision;
448
306
 
449
307
  this.elementStartPoint = overlay.container.appendChild(document.createElement("div"));
450
308
  this.elementEndPoint = overlay.container.appendChild(document.createElement("div"));
@@ -511,10 +369,10 @@ class MeasureLine {
511
369
 
512
370
  const distance = this.getDistance();
513
371
 
514
- this.elementLabel.style.display = visible && distance >= PRECISION ? "block" : "none";
372
+ this.elementLabel.style.display = visible && distance > 0 ? "block" : "none";
515
373
  this.elementLabel.style.left = `${point.x}px`;
516
374
  this.elementLabel.style.top = `${point.y}px`;
517
- this.elementLabel.innerHTML = `${distance.toFixed(2)} ${this.unit}`;
375
+ this.elementLabel.innerHTML = formatDistance(distance, this.units, this.precision);
518
376
  } else {
519
377
  this.elementLabel.style.display = "none";
520
378
  }