@inweb/viewer-three 25.12.1 → 26.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 (88) hide show
  1. package/dist/viewer-three.js +52994 -52727
  2. package/dist/viewer-three.js.map +1 -1
  3. package/dist/viewer-three.min.js +2 -3
  4. package/dist/viewer-three.module.js +1571 -1444
  5. package/dist/viewer-three.module.js.map +1 -1
  6. package/lib/Viewer/Viewer.d.ts +4 -4
  7. package/lib/Viewer/commands/ApplyModelTransform.d.ts +3 -1
  8. package/lib/Viewer/commands/ClearMarkup.d.ts +2 -1
  9. package/lib/Viewer/commands/ClearSelected.d.ts +2 -1
  10. package/lib/Viewer/commands/ClearSlices.d.ts +2 -1
  11. package/lib/Viewer/commands/CreatePreview.d.ts +2 -1
  12. package/lib/Viewer/commands/Explode.d.ts +3 -1
  13. package/lib/Viewer/commands/GetDefaultViewPositions.d.ts +1 -1
  14. package/lib/Viewer/commands/GetModels.d.ts +2 -1
  15. package/lib/Viewer/commands/GetSelected.d.ts +2 -1
  16. package/lib/Viewer/commands/HideSelected.d.ts +2 -1
  17. package/lib/Viewer/commands/IsolateSelected.d.ts +2 -1
  18. package/lib/Viewer/commands/RegenerateAll.d.ts +2 -1
  19. package/lib/Viewer/commands/ResetView.d.ts +2 -1
  20. package/lib/Viewer/commands/SelectModel.d.ts +2 -1
  21. package/lib/Viewer/commands/SetActiveDragger.d.ts +2 -1
  22. package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +2 -0
  23. package/lib/Viewer/commands/SetMarkupColor.d.ts +2 -1
  24. package/lib/Viewer/commands/SetSelected.d.ts +2 -1
  25. package/lib/Viewer/commands/ShowAll.d.ts +2 -1
  26. package/lib/Viewer/commands/ZoomToExtents.d.ts +2 -1
  27. package/lib/Viewer/commands/ZoomToObjects.d.ts +2 -1
  28. package/lib/Viewer/commands/ZoomToSelected.d.ts +2 -1
  29. package/lib/Viewer/commands/index.d.ts +22 -22
  30. package/lib/Viewer/components/AxesHelperComponent.d.ts +2 -2
  31. package/lib/Viewer/components/BackgroundComponent.d.ts +2 -2
  32. package/lib/Viewer/components/DefaultPositionComponent.d.ts +2 -3
  33. package/lib/Viewer/components/ExtentsComponent.d.ts +2 -2
  34. package/lib/Viewer/components/ExtentsHelperComponent.d.ts +2 -2
  35. package/lib/Viewer/components/LightComponent.d.ts +2 -2
  36. package/lib/Viewer/components/RenderLoopComponent.d.ts +2 -2
  37. package/lib/Viewer/components/ResizeCanvasComponent.d.ts +2 -2
  38. package/lib/Viewer/components/SelectionComponent.d.ts +2 -2
  39. package/lib/Viewer/components/ViewPositionComponent.d.ts +2 -3
  40. package/lib/Viewer/components/WCSHelperComponent.d.ts +2 -2
  41. package/lib/Viewer/components/index.d.ts +40 -0
  42. package/lib/Viewer/draggers/OrbitDragger.d.ts +2 -2
  43. package/lib/Viewer/draggers/WalkDragger.d.ts +2 -1
  44. package/lib/Viewer/draggers/index.d.ts +39 -0
  45. package/lib/index.d.ts +4 -1
  46. package/package.json +5 -5
  47. package/src/Viewer/Viewer.ts +37 -68
  48. package/src/Viewer/commands/ApplyModelTransform.ts +2 -6
  49. package/src/Viewer/commands/ClearMarkup.ts +3 -3
  50. package/src/Viewer/commands/ClearSelected.ts +1 -5
  51. package/src/Viewer/commands/ClearSlices.ts +3 -2
  52. package/src/Viewer/commands/CreatePreview.ts +1 -4
  53. package/src/Viewer/commands/Explode.ts +4 -5
  54. package/src/Viewer/commands/GetDefaultViewPositions.ts +1 -4
  55. package/src/Viewer/commands/GetModels.ts +2 -6
  56. package/src/Viewer/commands/GetSelected.ts +1 -4
  57. package/src/Viewer/commands/HideSelected.ts +1 -4
  58. package/src/Viewer/commands/IsolateSelected.ts +1 -5
  59. package/src/Viewer/commands/RegenerateAll.ts +1 -5
  60. package/src/Viewer/commands/ResetView.ts +1 -4
  61. package/src/Viewer/commands/SelectModel.ts +1 -4
  62. package/src/Viewer/commands/SetActiveDragger.ts +2 -3
  63. package/src/Viewer/commands/SetDefaultViewPosition.ts +1 -26
  64. package/src/Viewer/commands/SetMarkupColor.ts +3 -5
  65. package/src/Viewer/commands/SetSelected.ts +1 -4
  66. package/src/Viewer/commands/ShowAll.ts +1 -4
  67. package/src/Viewer/commands/ZoomToExtents.ts +1 -6
  68. package/src/Viewer/commands/ZoomToObjects.ts +1 -5
  69. package/src/Viewer/commands/ZoomToSelected.ts +1 -5
  70. package/src/Viewer/commands/index.ts +98 -22
  71. package/src/Viewer/components/AxesHelperComponent.ts +2 -2
  72. package/src/Viewer/components/BackgroundComponent.ts +2 -2
  73. package/src/Viewer/components/DefaultPositionComponent.ts +2 -3
  74. package/src/Viewer/components/ExtentsComponent.ts +2 -2
  75. package/src/Viewer/components/ExtentsHelperComponent.ts +2 -2
  76. package/src/Viewer/components/LightComponent.ts +2 -2
  77. package/src/Viewer/components/RenderLoopComponent.ts +2 -2
  78. package/src/Viewer/components/ResizeCanvasComponent.ts +2 -2
  79. package/src/Viewer/components/SelectionComponent.ts +2 -2
  80. package/src/Viewer/components/ViewPositionComponent.ts +2 -3
  81. package/src/Viewer/components/WCSHelperComponent.ts +2 -2
  82. package/src/Viewer/components/index.ts +91 -0
  83. package/src/Viewer/draggers/OrbitDragger.ts +3 -2
  84. package/src/Viewer/draggers/WalkDragger.ts +2 -1
  85. package/src/Viewer/draggers/index.ts +83 -0
  86. package/src/index.ts +5 -2
  87. package/lib/Viewer/IDisposable.d.ts +0 -6
  88. package/src/Viewer/IDisposable.ts +0 -29
@@ -1,14 +1,14 @@
1
- import { Vector2, Raycaster, MeshBasicMaterial, Box3, Vector3, Sphere, LoadingManager, LoaderUtils, EventDispatcher, MOUSE, TOUCH, Quaternion, Spherical, Controls, Clock, Line, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, DoubleSide, Plane, Object3D, Matrix4, Vector4, AmbientLight, DirectionalLight, Color, PMREMGenerator, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
2
-
3
- import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
4
-
5
1
  import Konva from "konva";
6
2
 
3
+ import { Line, BufferGeometry, Float32BufferAttribute, LineBasicMaterial, Mesh, MeshBasicMaterial, DoubleSide, Vector3, EventDispatcher, MOUSE, TOUCH, Quaternion, Spherical, Vector2, Plane, Object3D, Matrix4, Vector4, Raycaster, Controls, Clock, Box3, Sphere, Color, PMREMGenerator, AmbientLight, DirectionalLight, OrthographicCamera, CylinderGeometry, Sprite, CanvasTexture, SRGBColorSpace, SpriteMaterial, LoadingManager, LoaderUtils, Scene, PerspectiveCamera, WebGLRenderer, LinearToneMapping } from "three";
4
+
7
5
  import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
8
6
 
9
7
  import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment.js";
10
8
 
11
- class Commands {
9
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
10
+
11
+ class CommandsRegistry {
12
12
  constructor() {
13
13
  this._commands = new Map;
14
14
  }
@@ -52,22 +52,108 @@ class Commands {
52
52
  }
53
53
  }
54
54
 
55
- const _commands = new Map;
55
+ const _commandsRegistry = new Map;
56
+
57
+ function commandsRegistry(viewerType = "") {
58
+ let result = _commandsRegistry.get(viewerType);
59
+ if (!result) {
60
+ result = new CommandsRegistry;
61
+ _commandsRegistry.set(viewerType, result);
62
+ }
63
+ return result;
64
+ }
65
+
66
+ class Dragger {
67
+ constructor(viewer) {
68
+ this.name = "";
69
+ }
70
+ dispose() {}
71
+ }
72
+
73
+ class DraggersRegistry {
74
+ constructor() {
75
+ this._draggers = new Map;
76
+ }
77
+ registerDragger(name, provider) {
78
+ this._draggers.set(name, provider);
79
+ }
80
+ registerDraggerAlias(name, alias) {
81
+ const provider = this.getDragger(name);
82
+ if (provider) this.registerDragger(alias, (viewer => provider(viewer)));
83
+ }
84
+ getDragger(name) {
85
+ return this._draggers.get(name);
86
+ }
87
+ getDraggers() {
88
+ const map = new Map;
89
+ this._draggers.forEach(((value, key) => map.set(key, value)));
90
+ return map;
91
+ }
92
+ createDragger(name, viewer) {
93
+ const provider = this.getDragger(name);
94
+ if (!provider) return null;
95
+ const dragger = provider(viewer);
96
+ dragger.name = name;
97
+ return dragger;
98
+ }
99
+ }
100
+
101
+ const _draggersRegistry = new Map;
56
102
 
57
- function commands(viewerType = "") {
58
- let result = _commands.get(viewerType);
103
+ function draggersRegistry(viewerType = "") {
104
+ let result = _draggersRegistry.get(viewerType);
59
105
  if (!result) {
60
- result = new Commands;
61
- _commands.set(viewerType, result);
106
+ result = new DraggersRegistry;
107
+ _draggersRegistry.set(viewerType, result);
62
108
  }
63
109
  return result;
64
110
  }
65
111
 
66
- commands("").registerCommand("noop", (() => {}));
112
+ class Component {
113
+ constructor(viewer) {
114
+ this.name = "";
115
+ }
116
+ dispose() {}
117
+ }
118
+
119
+ class Components {
120
+ constructor() {
121
+ this._components = new Map;
122
+ }
123
+ registerComponent(name, provider) {
124
+ this._components.set(name, provider);
125
+ }
126
+ registerComponentAlias(name, alias) {
127
+ const provider = this.getComponent(name);
128
+ if (provider) this.registerComponent(alias, (viewer => provider(viewer)));
129
+ }
130
+ getComponent(name) {
131
+ return this._components.get(name);
132
+ }
133
+ getComponents() {
134
+ const map = new Map;
135
+ this._components.forEach(((value, key) => map.set(key, value)));
136
+ return map;
137
+ }
138
+ createComponent(name, viewer) {
139
+ const provider = this.getComponent(name);
140
+ if (!provider) return null;
141
+ const component = provider(viewer);
142
+ component.name = name;
143
+ return component;
144
+ }
145
+ }
67
146
 
68
- commands("VisualizeJS").registerCommand("noop", (() => {}));
147
+ const _components = new Map;
69
148
 
70
- commands("ThreeJS").registerCommand("noop", (() => {}));
149
+ function componentsRegistry(viewerType = "") {
150
+ let result = _components.get(viewerType);
151
+ if (!result) {
152
+ result = new Components;
153
+ _components.set(viewerType, result);
154
+ }
155
+ return result;
156
+ }
71
157
 
72
158
  function defaultOptions() {
73
159
  return {
@@ -381,616 +467,216 @@ const CanvasEvents = [ "click", "contextmenu", "dblclick", "mousedown", "mousele
381
467
 
382
468
  const CANVAS_EVENTS = CanvasEvents;
383
469
 
384
- class Dragger {
385
- constructor(viewer) {
386
- this.name = "";
387
- }
388
- initialize() {}
389
- dispose() {}
390
- updatePreview() {}
391
- }
392
-
393
- function applyModelTransform(viewer, model) {
394
- console.warn("applyModelTransform not implemented");
395
- }
396
-
397
- commands("ThreeJS").registerCommand("applyModelTransform", applyModelTransform);
398
-
399
- commands("ThreeJS").registerCommand("clearMarkup", (viewer => viewer.clearOverlay()));
400
-
401
- commands("ThreeJS").registerCommandAlias("clearMarkup", "clearOverlay");
402
-
403
- class SelectionComponent {
404
- constructor(viewer) {
405
- this.onPointerDown = event => {
406
- if (!event.isPrimary || event.button !== 0) return;
407
- this.getMousePosition(event, this.downPosition);
408
- };
409
- this.onPointerUp = event => {
410
- if (!event.isPrimary) return;
411
- const upPosition = this.getMousePosition(event, new Vector2);
412
- if (this.downPosition.distanceTo(upPosition) !== 0) return;
413
- const intersects = this.getPointerIntersects(upPosition);
414
- this.clearSelection();
415
- if (intersects.length > 0) this.select(intersects[0].object);
416
- this.viewer.update();
417
- this.viewer.emitEvent({
418
- type: "select",
419
- data: undefined,
420
- handles: this.viewer.getSelected()
421
- });
470
+ class WorldTransform {
471
+ screenToWorld(position) {
472
+ return {
473
+ x: position.x,
474
+ y: position.y,
475
+ z: 0
422
476
  };
423
- this.onDoubleClick = event => {
424
- if (event.button !== 0) return;
425
- this.viewer.executeCommand("zoomToSelected");
477
+ }
478
+ worldToScreen(position) {
479
+ return {
480
+ x: position.x,
481
+ y: position.y
426
482
  };
427
- this.optionsChange = () => {
428
- const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
429
- this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
430
- this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
431
- this.viewer.update();
483
+ }
484
+ getScale() {
485
+ return {
486
+ x: 1,
487
+ y: 1,
488
+ z: 1
432
489
  };
433
- this.viewer = viewer;
434
- this.raycaster = new Raycaster;
435
- this.downPosition = new Vector2;
436
- const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
437
- this.facesMaterial = new MeshBasicMaterial;
438
- this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
439
- this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
440
- this.facesMaterial.transparent = true;
441
- this.viewer.addEventListener("pointerdown", this.onPointerDown);
442
- this.viewer.addEventListener("pointerup", this.onPointerUp);
443
- this.viewer.addEventListener("dblclick", this.onDoubleClick);
444
- this.viewer.addEventListener("optionschange", this.optionsChange);
445
490
  }
446
- dispose() {
447
- this.facesMaterial.dispose();
448
- this.viewer.removeEventListener("pointerdown", this.onPointerDown);
449
- this.viewer.removeEventListener("pointerup", this.onPointerUp);
450
- this.viewer.removeEventListener("dblclick", this.onDoubleClick);
451
- this.viewer.removeEventListener("optionschange", this.optionsChange);
491
+ }
492
+
493
+ class MarkupColor {
494
+ constructor(r, g, b) {
495
+ this.setColor(r, g, b);
452
496
  }
453
- getMousePosition(event, target) {
454
- return target.set(event.clientX, event.clientY);
497
+ asHex() {
498
+ return "#" + this.HEX;
455
499
  }
456
- getPointerIntersects(mouse) {
457
- const rect = this.viewer.canvas.getBoundingClientRect();
458
- const x = (mouse.x - rect.left) / rect.width * 2 - 1;
459
- const y = -(mouse.y - rect.top) / rect.height * 2 + 1;
460
- const coords = new Vector2(x, y);
461
- this.raycaster.setFromCamera(coords, this.viewer.camera);
462
- const objects = [];
463
- this.viewer.scene.traverseVisible((child => objects.push(child)));
464
- this.raycaster.params = this.raycaster.params = {
465
- Mesh: {},
466
- Line: {
467
- threshold: .25
468
- },
469
- Line2: {
470
- threshold: .25
471
- },
472
- LOD: {},
473
- Points: {
474
- threshold: .1
475
- },
476
- Sprite: {}
500
+ asRGB() {
501
+ return {
502
+ r: this.R,
503
+ g: this.G,
504
+ b: this.B
477
505
  };
478
- return this.raycaster.intersectObjects(objects, false);
479
506
  }
480
- select(object) {
481
- if (object.isSelected) return;
482
- object.isSelected = true;
483
- object.originalMaterial = object.material;
484
- object.material = this.facesMaterial;
485
- this.viewer.selected.push(object);
507
+ setColor(r, g, b) {
508
+ this.R = r;
509
+ this.G = g;
510
+ this.B = b;
511
+ this.HEX = this.rgbToHex(r, g, b);
486
512
  }
487
- clearSelection() {
488
- this.viewer.selected.forEach((object => {
489
- object.isSelected = false;
490
- object.material = object.originalMaterial;
491
- }));
492
- this.viewer.selected.length = 0;
513
+ rgbToHex(r, g, b) {
514
+ const valueToHex = c => {
515
+ const hex = c.toString(16);
516
+ return hex === "0" ? "00" : hex;
517
+ };
518
+ return valueToHex(r) + valueToHex(g) + valueToHex(b);
493
519
  }
494
520
  }
495
521
 
496
- function clearSelected(viewer) {
497
- const selection = new SelectionComponent(viewer);
498
- selection.clearSelection();
499
- selection.dispose();
500
- viewer.update();
501
- viewer.emitEvent({
502
- type: "select",
503
- data: undefined,
504
- handles: []
505
- });
506
- }
507
-
508
- commands("ThreeJS").registerCommand("clearSelected", clearSelected);
509
-
510
- commands("ThreeJS").registerCommandAlias("clearSelected", "unselect");
511
-
512
- commands("ThreeJS").registerCommand("clearSlices", (viewer => viewer.clearSlices()));
513
-
514
- function createPreview(viewer, type = "image/jpeg", encoderOptions = .25) {
515
- viewer.update(true);
516
- return viewer.canvas.toDataURL(type, encoderOptions);
517
- }
518
-
519
- commands("ThreeJS").registerCommand("createPreview", createPreview);
520
-
521
- function calcObjectDepth(object, depth) {
522
- let res = depth;
523
- object.children.forEach((x => {
524
- const objectDepth = calcObjectDepth(x, depth + 1);
525
- if (res < objectDepth) res = objectDepth;
526
- }));
527
- object.originalPosition = object.position.clone();
528
- return res;
529
- }
522
+ const LineTypeSpecs = new Map([ [ "solid", [] ], [ "dot", [ 30, 30, .001, 30 ] ], [ "dash", [ 30, 30 ] ] ]);
530
523
 
531
- function explodeScene(scene, scale = 0) {
532
- scale /= 100;
533
- if (!scene.maxDepth) scene.maxDepth = calcObjectDepth(scene, 1);
534
- const maxDepth = scene.maxDepth;
535
- let explodeDepth = scale * (maxDepth - 1) + 1;
536
- if (maxDepth === 1) explodeDepth = 1;
537
- function explodeObject(object, depth, parentCenter, parentOffset) {
538
- const objectBox = (new Box3).setFromObject(object);
539
- const objectCenter = objectBox.getCenter(new Vector3);
540
- const objectOffset = parentOffset.clone();
541
- if (depth > 0 && depth <= explodeDepth) {
542
- const offset = objectCenter.clone().sub(parentCenter).multiplyScalar(scale);
543
- objectOffset.add(offset);
544
- }
545
- object.children.forEach((object => explodeObject(object, depth + 1, objectCenter, objectOffset)));
546
- const originalPosition = object.originalPosition;
547
- object.position.copy(originalPosition);
548
- if (scale > 0) {
549
- const direction = objectCenter.sub(parentCenter).normalize();
550
- object.position.add(direction.add(objectOffset));
524
+ class KonvaLine {
525
+ constructor(params, ref = null) {
526
+ var _a, _b;
527
+ if (ref) {
528
+ this._ref = ref;
529
+ return;
551
530
  }
552
- }
553
- const sceneExtents = (new Box3).setFromObject(scene);
554
- const sceneCenter = sceneExtents.getCenter(new Vector3);
555
- explodeObject(scene, 0, sceneCenter, new Vector3(0, 0, 0));
556
- }
557
-
558
- function explode(viewer, index = 0) {
559
- viewer.models.forEach((gltf => explodeScene(gltf.scene, index)));
560
- viewer.update();
561
- viewer.emitEvent({
562
- type: "explode",
563
- data: index
564
- });
565
- }
566
-
567
- commands("ThreeJS").registerCommand("explode", explode);
568
-
569
- commands("ThreeJS").registerCommand("collect", (viewer => explode(viewer, 0)));
570
-
571
- const defaultViewPositions = {
572
- top: new Vector3(0, 0, 1),
573
- bottom: new Vector3(0, 0, -1),
574
- left: new Vector3(-1, 0, 0),
575
- right: new Vector3(1, 0, 0),
576
- front: new Vector3(0, -1, 0),
577
- back: new Vector3(0, 1, 0),
578
- sw: new Vector3(-.5, -.5, 1).normalize(),
579
- se: new Vector3(.5, -.5, 1).normalize(),
580
- ne: new Vector3(.5, .5, 1).normalize(),
581
- nw: new Vector3(-.5, .5, 1).normalize()
582
- };
583
-
584
- function setDefaultViewPosition(viewer, position) {
585
- const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
586
- const center = viewer.extents.getCenter(new Vector3);
587
- const sphere = viewer.extents.getBoundingSphere(new Sphere);
588
- const offet = direction.clone().multiplyScalar(sphere.radius);
589
- const camera = viewer.camera;
590
- camera.position.copy(center).add(offet);
591
- camera.lookAt(center);
592
- camera.updateProjectionMatrix();
593
- camera.updateMatrixWorld();
594
- viewer.target.copy(center);
595
- viewer.update();
596
- viewer.emit({
597
- type: "viewposition",
598
- data: position
599
- });
600
- viewer.executeCommand("zoomToExtents");
601
- }
602
-
603
- commands("ThreeJS").registerCommand("setDefaultViewPosition", setDefaultViewPosition);
604
-
605
- commands("ThreeJS").registerCommand("top", (viewer => setDefaultViewPosition(viewer, "top")));
606
-
607
- commands("ThreeJS").registerCommand("bottom", (viewer => setDefaultViewPosition(viewer, "bottom")));
608
-
609
- commands("ThreeJS").registerCommand("left", (viewer => setDefaultViewPosition(viewer, "left")));
610
-
611
- commands("ThreeJS").registerCommand("right", (viewer => setDefaultViewPosition(viewer, "right")));
612
-
613
- commands("ThreeJS").registerCommand("front", (viewer => setDefaultViewPosition(viewer, "front")));
614
-
615
- commands("ThreeJS").registerCommand("back", (viewer => setDefaultViewPosition(viewer, "back")));
616
-
617
- commands("ThreeJS").registerCommand("sw", (viewer => setDefaultViewPosition(viewer, "sw")));
618
-
619
- commands("ThreeJS").registerCommand("se", (viewer => setDefaultViewPosition(viewer, "se")));
620
-
621
- commands("ThreeJS").registerCommand("ne", (viewer => setDefaultViewPosition(viewer, "ne")));
622
-
623
- commands("ThreeJS").registerCommand("nw", (viewer => setDefaultViewPosition(viewer, "nw")));
624
-
625
- commands("ThreeJS").registerCommandAlias("top", "k3DViewTop");
626
-
627
- commands("ThreeJS").registerCommandAlias("bottom", "k3DViewBottom");
628
-
629
- commands("ThreeJS").registerCommandAlias("left", "k3DViewLeft");
630
-
631
- commands("ThreeJS").registerCommandAlias("right", "k3DViewRight");
632
-
633
- commands("ThreeJS").registerCommandAlias("front", "k3DViewFront");
634
-
635
- commands("ThreeJS").registerCommandAlias("back", "k3DViewBack");
636
-
637
- commands("ThreeJS").registerCommandAlias("se", "k3DViewSE");
638
-
639
- commands("ThreeJS").registerCommandAlias("sw", "k3DViewSW");
640
-
641
- commands("ThreeJS").registerCommandAlias("ne", "k3DViewNE");
642
-
643
- commands("ThreeJS").registerCommandAlias("nw", "k3DViewNW");
644
-
645
- function getDefaultViewPositions() {
646
- return Object.keys(defaultViewPositions);
647
- }
648
-
649
- commands("ThreeJS").registerCommand("getDefaultViewPositions", getDefaultViewPositions);
650
-
651
- function getModels(viewer) {
652
- const handles = viewer.models.map((model => model.userData.handle || "")).filter((handle => handle));
653
- return handles;
654
- }
655
-
656
- commands("ThreeJS").registerCommand("getModels", getModels);
657
-
658
- function getSelected(viewer) {
659
- return viewer.selected.map((object => {
660
- var _a;
661
- return (_a = object.userData) === null || _a === void 0 ? void 0 : _a.handle;
662
- })).filter((handle => handle));
663
- }
664
-
665
- commands("ThreeJS").registerCommand("getSelected", getSelected);
666
-
667
- function hideSelected(viewer) {
668
- viewer.selected.forEach((object => object.visible = false));
669
- const selection = new SelectionComponent(viewer);
670
- selection.clearSelection();
671
- selection.dispose();
672
- viewer.update();
673
- viewer.emitEvent({
674
- type: "hide"
675
- });
676
- viewer.emitEvent({
677
- type: "select",
678
- data: undefined,
679
- handles: []
680
- });
681
- }
682
-
683
- commands("ThreeJS").registerCommand("hideSelected", hideSelected);
684
-
685
- function isolateSelected(viewer) {
686
- const selectedSet = new Set(viewer.selected);
687
- function isolateObject(object, depth) {
688
- let canBeIsolated = true;
689
- object.children.forEach((object => {
690
- if (selectedSet.has(object)) canBeIsolated = false; else isolateObject(object, depth + 1);
531
+ if (!params) params = {};
532
+ if (!params.points) params.points = [ {
533
+ x: 50,
534
+ y: 50
535
+ }, {
536
+ x: 100,
537
+ y: 100
538
+ } ];
539
+ const konvaPoints = [];
540
+ params.points.forEach((point => konvaPoints.push(point.x, point.y)));
541
+ this._ref = new Konva.Line({
542
+ stroke: (_a = params.color) !== null && _a !== void 0 ? _a : "#ff0000",
543
+ strokeWidth: (_b = params.width) !== null && _b !== void 0 ? _b : 4,
544
+ globalCompositeOperation: "source-over",
545
+ lineCap: "round",
546
+ lineJoin: "round",
547
+ points: konvaPoints,
548
+ draggable: true,
549
+ strokeScaleEnabled: false,
550
+ dash: LineTypeSpecs.get(params.type) || []
551
+ });
552
+ this._ref.on("transform", (e => {
553
+ const attrs = e.target.attrs;
554
+ if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
691
555
  }));
692
- if (canBeIsolated && depth > 0) object.visible = false;
693
- return canBeIsolated;
556
+ this._ref.id(this._ref._id.toString());
694
557
  }
695
- isolateObject(viewer.scene, 0);
696
- viewer.update();
697
- viewer.emitEvent({
698
- type: "isolate"
699
- });
700
- }
701
-
702
- commands("ThreeJS").registerCommand("isolateSelected", isolateSelected);
703
-
704
- function regenerateAll(viewer) {
705
- console.warn("regenerateAll not implemented");
706
- viewer.emit({
707
- type: "regenerateall"
708
- });
709
- }
710
-
711
- commands("ThreeJS").registerCommand("regenerateAll", regenerateAll);
712
-
713
- function resetView(viewer) {
714
- viewer.executeCommand("setActiveDragger");
715
- viewer.executeCommand("clearSlices");
716
- viewer.executeCommand("clearOverlay");
717
- viewer.executeCommand("setMarkupColor");
718
- viewer.executeCommand("clearSelected");
719
- viewer.executeCommand("showAll");
720
- viewer.executeCommand("explode", 0);
721
- viewer.executeCommand("zoomToExtents", true);
722
- viewer.executeCommand("k3DViewSW");
723
- viewer.emit({
724
- type: "resetview"
725
- });
726
- }
727
-
728
- commands("ThreeJS").registerCommand("resetView", resetView);
729
-
730
- function selectModel(viewer, handle) {
731
- console.warn("selectModel not implemented");
732
- viewer.emit({
733
- type: "select",
734
- data: []
735
- });
736
- }
737
-
738
- commands("ThreeJS").registerCommand("selectModel", selectModel);
739
-
740
- commands("ThreeJS").registerCommand("setActiveDragger", ((viewer, dragger = "") => {
741
- viewer.setActiveDragger(dragger);
742
- }));
558
+ ref() {
559
+ return this._ref;
560
+ }
561
+ id() {
562
+ return this._ref.id();
563
+ }
564
+ enableMouseEditing(value) {
565
+ this._ref.draggable(value);
566
+ }
567
+ type() {
568
+ return "Line";
569
+ }
570
+ getColor() {
571
+ return this._ref.stroke();
572
+ }
573
+ setColor(hex) {
574
+ this._ref.stroke(hex);
575
+ }
576
+ getRotation() {
577
+ return this._ref.rotation();
578
+ }
579
+ setRotation(degrees) {
580
+ this._ref.rotation(degrees);
581
+ }
582
+ getZIndex() {
583
+ return this._ref.zIndex();
584
+ }
585
+ setZIndex(zIndex) {
586
+ this._ref.zIndex(zIndex);
587
+ }
588
+ delete() {
589
+ this._ref.destroy();
590
+ this._ref = null;
591
+ }
592
+ getPoints() {
593
+ return this._ref.points();
594
+ }
595
+ setLineWidth(size) {
596
+ this._ref.strokeWidth(size);
597
+ }
598
+ getLineWidth() {
599
+ return this._ref.strokeWidth();
600
+ }
601
+ getLineType() {
602
+ const typeSpecs = this._ref.dash() || [];
603
+ let type;
604
+ switch (typeSpecs) {
605
+ case LineTypeSpecs.get("dot"):
606
+ type = "dot";
607
+ break;
743
608
 
744
- commands("ThreeJS").registerCommand("setMarkupColor", ((viewer, r = 255, g = 0, b = 0) => {
745
- console.warn("setMarkupColor not implemented");
746
- }));
609
+ case LineTypeSpecs.get("dash"):
610
+ type = "dash";
611
+ break;
747
612
 
748
- function setSelected(viewer, handles = []) {
749
- const handleSet = new Set(handles);
750
- const objects = [];
751
- viewer.scene.traverseVisible((child => {
752
- var _a;
753
- if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
754
- }));
755
- const selection = new SelectionComponent(viewer);
756
- selection.clearSelection();
757
- objects.forEach((object => selection.select(object)));
758
- selection.dispose();
759
- viewer.update();
760
- viewer.emitEvent({
761
- type: "select",
762
- data: undefined,
763
- handles: handles
764
- });
613
+ default:
614
+ type = "solid";
615
+ break;
616
+ }
617
+ return type;
618
+ }
619
+ setLineType(type) {
620
+ const specs = LineTypeSpecs.get(type);
621
+ if (specs) this._ref.dash(specs);
622
+ }
623
+ addPoints(points) {
624
+ let newPoints = this._ref.points();
625
+ points.forEach((point => {
626
+ newPoints = newPoints.concat([ point.x, point.y ]);
627
+ }));
628
+ this._ref.points(newPoints);
629
+ }
765
630
  }
766
631
 
767
- commands("ThreeJS").registerCommand("setSelected", setSelected);
768
-
769
- function showAll(viewer) {
770
- viewer.scene.traverse((object => object.visible = true));
771
- viewer.update();
772
- viewer.emitEvent({
773
- type: "showall"
774
- });
775
- }
776
-
777
- commands("ThreeJS").registerCommand("showAll", showAll);
778
-
779
- function zoomToExtents(viewer) {
780
- if (viewer.extents.isEmpty()) return;
781
- const center = viewer.extents.getCenter(new Vector3);
782
- const distance = viewer.extents.getBoundingSphere(new Sphere).radius;
783
- const delta = new Vector3(0, 0, 1);
784
- delta.applyQuaternion(viewer.camera.quaternion);
785
- delta.multiplyScalar(distance * 3);
786
- viewer.camera.position.copy(center).add(delta);
787
- viewer.target.copy(center);
788
- viewer.update();
789
- viewer.emitEvent({
790
- type: "zoom"
791
- });
792
- }
793
-
794
- commands("ThreeJS").registerCommand("zoomToExtents", zoomToExtents);
795
-
796
- commands("ThreeJS").registerCommandAlias("zoomToExtents", "zoomExtents");
797
-
798
- function zoomToObjects(viewer, handles = []) {
799
- const handleSet = new Set(handles);
800
- const objects = [];
801
- viewer.scene.traverseVisible((child => {
802
- var _a;
803
- if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
804
- }));
805
- const extents = objects.reduce(((result, object) => result.expandByObject(object)), new Box3);
806
- const center = extents.getCenter(new Vector3);
807
- const distance = extents.getBoundingSphere(new Sphere).radius;
808
- const delta = new Vector3(0, 0, 1);
809
- delta.applyQuaternion(viewer.camera.quaternion);
810
- delta.multiplyScalar(distance * 3);
811
- viewer.camera.position.copy(center).add(delta);
812
- viewer.target.copy(center);
813
- viewer.update();
814
- viewer.emitEvent({
815
- type: "zoom"
816
- });
817
- }
818
-
819
- commands("ThreeJS").registerCommand("zoomToObjects", zoomToObjects);
820
-
821
- function zoomToSelected(viewer) {
822
- const extents = viewer.selected.reduce(((result, object) => result.expandByObject(object)), new Box3);
823
- if (extents.isEmpty()) extents.copy(viewer.extents);
824
- const center = extents.getCenter(new Vector3);
825
- const distance = extents.getBoundingSphere(new Sphere).radius;
826
- const delta = new Vector3(0, 0, 1);
827
- delta.applyQuaternion(viewer.camera.quaternion);
828
- delta.multiplyScalar(distance * 3);
829
- viewer.camera.position.copy(center).add(delta);
830
- viewer.target.copy(center);
831
- viewer.update();
832
- viewer.emitEvent({
833
- type: "zoom"
834
- });
835
- }
836
-
837
- commands("ThreeJS").registerCommand("zoomToSelected", zoomToSelected);
838
-
839
- class GLTFLoadingManager extends LoadingManager {
840
- constructor(file, externalData = new Map, params = {}) {
841
- super();
842
- this.path = "";
843
- this.resourcePath = "";
844
- this.fileURL = "";
845
- this.dataURLs = new Map;
846
- this.path = params.path || "";
847
- if (typeof file === "string") {
848
- this.fileURL = file;
849
- this.resourcePath = LoaderUtils.extractUrlBase(file);
850
- } else {
851
- externalData.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
852
- externalData.set(this.fileURL, file);
853
- }
854
- externalData.forEach(((value, key) => {
855
- let dataURL;
856
- if (typeof value === "string") dataURL = value; else dataURL = URL.createObjectURL(new Blob([ value ]));
857
- this.dataURLs.set(key, dataURL);
858
- }));
859
- this.setURLModifier((url => {
860
- const key = decodeURI(url).replace(this.path, "").replace(this.resourcePath, "").replace(/^(\.?\/)/, "");
861
- const dataURL = this.dataURLs.get(key);
862
- return dataURL !== null && dataURL !== void 0 ? dataURL : url;
863
- }));
864
- }
865
- dispose() {
866
- this.dataURLs.forEach(URL.revokeObjectURL);
867
- }
868
- }
869
-
870
- class EventEmitter2 {
871
- constructor() {
872
- this._listeners = {};
873
- }
874
- addEventListener(type, listener) {
875
- if (this._listeners[type] === undefined) this._listeners[type] = [];
876
- this._listeners[type].push(listener);
877
- return this;
878
- }
879
- removeEventListener(type, listener) {
880
- if (this._listeners[type] === undefined) return this;
881
- const listeners = this._listeners[type].filter((x => x !== listener));
882
- if (listeners.length !== 0) this._listeners[type] = listeners; else delete this._listeners[type];
883
- return this;
884
- }
885
- removeAllListeners(type) {
886
- if (type) delete this._listeners[type]; else this._listeners = {};
887
- return this;
888
- }
889
- emitEvent(event) {
890
- if (this._listeners[event.type] === undefined) return false;
891
- const invoke = this._listeners[event.type].slice();
892
- invoke.forEach((listener => listener.call(this, event)));
893
- return true;
894
- }
895
- on(type, listener) {
896
- return this.addEventListener(type, listener);
897
- }
898
- off(type, listener) {
899
- return this.removeEventListener(type, listener);
900
- }
901
- emit(type, ...args) {
902
- if (typeof type === "string") return this.emitEvent({
903
- type: type,
904
- args: args
905
- }); else if (typeof type === "object") return this.emitEvent(type); else return false;
906
- }
907
- }
908
-
909
- class WorldTransform {
910
- screenToWorld(position) {
911
- return {
912
- x: position.x,
913
- y: position.y,
914
- z: 0
915
- };
916
- }
917
- worldToScreen(position) {
918
- return {
919
- x: position.x,
920
- y: position.y
921
- };
922
- }
923
- getScale() {
924
- return {
925
- x: 1,
926
- y: 1,
927
- z: 1
928
- };
929
- }
930
- }
931
-
932
- class MarkupColor {
933
- constructor(r, g, b) {
934
- this.setColor(r, g, b);
935
- }
936
- asHex() {
937
- return "#" + this.HEX;
938
- }
939
- asRGB() {
940
- return {
941
- r: this.R,
942
- g: this.G,
943
- b: this.B
944
- };
945
- }
946
- setColor(r, g, b) {
947
- this.R = r;
948
- this.G = g;
949
- this.B = b;
950
- this.HEX = this.rgbToHex(r, g, b);
951
- }
952
- rgbToHex(r, g, b) {
953
- const valueToHex = c => {
954
- const hex = c.toString(16);
955
- return hex === "0" ? "00" : hex;
956
- };
957
- return valueToHex(r) + valueToHex(g) + valueToHex(b);
958
- }
959
- }
960
-
961
- const LineTypeSpecs = new Map([ [ "solid", [] ], [ "dot", [ 30, 30, .001, 30 ] ], [ "dash", [ 30, 30 ] ] ]);
962
-
963
- class KonvaLine {
632
+ class KonvaText {
964
633
  constructor(params, ref = null) {
965
- var _a, _b;
634
+ var _a, _b, _c;
635
+ this.TEXT_FONT_FAMILY = "Calibri";
966
636
  if (ref) {
967
637
  this._ref = ref;
968
638
  return;
969
639
  }
970
640
  if (!params) params = {};
971
- if (!params.points) params.points = [ {
972
- x: 50,
973
- y: 50
974
- }, {
641
+ if (!params.position) params.position = {
975
642
  x: 100,
976
643
  y: 100
977
- } ];
978
- const konvaPoints = [];
979
- params.points.forEach((point => konvaPoints.push(point.x, point.y)));
980
- this._ref = new Konva.Line({
981
- stroke: (_a = params.color) !== null && _a !== void 0 ? _a : "#ff0000",
982
- strokeWidth: (_b = params.width) !== null && _b !== void 0 ? _b : 4,
983
- globalCompositeOperation: "source-over",
984
- lineCap: "round",
985
- lineJoin: "round",
986
- points: konvaPoints,
644
+ };
645
+ if (!params.text) params.text = "default";
646
+ this._ref = new Konva.Text({
647
+ x: params.position.x,
648
+ y: params.position.y,
649
+ text: params.text,
650
+ fontSize: (_a = params.fontSize) !== null && _a !== void 0 ? _a : 34,
651
+ fontFamily: this.TEXT_FONT_FAMILY,
652
+ fill: (_b = params.color) !== null && _b !== void 0 ? _b : "#ff0000",
653
+ align: "left",
987
654
  draggable: true,
988
- strokeScaleEnabled: false,
989
- dash: LineTypeSpecs.get(params.type) || []
655
+ rotation: (_c = params.rotation) !== null && _c !== void 0 ? _c : 0
990
656
  });
657
+ this._ref.width(this._ref.getTextWidth());
991
658
  this._ref.on("transform", (e => {
992
659
  const attrs = e.target.attrs;
993
660
  if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
661
+ const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
662
+ const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
663
+ let newWidth = this._ref.width();
664
+ if (scaleByX) newWidth *= attrs.scaleX;
665
+ let newHeight = this._ref.height();
666
+ if (scaleByY) newHeight *= attrs.scaleY;
667
+ const minWidth = 50;
668
+ if (newWidth < minWidth) newWidth = minWidth;
669
+ if (newHeight < Math.round(this.getFontSize())) newHeight = Math.round(this.getFontSize());
670
+ if (scaleByX) {
671
+ this._ref.width(newWidth);
672
+ }
673
+ if (scaleByY) {
674
+ this._ref.height(newHeight);
675
+ }
676
+ this._ref.scale({
677
+ x: 1,
678
+ y: 1
679
+ });
994
680
  }));
995
681
  this._ref.id(this._ref._id.toString());
996
682
  }
@@ -1004,13 +690,13 @@ class KonvaLine {
1004
690
  this._ref.draggable(value);
1005
691
  }
1006
692
  type() {
1007
- return "Line";
693
+ return "Text";
1008
694
  }
1009
695
  getColor() {
1010
- return this._ref.stroke();
696
+ return this._ref.fill();
1011
697
  }
1012
698
  setColor(hex) {
1013
- this._ref.stroke(hex);
699
+ this._ref.fill(hex);
1014
700
  }
1015
701
  getRotation() {
1016
702
  return this._ref.rotation();
@@ -1028,139 +714,14 @@ class KonvaLine {
1028
714
  this._ref.destroy();
1029
715
  this._ref = null;
1030
716
  }
1031
- getPoints() {
1032
- return this._ref.points();
717
+ getText() {
718
+ return this._ref.text();
1033
719
  }
1034
- setLineWidth(size) {
1035
- this._ref.strokeWidth(size);
720
+ setText(text) {
721
+ this._ref.text(text);
1036
722
  }
1037
- getLineWidth() {
1038
- return this._ref.strokeWidth();
1039
- }
1040
- getLineType() {
1041
- const typeSpecs = this._ref.dash() || [];
1042
- let type;
1043
- switch (typeSpecs) {
1044
- case LineTypeSpecs.get("dot"):
1045
- type = "dot";
1046
- break;
1047
-
1048
- case LineTypeSpecs.get("dash"):
1049
- type = "dash";
1050
- break;
1051
-
1052
- default:
1053
- type = "solid";
1054
- break;
1055
- }
1056
- return type;
1057
- }
1058
- setLineType(type) {
1059
- const specs = LineTypeSpecs.get(type);
1060
- if (specs) this._ref.dash(specs);
1061
- }
1062
- addPoints(points) {
1063
- let newPoints = this._ref.points();
1064
- points.forEach((point => {
1065
- newPoints = newPoints.concat([ point.x, point.y ]);
1066
- }));
1067
- this._ref.points(newPoints);
1068
- }
1069
- }
1070
-
1071
- class KonvaText {
1072
- constructor(params, ref = null) {
1073
- var _a, _b, _c;
1074
- this.TEXT_FONT_FAMILY = "Calibri";
1075
- if (ref) {
1076
- this._ref = ref;
1077
- return;
1078
- }
1079
- if (!params) params = {};
1080
- if (!params.position) params.position = {
1081
- x: 100,
1082
- y: 100
1083
- };
1084
- if (!params.text) params.text = "default";
1085
- this._ref = new Konva.Text({
1086
- x: params.position.x,
1087
- y: params.position.y,
1088
- text: params.text,
1089
- fontSize: (_a = params.fontSize) !== null && _a !== void 0 ? _a : 34,
1090
- fontFamily: this.TEXT_FONT_FAMILY,
1091
- fill: (_b = params.color) !== null && _b !== void 0 ? _b : "#ff0000",
1092
- align: "left",
1093
- draggable: true,
1094
- rotation: (_c = params.rotation) !== null && _c !== void 0 ? _c : 0
1095
- });
1096
- this._ref.width(this._ref.getTextWidth());
1097
- this._ref.on("transform", (e => {
1098
- const attrs = e.target.attrs;
1099
- if (attrs.rotation !== this._ref.rotation()) this._ref.rotation(attrs.rotation);
1100
- const scaleByX = Math.abs(attrs.scaleX - 1) > 1e-5;
1101
- const scaleByY = Math.abs(attrs.scaleY - 1) > 1e-5;
1102
- let newWidth = this._ref.width();
1103
- if (scaleByX) newWidth *= attrs.scaleX;
1104
- let newHeight = this._ref.height();
1105
- if (scaleByY) newHeight *= attrs.scaleY;
1106
- const minWidth = 50;
1107
- if (newWidth < minWidth) newWidth = minWidth;
1108
- if (newHeight < Math.round(this.getFontSize())) newHeight = Math.round(this.getFontSize());
1109
- if (scaleByX) {
1110
- this._ref.width(newWidth);
1111
- }
1112
- if (scaleByY) {
1113
- this._ref.height(newHeight);
1114
- }
1115
- this._ref.scale({
1116
- x: 1,
1117
- y: 1
1118
- });
1119
- }));
1120
- this._ref.id(this._ref._id.toString());
1121
- }
1122
- ref() {
1123
- return this._ref;
1124
- }
1125
- id() {
1126
- return this._ref.id();
1127
- }
1128
- enableMouseEditing(value) {
1129
- this._ref.draggable(value);
1130
- }
1131
- type() {
1132
- return "Text";
1133
- }
1134
- getColor() {
1135
- return this._ref.fill();
1136
- }
1137
- setColor(hex) {
1138
- this._ref.fill(hex);
1139
- }
1140
- getRotation() {
1141
- return this._ref.rotation();
1142
- }
1143
- setRotation(degrees) {
1144
- this._ref.rotation(degrees);
1145
- }
1146
- getZIndex() {
1147
- return this._ref.zIndex();
1148
- }
1149
- setZIndex(zIndex) {
1150
- this._ref.zIndex(zIndex);
1151
- }
1152
- delete() {
1153
- this._ref.destroy();
1154
- this._ref = null;
1155
- }
1156
- getText() {
1157
- return this._ref.text();
1158
- }
1159
- setText(text) {
1160
- this._ref.text(text);
1161
- }
1162
- getPosition() {
1163
- return this._ref.getPosition();
723
+ getPosition() {
724
+ return this._ref.getPosition();
1164
725
  }
1165
726
  setPosition(x, y) {
1166
727
  this._ref.setPosition({
@@ -2750,6 +2311,50 @@ class KonvaMarkup {
2750
2311
  }
2751
2312
  }
2752
2313
 
2314
+ class PlaneHelper extends Line {
2315
+ constructor(plane, size = 1, color = 16776960, offset = new Vector3) {
2316
+ const positions = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
2317
+ const geometry = new BufferGeometry;
2318
+ geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
2319
+ geometry.computeBoundingSphere();
2320
+ super(geometry, new LineBasicMaterial({
2321
+ color: color,
2322
+ toneMapped: false
2323
+ }));
2324
+ this.type = "PlaneHelper";
2325
+ this.plane = plane;
2326
+ this.size = size;
2327
+ this.offset = offset;
2328
+ const positions2 = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0 ];
2329
+ const geometry2 = new BufferGeometry;
2330
+ geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
2331
+ geometry2.computeBoundingSphere();
2332
+ this.helper = new Mesh(geometry2, new MeshBasicMaterial({
2333
+ color: color,
2334
+ opacity: .2,
2335
+ transparent: true,
2336
+ depthWrite: false,
2337
+ toneMapped: false,
2338
+ side: DoubleSide
2339
+ }));
2340
+ this.add(this.helper);
2341
+ }
2342
+ dispose() {
2343
+ this.geometry.dispose();
2344
+ this.material.dispose();
2345
+ this.children[0].geometry.dispose();
2346
+ this.children[0].material.dispose();
2347
+ }
2348
+ updateMatrixWorld(force) {
2349
+ this.position.set(0, 0, 0);
2350
+ this.lookAt(this.plane.normal);
2351
+ this.position.copy(this.offset);
2352
+ this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
2353
+ this.scale.set(.5 * this.size, .5 * this.size, 1);
2354
+ super.updateMatrixWorld(force);
2355
+ }
2356
+ }
2357
+
2753
2358
  const _changeEvent = {
2754
2359
  type: "change"
2755
2360
  };
@@ -3305,214 +2910,642 @@ class OrbitControls extends EventDispatcher {
3305
2910
  handleMouseMoveDolly(event);
3306
2911
  break;
3307
2912
 
3308
- case STATE.PAN:
3309
- if (scope.enablePan === false) return;
3310
- handleMouseMovePan(event);
3311
- break;
3312
- }
3313
- }
3314
- function onMouseWheel(event) {
3315
- if (scope.enabled === false || scope.enableZoom === false || scope.state !== STATE.NONE) return;
3316
- event.preventDefault();
3317
- scope.dispatchEvent(_startEvent);
3318
- handleMouseWheel(event);
3319
- scope.dispatchEvent(_endEvent);
3320
- }
3321
- function onKeyDown(event) {
3322
- if (scope.enabled === false || scope.enablePan === false) return;
3323
- handleKeyDown(event);
3324
- }
3325
- function onTouchStart(event) {
3326
- trackPointer(event);
3327
- switch (scope.pointers.length) {
3328
- case 1:
3329
- switch (scope.touches.ONE) {
3330
- case TOUCH.ROTATE:
3331
- if (scope.enableRotate === false) return;
3332
- handleTouchStartRotate();
3333
- scope.state = STATE.TOUCH_ROTATE;
3334
- break;
2913
+ case STATE.PAN:
2914
+ if (scope.enablePan === false) return;
2915
+ handleMouseMovePan(event);
2916
+ break;
2917
+ }
2918
+ }
2919
+ function onMouseWheel(event) {
2920
+ if (scope.enabled === false || scope.enableZoom === false || scope.state !== STATE.NONE) return;
2921
+ event.preventDefault();
2922
+ scope.dispatchEvent(_startEvent);
2923
+ handleMouseWheel(event);
2924
+ scope.dispatchEvent(_endEvent);
2925
+ }
2926
+ function onKeyDown(event) {
2927
+ if (scope.enabled === false || scope.enablePan === false) return;
2928
+ handleKeyDown(event);
2929
+ }
2930
+ function onTouchStart(event) {
2931
+ trackPointer(event);
2932
+ switch (scope.pointers.length) {
2933
+ case 1:
2934
+ switch (scope.touches.ONE) {
2935
+ case TOUCH.ROTATE:
2936
+ if (scope.enableRotate === false) return;
2937
+ handleTouchStartRotate();
2938
+ scope.state = STATE.TOUCH_ROTATE;
2939
+ break;
2940
+
2941
+ case TOUCH.PAN:
2942
+ if (scope.enablePan === false) return;
2943
+ handleTouchStartPan();
2944
+ scope.state = STATE.TOUCH_PAN;
2945
+ break;
2946
+
2947
+ default:
2948
+ scope.state = STATE.NONE;
2949
+ }
2950
+ break;
2951
+
2952
+ case 2:
2953
+ switch (scope.touches.TWO) {
2954
+ case TOUCH.DOLLY_PAN:
2955
+ if (scope.enableZoom === false && scope.enablePan === false) return;
2956
+ handleTouchStartDollyPan();
2957
+ scope.state = STATE.TOUCH_DOLLY_PAN;
2958
+ break;
2959
+
2960
+ case TOUCH.DOLLY_ROTATE:
2961
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
2962
+ handleTouchStartDollyRotate();
2963
+ scope.state = STATE.TOUCH_DOLLY_ROTATE;
2964
+ break;
2965
+
2966
+ default:
2967
+ scope.state = STATE.NONE;
2968
+ }
2969
+ break;
2970
+
2971
+ default:
2972
+ scope.state = STATE.NONE;
2973
+ }
2974
+ if (scope.state !== STATE.NONE) {
2975
+ scope.dispatchEvent(_startEvent);
2976
+ }
2977
+ }
2978
+ function onTouchMove(event) {
2979
+ trackPointer(event);
2980
+ switch (scope.state) {
2981
+ case STATE.TOUCH_ROTATE:
2982
+ if (scope.enableRotate === false) return;
2983
+ handleTouchMoveRotate(event);
2984
+ scope.update();
2985
+ break;
2986
+
2987
+ case STATE.TOUCH_PAN:
2988
+ if (scope.enablePan === false) return;
2989
+ handleTouchMovePan(event);
2990
+ scope.update();
2991
+ break;
2992
+
2993
+ case STATE.TOUCH_DOLLY_PAN:
2994
+ if (scope.enableZoom === false && scope.enablePan === false) return;
2995
+ handleTouchMoveDollyPan(event);
2996
+ scope.update();
2997
+ break;
2998
+
2999
+ case STATE.TOUCH_DOLLY_ROTATE:
3000
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
3001
+ handleTouchMoveDollyRotate(event);
3002
+ scope.update();
3003
+ break;
3004
+
3005
+ default:
3006
+ scope.state = STATE.NONE;
3007
+ }
3008
+ }
3009
+ function onContextMenu(event) {
3010
+ if (scope.enabled === false) return;
3011
+ event.preventDefault();
3012
+ }
3013
+ function addPointer(event) {
3014
+ scope.pointers.push(event);
3015
+ }
3016
+ function removePointer(event) {
3017
+ delete scope.pointerPositions[event.pointerId];
3018
+ for (let i = 0; i < scope.pointers.length; i++) {
3019
+ if (scope.pointers[i].pointerId == event.pointerId) {
3020
+ scope.pointers.splice(i, 1);
3021
+ return;
3022
+ }
3023
+ }
3024
+ }
3025
+ function trackPointer(event) {
3026
+ let position = scope.pointerPositions[event.pointerId];
3027
+ if (position === undefined) {
3028
+ position = new Vector2;
3029
+ scope.pointerPositions[event.pointerId] = position;
3030
+ }
3031
+ position.set(event.pageX, event.pageY);
3032
+ }
3033
+ function getSecondPointerPosition(event) {
3034
+ const pointer = event.pointerId === scope.pointers[0].pointerId ? scope.pointers[1] : scope.pointers[0];
3035
+ return scope.pointerPositions[pointer.pointerId];
3036
+ }
3037
+ scope.domElement.addEventListener("contextmenu", onContextMenu);
3038
+ scope.domElement.addEventListener("pointerdown", onPointerDown);
3039
+ scope.domElement.addEventListener("pointercancel", onPointerUp);
3040
+ scope.domElement.addEventListener("wheel", onMouseWheel, {
3041
+ passive: false
3042
+ });
3043
+ this.update();
3044
+ }
3045
+ }
3046
+
3047
+ class OrbitDragger {
3048
+ constructor(viewer) {
3049
+ this.updateControls = () => {
3050
+ this.orbit.maxDistance = this.viewer.camera.far;
3051
+ this.orbit.minDistance = this.viewer.camera.near;
3052
+ this.orbit.target.copy(this.viewer.target);
3053
+ this.orbit.update();
3054
+ };
3055
+ this.controlsStart = () => {
3056
+ this.changed = false;
3057
+ };
3058
+ this.controlsChange = () => {
3059
+ this.viewer.target.copy(this.orbit.target);
3060
+ this.viewer.update();
3061
+ switch (this.orbit.state) {
3062
+ case STATE.PAN:
3063
+ case STATE.TOUCH_PAN:
3064
+ this.viewer.emitEvent({
3065
+ type: "pan",
3066
+ x: this.orbit.panEnd.x,
3067
+ y: this.orbit.panEnd.y,
3068
+ dX: this.orbit.panDelta.x,
3069
+ dY: this.orbit.panDelta.y
3070
+ });
3071
+ break;
3072
+
3073
+ case STATE.DOLLY:
3074
+ this.viewer.emitEvent({
3075
+ type: "zoomat",
3076
+ data: this.orbit.dollyScale,
3077
+ x: this.orbit.dollyEnd.x,
3078
+ y: this.orbit.dollyEnd.y
3079
+ });
3080
+ break;
3081
+ }
3082
+ this.changed = true;
3083
+ };
3084
+ this.stopContextMenu = event => {
3085
+ if (this.changed) {
3086
+ event.preventDefault();
3087
+ event.stopPropagation();
3088
+ }
3089
+ };
3090
+ this.orbit = new OrbitControls(viewer.camera, viewer.canvas);
3091
+ this.orbit.mouseButtons = {
3092
+ LEFT: MOUSE.ROTATE,
3093
+ MIDDLE: MOUSE.PAN,
3094
+ RIGHT: MOUSE.PAN
3095
+ };
3096
+ this.orbit.touches = {
3097
+ ONE: TOUCH.ROTATE,
3098
+ TWO: TOUCH.DOLLY_PAN
3099
+ };
3100
+ this.orbit.screenSpacePanning = true;
3101
+ this.orbit.rotateSpeed = .33;
3102
+ this.orbit.addEventListener("start", this.controlsStart);
3103
+ this.orbit.addEventListener("change", this.controlsChange);
3104
+ this.changed = false;
3105
+ this.viewer = viewer;
3106
+ this.viewer.on("geometryend", this.updateControls);
3107
+ this.viewer.on("viewposition", this.updateControls);
3108
+ this.viewer.on("zoom", this.updateControls);
3109
+ this.viewer.on("drawviewpoint", this.updateControls);
3110
+ this.viewer.on("contextmenu", this.stopContextMenu);
3111
+ this.updateControls();
3112
+ }
3113
+ dispose() {
3114
+ this.viewer.off("geometryend", this.updateControls);
3115
+ this.viewer.off("viewposition", this.updateControls);
3116
+ this.viewer.off("zoom", this.updateControls);
3117
+ this.viewer.off("drawviewpoint", this.updateControls);
3118
+ this.viewer.off("contextmenu", this.stopContextMenu);
3119
+ this.orbit.removeEventListener("start", this.controlsStart);
3120
+ this.orbit.removeEventListener("change", this.controlsChange);
3121
+ this.orbit.dispose();
3122
+ }
3123
+ }
3124
+
3125
+ class CuttingPlaneDragger extends OrbitDragger {
3126
+ constructor(viewer, normal, color) {
3127
+ super(viewer);
3128
+ this.transformChange = () => {
3129
+ this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
3130
+ this.viewer.update();
3131
+ };
3132
+ this.transformDrag = event => {
3133
+ this.orbit.enabled = !event.value;
3134
+ };
3135
+ this.viewerExplode = () => {
3136
+ this.planeHelper.size = this.viewer.extents.getSize(new Vector3).length();
3137
+ this.viewer.update();
3138
+ };
3139
+ this.onDoubleClick = event => {
3140
+ event.stopPropagation();
3141
+ this.plane.negate();
3142
+ this.viewer.update();
3143
+ };
3144
+ const size = viewer.extents.getSize(new Vector3).length();
3145
+ const center = viewer.extents.getCenter(new Vector3);
3146
+ const constant = -center.dot(normal);
3147
+ this.plane = new Plane(normal, constant);
3148
+ if (!viewer.renderer.clippingPlanes) viewer.renderer.clippingPlanes = [];
3149
+ viewer.renderer.clippingPlanes.push(this.plane);
3150
+ this.planeHelper = new PlaneHelper(this.plane, size, color, center);
3151
+ this.viewer.helpers.add(this.planeHelper);
3152
+ this.planeCenter = new Object3D;
3153
+ this.planeCenter.position.copy(viewer.extents.getCenter(new Vector3));
3154
+ this.viewer.helpers.add(this.planeCenter);
3155
+ this.transform = new TransformControls(viewer.camera, viewer.canvas);
3156
+ this.transform.showX = !!normal.x;
3157
+ this.transform.showY = !!normal.y;
3158
+ this.transform.showZ = !!normal.z;
3159
+ this.transform.attach(this.planeCenter);
3160
+ this.transform.addEventListener("change", this.transformChange);
3161
+ this.transform.addEventListener("dragging-changed", this.transformDrag);
3162
+ this.viewer.helpers.add(this.transform.getHelper());
3163
+ this.viewer.on("explode", this.viewerExplode);
3164
+ this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
3165
+ this.viewer.update();
3166
+ }
3167
+ dispose() {
3168
+ this.viewer.off("explode", this.viewerExplode);
3169
+ this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
3170
+ this.transform.removeEventListener("change", this.transformChange);
3171
+ this.transform.removeEventListener("dragging-changed", this.transformDrag);
3172
+ this.transform.getHelper().removeFromParent();
3173
+ this.transform.detach();
3174
+ this.transform.dispose();
3175
+ this.planeHelper.removeFromParent();
3176
+ this.planeHelper.dispose();
3177
+ this.planeCenter.removeFromParent();
3178
+ super.dispose();
3179
+ }
3180
+ }
3181
+
3182
+ class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
3183
+ constructor(viewer) {
3184
+ super(viewer, new Vector3(1, 0, 0), 16711680);
3185
+ }
3186
+ }
3187
+
3188
+ class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
3189
+ constructor(viewer) {
3190
+ super(viewer, new Vector3(0, 1, 0), 65280);
3191
+ }
3192
+ }
3193
+
3194
+ class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
3195
+ constructor(viewer) {
3196
+ super(viewer, new Vector3(0, 0, 1), 255);
3197
+ }
3198
+ }
3199
+
3200
+ const PRECISION = .01;
3201
+
3202
+ class MeasureLineDragger extends OrbitDragger {
3203
+ constructor(viewer) {
3204
+ super(viewer);
3205
+ this.onPointerDown = event => {
3206
+ if (event.button !== 0) return;
3207
+ this.line.startPoint = this.snapper.getSnapPoint(event);
3208
+ this.line.render();
3209
+ this.viewer.canvas.setPointerCapture(event.pointerId);
3210
+ this.orbit.enabled = !this.line.startPoint;
3211
+ };
3212
+ this.onPointerMove = event => {
3213
+ if (this.orbit.enabled && this.orbit.state !== -1) return;
3214
+ this.line.endPoint = this.snapper.getSnapPoint(event);
3215
+ this.line.render();
3216
+ if (this.line.startPoint) this.changed = true;
3217
+ };
3218
+ this.onPointerUp = event => {
3219
+ if (this.line.startPoint && this.line.endPoint && this.line.getDistance() >= PRECISION) {
3220
+ this.line = new MeasureLine(this.overlay);
3221
+ this.overlay.addLine(this.line);
3222
+ } else {
3223
+ this.line.startPoint = undefined;
3224
+ this.line.endPoint = undefined;
3225
+ this.line.render();
3226
+ }
3227
+ this.viewer.canvas.releasePointerCapture(event.pointerId);
3228
+ this.orbit.enabled = true;
3229
+ };
3230
+ this.onPointerCancel = event => {
3231
+ this.viewer.canvas.dispatchEvent(new PointerEvent("pointerup", event));
3232
+ };
3233
+ this.onPointerLeave = () => {
3234
+ this.line.endPoint = undefined;
3235
+ this.line.render();
3236
+ };
3237
+ this.renderOverlay = () => {
3238
+ this.overlay.render();
3239
+ };
3240
+ this.updateSnapper = () => {
3241
+ this.snapper.update(this.viewer.scene);
3242
+ };
3243
+ this.overlay = new MeasureOverlay(viewer.camera, viewer.canvas);
3244
+ this.overlay.attach();
3245
+ this.line = new MeasureLine(this.overlay);
3246
+ this.overlay.addLine(this.line);
3247
+ this.snapper = new MeasureSnapper(viewer.camera, viewer.canvas);
3248
+ this.snapper.update(viewer.scene);
3249
+ this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown);
3250
+ this.viewer.canvas.addEventListener("pointermove", this.onPointerMove);
3251
+ this.viewer.canvas.addEventListener("pointerup", this.onPointerUp);
3252
+ this.viewer.canvas.addEventListener("pointercancel", this.onPointerCancel);
3253
+ this.viewer.canvas.addEventListener("pointerleave", this.onPointerLeave);
3254
+ this.viewer.addEventListener("render", this.renderOverlay);
3255
+ this.viewer.addEventListener("hide", this.updateSnapper);
3256
+ this.viewer.addEventListener("isolate", this.updateSnapper);
3257
+ this.viewer.addEventListener("showall", this.updateSnapper);
3258
+ }
3259
+ dispose() {
3260
+ this.viewer.canvas.removeEventListener("pointerdown", this.onPointerDown);
3261
+ this.viewer.canvas.removeEventListener("pointermove", this.onPointerMove);
3262
+ this.viewer.canvas.removeEventListener("pointerup", this.onPointerUp);
3263
+ this.viewer.canvas.removeEventListener("pointercancel", this.onPointerCancel);
3264
+ this.viewer.canvas.removeEventListener("pointerleave", this.onPointerLeave);
3265
+ this.viewer.removeEventListener("render", this.renderOverlay);
3266
+ this.viewer.removeEventListener("hide", this.updateSnapper);
3267
+ this.viewer.removeEventListener("isolate", this.updateSnapper);
3268
+ this.viewer.removeEventListener("showall", this.updateSnapper);
3269
+ this.overlay.detach();
3270
+ this.overlay.dispose();
3271
+ super.dispose();
3272
+ }
3273
+ }
3274
+
3275
+ class MeasureSnapper {
3276
+ constructor(camera, canvas) {
3277
+ this.objects = [];
3278
+ this.camera = camera;
3279
+ this.canvas = canvas;
3280
+ this.raycaster = new Raycaster;
3281
+ }
3282
+ getSnapPoint(event) {
3283
+ const mouse = new Vector2(event.clientX, event.clientY);
3284
+ const rect = this.canvas.getBoundingClientRect();
3285
+ const x = (mouse.x - rect.left) / rect.width * 2 - 1;
3286
+ const y = -(mouse.y - rect.top) / rect.height * 2 + 1;
3287
+ const coords = new Vector2(x, y);
3288
+ this.raycaster.setFromCamera(coords, this.camera);
3289
+ this.raycaster.params = {
3290
+ Mesh: {},
3291
+ Line: {
3292
+ threshold: .25
3293
+ },
3294
+ Line2: {
3295
+ threshold: .25
3296
+ },
3297
+ LOD: {},
3298
+ Points: {
3299
+ threshold: .1
3300
+ },
3301
+ Sprite: {}
3302
+ };
3303
+ const intersects = this.raycaster.intersectObjects(this.objects, false);
3304
+ if (intersects.length === 0) return undefined;
3305
+ return intersects[0].point;
3306
+ }
3307
+ update(scene) {
3308
+ this.objects = [];
3309
+ scene.traverseVisible((child => this.objects.push(child)));
3310
+ }
3311
+ }
3312
+
3313
+ class MeasureOverlay {
3314
+ constructor(camera, canvas) {
3315
+ this.lines = [];
3316
+ this.camera = camera;
3317
+ this.canvas = canvas;
3318
+ this.projector = new MeasureProjector(camera, canvas);
3319
+ }
3320
+ attach() {
3321
+ this.container = document.createElement("div");
3322
+ this.container.id = "measure-container";
3323
+ this.container.style.background = "rgba(0,0,0,0)";
3324
+ this.container.style.position = "absolute";
3325
+ this.container.style.top = "0px";
3326
+ this.container.style.left = "0px";
3327
+ this.container.style.width = "100%";
3328
+ this.container.style.height = "100%";
3329
+ this.container.style.outline = "none";
3330
+ this.container.style.pointerEvents = "none";
3331
+ this.container.style.overflow = "hidden";
3332
+ this.canvas.parentElement.appendChild(this.container);
3333
+ }
3334
+ dispose() {
3335
+ this.clear();
3336
+ }
3337
+ detach() {
3338
+ this.container.remove();
3339
+ this.container = undefined;
3340
+ }
3341
+ clear() {
3342
+ this.lines.forEach((line => line.dispose()));
3343
+ this.lines = [];
3344
+ }
3345
+ render() {
3346
+ this.projector.updateProjectionMatrix();
3347
+ this.lines.forEach((line => line.render()));
3348
+ }
3349
+ update() {
3350
+ this.lines.forEach((line => line.update()));
3351
+ }
3352
+ addLine(line) {
3353
+ this.lines.push(line);
3354
+ }
3355
+ removeLine(line) {
3356
+ this.lines = this.lines.filter((x => x !== line));
3357
+ }
3358
+ }
3359
+
3360
+ const _middlePoint = new Vector3;
3361
+
3362
+ class MeasureLine {
3363
+ constructor(overlay) {
3364
+ this.id = Date.now();
3365
+ this.unit = "";
3366
+ this.scale = 1;
3367
+ this.size = 10;
3368
+ this.lineWidth = 2;
3369
+ this.style = {
3370
+ border: "2px solid #FFFFFF",
3371
+ background: "#009bff",
3372
+ boxShadow: "0 0 10px rgba(0,0,0,0.5)",
3373
+ color: "white",
3374
+ font: "1rem system-ui"
3375
+ };
3376
+ this.overlay = overlay;
3377
+ this.elementStartPoint = overlay.container.appendChild(document.createElement("div"));
3378
+ this.elementEndPoint = overlay.container.appendChild(document.createElement("div"));
3379
+ this.elementLine = overlay.container.appendChild(document.createElement("div"));
3380
+ this.elementLabel = overlay.container.appendChild(document.createElement("div"));
3381
+ this.update();
3382
+ }
3383
+ dispose() {
3384
+ this.elementStartPoint.remove();
3385
+ this.elementEndPoint.remove();
3386
+ this.elementLine.remove();
3387
+ this.elementLabel.remove();
3388
+ }
3389
+ render() {
3390
+ const projector = this.overlay.projector;
3391
+ if (this.startPoint) {
3392
+ const {point: point, visible: visible} = projector.projectPoint(this.startPoint);
3393
+ this.elementStartPoint.style.display = visible ? "block" : "none";
3394
+ this.elementStartPoint.style.left = `${point.x}px`;
3395
+ this.elementStartPoint.style.top = `${point.y}px`;
3396
+ } else {
3397
+ this.elementStartPoint.style.display = "none";
3398
+ }
3399
+ if (this.endPoint) {
3400
+ const {point: point, visible: visible} = projector.projectPoint(this.endPoint);
3401
+ this.elementEndPoint.style.display = visible ? "block" : "none";
3402
+ this.elementEndPoint.style.left = `${point.x}px`;
3403
+ this.elementEndPoint.style.top = `${point.y}px`;
3404
+ } else {
3405
+ this.elementEndPoint.style.display = "none";
3406
+ }
3407
+ if (this.startPoint && this.endPoint) {
3408
+ const {point1: point1, point2: point2, visible: visible} = projector.projectLine(this.startPoint, this.endPoint);
3409
+ point2.sub(point1);
3410
+ const angle = point2.angle();
3411
+ const width = point2.length();
3412
+ this.elementLine.style.display = visible ? "block" : "none";
3413
+ this.elementLine.style.left = `${point1.x}px`;
3414
+ this.elementLine.style.top = `${point1.y}px`;
3415
+ this.elementLine.style.width = `${width}px`;
3416
+ this.elementLine.style.transform = `translate(0px, ${-this.lineWidth / 2}px) rotate(${angle}rad)`;
3417
+ } else {
3418
+ this.elementLine.style.display = "none";
3419
+ }
3420
+ if (this.startPoint && this.endPoint) {
3421
+ _middlePoint.lerpVectors(this.startPoint, this.endPoint, .5);
3422
+ const {point: point, visible: visible} = projector.projectPoint(_middlePoint);
3423
+ const distance = this.getDistance();
3424
+ this.elementLabel.style.display = visible && distance >= PRECISION ? "block" : "none";
3425
+ this.elementLabel.style.left = `${point.x}px`;
3426
+ this.elementLabel.style.top = `${point.y}px`;
3427
+ this.elementLabel.innerHTML = `${distance.toFixed(2)} ${this.unit}`;
3428
+ } else {
3429
+ this.elementLabel.style.display = "none";
3430
+ }
3431
+ }
3432
+ update() {
3433
+ this.elementStartPoint.id = `markup-dot-start-${this.id}`;
3434
+ this.elementStartPoint.style.position = "absolute";
3435
+ this.elementStartPoint.style.zIndex = "2";
3436
+ this.elementStartPoint.style.width = `${this.size}px`;
3437
+ this.elementStartPoint.style.height = `${this.size}px`;
3438
+ this.elementStartPoint.style.border = this.style.border;
3439
+ this.elementStartPoint.style.borderRadius = `${this.size}px`;
3440
+ this.elementStartPoint.style.background = this.style.background;
3441
+ this.elementStartPoint.style.boxShadow = this.style.boxShadow;
3442
+ this.elementStartPoint.style.transform = "translate(-50%, -50%)";
3443
+ this.elementEndPoint.id = `markup-dot-end-${this.id}`;
3444
+ this.elementEndPoint.style.position = "absolute";
3445
+ this.elementEndPoint.style.zIndex = "2";
3446
+ this.elementEndPoint.style.width = `${this.size}px`;
3447
+ this.elementEndPoint.style.height = `${this.size}px`;
3448
+ this.elementEndPoint.style.border = this.style.border;
3449
+ this.elementEndPoint.style.borderRadius = `${this.size}px`;
3450
+ this.elementEndPoint.style.background = this.style.background;
3451
+ this.elementEndPoint.style.boxShadow = this.style.boxShadow;
3452
+ this.elementEndPoint.style.transform = "translate(-50%, -50%)";
3453
+ this.elementLine.id = `markup-line-${this.id}`;
3454
+ this.elementLine.style.position = "absolute";
3455
+ this.elementLine.style.zIndex = "1";
3456
+ this.elementLine.style.height = `${this.lineWidth}px`;
3457
+ this.elementLine.style.background = this.style.background;
3458
+ this.elementLine.style.boxShadow = this.style.boxShadow;
3459
+ this.elementLine.style.transformOrigin = `0px ${this.lineWidth / 2}px`;
3460
+ this.elementLabel.id = `markup-label-${this.id}`;
3461
+ this.elementLabel.style.position = "absolute";
3462
+ this.elementLabel.style.zIndex = "3";
3463
+ this.elementLabel.style.padding = "2px";
3464
+ this.elementLabel.style.paddingInline = "5px";
3465
+ this.elementLabel.style.borderRadius = "5px";
3466
+ this.elementLabel.style.background = this.style.background;
3467
+ this.elementLabel.style.boxShadow = this.style.boxShadow;
3468
+ this.elementLabel.style.color = this.style.color;
3469
+ this.elementLabel.style.font = this.style.font;
3470
+ this.elementLabel.style.transform = "translate(-50%, -50%)";
3471
+ }
3472
+ getDistance() {
3473
+ return this.startPoint.distanceTo(this.endPoint) / this.scale;
3474
+ }
3475
+ }
3476
+
3477
+ let _widthHalf;
3335
3478
 
3336
- case TOUCH.PAN:
3337
- if (scope.enablePan === false) return;
3338
- handleTouchStartPan();
3339
- scope.state = STATE.TOUCH_PAN;
3340
- break;
3479
+ let _heightHalf;
3341
3480
 
3342
- default:
3343
- scope.state = STATE.NONE;
3344
- }
3345
- break;
3481
+ const _viewMatrix = new Matrix4;
3346
3482
 
3347
- case 2:
3348
- switch (scope.touches.TWO) {
3349
- case TOUCH.DOLLY_PAN:
3350
- if (scope.enableZoom === false && scope.enablePan === false) return;
3351
- handleTouchStartDollyPan();
3352
- scope.state = STATE.TOUCH_DOLLY_PAN;
3353
- break;
3483
+ const _viewProjectionMatrix = new Matrix4;
3354
3484
 
3355
- case TOUCH.DOLLY_ROTATE:
3356
- if (scope.enableZoom === false && scope.enableRotate === false) return;
3357
- handleTouchStartDollyRotate();
3358
- scope.state = STATE.TOUCH_DOLLY_ROTATE;
3359
- break;
3485
+ const _vector = new Vector3;
3360
3486
 
3361
- default:
3362
- scope.state = STATE.NONE;
3363
- }
3364
- break;
3487
+ const _vector1 = new Vector4;
3365
3488
 
3366
- default:
3367
- scope.state = STATE.NONE;
3368
- }
3369
- if (scope.state !== STATE.NONE) {
3370
- scope.dispatchEvent(_startEvent);
3371
- }
3372
- }
3373
- function onTouchMove(event) {
3374
- trackPointer(event);
3375
- switch (scope.state) {
3376
- case STATE.TOUCH_ROTATE:
3377
- if (scope.enableRotate === false) return;
3378
- handleTouchMoveRotate(event);
3379
- scope.update();
3380
- break;
3489
+ const _vector2 = new Vector4;
3381
3490
 
3382
- case STATE.TOUCH_PAN:
3383
- if (scope.enablePan === false) return;
3384
- handleTouchMovePan(event);
3385
- scope.update();
3386
- break;
3491
+ const point = new Vector2;
3387
3492
 
3388
- case STATE.TOUCH_DOLLY_PAN:
3389
- if (scope.enableZoom === false && scope.enablePan === false) return;
3390
- handleTouchMoveDollyPan(event);
3391
- scope.update();
3392
- break;
3493
+ const point1 = new Vector2;
3393
3494
 
3394
- case STATE.TOUCH_DOLLY_ROTATE:
3395
- if (scope.enableZoom === false && scope.enableRotate === false) return;
3396
- handleTouchMoveDollyRotate(event);
3397
- scope.update();
3398
- break;
3495
+ const point2 = new Vector2;
3399
3496
 
3400
- default:
3401
- scope.state = STATE.NONE;
3402
- }
3403
- }
3404
- function onContextMenu(event) {
3405
- if (scope.enabled === false) return;
3406
- event.preventDefault();
3407
- }
3408
- function addPointer(event) {
3409
- scope.pointers.push(event);
3410
- }
3411
- function removePointer(event) {
3412
- delete scope.pointerPositions[event.pointerId];
3413
- for (let i = 0; i < scope.pointers.length; i++) {
3414
- if (scope.pointers[i].pointerId == event.pointerId) {
3415
- scope.pointers.splice(i, 1);
3416
- return;
3417
- }
3418
- }
3419
- }
3420
- function trackPointer(event) {
3421
- let position = scope.pointerPositions[event.pointerId];
3422
- if (position === undefined) {
3423
- position = new Vector2;
3424
- scope.pointerPositions[event.pointerId] = position;
3425
- }
3426
- position.set(event.pageX, event.pageY);
3427
- }
3428
- function getSecondPointerPosition(event) {
3429
- const pointer = event.pointerId === scope.pointers[0].pointerId ? scope.pointers[1] : scope.pointers[0];
3430
- return scope.pointerPositions[pointer.pointerId];
3431
- }
3432
- scope.domElement.addEventListener("contextmenu", onContextMenu);
3433
- scope.domElement.addEventListener("pointerdown", onPointerDown);
3434
- scope.domElement.addEventListener("pointercancel", onPointerUp);
3435
- scope.domElement.addEventListener("wheel", onMouseWheel, {
3436
- passive: false
3437
- });
3438
- this.update();
3497
+ class MeasureProjector {
3498
+ constructor(camera, canvas) {
3499
+ this.camera = camera;
3500
+ this.canvas = canvas;
3439
3501
  }
3440
- }
3441
-
3442
- class OrbitDragger {
3443
- constructor(viewer) {
3444
- this.updateControls = () => {
3445
- this.orbit.maxDistance = this.viewer.camera.far;
3446
- this.orbit.minDistance = this.viewer.camera.near;
3447
- this.orbit.target.copy(this.viewer.target);
3448
- this.orbit.update();
3449
- };
3450
- this.controlsStart = () => {
3451
- this.changed = false;
3452
- };
3453
- this.controlsChange = () => {
3454
- this.viewer.target.copy(this.orbit.target);
3455
- this.viewer.update();
3456
- switch (this.orbit.state) {
3457
- case STATE.PAN:
3458
- case STATE.TOUCH_PAN:
3459
- this.viewer.emitEvent({
3460
- type: "pan",
3461
- x: this.orbit.panEnd.x,
3462
- y: this.orbit.panEnd.y,
3463
- dX: this.orbit.panDelta.x,
3464
- dY: this.orbit.panDelta.y
3465
- });
3466
- break;
3467
-
3468
- case STATE.DOLLY:
3469
- this.viewer.emitEvent({
3470
- type: "zoomat",
3471
- data: this.orbit.dollyScale,
3472
- x: this.orbit.dollyEnd.x,
3473
- y: this.orbit.dollyEnd.y
3474
- });
3475
- break;
3476
- }
3477
- this.changed = true;
3478
- };
3479
- this.stopContextMenu = event => {
3480
- if (this.changed) {
3481
- event.preventDefault();
3482
- event.stopPropagation();
3483
- }
3484
- };
3485
- this.orbit = new OrbitControls(viewer.camera, viewer.canvas);
3486
- this.orbit.mouseButtons = {
3487
- LEFT: MOUSE.ROTATE,
3488
- MIDDLE: MOUSE.PAN,
3489
- RIGHT: MOUSE.PAN
3490
- };
3491
- this.orbit.touches = {
3492
- ONE: TOUCH.ROTATE,
3493
- TWO: TOUCH.DOLLY_PAN
3502
+ updateProjectionMatrix() {
3503
+ const rect = this.canvas.getBoundingClientRect();
3504
+ _widthHalf = rect.width / 2;
3505
+ _heightHalf = rect.height / 2;
3506
+ _viewMatrix.copy(this.camera.matrixWorldInverse);
3507
+ _viewProjectionMatrix.multiplyMatrices(this.camera.projectionMatrix, _viewMatrix);
3508
+ }
3509
+ projectPoint(p) {
3510
+ _vector.copy(p).applyMatrix4(_viewProjectionMatrix);
3511
+ const visible = _vector.z >= -1 && _vector.z <= 1;
3512
+ point.x = (_vector.x + 1) * _widthHalf;
3513
+ point.y = (-_vector.y + 1) * _heightHalf;
3514
+ return {
3515
+ point: point,
3516
+ visible: visible
3494
3517
  };
3495
- this.orbit.screenSpacePanning = true;
3496
- this.orbit.rotateSpeed = .33;
3497
- this.orbit.addEventListener("start", this.controlsStart);
3498
- this.orbit.addEventListener("change", this.controlsChange);
3499
- this.changed = false;
3500
- this.viewer = viewer;
3501
- this.viewer.on("geometryend", this.updateControls);
3502
- this.viewer.on("viewposition", this.updateControls);
3503
- this.viewer.on("zoom", this.updateControls);
3504
- this.viewer.on("drawviewpoint", this.updateControls);
3505
- this.viewer.on("contextmenu", this.stopContextMenu);
3506
- this.updateControls();
3507
3518
  }
3508
- dispose() {
3509
- this.viewer.off("geometryend", this.updateControls);
3510
- this.viewer.off("viewposition", this.updateControls);
3511
- this.viewer.off("zoom", this.updateControls);
3512
- this.viewer.off("drawviewpoint", this.updateControls);
3513
- this.viewer.off("contextmenu", this.stopContextMenu);
3514
- this.orbit.removeEventListener("change", this.controlsChange);
3515
- this.orbit.dispose();
3519
+ projectLine(p1, p2) {
3520
+ let visible;
3521
+ _vector1.copy(p1).applyMatrix4(_viewProjectionMatrix);
3522
+ _vector2.copy(p2).applyMatrix4(_viewProjectionMatrix);
3523
+ const bc1near = _vector1.z + _vector1.w;
3524
+ const bc2near = _vector2.z + _vector2.w;
3525
+ const bc1far = -_vector1.z + _vector1.w;
3526
+ const bc2far = -_vector2.z + _vector2.w;
3527
+ if (bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0) visible = true; else if (bc1near < 0 && bc2near < 0 || bc1far < 0 && bc2far < 0) visible = false; else {
3528
+ let alpha1 = 0;
3529
+ let alpha2 = 1;
3530
+ if (bc1near < 0) alpha1 = Math.max(alpha1, bc1near / (bc1near - bc2near)); else if (bc2near < 0) alpha2 = Math.min(alpha2, bc1near / (bc1near - bc2near));
3531
+ if (bc1far < 0) alpha1 = Math.max(alpha1, bc1far / (bc1far - bc2far)); else if (bc2far < 0) alpha2 = Math.min(alpha2, bc1far / (bc1far - bc2far));
3532
+ visible = alpha2 >= alpha1;
3533
+ if (visible) {
3534
+ _vector1.lerp(_vector2, alpha1);
3535
+ _vector2.lerp(_vector1, 1 - alpha2);
3536
+ }
3537
+ }
3538
+ _vector1.multiplyScalar(1 / _vector1.w);
3539
+ _vector2.multiplyScalar(1 / _vector2.w);
3540
+ point1.x = (_vector1.x + 1) * _widthHalf;
3541
+ point1.y = (-_vector1.y + 1) * _heightHalf;
3542
+ point2.x = (_vector2.x + 1) * _widthHalf;
3543
+ point2.y = (-_vector2.y + 1) * _heightHalf;
3544
+ return {
3545
+ point1: point1,
3546
+ point2: point2,
3547
+ visible: visible
3548
+ };
3516
3549
  }
3517
3550
  }
3518
3551
 
@@ -3527,17 +3560,6 @@ class PanDragger extends OrbitDragger {
3527
3560
  }
3528
3561
  }
3529
3562
 
3530
- class ZoomDragger extends OrbitDragger {
3531
- constructor(viewer) {
3532
- super(viewer);
3533
- this.orbit.mouseButtons = {
3534
- LEFT: MOUSE.DOLLY,
3535
- MIDDLE: MOUSE.PAN,
3536
- RIGHT: MOUSE.PAN
3537
- };
3538
- }
3539
- }
3540
-
3541
3563
  class WalkControls extends Controls {
3542
3564
  constructor(camera, canvas) {
3543
3565
  super(camera, canvas);
@@ -3720,474 +3742,539 @@ class WalkDragger {
3720
3742
  }
3721
3743
  }
3722
3744
 
3723
- class PlaneHelper extends Line {
3724
- constructor(plane, size = 1, color = 16776960, offset = new Vector3) {
3725
- const positions = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, -1, 0, 1, 1, 0 ];
3726
- const geometry = new BufferGeometry;
3727
- geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
3728
- geometry.computeBoundingSphere();
3729
- super(geometry, new LineBasicMaterial({
3730
- color: color,
3731
- toneMapped: false
3732
- }));
3733
- this.type = "PlaneHelper";
3734
- this.plane = plane;
3735
- this.size = size;
3736
- this.offset = offset;
3737
- const positions2 = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0 ];
3738
- const geometry2 = new BufferGeometry;
3739
- geometry2.setAttribute("position", new Float32BufferAttribute(positions2, 3));
3740
- geometry2.computeBoundingSphere();
3741
- this.helper = new Mesh(geometry2, new MeshBasicMaterial({
3742
- color: color,
3743
- opacity: .2,
3744
- transparent: true,
3745
- depthWrite: false,
3746
- toneMapped: false,
3747
- side: DoubleSide
3745
+ class ZoomDragger extends OrbitDragger {
3746
+ constructor(viewer) {
3747
+ super(viewer);
3748
+ this.orbit.mouseButtons = {
3749
+ LEFT: MOUSE.DOLLY,
3750
+ MIDDLE: MOUSE.PAN,
3751
+ RIGHT: MOUSE.PAN
3752
+ };
3753
+ }
3754
+ }
3755
+
3756
+ const draggers = draggersRegistry("threejs");
3757
+
3758
+ draggers.registerDragger("Pan", (viewer => new PanDragger(viewer)));
3759
+
3760
+ draggers.registerDragger("Orbit", (viewer => new OrbitDragger(viewer)));
3761
+
3762
+ draggers.registerDragger("Zoom", (viewer => new ZoomDragger(viewer)));
3763
+
3764
+ draggers.registerDragger("MeasureLine", (viewer => new MeasureLineDragger(viewer)));
3765
+
3766
+ draggers.registerDragger("CuttingPlaneXAxis", (viewer => new CuttingPlaneXAxisDragger(viewer)));
3767
+
3768
+ draggers.registerDragger("CuttingPlaneYAxis", (viewer => new CuttingPlaneYAxisDragger(viewer)));
3769
+
3770
+ draggers.registerDragger("CuttingPlaneZAxis", (viewer => new CuttingPlaneZAxisDragger(viewer)));
3771
+
3772
+ draggers.registerDragger("Walk", (viewer => new WalkDragger(viewer)));
3773
+
3774
+ function applyModelTransform(viewer, model) {
3775
+ console.warn("applyModelTransform not implemented");
3776
+ }
3777
+
3778
+ function clearMarkup(viewer) {
3779
+ viewer.clearOverlay();
3780
+ }
3781
+
3782
+ class SelectionComponent {
3783
+ constructor(viewer) {
3784
+ this.onPointerDown = event => {
3785
+ if (!event.isPrimary || event.button !== 0) return;
3786
+ this.getMousePosition(event, this.downPosition);
3787
+ };
3788
+ this.onPointerUp = event => {
3789
+ if (!event.isPrimary) return;
3790
+ const upPosition = this.getMousePosition(event, new Vector2);
3791
+ if (this.downPosition.distanceTo(upPosition) !== 0) return;
3792
+ const intersects = this.getPointerIntersects(upPosition);
3793
+ this.clearSelection();
3794
+ if (intersects.length > 0) this.select(intersects[0].object);
3795
+ this.viewer.update();
3796
+ this.viewer.emitEvent({
3797
+ type: "select",
3798
+ data: undefined,
3799
+ handles: this.viewer.getSelected()
3800
+ });
3801
+ };
3802
+ this.onDoubleClick = event => {
3803
+ if (event.button !== 0) return;
3804
+ this.viewer.executeCommand("zoomToSelected");
3805
+ };
3806
+ this.optionsChange = () => {
3807
+ const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
3808
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
3809
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
3810
+ this.viewer.update();
3811
+ };
3812
+ this.viewer = viewer;
3813
+ this.raycaster = new Raycaster;
3814
+ this.downPosition = new Vector2;
3815
+ const {facesColor: facesColor, facesTransparancy: facesTransparancy} = this.viewer.options;
3816
+ this.facesMaterial = new MeshBasicMaterial;
3817
+ this.facesMaterial.color.setRGB(facesColor.r / 255, facesColor.g / 255, facesColor.b / 255);
3818
+ this.facesMaterial.opacity = (255 - facesTransparancy) / 255;
3819
+ this.facesMaterial.transparent = true;
3820
+ this.viewer.addEventListener("pointerdown", this.onPointerDown);
3821
+ this.viewer.addEventListener("pointerup", this.onPointerUp);
3822
+ this.viewer.addEventListener("dblclick", this.onDoubleClick);
3823
+ this.viewer.addEventListener("optionschange", this.optionsChange);
3824
+ }
3825
+ dispose() {
3826
+ this.facesMaterial.dispose();
3827
+ this.viewer.removeEventListener("pointerdown", this.onPointerDown);
3828
+ this.viewer.removeEventListener("pointerup", this.onPointerUp);
3829
+ this.viewer.removeEventListener("dblclick", this.onDoubleClick);
3830
+ this.viewer.removeEventListener("optionschange", this.optionsChange);
3831
+ }
3832
+ getMousePosition(event, target) {
3833
+ return target.set(event.clientX, event.clientY);
3834
+ }
3835
+ getPointerIntersects(mouse) {
3836
+ const rect = this.viewer.canvas.getBoundingClientRect();
3837
+ const x = (mouse.x - rect.left) / rect.width * 2 - 1;
3838
+ const y = -(mouse.y - rect.top) / rect.height * 2 + 1;
3839
+ const coords = new Vector2(x, y);
3840
+ this.raycaster.setFromCamera(coords, this.viewer.camera);
3841
+ const objects = [];
3842
+ this.viewer.scene.traverseVisible((child => objects.push(child)));
3843
+ this.raycaster.params = this.raycaster.params = {
3844
+ Mesh: {},
3845
+ Line: {
3846
+ threshold: .25
3847
+ },
3848
+ Line2: {
3849
+ threshold: .25
3850
+ },
3851
+ LOD: {},
3852
+ Points: {
3853
+ threshold: .1
3854
+ },
3855
+ Sprite: {}
3856
+ };
3857
+ return this.raycaster.intersectObjects(objects, false);
3858
+ }
3859
+ select(object) {
3860
+ if (object.isSelected) return;
3861
+ object.isSelected = true;
3862
+ object.originalMaterial = object.material;
3863
+ object.material = this.facesMaterial;
3864
+ this.viewer.selected.push(object);
3865
+ }
3866
+ clearSelection() {
3867
+ this.viewer.selected.forEach((object => {
3868
+ object.isSelected = false;
3869
+ object.material = object.originalMaterial;
3870
+ }));
3871
+ this.viewer.selected.length = 0;
3872
+ }
3873
+ }
3874
+
3875
+ function clearSelected(viewer) {
3876
+ const selection = new SelectionComponent(viewer);
3877
+ selection.clearSelection();
3878
+ selection.dispose();
3879
+ viewer.update();
3880
+ viewer.emitEvent({
3881
+ type: "select",
3882
+ data: undefined,
3883
+ handles: []
3884
+ });
3885
+ }
3886
+
3887
+ function clearSlices(viewer) {
3888
+ viewer.clearSlices();
3889
+ }
3890
+
3891
+ function createPreview(viewer, type = "image/jpeg", encoderOptions = .25) {
3892
+ viewer.update(true);
3893
+ return viewer.canvas.toDataURL(type, encoderOptions);
3894
+ }
3895
+
3896
+ function calcObjectDepth(object, depth) {
3897
+ let res = depth;
3898
+ object.children.forEach((x => {
3899
+ const objectDepth = calcObjectDepth(x, depth + 1);
3900
+ if (res < objectDepth) res = objectDepth;
3901
+ }));
3902
+ object.originalPosition = object.position.clone();
3903
+ return res;
3904
+ }
3905
+
3906
+ function explodeScene(scene, scale = 0) {
3907
+ scale /= 100;
3908
+ if (!scene.maxDepth) scene.maxDepth = calcObjectDepth(scene, 1);
3909
+ const maxDepth = scene.maxDepth;
3910
+ let explodeDepth = scale * (maxDepth - 1) + 1;
3911
+ if (maxDepth === 1) explodeDepth = 1;
3912
+ function explodeObject(object, depth, parentCenter, parentOffset) {
3913
+ const objectBox = (new Box3).setFromObject(object);
3914
+ const objectCenter = objectBox.getCenter(new Vector3);
3915
+ const objectOffset = parentOffset.clone();
3916
+ if (depth > 0 && depth <= explodeDepth) {
3917
+ const offset = objectCenter.clone().sub(parentCenter).multiplyScalar(scale);
3918
+ objectOffset.add(offset);
3919
+ }
3920
+ object.children.forEach((object => explodeObject(object, depth + 1, objectCenter, objectOffset)));
3921
+ const originalPosition = object.originalPosition;
3922
+ object.position.copy(originalPosition);
3923
+ if (scale > 0) {
3924
+ const direction = objectCenter.sub(parentCenter).normalize();
3925
+ object.position.add(direction.add(objectOffset));
3926
+ }
3927
+ }
3928
+ const sceneExtents = (new Box3).setFromObject(scene);
3929
+ const sceneCenter = sceneExtents.getCenter(new Vector3);
3930
+ explodeObject(scene, 0, sceneCenter, new Vector3(0, 0, 0));
3931
+ }
3932
+
3933
+ function explode(viewer, index = 0) {
3934
+ viewer.models.forEach((gltf => explodeScene(gltf.scene, index)));
3935
+ viewer.update();
3936
+ viewer.emitEvent({
3937
+ type: "explode",
3938
+ data: index
3939
+ });
3940
+ }
3941
+
3942
+ function collect(viewer) {
3943
+ explode(viewer, 0);
3944
+ }
3945
+
3946
+ const defaultViewPositions = {
3947
+ top: new Vector3(0, 0, 1),
3948
+ bottom: new Vector3(0, 0, -1),
3949
+ left: new Vector3(-1, 0, 0),
3950
+ right: new Vector3(1, 0, 0),
3951
+ front: new Vector3(0, -1, 0),
3952
+ back: new Vector3(0, 1, 0),
3953
+ sw: new Vector3(-.5, -.5, 1).normalize(),
3954
+ se: new Vector3(.5, -.5, 1).normalize(),
3955
+ ne: new Vector3(.5, .5, 1).normalize(),
3956
+ nw: new Vector3(-.5, .5, 1).normalize()
3957
+ };
3958
+
3959
+ function setDefaultViewPosition(viewer, position) {
3960
+ const direction = defaultViewPositions[position] || defaultViewPositions["sw"];
3961
+ const center = viewer.extents.getCenter(new Vector3);
3962
+ const sphere = viewer.extents.getBoundingSphere(new Sphere);
3963
+ const offet = direction.clone().multiplyScalar(sphere.radius);
3964
+ const camera = viewer.camera;
3965
+ camera.position.copy(center).add(offet);
3966
+ camera.lookAt(center);
3967
+ camera.updateProjectionMatrix();
3968
+ camera.updateMatrixWorld();
3969
+ viewer.target.copy(center);
3970
+ viewer.update();
3971
+ viewer.emit({
3972
+ type: "viewposition",
3973
+ data: position
3974
+ });
3975
+ viewer.executeCommand("zoomToExtents");
3976
+ }
3977
+
3978
+ function getDefaultViewPositions() {
3979
+ return Object.keys(defaultViewPositions);
3980
+ }
3981
+
3982
+ function getModels(viewer) {
3983
+ return viewer.models.map((model => {
3984
+ var _a;
3985
+ return ((_a = model.userData) === null || _a === void 0 ? void 0 : _a.handle) || "";
3986
+ })).filter((handle => handle));
3987
+ }
3988
+
3989
+ function getSelected(viewer) {
3990
+ return viewer.selected.map((object => {
3991
+ var _a;
3992
+ return (_a = object.userData) === null || _a === void 0 ? void 0 : _a.handle;
3993
+ })).filter((handle => handle));
3994
+ }
3995
+
3996
+ function hideSelected(viewer) {
3997
+ viewer.selected.forEach((object => object.visible = false));
3998
+ const selection = new SelectionComponent(viewer);
3999
+ selection.clearSelection();
4000
+ selection.dispose();
4001
+ viewer.update();
4002
+ viewer.emitEvent({
4003
+ type: "hide"
4004
+ });
4005
+ viewer.emitEvent({
4006
+ type: "select",
4007
+ data: undefined,
4008
+ handles: []
4009
+ });
4010
+ }
4011
+
4012
+ function isolateSelected(viewer) {
4013
+ const selectedSet = new Set(viewer.selected);
4014
+ function isolateObject(object, depth) {
4015
+ let canBeIsolated = true;
4016
+ object.children.forEach((object => {
4017
+ if (selectedSet.has(object)) canBeIsolated = false; else isolateObject(object, depth + 1);
3748
4018
  }));
3749
- this.add(this.helper);
3750
- }
3751
- dispose() {
3752
- this.geometry.dispose();
3753
- this.material.dispose();
3754
- this.children[0].geometry.dispose();
3755
- this.children[0].material.dispose();
3756
- }
3757
- updateMatrixWorld(force) {
3758
- this.position.set(0, 0, 0);
3759
- this.lookAt(this.plane.normal);
3760
- this.position.copy(this.offset);
3761
- this.translateZ(-(this.offset.dot(this.plane.normal) + this.plane.constant));
3762
- this.scale.set(.5 * this.size, .5 * this.size, 1);
3763
- super.updateMatrixWorld(force);
4019
+ if (canBeIsolated && depth > 0) object.visible = false;
4020
+ return canBeIsolated;
3764
4021
  }
4022
+ isolateObject(viewer.scene, 0);
4023
+ viewer.update();
4024
+ viewer.emitEvent({
4025
+ type: "isolate"
4026
+ });
3765
4027
  }
3766
4028
 
3767
- class CuttingPlaneDragger extends OrbitDragger {
3768
- constructor(viewer, normal, color) {
3769
- super(viewer);
3770
- this.transformChange = () => {
3771
- this.plane.constant = -this.planeCenter.position.dot(this.plane.normal);
3772
- this.viewer.update();
3773
- };
3774
- this.transformDrag = event => {
3775
- this.orbit.enabled = !event.value;
3776
- };
3777
- this.viewerExplode = () => {
3778
- this.planeHelper.size = this.viewer.extents.getSize(new Vector3).length();
3779
- this.viewer.update();
3780
- };
3781
- this.onDoubleClick = event => {
3782
- event.stopPropagation();
3783
- this.plane.negate();
3784
- this.viewer.update();
3785
- };
3786
- const size = viewer.extents.getSize(new Vector3).length();
3787
- const center = viewer.extents.getCenter(new Vector3);
3788
- const constant = -center.dot(normal);
3789
- this.plane = new Plane(normal, constant);
3790
- if (!viewer.renderer.clippingPlanes) viewer.renderer.clippingPlanes = [];
3791
- viewer.renderer.clippingPlanes.push(this.plane);
3792
- this.planeHelper = new PlaneHelper(this.plane, size, color, center);
3793
- this.viewer.helpers.add(this.planeHelper);
3794
- this.planeCenter = new Object3D;
3795
- this.planeCenter.position.copy(viewer.extents.getCenter(new Vector3));
3796
- this.viewer.helpers.add(this.planeCenter);
3797
- this.transform = new TransformControls(viewer.camera, viewer.canvas);
3798
- this.transform.showX = !!normal.x;
3799
- this.transform.showY = !!normal.y;
3800
- this.transform.showZ = !!normal.z;
3801
- this.transform.attach(this.planeCenter);
3802
- this.transform.addEventListener("change", this.transformChange);
3803
- this.transform.addEventListener("dragging-changed", this.transformDrag);
3804
- this.viewer.helpers.add(this.transform.getHelper());
3805
- this.viewer.on("explode", this.viewerExplode);
3806
- this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
3807
- this.viewer.update();
3808
- }
3809
- dispose() {
3810
- this.viewer.off("explode", this.viewerExplode);
3811
- this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
3812
- this.transform.removeEventListener("change", this.transformChange);
3813
- this.transform.removeEventListener("dragging-changed", this.transformDrag);
3814
- this.transform.getHelper().removeFromParent();
3815
- this.transform.detach();
3816
- this.transform.dispose();
3817
- this.planeHelper.removeFromParent();
3818
- this.planeHelper.dispose();
3819
- this.planeCenter.removeFromParent();
3820
- super.dispose();
3821
- }
4029
+ function regenerateAll(viewer) {
4030
+ viewer.emit({
4031
+ type: "regenerateall"
4032
+ });
3822
4033
  }
3823
4034
 
3824
- class CuttingPlaneXAxisDragger extends CuttingPlaneDragger {
3825
- constructor(viewer) {
3826
- super(viewer, new Vector3(1, 0, 0), 16711680);
3827
- }
4035
+ function resetView(viewer) {
4036
+ viewer.executeCommand("setActiveDragger");
4037
+ viewer.executeCommand("clearSlices");
4038
+ viewer.executeCommand("clearOverlay");
4039
+ viewer.executeCommand("setMarkupColor");
4040
+ viewer.executeCommand("clearSelected");
4041
+ viewer.executeCommand("showAll");
4042
+ viewer.executeCommand("explode", 0);
4043
+ viewer.executeCommand("zoomToExtents", true);
4044
+ viewer.executeCommand("k3DViewSW");
4045
+ viewer.emit({
4046
+ type: "resetview"
4047
+ });
3828
4048
  }
3829
4049
 
3830
- class CuttingPlaneYAxisDragger extends CuttingPlaneDragger {
3831
- constructor(viewer) {
3832
- super(viewer, new Vector3(0, 1, 0), 65280);
3833
- }
4050
+ function selectModel(viewer, handle) {
4051
+ console.warn("selectModel not implemented");
4052
+ viewer.emit({
4053
+ type: "select",
4054
+ data: []
4055
+ });
3834
4056
  }
3835
4057
 
3836
- class CuttingPlaneZAxisDragger extends CuttingPlaneDragger {
3837
- constructor(viewer) {
3838
- super(viewer, new Vector3(0, 0, 1), 255);
3839
- }
4058
+ function setActiveDragger(viewer, dragger = "") {
4059
+ viewer.setActiveDragger(dragger);
3840
4060
  }
3841
4061
 
3842
- const PRECISION = .01;
4062
+ function setMarkupColor(viewer, r = 255, g = 0, b = 0) {
4063
+ viewer.markup.setMarkupColor(r, g, b);
4064
+ }
3843
4065
 
3844
- class MeasureLineDragger extends OrbitDragger {
3845
- constructor(viewer) {
3846
- super(viewer);
3847
- this.onPointerDown = event => {
3848
- if (event.button !== 0) return;
3849
- this.line.startPoint = this.snapper.getSnapPoint(event);
3850
- this.line.render();
3851
- this.viewer.canvas.setPointerCapture(event.pointerId);
3852
- this.orbit.enabled = !this.line.startPoint;
3853
- };
3854
- this.onPointerMove = event => {
3855
- if (this.orbit.enabled && this.orbit.state !== -1) return;
3856
- this.line.endPoint = this.snapper.getSnapPoint(event);
3857
- this.line.render();
3858
- if (this.line.startPoint) this.changed = true;
3859
- };
3860
- this.onPointerUp = event => {
3861
- if (this.line.startPoint && this.line.endPoint && this.line.getDistance() >= PRECISION) {
3862
- this.line = new MeasureLine(this.overlay);
3863
- this.overlay.addLine(this.line);
3864
- } else {
3865
- this.line.startPoint = undefined;
3866
- this.line.endPoint = undefined;
3867
- this.line.render();
3868
- }
3869
- this.viewer.canvas.releasePointerCapture(event.pointerId);
3870
- this.orbit.enabled = true;
3871
- };
3872
- this.onPointerCancel = event => {
3873
- this.viewer.canvas.dispatchEvent(new PointerEvent("pointerup", event));
3874
- };
3875
- this.onPointerLeave = () => {
3876
- this.line.endPoint = undefined;
3877
- this.line.render();
3878
- };
3879
- this.renderOverlay = () => {
3880
- this.overlay.render();
3881
- };
3882
- this.updateSnapper = () => {
3883
- this.snapper.update(this.viewer.scene);
3884
- };
3885
- this.overlay = new MeasureOverlay(viewer.camera, viewer.canvas);
3886
- this.overlay.attach();
3887
- this.line = new MeasureLine(this.overlay);
3888
- this.overlay.addLine(this.line);
3889
- this.snapper = new MeasureSnapper(viewer.camera, viewer.canvas);
3890
- this.snapper.update(viewer.scene);
3891
- this.viewer.canvas.addEventListener("pointerdown", this.onPointerDown);
3892
- this.viewer.canvas.addEventListener("pointermove", this.onPointerMove);
3893
- this.viewer.canvas.addEventListener("pointerup", this.onPointerUp);
3894
- this.viewer.canvas.addEventListener("pointercancel", this.onPointerCancel);
3895
- this.viewer.canvas.addEventListener("pointerleave", this.onPointerLeave);
3896
- this.viewer.addEventListener("render", this.renderOverlay);
3897
- this.viewer.addEventListener("hide", this.updateSnapper);
3898
- this.viewer.addEventListener("isolate", this.updateSnapper);
3899
- this.viewer.addEventListener("showall", this.updateSnapper);
3900
- }
3901
- dispose() {
3902
- this.viewer.canvas.removeEventListener("pointerdown", this.onPointerDown);
3903
- this.viewer.canvas.removeEventListener("pointermove", this.onPointerMove);
3904
- this.viewer.canvas.removeEventListener("pointerup", this.onPointerUp);
3905
- this.viewer.canvas.removeEventListener("pointercancel", this.onPointerCancel);
3906
- this.viewer.canvas.removeEventListener("pointerleave", this.onPointerLeave);
3907
- this.viewer.removeEventListener("render", this.renderOverlay);
3908
- this.viewer.removeEventListener("hide", this.updateSnapper);
3909
- this.viewer.removeEventListener("isolate", this.updateSnapper);
3910
- this.viewer.removeEventListener("showall", this.updateSnapper);
3911
- this.overlay.detach();
3912
- this.overlay.dispose();
3913
- super.dispose();
3914
- }
4066
+ function setSelected(viewer, handles = []) {
4067
+ const handleSet = new Set(handles);
4068
+ const objects = [];
4069
+ viewer.scene.traverseVisible((child => {
4070
+ var _a;
4071
+ if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
4072
+ }));
4073
+ const selection = new SelectionComponent(viewer);
4074
+ selection.clearSelection();
4075
+ objects.forEach((object => selection.select(object)));
4076
+ selection.dispose();
4077
+ viewer.update();
4078
+ viewer.emitEvent({
4079
+ type: "select",
4080
+ data: undefined,
4081
+ handles: handles
4082
+ });
4083
+ }
4084
+
4085
+ function showAll(viewer) {
4086
+ viewer.scene.traverse((object => object.visible = true));
4087
+ viewer.update();
4088
+ viewer.emitEvent({
4089
+ type: "showall"
4090
+ });
4091
+ }
4092
+
4093
+ function zoomToExtents(viewer) {
4094
+ if (viewer.extents.isEmpty()) return;
4095
+ const center = viewer.extents.getCenter(new Vector3);
4096
+ const distance = viewer.extents.getBoundingSphere(new Sphere).radius;
4097
+ const delta = new Vector3(0, 0, 1);
4098
+ delta.applyQuaternion(viewer.camera.quaternion);
4099
+ delta.multiplyScalar(distance * 3);
4100
+ viewer.camera.position.copy(center).add(delta);
4101
+ viewer.target.copy(center);
4102
+ viewer.update();
4103
+ viewer.emitEvent({
4104
+ type: "zoom"
4105
+ });
3915
4106
  }
3916
4107
 
3917
- class MeasureSnapper {
3918
- constructor(camera, canvas) {
3919
- this.objects = [];
3920
- this.camera = camera;
3921
- this.canvas = canvas;
3922
- this.raycaster = new Raycaster;
3923
- }
3924
- getSnapPoint(event) {
3925
- const mouse = new Vector2(event.clientX, event.clientY);
3926
- const rect = this.canvas.getBoundingClientRect();
3927
- const x = (mouse.x - rect.left) / rect.width * 2 - 1;
3928
- const y = -(mouse.y - rect.top) / rect.height * 2 + 1;
3929
- const coords = new Vector2(x, y);
3930
- this.raycaster.setFromCamera(coords, this.camera);
3931
- this.raycaster.params = {
3932
- Mesh: {},
3933
- Line: {
3934
- threshold: .25
3935
- },
3936
- Line2: {
3937
- threshold: .25
3938
- },
3939
- LOD: {},
3940
- Points: {
3941
- threshold: .1
3942
- },
3943
- Sprite: {}
3944
- };
3945
- const intersects = this.raycaster.intersectObjects(this.objects, false);
3946
- if (intersects.length === 0) return undefined;
3947
- return intersects[0].point;
3948
- }
3949
- update(scene) {
3950
- this.objects = [];
3951
- scene.traverseVisible((child => this.objects.push(child)));
3952
- }
4108
+ function zoomToObjects(viewer, handles = []) {
4109
+ const handleSet = new Set(handles);
4110
+ const objects = [];
4111
+ viewer.scene.traverseVisible((child => {
4112
+ var _a;
4113
+ if (handleSet.has((_a = child.userData) === null || _a === void 0 ? void 0 : _a.handle)) objects.push(child);
4114
+ }));
4115
+ const extents = objects.reduce(((result, object) => result.expandByObject(object)), new Box3);
4116
+ const center = extents.getCenter(new Vector3);
4117
+ const distance = extents.getBoundingSphere(new Sphere).radius;
4118
+ const delta = new Vector3(0, 0, 1);
4119
+ delta.applyQuaternion(viewer.camera.quaternion);
4120
+ delta.multiplyScalar(distance * 3);
4121
+ viewer.camera.position.copy(center).add(delta);
4122
+ viewer.target.copy(center);
4123
+ viewer.update();
4124
+ viewer.emitEvent({
4125
+ type: "zoom"
4126
+ });
3953
4127
  }
3954
4128
 
3955
- class MeasureOverlay {
3956
- constructor(camera, canvas) {
3957
- this.lines = [];
3958
- this.camera = camera;
3959
- this.canvas = canvas;
3960
- this.projector = new MeasureProjector(camera, canvas);
3961
- }
3962
- attach() {
3963
- this.container = document.createElement("div");
3964
- this.container.id = "measure-container";
3965
- this.container.style.background = "rgba(0,0,0,0)";
3966
- this.container.style.position = "absolute";
3967
- this.container.style.top = "0px";
3968
- this.container.style.left = "0px";
3969
- this.container.style.width = "100%";
3970
- this.container.style.height = "100%";
3971
- this.container.style.outline = "none";
3972
- this.container.style.pointerEvents = "none";
3973
- this.container.style.overflow = "hidden";
3974
- this.canvas.parentElement.appendChild(this.container);
3975
- }
3976
- dispose() {
3977
- this.clear();
3978
- }
3979
- detach() {
3980
- this.container.remove();
3981
- this.container = undefined;
3982
- }
3983
- clear() {
3984
- this.lines.forEach((line => line.dispose()));
3985
- this.lines = [];
3986
- }
3987
- render() {
3988
- this.projector.updateProjectionMatrix();
3989
- this.lines.forEach((line => line.render()));
3990
- }
3991
- update() {
3992
- this.lines.forEach((line => line.update()));
3993
- }
3994
- addLine(line) {
3995
- this.lines.push(line);
3996
- }
3997
- removeLine(line) {
3998
- this.lines = this.lines.filter((x => x !== line));
3999
- }
4129
+ function zoomToSelected(viewer) {
4130
+ const extents = viewer.selected.reduce(((result, object) => result.expandByObject(object)), new Box3);
4131
+ if (extents.isEmpty()) extents.copy(viewer.extents);
4132
+ const center = extents.getCenter(new Vector3);
4133
+ const distance = extents.getBoundingSphere(new Sphere).radius;
4134
+ const delta = new Vector3(0, 0, 1);
4135
+ delta.applyQuaternion(viewer.camera.quaternion);
4136
+ delta.multiplyScalar(distance * 3);
4137
+ viewer.camera.position.copy(center).add(delta);
4138
+ viewer.target.copy(center);
4139
+ viewer.update();
4140
+ viewer.emitEvent({
4141
+ type: "zoom"
4142
+ });
4000
4143
  }
4001
4144
 
4002
- const _middlePoint = new Vector3;
4145
+ const commands = commandsRegistry("threejs");
4003
4146
 
4004
- class MeasureLine {
4005
- constructor(overlay) {
4006
- this.id = Date.now();
4007
- this.unit = "";
4008
- this.scale = 1;
4009
- this.size = 10;
4010
- this.lineWidth = 2;
4011
- this.style = {
4012
- border: "2px solid #FFFFFF",
4013
- background: "#009bff",
4014
- boxShadow: "0 0 10px rgba(0,0,0,0.5)",
4015
- color: "white",
4016
- font: "1rem system-ui"
4017
- };
4018
- this.overlay = overlay;
4019
- this.elementStartPoint = overlay.container.appendChild(document.createElement("div"));
4020
- this.elementEndPoint = overlay.container.appendChild(document.createElement("div"));
4021
- this.elementLine = overlay.container.appendChild(document.createElement("div"));
4022
- this.elementLabel = overlay.container.appendChild(document.createElement("div"));
4023
- this.update();
4024
- }
4025
- dispose() {
4026
- this.elementStartPoint.remove();
4027
- this.elementEndPoint.remove();
4028
- this.elementLine.remove();
4029
- this.elementLabel.remove();
4030
- }
4031
- render() {
4032
- const projector = this.overlay.projector;
4033
- if (this.startPoint) {
4034
- const {point: point, visible: visible} = projector.projectPoint(this.startPoint);
4035
- this.elementStartPoint.style.display = visible ? "block" : "none";
4036
- this.elementStartPoint.style.left = `${point.x}px`;
4037
- this.elementStartPoint.style.top = `${point.y}px`;
4038
- } else {
4039
- this.elementStartPoint.style.display = "none";
4040
- }
4041
- if (this.endPoint) {
4042
- const {point: point, visible: visible} = projector.projectPoint(this.endPoint);
4043
- this.elementEndPoint.style.display = visible ? "block" : "none";
4044
- this.elementEndPoint.style.left = `${point.x}px`;
4045
- this.elementEndPoint.style.top = `${point.y}px`;
4046
- } else {
4047
- this.elementEndPoint.style.display = "none";
4048
- }
4049
- if (this.startPoint && this.endPoint) {
4050
- const {point1: point1, point2: point2, visible: visible} = projector.projectLine(this.startPoint, this.endPoint);
4051
- point2.sub(point1);
4052
- const angle = point2.angle();
4053
- const width = point2.length();
4054
- this.elementLine.style.display = visible ? "block" : "none";
4055
- this.elementLine.style.left = `${point1.x}px`;
4056
- this.elementLine.style.top = `${point1.y}px`;
4057
- this.elementLine.style.width = `${width}px`;
4058
- this.elementLine.style.transform = `translate(0px, ${-this.lineWidth / 2}px) rotate(${angle}rad)`;
4059
- } else {
4060
- this.elementLine.style.display = "none";
4061
- }
4062
- if (this.startPoint && this.endPoint) {
4063
- _middlePoint.lerpVectors(this.startPoint, this.endPoint, .5);
4064
- const {point: point, visible: visible} = projector.projectPoint(_middlePoint);
4065
- const distance = this.getDistance();
4066
- this.elementLabel.style.display = visible && distance >= PRECISION ? "block" : "none";
4067
- this.elementLabel.style.left = `${point.x}px`;
4068
- this.elementLabel.style.top = `${point.y}px`;
4069
- this.elementLabel.innerHTML = `${distance.toFixed(2)} ${this.unit}`;
4070
- } else {
4071
- this.elementLabel.style.display = "none";
4072
- }
4073
- }
4074
- update() {
4075
- this.elementStartPoint.id = `markup-dot-start-${this.id}`;
4076
- this.elementStartPoint.style.position = "absolute";
4077
- this.elementStartPoint.style.zIndex = "2";
4078
- this.elementStartPoint.style.width = `${this.size}px`;
4079
- this.elementStartPoint.style.height = `${this.size}px`;
4080
- this.elementStartPoint.style.border = this.style.border;
4081
- this.elementStartPoint.style.borderRadius = `${this.size}px`;
4082
- this.elementStartPoint.style.background = this.style.background;
4083
- this.elementStartPoint.style.boxShadow = this.style.boxShadow;
4084
- this.elementStartPoint.style.transform = "translate(-50%, -50%)";
4085
- this.elementEndPoint.id = `markup-dot-end-${this.id}`;
4086
- this.elementEndPoint.style.position = "absolute";
4087
- this.elementEndPoint.style.zIndex = "2";
4088
- this.elementEndPoint.style.width = `${this.size}px`;
4089
- this.elementEndPoint.style.height = `${this.size}px`;
4090
- this.elementEndPoint.style.border = this.style.border;
4091
- this.elementEndPoint.style.borderRadius = `${this.size}px`;
4092
- this.elementEndPoint.style.background = this.style.background;
4093
- this.elementEndPoint.style.boxShadow = this.style.boxShadow;
4094
- this.elementEndPoint.style.transform = "translate(-50%, -50%)";
4095
- this.elementLine.id = `markup-line-${this.id}`;
4096
- this.elementLine.style.position = "absolute";
4097
- this.elementLine.style.zIndex = "1";
4098
- this.elementLine.style.height = `${this.lineWidth}px`;
4099
- this.elementLine.style.background = this.style.background;
4100
- this.elementLine.style.boxShadow = this.style.boxShadow;
4101
- this.elementLine.style.transformOrigin = `0px ${this.lineWidth / 2}px`;
4102
- this.elementLabel.id = `markup-label-${this.id}`;
4103
- this.elementLabel.style.position = "absolute";
4104
- this.elementLabel.style.zIndex = "3";
4105
- this.elementLabel.style.padding = "2px";
4106
- this.elementLabel.style.paddingInline = "5px";
4107
- this.elementLabel.style.borderRadius = "5px";
4108
- this.elementLabel.style.background = this.style.background;
4109
- this.elementLabel.style.boxShadow = this.style.boxShadow;
4110
- this.elementLabel.style.color = this.style.color;
4111
- this.elementLabel.style.font = this.style.font;
4112
- this.elementLabel.style.transform = "translate(-50%, -50%)";
4113
- }
4114
- getDistance() {
4115
- return this.startPoint.distanceTo(this.endPoint) / this.scale;
4116
- }
4117
- }
4147
+ commands.registerCommand("applyModelTransform", applyModelTransform);
4148
+
4149
+ commands.registerCommand("clearMarkup", clearMarkup);
4150
+
4151
+ commands.registerCommand("clearSelected", clearSelected);
4152
+
4153
+ commands.registerCommand("clearSlices", clearSlices);
4154
+
4155
+ commands.registerCommand("createPreview", createPreview);
4156
+
4157
+ commands.registerCommand("explode", explode);
4158
+
4159
+ commands.registerCommand("collect", collect);
4160
+
4161
+ commands.registerCommand("getDefaultViewPositions", getDefaultViewPositions);
4162
+
4163
+ commands.registerCommand("getModels", getModels);
4164
+
4165
+ commands.registerCommand("getSelected", getSelected);
4166
+
4167
+ commands.registerCommand("hideSelected", hideSelected);
4168
+
4169
+ commands.registerCommand("isolateSelected", isolateSelected);
4170
+
4171
+ commands.registerCommand("regenerateAll", regenerateAll);
4172
+
4173
+ commands.registerCommand("resetView", resetView);
4174
+
4175
+ commands.registerCommand("selectModel", selectModel);
4118
4176
 
4119
- let _widthHalf;
4177
+ commands.registerCommand("setActiveDragger", setActiveDragger);
4120
4178
 
4121
- let _heightHalf;
4179
+ commands.registerCommand("setDefaultViewPosition", setDefaultViewPosition);
4122
4180
 
4123
- const _viewMatrix = new Matrix4;
4181
+ commands.registerCommand("setMarkupColor", setMarkupColor);
4124
4182
 
4125
- const _viewProjectionMatrix = new Matrix4;
4183
+ commands.registerCommand("setSelected", setSelected);
4126
4184
 
4127
- const _vector = new Vector3;
4185
+ commands.registerCommand("showAll", showAll);
4128
4186
 
4129
- const _vector1 = new Vector4;
4187
+ commands.registerCommand("zoomToExtents", zoomToExtents);
4130
4188
 
4131
- const _vector2 = new Vector4;
4189
+ commands.registerCommand("zoomToObjects", zoomToObjects);
4132
4190
 
4133
- const point = new Vector2;
4191
+ commands.registerCommand("zoomToSelected", zoomToSelected);
4134
4192
 
4135
- const point1 = new Vector2;
4193
+ commands.registerCommand("top", (viewer => setDefaultViewPosition(viewer, "top")));
4136
4194
 
4137
- const point2 = new Vector2;
4195
+ commands.registerCommand("bottom", (viewer => setDefaultViewPosition(viewer, "bottom")));
4138
4196
 
4139
- class MeasureProjector {
4140
- constructor(camera, canvas) {
4141
- this.camera = camera;
4142
- this.canvas = canvas;
4197
+ commands.registerCommand("left", (viewer => setDefaultViewPosition(viewer, "left")));
4198
+
4199
+ commands.registerCommand("right", (viewer => setDefaultViewPosition(viewer, "right")));
4200
+
4201
+ commands.registerCommand("front", (viewer => setDefaultViewPosition(viewer, "front")));
4202
+
4203
+ commands.registerCommand("back", (viewer => setDefaultViewPosition(viewer, "back")));
4204
+
4205
+ commands.registerCommand("sw", (viewer => setDefaultViewPosition(viewer, "sw")));
4206
+
4207
+ commands.registerCommand("se", (viewer => setDefaultViewPosition(viewer, "se")));
4208
+
4209
+ commands.registerCommand("ne", (viewer => setDefaultViewPosition(viewer, "ne")));
4210
+
4211
+ commands.registerCommand("nw", (viewer => setDefaultViewPosition(viewer, "nw")));
4212
+
4213
+ commands.registerCommandAlias("clearMarkup", "clearOverlay");
4214
+
4215
+ commands.registerCommandAlias("clearSelected", "unselect");
4216
+
4217
+ commands.registerCommandAlias("zoomToExtents", "zoomExtents");
4218
+
4219
+ commands.registerCommandAlias("top", "k3DViewTop");
4220
+
4221
+ commands.registerCommandAlias("bottom", "k3DViewBottom");
4222
+
4223
+ commands.registerCommandAlias("left", "k3DViewLeft");
4224
+
4225
+ commands.registerCommandAlias("right", "k3DViewRight");
4226
+
4227
+ commands.registerCommandAlias("front", "k3DViewFront");
4228
+
4229
+ commands.registerCommandAlias("back", "k3DViewBack");
4230
+
4231
+ commands.registerCommandAlias("se", "k3DViewSE");
4232
+
4233
+ commands.registerCommandAlias("sw", "k3DViewSW");
4234
+
4235
+ commands.registerCommandAlias("ne", "k3DViewNE");
4236
+
4237
+ commands.registerCommandAlias("nw", "k3DViewNW");
4238
+
4239
+ class BackgroundComponent {
4240
+ constructor(viewer) {
4241
+ this.syncOptions = () => {
4242
+ this.backgroundColor.setHex(16777215);
4243
+ };
4244
+ this.viewer = viewer;
4245
+ this.backgroundColor = new Color(16777215);
4246
+ const environment = new RoomEnvironment;
4247
+ const pmremGenerator = new PMREMGenerator(this.viewer.renderer);
4248
+ this.viewer.renderer.setClearColor(this.backgroundColor);
4249
+ this.viewer.scene.background = this.backgroundColor;
4250
+ this.viewer.scene.environment = pmremGenerator.fromScene(environment).texture;
4251
+ this.viewer.addEventListener("optionschange", this.syncOptions);
4252
+ environment.dispose();
4143
4253
  }
4144
- updateProjectionMatrix() {
4145
- const rect = this.canvas.getBoundingClientRect();
4146
- _widthHalf = rect.width / 2;
4147
- _heightHalf = rect.height / 2;
4148
- _viewMatrix.copy(this.camera.matrixWorldInverse);
4149
- _viewProjectionMatrix.multiplyMatrices(this.camera.projectionMatrix, _viewMatrix);
4254
+ dispose() {
4255
+ this.viewer.removeEventListener("optionschange", this.syncOptions);
4256
+ this.viewer.scene.environment = undefined;
4257
+ this.viewer.scene.background = undefined;
4150
4258
  }
4151
- projectPoint(p) {
4152
- _vector.copy(p).applyMatrix4(_viewProjectionMatrix);
4153
- const visible = _vector.z >= -1 && _vector.z <= 1;
4154
- point.x = (_vector.x + 1) * _widthHalf;
4155
- point.y = (-_vector.y + 1) * _heightHalf;
4156
- return {
4157
- point: point,
4158
- visible: visible
4259
+ }
4260
+
4261
+ class DefaultPositionComponent {
4262
+ constructor(viewer) {
4263
+ this.geometryEnd = event => {
4264
+ const box = this.viewer.extents;
4265
+ const size = box.getSize(new Vector3).length();
4266
+ this.viewer.camera.near = size / 100;
4267
+ this.viewer.camera.far = size * 100;
4268
+ this.viewer.camera.updateMatrixWorld();
4269
+ this.viewer.camera.updateProjectionMatrix();
4270
+ this.viewer.executeCommand("setDefaultViewPosition", "sw");
4271
+ this.viewer.executeCommand("zoomToExtents");
4159
4272
  };
4273
+ this.viewer = viewer;
4274
+ this.viewer.addEventListener("geometryend", this.geometryEnd);
4160
4275
  }
4161
- projectLine(p1, p2) {
4162
- let visible;
4163
- _vector1.copy(p1).applyMatrix4(_viewProjectionMatrix);
4164
- _vector2.copy(p2).applyMatrix4(_viewProjectionMatrix);
4165
- const bc1near = _vector1.z + _vector1.w;
4166
- const bc2near = _vector2.z + _vector2.w;
4167
- const bc1far = -_vector1.z + _vector1.w;
4168
- const bc2far = -_vector2.z + _vector2.w;
4169
- if (bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0) visible = true; else if (bc1near < 0 && bc2near < 0 || bc1far < 0 && bc2far < 0) visible = false; else {
4170
- let alpha1 = 0;
4171
- let alpha2 = 1;
4172
- if (bc1near < 0) alpha1 = Math.max(alpha1, bc1near / (bc1near - bc2near)); else if (bc2near < 0) alpha2 = Math.min(alpha2, bc1near / (bc1near - bc2near));
4173
- if (bc1far < 0) alpha1 = Math.max(alpha1, bc1far / (bc1far - bc2far)); else if (bc2far < 0) alpha2 = Math.min(alpha2, bc1far / (bc1far - bc2far));
4174
- visible = alpha2 >= alpha1;
4175
- if (visible) {
4176
- _vector1.lerp(_vector2, alpha1);
4177
- _vector2.lerp(_vector1, 1 - alpha2);
4178
- }
4179
- }
4180
- _vector1.multiplyScalar(1 / _vector1.w);
4181
- _vector2.multiplyScalar(1 / _vector2.w);
4182
- point1.x = (_vector1.x + 1) * _widthHalf;
4183
- point1.y = (-_vector1.y + 1) * _heightHalf;
4184
- point2.x = (_vector2.x + 1) * _widthHalf;
4185
- point2.y = (-_vector2.y + 1) * _heightHalf;
4186
- return {
4187
- point1: point1,
4188
- point2: point2,
4189
- visible: visible
4190
- };
4276
+ dispose() {
4277
+ this.viewer.removeEventListener("geometryend", this.geometryEnd);
4191
4278
  }
4192
4279
  }
4193
4280
 
@@ -4227,45 +4314,17 @@ class LightComponent {
4227
4314
  }
4228
4315
  }
4229
4316
 
4230
- class BackgroundComponent {
4231
- constructor(viewer) {
4232
- this.syncOptions = () => {
4233
- this.backgroundColor.setHex(16777215);
4234
- };
4235
- this.viewer = viewer;
4236
- this.backgroundColor = new Color(16777215);
4237
- const environment = new RoomEnvironment;
4238
- const pmremGenerator = new PMREMGenerator(this.viewer.renderer);
4239
- this.viewer.renderer.setClearColor(this.backgroundColor);
4240
- this.viewer.scene.background = this.backgroundColor;
4241
- this.viewer.scene.environment = pmremGenerator.fromScene(environment).texture;
4242
- this.viewer.addEventListener("optionschange", this.syncOptions);
4243
- environment.dispose();
4244
- }
4245
- dispose() {
4246
- this.viewer.removeEventListener("optionschange", this.syncOptions);
4247
- this.viewer.scene.environment = undefined;
4248
- this.viewer.scene.background = undefined;
4249
- }
4250
- }
4251
-
4252
- class DefaultPositionComponent {
4317
+ class RenderLoopComponent {
4253
4318
  constructor(viewer) {
4254
- this.geometryEnd = event => {
4255
- const box = this.viewer.extents;
4256
- const size = box.getSize(new Vector3).length();
4257
- this.viewer.camera.near = size / 100;
4258
- this.viewer.camera.far = size * 100;
4259
- this.viewer.camera.updateMatrixWorld();
4260
- this.viewer.camera.updateProjectionMatrix();
4261
- this.viewer.executeCommand("setDefaultViewPosition", "sw");
4262
- this.viewer.executeCommand("zoomToExtents");
4319
+ this.animate = (time = 0) => {
4320
+ this.requestId = requestAnimationFrame(this.animate);
4321
+ this.viewer.render(time);
4263
4322
  };
4264
4323
  this.viewer = viewer;
4265
- this.viewer.addEventListener("geometryend", this.geometryEnd);
4324
+ this.animate();
4266
4325
  }
4267
4326
  dispose() {
4268
- this.viewer.removeEventListener("geometryend", this.geometryEnd);
4327
+ cancelAnimationFrame(this.requestId);
4269
4328
  }
4270
4329
  }
4271
4330
 
@@ -4293,20 +4352,6 @@ class ResizeCanvasComponent {
4293
4352
  }
4294
4353
  }
4295
4354
 
4296
- class RenderLoopComponent {
4297
- constructor(viewer) {
4298
- this.animate = (time = 0) => {
4299
- this.requestId = requestAnimationFrame(this.animate);
4300
- this.viewer.render(time);
4301
- };
4302
- this.viewer = viewer;
4303
- this.animate();
4304
- }
4305
- dispose() {
4306
- cancelAnimationFrame(this.requestId);
4307
- }
4308
- }
4309
-
4310
4355
  class WCSHelper extends Object3D {
4311
4356
  constructor(camera) {
4312
4357
  super();
@@ -4405,6 +4450,94 @@ class WCSHelperComponent {
4405
4450
  }
4406
4451
  }
4407
4452
 
4453
+ const components = componentsRegistry("threejs");
4454
+
4455
+ components.registerComponent("ExtentsComponent", (viewer => new ExtentsComponent(viewer)));
4456
+
4457
+ components.registerComponent("LightComponent", (viewer => new LightComponent(viewer)));
4458
+
4459
+ components.registerComponent("BackgroundComponent", (viewer => new BackgroundComponent(viewer)));
4460
+
4461
+ components.registerComponent("ResizeCanvasComponent", (viewer => new ResizeCanvasComponent(viewer)));
4462
+
4463
+ components.registerComponent("RenderLoopComponent", (viewer => new RenderLoopComponent(viewer)));
4464
+
4465
+ components.registerComponent("DefaultPositionComponent", (viewer => new DefaultPositionComponent(viewer)));
4466
+
4467
+ components.registerComponent("SelectionComponent", (viewer => new SelectionComponent(viewer)));
4468
+
4469
+ components.registerComponent("WCSHelperComponent", (viewer => new WCSHelperComponent(viewer)));
4470
+
4471
+ class GLTFLoadingManager extends LoadingManager {
4472
+ constructor(file, externalData = new Map, params = {}) {
4473
+ super();
4474
+ this.path = "";
4475
+ this.resourcePath = "";
4476
+ this.fileURL = "";
4477
+ this.dataURLs = new Map;
4478
+ this.path = params.path || "";
4479
+ if (typeof file === "string") {
4480
+ this.fileURL = file;
4481
+ this.resourcePath = LoaderUtils.extractUrlBase(file);
4482
+ } else {
4483
+ externalData.forEach(((value, key) => this.fileURL = value === file ? key : this.fileURL));
4484
+ externalData.set(this.fileURL, file);
4485
+ }
4486
+ externalData.forEach(((value, key) => {
4487
+ let dataURL;
4488
+ if (typeof value === "string") dataURL = value; else dataURL = URL.createObjectURL(new Blob([ value ]));
4489
+ this.dataURLs.set(key, dataURL);
4490
+ }));
4491
+ this.setURLModifier((url => {
4492
+ const key = decodeURI(url).replace(this.path, "").replace(this.resourcePath, "").replace(/^(\.?\/)/, "");
4493
+ const dataURL = this.dataURLs.get(key);
4494
+ return dataURL !== null && dataURL !== void 0 ? dataURL : url;
4495
+ }));
4496
+ }
4497
+ dispose() {
4498
+ this.dataURLs.forEach(URL.revokeObjectURL);
4499
+ }
4500
+ }
4501
+
4502
+ class EventEmitter2 {
4503
+ constructor() {
4504
+ this._listeners = {};
4505
+ }
4506
+ addEventListener(type, listener) {
4507
+ if (this._listeners[type] === undefined) this._listeners[type] = [];
4508
+ this._listeners[type].push(listener);
4509
+ return this;
4510
+ }
4511
+ removeEventListener(type, listener) {
4512
+ if (this._listeners[type] === undefined) return this;
4513
+ const listeners = this._listeners[type].filter((x => x !== listener));
4514
+ if (listeners.length !== 0) this._listeners[type] = listeners; else delete this._listeners[type];
4515
+ return this;
4516
+ }
4517
+ removeAllListeners(type) {
4518
+ if (type) delete this._listeners[type]; else this._listeners = {};
4519
+ return this;
4520
+ }
4521
+ emitEvent(event) {
4522
+ if (this._listeners[event.type] === undefined) return false;
4523
+ const invoke = this._listeners[event.type].slice();
4524
+ invoke.forEach((listener => listener.call(this, event)));
4525
+ return true;
4526
+ }
4527
+ on(type, listener) {
4528
+ return this.addEventListener(type, listener);
4529
+ }
4530
+ off(type, listener) {
4531
+ return this.removeEventListener(type, listener);
4532
+ }
4533
+ emit(type, ...args) {
4534
+ if (typeof type === "string") return this.emitEvent({
4535
+ type: type,
4536
+ args: args
4537
+ }); else if (typeof type === "object") return this.emitEvent(type); else return false;
4538
+ }
4539
+ }
4540
+
4408
4541
  class Viewer extends EventEmitter2 {
4409
4542
  constructor(client) {
4410
4543
  super();
@@ -4412,22 +4545,12 @@ class Viewer extends EventEmitter2 {
4412
4545
  this.client = client;
4413
4546
  this.canvasEvents = CANVAS_EVENTS;
4414
4547
  this.canvaseventlistener = event => this.emit(event);
4548
+ this.models = [];
4549
+ this.selected = [];
4415
4550
  this.extents = new Box3;
4416
4551
  this.target = new Vector3;
4417
- this.draggerFactory = {
4418
- Pan: PanDragger,
4419
- Zoom: ZoomDragger,
4420
- Orbit: OrbitDragger,
4421
- Walk: WalkDragger,
4422
- CuttingPlaneXAxis: CuttingPlaneXAxisDragger,
4423
- CuttingPlaneYAxis: CuttingPlaneYAxisDragger,
4424
- CuttingPlaneZAxis: CuttingPlaneZAxisDragger,
4425
- MeasureLine: MeasureLineDragger
4426
- };
4427
4552
  this._activeDragger = null;
4428
- this.models = [];
4429
- this.components = [];
4430
- this.selected = [];
4553
+ this._components = [];
4431
4554
  this.renderTime = 0;
4432
4555
  this.render = this.render.bind(this);
4433
4556
  this.update = this.update.bind(this);
@@ -4437,7 +4560,10 @@ class Viewer extends EventEmitter2 {
4437
4560
  return this._options;
4438
4561
  }
4439
4562
  get draggers() {
4440
- return Object.keys(this.draggerFactory);
4563
+ return [ ...draggers.getDraggers().keys() ];
4564
+ }
4565
+ get components() {
4566
+ return [ ...components.getComponents().keys() ];
4441
4567
  }
4442
4568
  get markup() {
4443
4569
  return this._markup;
@@ -4462,14 +4588,9 @@ class Viewer extends EventEmitter2 {
4462
4588
  this.canvas = canvas;
4463
4589
  this.canvasEvents.forEach((x => canvas.addEventListener(x, this.canvaseventlistener)));
4464
4590
  this._markup.initialize(this.canvas, this.canvasEvents, this, this);
4465
- this.components.push(new ExtentsComponent(this));
4466
- this.components.push(new LightComponent(this));
4467
- this.components.push(new BackgroundComponent(this));
4468
- this.components.push(new DefaultPositionComponent(this));
4469
- this.components.push(new ResizeCanvasComponent(this));
4470
- this.components.push(new RenderLoopComponent(this));
4471
- this.components.push(new SelectionComponent(this));
4472
- this.components.push(new WCSHelperComponent(this));
4591
+ for (let name of components.getComponents().keys()) {
4592
+ this._components.push(components.createComponent(name, this));
4593
+ }
4473
4594
  this.syncOptions();
4474
4595
  this.syncOverlay();
4475
4596
  this.renderTime = performance.now();
@@ -4495,8 +4616,8 @@ class Viewer extends EventEmitter2 {
4495
4616
  this.emitEvent({
4496
4617
  type: "dispose"
4497
4618
  });
4498
- this.components.forEach((component => component.dispose()));
4499
- this.components = [];
4619
+ this._components.forEach((component => component.dispose()));
4620
+ this._components = [];
4500
4621
  this.setActiveDragger();
4501
4622
  this.removeAllListeners();
4502
4623
  this.clear();
@@ -4516,6 +4637,7 @@ class Viewer extends EventEmitter2 {
4516
4637
  return !!this.renderer;
4517
4638
  }
4518
4639
  render(time) {
4640
+ var _a, _b;
4519
4641
  if (!this.renderNeeded) return;
4520
4642
  if (!this.renderer) return;
4521
4643
  this.renderNeeded = false;
@@ -4527,6 +4649,7 @@ class Viewer extends EventEmitter2 {
4527
4649
  this.renderer.autoClear = false;
4528
4650
  this.renderer.render(this.helpers, this.camera);
4529
4651
  this.renderer.clippingPlanes = clippingPlanes;
4652
+ (_b = (_a = this._activeDragger) === null || _a === void 0 ? void 0 : _a.updatePreview) === null || _b === void 0 ? void 0 : _b.call(_a);
4530
4653
  const deltaTime = (time - this.renderTime) / 1e3;
4531
4654
  this.renderTime = time;
4532
4655
  this.emitEvent({
@@ -4704,21 +4827,25 @@ class Viewer extends EventEmitter2 {
4704
4827
  return this._activeDragger;
4705
4828
  }
4706
4829
  setActiveDragger(name = "") {
4830
+ var _a, _b;
4707
4831
  if (!this._activeDragger || this._activeDragger.name !== name) {
4832
+ const oldDragger = this._activeDragger;
4833
+ let newDragger = null;
4708
4834
  if (this._activeDragger) {
4709
4835
  this._activeDragger.dispose();
4710
4836
  this._activeDragger = null;
4711
4837
  }
4712
4838
  if (this.isInitialized()) {
4713
- const Constructor = this.draggerFactory[name];
4714
- if (Constructor) {
4715
- this._activeDragger = new Constructor(this);
4716
- this._activeDragger.name = name;
4839
+ newDragger = draggers.createDragger(name, this);
4840
+ if (newDragger) {
4841
+ this._activeDragger = newDragger;
4842
+ (_b = (_a = this._activeDragger).initialize) === null || _b === void 0 ? void 0 : _b.call(_a);
4717
4843
  }
4718
4844
  }
4719
4845
  const canvas = this.canvas;
4720
4846
  if (canvas) {
4721
- canvas.className = canvas.className.split(" ").filter((x => !x.startsWith("oda-cursor-"))).filter((x => x)).concat(`oda-cursor-${name.toLowerCase()}`).join(" ");
4847
+ if (oldDragger) canvas.classList.remove(`oda-cursor-${oldDragger.name.toLowerCase()}`);
4848
+ if (newDragger) canvas.classList.add(`oda-cursor-${newDragger.name.toLowerCase()}`);
4722
4849
  }
4723
4850
  this.emitEvent({
4724
4851
  type: "changeactivedragger",
@@ -4778,10 +4905,10 @@ class Viewer extends EventEmitter2 {
4778
4905
  };
4779
4906
  }
4780
4907
  executeCommand(id, ...args) {
4781
- return commands("ThreeJS").executeCommand(id, this, ...args);
4908
+ return commands.executeCommand(id, this, ...args);
4782
4909
  }
4783
- getComponent(type) {
4784
- return this.components.find((component => component instanceof type));
4910
+ getComponent(name) {
4911
+ return this._components.find((component => component.name === name));
4785
4912
  }
4786
4913
  drawViewpoint(viewpoint) {
4787
4914
  var _a, _b, _c;
@@ -4870,5 +4997,5 @@ class Viewer extends EventEmitter2 {
4870
4997
  }
4871
4998
  }
4872
4999
 
4873
- export { CANVAS_EVENTS, CanvasEvents, Dragger, Options, Viewer, commands, defaultOptions };
5000
+ export { CANVAS_EVENTS, CanvasEvents, Component, Dragger, KonvaMarkup as Markup, Options, Viewer, commands, commandsRegistry, components, componentsRegistry, defaultOptions, draggers, draggersRegistry };
4874
5001
  //# sourceMappingURL=viewer-three.module.js.map