@shapediver/viewer.features.drawing-tools 3.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.
- package/LICENSE +73 -0
- package/README.md +161 -0
- package/dist/api/implementation/DrawingToolsApi.d.ts +31 -0
- package/dist/api/implementation/DrawingToolsApi.d.ts.map +1 -0
- package/dist/api/implementation/DrawingToolsApi.js +111 -0
- package/dist/api/implementation/DrawingToolsApi.js.map +1 -0
- package/dist/api/implementation/restrictions/AbstractRestrictionApi.d.ts +10 -0
- package/dist/api/implementation/restrictions/AbstractRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/AbstractRestrictionApi.js +38 -0
- package/dist/api/implementation/restrictions/AbstractRestrictionApi.js.map +1 -0
- package/dist/api/implementation/restrictions/AbstractSnapRestrictionApi.d.ts +11 -0
- package/dist/api/implementation/restrictions/AbstractSnapRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/AbstractSnapRestrictionApi.js +40 -0
- package/dist/api/implementation/restrictions/AbstractSnapRestrictionApi.js.map +1 -0
- package/dist/api/implementation/restrictions/axis/AxisRestrictionApi.d.ts +7 -0
- package/dist/api/implementation/restrictions/axis/AxisRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/axis/AxisRestrictionApi.js +24 -0
- package/dist/api/implementation/restrictions/axis/AxisRestrictionApi.js.map +1 -0
- package/dist/api/implementation/restrictions/geometry/GeometryRestrictionApi.d.ts +15 -0
- package/dist/api/implementation/restrictions/geometry/GeometryRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/geometry/GeometryRestrictionApi.js +54 -0
- package/dist/api/implementation/restrictions/geometry/GeometryRestrictionApi.js.map +1 -0
- package/dist/api/implementation/restrictions/plane/PlaneRestrictionApi.d.ts +18 -0
- package/dist/api/implementation/restrictions/plane/PlaneRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/plane/PlaneRestrictionApi.js +61 -0
- package/dist/api/implementation/restrictions/plane/PlaneRestrictionApi.js.map +1 -0
- package/dist/api/implementation/restrictions/plane/snap/AngularRestrictionApi.d.ts +10 -0
- package/dist/api/implementation/restrictions/plane/snap/AngularRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/plane/snap/AngularRestrictionApi.js +40 -0
- package/dist/api/implementation/restrictions/plane/snap/AngularRestrictionApi.js.map +1 -0
- package/dist/api/implementation/restrictions/plane/snap/GridRestrictionApi.d.ts +10 -0
- package/dist/api/implementation/restrictions/plane/snap/GridRestrictionApi.d.ts.map +1 -0
- package/dist/api/implementation/restrictions/plane/snap/GridRestrictionApi.js +40 -0
- package/dist/api/implementation/restrictions/plane/snap/GridRestrictionApi.js.map +1 -0
- package/dist/api/interfaces/IDrawingToolsApi.d.ts +89 -0
- package/dist/api/interfaces/IDrawingToolsApi.d.ts.map +1 -0
- package/dist/api/interfaces/IDrawingToolsApi.js +3 -0
- package/dist/api/interfaces/IDrawingToolsApi.js.map +1 -0
- package/dist/api/interfaces/IRestrictionApi.d.ts +11 -0
- package/dist/api/interfaces/IRestrictionApi.d.ts.map +1 -0
- package/dist/api/interfaces/IRestrictionApi.js +3 -0
- package/dist/api/interfaces/IRestrictionApi.js.map +1 -0
- package/dist/api/interfaces/ISnapRestrictionApi.d.ts +13 -0
- package/dist/api/interfaces/ISnapRestrictionApi.d.ts.map +1 -0
- package/dist/api/interfaces/ISnapRestrictionApi.js +3 -0
- package/dist/api/interfaces/ISnapRestrictionApi.js.map +1 -0
- package/dist/business/implementation/DrawingToolsManager.d.ts +95 -0
- package/dist/business/implementation/DrawingToolsManager.d.ts.map +1 -0
- package/dist/business/implementation/DrawingToolsManager.js +544 -0
- package/dist/business/implementation/DrawingToolsManager.js.map +1 -0
- package/dist/business/implementation/managers/HistoryManager.d.ts +19 -0
- package/dist/business/implementation/managers/HistoryManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/HistoryManager.js +89 -0
- package/dist/business/implementation/managers/HistoryManager.js.map +1 -0
- package/dist/business/implementation/managers/TextVisualizationManager.d.ts +14 -0
- package/dist/business/implementation/managers/TextVisualizationManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/TextVisualizationManager.js +228 -0
- package/dist/business/implementation/managers/TextVisualizationManager.js.map +1 -0
- package/dist/business/implementation/managers/geometry/GeometryManager.d.ts +23 -0
- package/dist/business/implementation/managers/geometry/GeometryManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/geometry/GeometryManager.js +82 -0
- package/dist/business/implementation/managers/geometry/GeometryManager.js.map +1 -0
- package/dist/business/implementation/managers/geometry/GeometryMathManager.d.ts +73 -0
- package/dist/business/implementation/managers/geometry/GeometryMathManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/geometry/GeometryMathManager.js +230 -0
- package/dist/business/implementation/managers/geometry/GeometryMathManager.js.map +1 -0
- package/dist/business/implementation/managers/geometry/GeometryState.d.ts +46 -0
- package/dist/business/implementation/managers/geometry/GeometryState.d.ts.map +1 -0
- package/dist/business/implementation/managers/geometry/GeometryState.js +323 -0
- package/dist/business/implementation/managers/geometry/GeometryState.js.map +1 -0
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.d.ts +16 -0
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.d.ts.map +1 -0
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.js +157 -0
- package/dist/business/implementation/managers/geometry/helpers/GeometryManagerHelper.js.map +1 -0
- package/dist/business/implementation/managers/interaction/EventManager.d.ts +26 -0
- package/dist/business/implementation/managers/interaction/EventManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/EventManager.js +63 -0
- package/dist/business/implementation/managers/interaction/EventManager.js.map +1 -0
- package/dist/business/implementation/managers/interaction/InteractionManager.d.ts +39 -0
- package/dist/business/implementation/managers/interaction/InteractionManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/InteractionManager.js +237 -0
- package/dist/business/implementation/managers/interaction/InteractionManager.js.map +1 -0
- package/dist/business/implementation/managers/interaction/RestrictionManager.d.ts +19 -0
- package/dist/business/implementation/managers/interaction/RestrictionManager.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/RestrictionManager.js +117 -0
- package/dist/business/implementation/managers/interaction/RestrictionManager.js.map +1 -0
- package/dist/business/implementation/managers/interaction/handlers/DeletionInteractionHandler.d.ts +10 -0
- package/dist/business/implementation/managers/interaction/handlers/DeletionInteractionHandler.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/handlers/DeletionInteractionHandler.js +52 -0
- package/dist/business/implementation/managers/interaction/handlers/DeletionInteractionHandler.js.map +1 -0
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.d.ts +14 -0
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.js +135 -0
- package/dist/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.js.map +1 -0
- package/dist/business/implementation/managers/interaction/handlers/MidPointInteractionHandler.d.ts +16 -0
- package/dist/business/implementation/managers/interaction/handlers/MidPointInteractionHandler.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/handlers/MidPointInteractionHandler.js +113 -0
- package/dist/business/implementation/managers/interaction/handlers/MidPointInteractionHandler.js.map +1 -0
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.d.ts +58 -0
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.js +377 -0
- package/dist/business/implementation/managers/interaction/helpers/InteractionManagerHelper.js.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/AbstractRestriction.d.ts +19 -0
- package/dist/business/implementation/managers/interaction/restrictions/AbstractRestriction.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/AbstractRestriction.js +105 -0
- package/dist/business/implementation/managers/interaction/restrictions/AbstractRestriction.js.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/axis/AxisRestriction.d.ts +22 -0
- package/dist/business/implementation/managers/interaction/restrictions/axis/AxisRestriction.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/axis/AxisRestriction.js +96 -0
- package/dist/business/implementation/managers/interaction/restrictions/axis/AxisRestriction.js.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/geometry/GeometryRestriction.d.ts +39 -0
- package/dist/business/implementation/managers/interaction/restrictions/geometry/GeometryRestriction.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/geometry/GeometryRestriction.js +215 -0
- package/dist/business/implementation/managers/interaction/restrictions/geometry/GeometryRestriction.js.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/PlaneRestriction.d.ts +58 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/PlaneRestriction.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/PlaneRestriction.js +180 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/PlaneRestriction.js.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/AngularRestriction.d.ts +38 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/AngularRestriction.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/AngularRestriction.js +308 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/AngularRestriction.js.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/GridRestriction.d.ts +37 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/GridRestriction.d.ts.map +1 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/GridRestriction.js +228 -0
- package/dist/business/implementation/managers/interaction/restrictions/plane/snap/GridRestriction.js.map +1 -0
- package/dist/business/implementation/utils/numberCleaner.d.ts +2 -0
- package/dist/business/implementation/utils/numberCleaner.d.ts.map +1 -0
- package/dist/business/implementation/utils/numberCleaner.js +9 -0
- package/dist/business/implementation/utils/numberCleaner.js.map +1 -0
- package/dist/business/interfaces/IDrawingToolsManager.d.ts +270 -0
- package/dist/business/interfaces/IDrawingToolsManager.d.ts.map +1 -0
- package/dist/business/interfaces/IDrawingToolsManager.js +16 -0
- package/dist/business/interfaces/IDrawingToolsManager.js.map +1 -0
- package/dist/business/interfaces/IManager.d.ts +4 -0
- package/dist/business/interfaces/IManager.d.ts.map +1 -0
- package/dist/business/interfaces/IManager.js +3 -0
- package/dist/business/interfaces/IManager.js.map +1 -0
- package/dist/business/interfaces/IRestriction.d.ts +41 -0
- package/dist/business/interfaces/IRestriction.d.ts.map +1 -0
- package/dist/business/interfaces/IRestriction.js +13 -0
- package/dist/business/interfaces/IRestriction.js.map +1 -0
- package/dist/business/interfaces/IRestrictionBase.d.ts +19 -0
- package/dist/business/interfaces/IRestrictionBase.d.ts.map +1 -0
- package/dist/business/interfaces/IRestrictionBase.js +5 -0
- package/dist/business/interfaces/IRestrictionBase.js.map +1 -0
- package/dist/business/interfaces/ISnapRestriction.d.ts +50 -0
- package/dist/business/interfaces/ISnapRestriction.d.ts.map +1 -0
- package/dist/business/interfaces/ISnapRestriction.js +4 -0
- package/dist/business/interfaces/ISnapRestriction.js.map +1 -0
- package/dist/business/interfaces/events/EventResponseMapping.d.ts +19 -0
- package/dist/business/interfaces/events/EventResponseMapping.d.ts.map +1 -0
- package/dist/business/interfaces/events/EventResponseMapping.js +4 -0
- package/dist/business/interfaces/events/EventResponseMapping.js.map +1 -0
- package/dist/business/interfaces/events/IDrawingToolsEvent.d.ts +12 -0
- package/dist/business/interfaces/events/IDrawingToolsEvent.d.ts.map +1 -0
- package/dist/business/interfaces/events/IDrawingToolsEvent.js +3 -0
- package/dist/business/interfaces/events/IDrawingToolsEvent.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/three/CSS2DRenderer.d.ts +32 -0
- package/dist/three/CSS2DRenderer.d.ts.map +1 -0
- package/dist/three/CSS2DRenderer.js +137 -0
- package/dist/three/CSS2DRenderer.js.map +1 -0
- package/package.json +55 -0
- package/src/api/implementation/DrawingToolsApi.ts +135 -0
- package/src/api/implementation/restrictions/AbstractRestrictionApi.ts +34 -0
- package/src/api/implementation/restrictions/AbstractSnapRestrictionApi.ts +36 -0
- package/src/api/implementation/restrictions/axis/AxisRestrictionApi.ts +19 -0
- package/src/api/implementation/restrictions/geometry/GeometryRestrictionApi.ts +56 -0
- package/src/api/implementation/restrictions/plane/PlaneRestrictionApi.ts +63 -0
- package/src/api/implementation/restrictions/plane/snap/AngularRestrictionApi.ts +35 -0
- package/src/api/implementation/restrictions/plane/snap/GridRestrictionApi.ts +35 -0
- package/src/api/interfaces/IDrawingToolsApi.ts +99 -0
- package/src/api/interfaces/IRestrictionApi.ts +15 -0
- package/src/api/interfaces/ISnapRestrictionApi.ts +18 -0
- package/src/business/implementation/DrawingToolsManager.ts +619 -0
- package/src/business/implementation/managers/HistoryManager.ts +101 -0
- package/src/business/implementation/managers/TextVisualizationManager.ts +245 -0
- package/src/business/implementation/managers/geometry/GeometryManager.ts +95 -0
- package/src/business/implementation/managers/geometry/GeometryMathManager.ts +273 -0
- package/src/business/implementation/managers/geometry/GeometryState.ts +436 -0
- package/src/business/implementation/managers/geometry/helpers/GeometryManagerHelper.ts +170 -0
- package/src/business/implementation/managers/interaction/EventManager.ts +80 -0
- package/src/business/implementation/managers/interaction/InteractionManager.ts +268 -0
- package/src/business/implementation/managers/interaction/RestrictionManager.ts +135 -0
- package/src/business/implementation/managers/interaction/handlers/DeletionInteractionHandler.ts +48 -0
- package/src/business/implementation/managers/interaction/handlers/InsertionInteractionHandler.ts +149 -0
- package/src/business/implementation/managers/interaction/handlers/MidPointInteractionHandler.ts +127 -0
- package/src/business/implementation/managers/interaction/helpers/InteractionManagerHelper.ts +411 -0
- package/src/business/implementation/managers/interaction/restrictions/AbstractRestriction.ts +99 -0
- package/src/business/implementation/managers/interaction/restrictions/axis/AxisRestriction.ts +107 -0
- package/src/business/implementation/managers/interaction/restrictions/geometry/GeometryRestriction.ts +237 -0
- package/src/business/implementation/managers/interaction/restrictions/plane/PlaneRestriction.ts +257 -0
- package/src/business/implementation/managers/interaction/restrictions/plane/snap/AngularRestriction.ts +384 -0
- package/src/business/implementation/managers/interaction/restrictions/plane/snap/GridRestriction.ts +262 -0
- package/src/business/implementation/utils/numberCleaner.ts +5 -0
- package/src/business/interfaces/IDrawingToolsManager.ts +313 -0
- package/src/business/interfaces/IManager.ts +7 -0
- package/src/business/interfaces/IRestriction.ts +64 -0
- package/src/business/interfaces/IRestrictionBase.ts +33 -0
- package/src/business/interfaces/ISnapRestriction.ts +70 -0
- package/src/business/interfaces/events/EventResponseMapping.ts +19 -0
- package/src/business/interfaces/events/IDrawingToolsEvent.ts +16 -0
- package/src/index.ts +72 -0
- package/src/three/CSS2DRenderer.ts +212 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { AbstractRestriction } from '../../AbstractRestriction';
|
|
2
|
+
import { CSS2DObject } from '../../../../../../../three/CSS2DRenderer';
|
|
3
|
+
import { DrawingToolsManager } from '../../../../../DrawingToolsManager';
|
|
4
|
+
import { GeometryMathManager } from '../../../../geometry/GeometryMathManager';
|
|
5
|
+
import { ISnapRestriction, SnapRestrictionProperties } from '../../../../../../interfaces/ISnapRestriction';
|
|
6
|
+
import { numberCleaner } from '../../../../../utils/numberCleaner';
|
|
7
|
+
import { PlaneRestriction } from '../PlaneRestriction';
|
|
8
|
+
import { RestrictionMetaData } from '../../../../../../interfaces/IRestriction';
|
|
9
|
+
import { sceneTree } from '@shapediver/viewer';
|
|
10
|
+
import { Settings } from '../../../../../../interfaces/IDrawingToolsManager';
|
|
11
|
+
import { vec3 } from 'gl-matrix';
|
|
12
|
+
|
|
13
|
+
// #region Type aliases (1)
|
|
14
|
+
|
|
15
|
+
export type AngularRestrictionProperties = {
|
|
16
|
+
/**
|
|
17
|
+
* Step size for the angles
|
|
18
|
+
*/
|
|
19
|
+
angleStep?: number;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* If the angle step is editable for change to the end user.
|
|
23
|
+
* If it is not editable, the angle step cannot be changed from the default value.
|
|
24
|
+
*/
|
|
25
|
+
angleStepEditable?: boolean;
|
|
26
|
+
} & SnapRestrictionProperties;
|
|
27
|
+
|
|
28
|
+
// #endregion Type aliases (1)
|
|
29
|
+
|
|
30
|
+
// #region Classes (1)
|
|
31
|
+
|
|
32
|
+
export class AngularRestriction extends AbstractRestriction implements ISnapRestriction {
|
|
33
|
+
// #region Properties (16)
|
|
34
|
+
|
|
35
|
+
readonly #activationKey: string;
|
|
36
|
+
readonly #drawingToolsManager: DrawingToolsManager;
|
|
37
|
+
readonly #geometryMathManager: GeometryMathManager;
|
|
38
|
+
readonly #planeRestriction: PlaneRestriction;
|
|
39
|
+
readonly #settings: Settings;
|
|
40
|
+
|
|
41
|
+
#active: boolean = false;
|
|
42
|
+
#activePolarGrids = {
|
|
43
|
+
next: false,
|
|
44
|
+
previous: false
|
|
45
|
+
};
|
|
46
|
+
#angleStep: number;
|
|
47
|
+
#angleStepEditable: boolean = true;
|
|
48
|
+
#angles: number[] = [];
|
|
49
|
+
#labelNext?: CSS2DObject;
|
|
50
|
+
#labelPrevious?: CSS2DObject;
|
|
51
|
+
#normal: vec3;
|
|
52
|
+
#priority: number = 0;
|
|
53
|
+
#vectorU: vec3;
|
|
54
|
+
#vectorV: vec3;
|
|
55
|
+
|
|
56
|
+
// #endregion Properties (16)
|
|
57
|
+
|
|
58
|
+
// #region Constructors (1)
|
|
59
|
+
|
|
60
|
+
constructor(drawingToolsManager: DrawingToolsManager, planeRestriction: PlaneRestriction, properties?: AngularRestrictionProperties) {
|
|
61
|
+
super(drawingToolsManager, 'angular');
|
|
62
|
+
|
|
63
|
+
this.#drawingToolsManager = drawingToolsManager;
|
|
64
|
+
this.#geometryMathManager = drawingToolsManager.geometryMathManager;
|
|
65
|
+
this.#settings = drawingToolsManager.settings;
|
|
66
|
+
|
|
67
|
+
this.#planeRestriction = planeRestriction;
|
|
68
|
+
|
|
69
|
+
// we store the properties of the plane restriction
|
|
70
|
+
// as we need them to calculate the transformation matrices
|
|
71
|
+
// and the offset of the grid size to the origin
|
|
72
|
+
this.#vectorU = planeRestriction.vectorU!;
|
|
73
|
+
this.#vectorV = planeRestriction.vectorV!;
|
|
74
|
+
this.#normal = planeRestriction.normal;
|
|
75
|
+
|
|
76
|
+
this.#activationKey = properties?.activationKey || 'a';
|
|
77
|
+
this.enabled = properties?.enabled ?? false;
|
|
78
|
+
this._enabledEditable = properties?.enabledEditable ?? true;
|
|
79
|
+
this.#angleStep = properties?.angleStep || Math.PI / 12;
|
|
80
|
+
this.#angleStepEditable = properties?.angleStepEditable ?? true;
|
|
81
|
+
this.#priority = properties?.priority || 0;
|
|
82
|
+
|
|
83
|
+
// calculate the angles
|
|
84
|
+
this.calculateAngles();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// #endregion Constructors (1)
|
|
88
|
+
|
|
89
|
+
// #region Public Getters And Setters (8)
|
|
90
|
+
|
|
91
|
+
public get active(): boolean {
|
|
92
|
+
return this.#active;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public set active(value: boolean) {
|
|
96
|
+
this.#active = value;
|
|
97
|
+
|
|
98
|
+
if (value === false) {
|
|
99
|
+
if (this.#labelNext) this.#labelNext.visible = false;
|
|
100
|
+
if (this.#labelPrevious) this.#labelPrevious.visible = false;
|
|
101
|
+
} else {
|
|
102
|
+
if (this.#labelNext && this.#activePolarGrids.next) this.#labelNext.visible = true;
|
|
103
|
+
if (this.#labelPrevious && this.#activePolarGrids.previous) this.#labelPrevious.visible = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public get angleStep(): number {
|
|
108
|
+
return this.#angleStep;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public set angleStep(value: number) {
|
|
112
|
+
if (this.#angleStepEditable === false) return;
|
|
113
|
+
|
|
114
|
+
this.#angleStep = value;
|
|
115
|
+
this.calculateAngles();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public get angleStepEditable(): boolean {
|
|
119
|
+
return this.#angleStepEditable;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public get enabledEditable(): boolean {
|
|
123
|
+
return this._enabledEditable;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public get priority(): number {
|
|
127
|
+
return this.#priority;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
public set priority(value: number) {
|
|
131
|
+
this.#priority = value;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// #endregion Public Getters And Setters (8)
|
|
135
|
+
|
|
136
|
+
// #region Public Methods (2)
|
|
137
|
+
|
|
138
|
+
public snap(point: vec3, metaData?: RestrictionMetaData): vec3 | undefined {
|
|
139
|
+
// if the restriction is not enabled OR the activation key is set and the key is not pressed, return
|
|
140
|
+
if (this.enabled === false && this.#drawingToolsManager.keyPressed(this.#activationKey) === false) return;
|
|
141
|
+
|
|
142
|
+
if (this.#labelNext) this.#labelNext.visible = false;
|
|
143
|
+
if (this.#labelPrevious) this.#labelPrevious.visible = false;
|
|
144
|
+
|
|
145
|
+
this.#activePolarGrids = {
|
|
146
|
+
next: false,
|
|
147
|
+
previous: false
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const positionArray = this.#drawingToolsManager.positionArray;
|
|
151
|
+
|
|
152
|
+
let previousIndex, nextIndex;
|
|
153
|
+
if (metaData !== undefined && metaData.index !== undefined) {
|
|
154
|
+
previousIndex = this.getPreviousIndex(metaData.index);
|
|
155
|
+
nextIndex = this.getNextIndex(metaData.index);
|
|
156
|
+
} else {
|
|
157
|
+
// if no index was provided, it is a new point
|
|
158
|
+
previousIndex = positionArray.length / 3 - 1;
|
|
159
|
+
nextIndex = 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const previousPreviousIndex = this.getPreviousIndex(previousIndex);
|
|
163
|
+
const nextNextIndex = this.getNextIndex(nextIndex);
|
|
164
|
+
|
|
165
|
+
if (positionArray.length / 3 < 2) return;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Explanation of the algorithm:
|
|
169
|
+
* 1. Project the point onto the XY-Plane
|
|
170
|
+
* 2. Find the next point and the previous point
|
|
171
|
+
* 3. Project the next and previous point onto the XY-Plane
|
|
172
|
+
* 4. Calculate the angle between the point and the next and previous point
|
|
173
|
+
* 5. Determine which if the angles are in the range to snap to
|
|
174
|
+
* a. If both are in the range, snap to the intersection of the two lines
|
|
175
|
+
* b. If only one is in the range, snap to the intersection of the line and the plane
|
|
176
|
+
* c. If none is in the range, return
|
|
177
|
+
* 6. Reverse the projection to the original coordinate system
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
// get the next and previous point from the position array
|
|
181
|
+
const nextPointFromData = vec3.fromValues(positionArray.at((nextIndex * 3))!, positionArray.at((nextIndex * 3) + 1)!, positionArray.at((nextIndex * 3) + 2)!);
|
|
182
|
+
const nextNextPointFromData = vec3.fromValues(positionArray.at((nextNextIndex * 3))!, positionArray.at((nextNextIndex * 3) + 1)!, positionArray.at((nextNextIndex * 3) + 2)!);
|
|
183
|
+
const previousPointFromData = vec3.fromValues(positionArray.at((previousIndex * 3))!, positionArray.at((previousIndex * 3) + 1)!, positionArray.at((previousIndex * 3) + 2)!);
|
|
184
|
+
const previousPreviousPointFromData = vec3.fromValues(positionArray.at((previousPreviousIndex * 3))!, positionArray.at((previousPreviousIndex * 3) + 1)!, positionArray.at((previousPreviousIndex * 3) + 2)!);
|
|
185
|
+
|
|
186
|
+
// project them onto the same plane as the point
|
|
187
|
+
const nextPointProjected = vec3.sub(vec3.create(), nextPointFromData, vec3.scale(vec3.create(), this.#normal, vec3.dot(vec3.sub(vec3.create(), nextPointFromData, point), this.#normal)));
|
|
188
|
+
const nextNextPointProjected = vec3.sub(vec3.create(), nextNextPointFromData, vec3.scale(vec3.create(), this.#normal, vec3.dot(vec3.sub(vec3.create(), nextNextPointFromData, point), this.#normal)));
|
|
189
|
+
const previousPointProjected = vec3.sub(vec3.create(), previousPointFromData, vec3.scale(vec3.create(), this.#normal, vec3.dot(vec3.sub(vec3.create(), previousPointFromData, point), this.#normal)));
|
|
190
|
+
const previousPreviousPointProjected = vec3.sub(vec3.create(), previousPreviousPointFromData, vec3.scale(vec3.create(), this.#normal, vec3.dot(vec3.sub(vec3.create(), previousPreviousPointFromData, point), this.#normal)));
|
|
191
|
+
|
|
192
|
+
// project the point onto the XY-Plane
|
|
193
|
+
const pointProjected = vec3.transformMat4(vec3.create(), point, this.#planeRestriction.transformationToXYPlaneMatrix);
|
|
194
|
+
vec3.transformMat4(nextPointProjected, nextPointProjected, this.#planeRestriction.transformationToXYPlaneMatrix);
|
|
195
|
+
vec3.transformMat4(nextNextPointProjected, nextNextPointProjected, this.#planeRestriction.transformationToXYPlaneMatrix);
|
|
196
|
+
vec3.transformMat4(previousPointProjected, previousPointProjected, this.#planeRestriction.transformationToXYPlaneMatrix);
|
|
197
|
+
vec3.transformMat4(previousPreviousPointProjected, previousPreviousPointProjected, this.#planeRestriction.transformationToXYPlaneMatrix);
|
|
198
|
+
|
|
199
|
+
// calculate the angle between the next and previous point and the point to restrict on the axis
|
|
200
|
+
const { angularDifference: angularDifferenceNext, crossProduct: crossProductNext, closestAngle: closestAngleNext } = this.getAngularDifference({ start: nextPointProjected, end: nextNextPointProjected }, { start: nextPointProjected, end: pointProjected });
|
|
201
|
+
const { angularDifference: angularDifferencePrevious, crossProduct: crossProductPrevious, closestAngle: closestAnglePrevious } = this.getAngularDifference({ start: previousPointProjected, end: previousPreviousPointProjected }, { start: previousPointProjected, end: pointProjected });
|
|
202
|
+
|
|
203
|
+
// calculate the distances in screen space so we can check how close it is
|
|
204
|
+
const resultPointNextAngle = vec3.rotateZ(vec3.create(), pointProjected, nextPointProjected, crossProductNext[2] < 0 ? -angularDifferenceNext : angularDifferenceNext);
|
|
205
|
+
const screenSpaceDistanceCheckNextAngle = this.#geometryMathManager.screenSpaceDistanceCheck(resultPointNextAngle, pointProjected, this.#settings.visualization.points.size_0! * this.#settings.visualization.distanceMultiplicationFactor);
|
|
206
|
+
const resultPointPreviousAngle = vec3.rotateZ(vec3.create(), pointProjected, previousPointProjected, crossProductPrevious[2] < 0 ? -angularDifferencePrevious : angularDifferencePrevious);
|
|
207
|
+
const screenSpaceDistanceCheckPreviousAngle = this.#geometryMathManager.screenSpaceDistanceCheck(resultPointPreviousAngle, pointProjected, this.#settings.visualization.points.size_0! * this.#settings.visualization.distanceMultiplicationFactor);
|
|
208
|
+
|
|
209
|
+
if (screenSpaceDistanceCheckNextAngle.check === false && screenSpaceDistanceCheckPreviousAngle.check === false) return;
|
|
210
|
+
|
|
211
|
+
// snap to clear defined point if both distances are smaller than threshold
|
|
212
|
+
if (positionArray.length > 6 && screenSpaceDistanceCheckNextAngle.check === true && screenSpaceDistanceCheckPreviousAngle.check === true) {
|
|
213
|
+
const rayDirectionNext = vec3.normalize(vec3.create(), vec3.sub(vec3.create(), resultPointNextAngle, nextPointProjected));
|
|
214
|
+
const rayDirectionPrevious = vec3.normalize(vec3.create(), vec3.sub(vec3.create(), resultPointPreviousAngle, previousPointProjected));
|
|
215
|
+
|
|
216
|
+
const crossProduct = vec3.cross(vec3.create(), rayDirectionNext, rayDirectionPrevious);
|
|
217
|
+
const crossProductLength = vec3.length(crossProduct);
|
|
218
|
+
|
|
219
|
+
if (crossProductLength < 0.001) {
|
|
220
|
+
vec3.transformMat4(resultPointNextAngle, resultPointNextAngle, this.#planeRestriction.transformationFromXYPlaneMatrix);
|
|
221
|
+
return resultPointNextAngle;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const t = vec3.sub(vec3.create(), previousPointProjected, nextPointProjected);
|
|
225
|
+
const u = vec3.cross(vec3.create(), t, rayDirectionPrevious);
|
|
226
|
+
const v = vec3.cross(vec3.create(), t, rayDirectionNext);
|
|
227
|
+
|
|
228
|
+
const tValue = vec3.dot(u, crossProduct) / crossProductLength ** 2;
|
|
229
|
+
const uValue = vec3.dot(v, crossProduct) / crossProductLength ** 2;
|
|
230
|
+
|
|
231
|
+
if (tValue < 0 || uValue < 0) {
|
|
232
|
+
vec3.transformMat4(resultPointNextAngle, resultPointNextAngle, this.#planeRestriction.transformationFromXYPlaneMatrix);
|
|
233
|
+
return resultPointNextAngle;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const intersection = vec3.add(vec3.create(), nextPointProjected, vec3.scale(vec3.create(), rayDirectionNext, tValue));
|
|
237
|
+
this.#labelNext = this.createGrid(this.#labelNext, nextPointFromData, closestAngleNext);
|
|
238
|
+
this.#activePolarGrids.next = true;
|
|
239
|
+
this.#labelPrevious = this.createGrid(this.#labelPrevious, previousPointFromData, closestAnglePrevious);
|
|
240
|
+
this.#activePolarGrids.previous = true;
|
|
241
|
+
|
|
242
|
+
// reverse the projection to the original coordinate system
|
|
243
|
+
vec3.transformMat4(intersection, intersection, this.#planeRestriction.transformationFromXYPlaneMatrix);
|
|
244
|
+
return intersection;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// check which distance to the projection is smaller
|
|
248
|
+
if (screenSpaceDistanceCheckNextAngle.distanceSquared < screenSpaceDistanceCheckPreviousAngle.distanceSquared) {
|
|
249
|
+
this.#labelNext = this.createGrid(this.#labelNext, nextPointFromData, closestAngleNext);
|
|
250
|
+
this.#activePolarGrids.next = true;
|
|
251
|
+
|
|
252
|
+
// reverse the projection to the original coordinate system
|
|
253
|
+
vec3.transformMat4(resultPointNextAngle, resultPointNextAngle, this.#planeRestriction.transformationFromXYPlaneMatrix);
|
|
254
|
+
return resultPointNextAngle;
|
|
255
|
+
} else {
|
|
256
|
+
this.#labelPrevious = this.createGrid(this.#labelPrevious, previousPointFromData, closestAnglePrevious);
|
|
257
|
+
this.#activePolarGrids.previous = true;
|
|
258
|
+
|
|
259
|
+
// reverse the projection to the original coordinate system
|
|
260
|
+
vec3.transformMat4(resultPointPreviousAngle, resultPointPreviousAngle, this.#planeRestriction.transformationFromXYPlaneMatrix);
|
|
261
|
+
return resultPointPreviousAngle;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public updatePlaneDefinition(origin: vec3, vectorU: vec3, vectorV: vec3, normal: vec3): void {
|
|
266
|
+
this.#vectorU = vectorU;
|
|
267
|
+
this.#vectorV = vectorV;
|
|
268
|
+
this.#normal = normal;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// #endregion Public Methods (2)
|
|
272
|
+
|
|
273
|
+
// #region Protected Methods (1)
|
|
274
|
+
|
|
275
|
+
protected visibilityChanged(visible: boolean): void {
|
|
276
|
+
if (visible === false) {
|
|
277
|
+
if (this.#labelNext) this.#labelNext.visible = false;
|
|
278
|
+
if (this.#labelPrevious) this.#labelPrevious.visible = false;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// #endregion Protected Methods (1)
|
|
283
|
+
|
|
284
|
+
// #region Private Methods (5)
|
|
285
|
+
|
|
286
|
+
private calculateAngles() {
|
|
287
|
+
this.#angles = [];
|
|
288
|
+
for (let i = 0; i <= Math.PI + 0.0001; i += this.#angleStep) {
|
|
289
|
+
this.#angles.push(i);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private createGrid(label: CSS2DObject | undefined, position: vec3, angle: number): CSS2DObject {
|
|
294
|
+
if (label)
|
|
295
|
+
this._object3D.remove(label);
|
|
296
|
+
|
|
297
|
+
let radius = sceneTree.root.boundingBox.boundingSphere.radius / 100;
|
|
298
|
+
if (radius === Infinity)
|
|
299
|
+
radius = 1;
|
|
300
|
+
|
|
301
|
+
const text = document.createElement('div');
|
|
302
|
+
text.className = 'label';
|
|
303
|
+
|
|
304
|
+
const child = document.createElement('div');
|
|
305
|
+
child.className = 'angular-label';
|
|
306
|
+
|
|
307
|
+
const style = document.createElement('style');
|
|
308
|
+
style.textContent = `
|
|
309
|
+
.angular-label {
|
|
310
|
+
display: flex;
|
|
311
|
+
justify-content: center;
|
|
312
|
+
align-items: center;
|
|
313
|
+
width: 40px;
|
|
314
|
+
height: 40px;
|
|
315
|
+
color: white;
|
|
316
|
+
background-color: ${this.#settings.visualization.points.color_1};
|
|
317
|
+
border-radius: 50%;
|
|
318
|
+
font-size: 16px;
|
|
319
|
+
text-align: center;
|
|
320
|
+
}
|
|
321
|
+
`;
|
|
322
|
+
document.head.appendChild(style);
|
|
323
|
+
|
|
324
|
+
child.textContent = `${numberCleaner((angle / Math.PI) * 180)}°`;
|
|
325
|
+
text.appendChild(child);
|
|
326
|
+
|
|
327
|
+
label = new CSS2DObject(text);
|
|
328
|
+
label.position.set(position[0], position[1], position[2]);
|
|
329
|
+
label.visible = false;
|
|
330
|
+
this._object3D.add(label);
|
|
331
|
+
|
|
332
|
+
return label;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private getAngularDifference(
|
|
336
|
+
line: {
|
|
337
|
+
start: vec3, end: vec3
|
|
338
|
+
},
|
|
339
|
+
referenceLine: {
|
|
340
|
+
start: vec3, end: vec3
|
|
341
|
+
}
|
|
342
|
+
): {
|
|
343
|
+
angularDifference: number,
|
|
344
|
+
crossProduct: vec3,
|
|
345
|
+
closestAngle: number
|
|
346
|
+
} {
|
|
347
|
+
const lineDirection = vec3.normalize(vec3.create(), vec3.sub(vec3.create(), line.end, line.start));
|
|
348
|
+
const referenceLineDirection = vec3.normalize(vec3.create(), vec3.sub(vec3.create(), referenceLine.end, referenceLine.start));
|
|
349
|
+
|
|
350
|
+
// calculate the angle between the lineDirection and the referenceLineDirection
|
|
351
|
+
const angleReference = vec3.angle(lineDirection, referenceLineDirection);
|
|
352
|
+
const crossProduct = vec3.cross(vec3.create(), lineDirection, referenceLineDirection);
|
|
353
|
+
|
|
354
|
+
// find the angle that is closest to the angle of the previous point
|
|
355
|
+
let closestAngle = this.#angles[0];
|
|
356
|
+
for (let i = 0; i < this.#angles.length; i++) {
|
|
357
|
+
const angle = this.#angles[i];
|
|
358
|
+
|
|
359
|
+
if (Math.abs(angleReference - angle) < Math.abs(angleReference - closestAngle))
|
|
360
|
+
closestAngle = angle;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// move the point to the closest angle
|
|
364
|
+
const angularDifference = closestAngle - angleReference;
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
angularDifference,
|
|
368
|
+
crossProduct,
|
|
369
|
+
closestAngle
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private getNextIndex(index: number): number {
|
|
374
|
+
return index + 1 > this.#drawingToolsManager.positionArray.length / 3 - 1 ? 0 : index + 1;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
private getPreviousIndex(index: number): number {
|
|
378
|
+
return index - 1 < 0 ? this.#drawingToolsManager.positionArray.length / 3 - 1 : index - 1;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// #endregion Private Methods (5)
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// #endregion Classes (1)
|
package/src/business/implementation/managers/interaction/restrictions/plane/snap/GridRestriction.ts
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { AbstractRestriction } from '../../AbstractRestriction';
|
|
3
|
+
import { DrawingToolsManager } from '../../../../../DrawingToolsManager';
|
|
4
|
+
import { Box, sceneTree } from '@shapediver/viewer';
|
|
5
|
+
import { ISnapRestriction, SnapRestrictionProperties } from '../../../../../../interfaces/ISnapRestriction';
|
|
6
|
+
import { PlaneRestriction } from '../PlaneRestriction';
|
|
7
|
+
import { vec3 } from 'gl-matrix';
|
|
8
|
+
|
|
9
|
+
// #region Type aliases (1)
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Properties for the grid restriction
|
|
13
|
+
*/
|
|
14
|
+
export type GridRestrictionProperties = {
|
|
15
|
+
/**
|
|
16
|
+
* Size of the grid unit
|
|
17
|
+
*/
|
|
18
|
+
gridUnit?: number;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* If the grid unit is editable for change to the end user.
|
|
22
|
+
* If it is not editable, the grid unit cannot be changed from the default value.
|
|
23
|
+
*/
|
|
24
|
+
gridUnitEditable?: boolean;
|
|
25
|
+
} & SnapRestrictionProperties;
|
|
26
|
+
|
|
27
|
+
// #endregion Type aliases (1)
|
|
28
|
+
|
|
29
|
+
// #region Classes (1)
|
|
30
|
+
|
|
31
|
+
export class GridRestriction extends AbstractRestriction implements ISnapRestriction {
|
|
32
|
+
// #region Properties (15)
|
|
33
|
+
|
|
34
|
+
readonly #activationKey: string;
|
|
35
|
+
readonly #drawingToolsManager: DrawingToolsManager;
|
|
36
|
+
readonly #planeRestriction: PlaneRestriction;
|
|
37
|
+
|
|
38
|
+
#active: boolean = false;
|
|
39
|
+
#gridHelper?: THREE.GridHelper;
|
|
40
|
+
#gridSize: number = 100;
|
|
41
|
+
#gridUnit: number;
|
|
42
|
+
#gridUnitEditable: boolean = true;
|
|
43
|
+
#normal: vec3;
|
|
44
|
+
#offsetFromUnit: vec3 = vec3.create();
|
|
45
|
+
#origin: vec3;
|
|
46
|
+
#priority: number = 0;
|
|
47
|
+
#vectorU: vec3;
|
|
48
|
+
#vectorV: vec3;
|
|
49
|
+
|
|
50
|
+
// #endregion Properties (15)
|
|
51
|
+
|
|
52
|
+
// #region Constructors (1)
|
|
53
|
+
|
|
54
|
+
constructor(drawingToolsManager: DrawingToolsManager, planeRestriction: PlaneRestriction, properties?: GridRestrictionProperties) {
|
|
55
|
+
super(drawingToolsManager, 'grid');
|
|
56
|
+
|
|
57
|
+
this.#drawingToolsManager = drawingToolsManager;
|
|
58
|
+
this.#planeRestriction = planeRestriction;
|
|
59
|
+
|
|
60
|
+
// we store the properties of the plane restriction
|
|
61
|
+
// as we need them to calculate the transformation matrices
|
|
62
|
+
// and the offset of the grid size to the origin
|
|
63
|
+
this.#vectorU = planeRestriction.vectorU!;
|
|
64
|
+
this.#vectorV = planeRestriction.vectorV!;
|
|
65
|
+
this.#normal = planeRestriction.normal;
|
|
66
|
+
this.#origin = planeRestriction.origin;
|
|
67
|
+
|
|
68
|
+
this.#activationKey = properties?.activationKey || 'g';
|
|
69
|
+
this.enabled = properties?.enabled ?? false;
|
|
70
|
+
this._enabledEditable = properties?.enabledEditable ?? true;
|
|
71
|
+
this.#gridUnit = properties?.gridUnit || 1;
|
|
72
|
+
this.#gridUnitEditable = properties?.gridUnitEditable ?? true;
|
|
73
|
+
this.#priority = properties?.priority || 0;
|
|
74
|
+
|
|
75
|
+
// create the offset of the grid size to origin
|
|
76
|
+
this.createOffsetFromUnit();
|
|
77
|
+
|
|
78
|
+
// calculate offset of grid size to origin
|
|
79
|
+
this.createGridVisualization();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// #endregion Constructors (1)
|
|
83
|
+
|
|
84
|
+
// #region Public Getters And Setters (8)
|
|
85
|
+
|
|
86
|
+
public get active(): boolean {
|
|
87
|
+
return this.#active;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public set active(value: boolean) {
|
|
91
|
+
this.#active = value;
|
|
92
|
+
|
|
93
|
+
if (this.#gridHelper) this.#gridHelper.visible = value;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public get enabledEditable(): boolean {
|
|
97
|
+
return this._enabledEditable;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public get gridUnit(): number {
|
|
101
|
+
return this.#gridUnit;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public set gridUnit(value: number) {
|
|
105
|
+
if (this.#gridUnitEditable === false) return;
|
|
106
|
+
|
|
107
|
+
this.#gridUnit = value;
|
|
108
|
+
this.createOffsetFromUnit();
|
|
109
|
+
this.createGridVisualization();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public get gridUnitEditable(): boolean {
|
|
113
|
+
return this.#gridUnitEditable;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public get priority(): number {
|
|
117
|
+
return this.#priority;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public set priority(value: number) {
|
|
121
|
+
this.#priority = value;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// #endregion Public Getters And Setters (8)
|
|
125
|
+
|
|
126
|
+
// #region Public Methods (2)
|
|
127
|
+
|
|
128
|
+
// public get
|
|
129
|
+
public snap(point: vec3): vec3 | undefined {
|
|
130
|
+
// if the restriction is not enabled OR the activation key is set and the key is not pressed, return
|
|
131
|
+
if (this.enabled === false && this.#drawingToolsManager.keyPressed(this.#activationKey) === false) return;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Explanation of the following code:
|
|
135
|
+
* 1. Calculate the projection of the origin onto the plane that is created by the point and the normal
|
|
136
|
+
* 2. Move the grid helper to the projected origin
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
// vector from the point to the origin
|
|
140
|
+
const v = vec3.sub(vec3.create(), this.#origin, point);
|
|
141
|
+
|
|
142
|
+
// dot product of the vector and the normal
|
|
143
|
+
const dot = vec3.dot(v, this.#normal);
|
|
144
|
+
|
|
145
|
+
// projection of the origin onto the plane that is created by the point and the normal
|
|
146
|
+
const adjustedOrigin = vec3.add(vec3.create(), this.#origin, this.#offsetFromUnit);
|
|
147
|
+
const projectedOrigin = vec3.sub(vec3.create(), adjustedOrigin, vec3.scale(vec3.create(), this.#normal, dot));
|
|
148
|
+
|
|
149
|
+
// we move the grid helper to the projected origin
|
|
150
|
+
if (this.#gridHelper) {
|
|
151
|
+
this.#gridHelper.position.copy(new THREE.Vector3(projectedOrigin[0], projectedOrigin[1], projectedOrigin[2]));
|
|
152
|
+
this.#gridHelper.visible = false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Explanation of the following code:
|
|
157
|
+
* 1. Rotate the point so that the normal of the plane is aligned with the Z axis (with previously calculated transformation matrix)
|
|
158
|
+
* 2. Snap the point to the grid
|
|
159
|
+
* 3. Rotate the point back to the original coordinate system (with previously calculated transformation matrix)
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
// Apply the transformation to the point
|
|
163
|
+
const rotatedPoint = vec3.transformMat4(vec3.create(), point, this.#planeRestriction.transformationToXYPlaneMatrix);
|
|
164
|
+
|
|
165
|
+
// Snap the offset to the grid
|
|
166
|
+
const snappedOffset = vec3.create();
|
|
167
|
+
snappedOffset[0] = Math.round(rotatedPoint[0] / this.#gridUnit) * this.#gridUnit;
|
|
168
|
+
snappedOffset[1] = Math.round(rotatedPoint[1] / this.#gridUnit) * this.#gridUnit;
|
|
169
|
+
snappedOffset[2] = rotatedPoint[2];
|
|
170
|
+
|
|
171
|
+
// Move the snapped point back to the original coordinate system
|
|
172
|
+
const snappedPoint = vec3.transformMat4(vec3.create(), snappedOffset, this.#planeRestriction.transformationFromXYPlaneMatrix);
|
|
173
|
+
|
|
174
|
+
return snappedPoint;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public updatePlaneDefinition(origin: vec3, vectorU: vec3, vectorV: vec3, normal: vec3): void {
|
|
178
|
+
this.#origin = origin;
|
|
179
|
+
this.#vectorU = vectorU;
|
|
180
|
+
this.#vectorV = vectorV;
|
|
181
|
+
this.#normal = normal;
|
|
182
|
+
|
|
183
|
+
this.createOffsetFromUnit();
|
|
184
|
+
this.createGridVisualization();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// #endregion Public Methods (2)
|
|
188
|
+
|
|
189
|
+
// #region Protected Methods (1)
|
|
190
|
+
|
|
191
|
+
protected visibilityChanged(visible: boolean): void {
|
|
192
|
+
if (visible === false) {
|
|
193
|
+
if (this.#gridHelper) {
|
|
194
|
+
this.#gridHelper.visible = false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// #endregion Protected Methods (1)
|
|
200
|
+
|
|
201
|
+
// #region Private Methods (2)
|
|
202
|
+
|
|
203
|
+
private createGridVisualization(): void {
|
|
204
|
+
if (this.#gridHelper) {
|
|
205
|
+
this._object3D.remove(this.#gridHelper);
|
|
206
|
+
this.#gridHelper.dispose();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const bb = new Box();
|
|
210
|
+
for(let i = 0; i < sceneTree.root.children.length; i++) {
|
|
211
|
+
if((sceneTree.root.children[i] as unknown as { sessionNode?: boolean }).sessionNode === true) {
|
|
212
|
+
bb.union(sceneTree.root.children[i].boundingBox);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const radius = bb.boundingSphere.radius;
|
|
217
|
+
this.#gridSize = radius * 2;
|
|
218
|
+
if (this.#gridSize === Infinity || this.#gridSize === -Infinity || isNaN(this.#gridSize) || this.#gridSize === 0)
|
|
219
|
+
this.#gridSize = 100;
|
|
220
|
+
|
|
221
|
+
// if the grid size is not divisible by the grid unit, we need to adjust the grid size
|
|
222
|
+
let gridSize = this.#gridUnit * Math.ceil(this.#gridSize / this.#gridUnit);
|
|
223
|
+
// if the number of divisions is odd, we need to add one more division
|
|
224
|
+
if (gridSize / this.#gridUnit % 2 === 1)
|
|
225
|
+
gridSize += this.#gridUnit;
|
|
226
|
+
|
|
227
|
+
// todo adjust grid size so that is divisible by grid unit
|
|
228
|
+
this.#gridHelper = new THREE.GridHelper(gridSize, gridSize / this.#gridUnit, 0x666666, 0x222222);
|
|
229
|
+
const adjustedOrigin = vec3.add(vec3.create(), this.#origin, this.#offsetFromUnit);
|
|
230
|
+
this.#gridHelper.position.copy(new THREE.Vector3(adjustedOrigin[0], adjustedOrigin[1], adjustedOrigin[2]));
|
|
231
|
+
this.#gridHelper.visible = false;
|
|
232
|
+
|
|
233
|
+
this.#gridHelper.renderOrder = 100;
|
|
234
|
+
(this.#gridHelper.material as THREE.LineBasicMaterial).depthTest = false;
|
|
235
|
+
(this.#gridHelper.material as THREE.LineBasicMaterial).transparent = true;
|
|
236
|
+
|
|
237
|
+
// three.js uses a right-handed coordinate system, so we need to rotate the grid helper
|
|
238
|
+
const rotationMatrix = new THREE.Matrix4().fromArray([
|
|
239
|
+
this.#vectorU[0], this.#vectorU[1], this.#vectorU[2], 0,
|
|
240
|
+
this.#vectorV[0], this.#vectorV[1], this.#vectorV[2], 0,
|
|
241
|
+
this.#normal[0], this.#normal[1], this.#normal[2], 0,
|
|
242
|
+
0, 0, 0, 1
|
|
243
|
+
]);
|
|
244
|
+
|
|
245
|
+
this.#gridHelper.rotation.setFromRotationMatrix(rotationMatrix);
|
|
246
|
+
// three.js grid helper is created in the XY plane, so we need to rotate it by 90 degrees around the X axis
|
|
247
|
+
this.#gridHelper.rotateX(Math.PI / 2);
|
|
248
|
+
|
|
249
|
+
this._object3D.add(this.#gridHelper);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private createOffsetFromUnit(): void {
|
|
253
|
+
// Calculate the offset of the rotated point from the rotated origin
|
|
254
|
+
this.#offsetFromUnit[0] = this.#gridUnit * Math.round(this.#origin[0] / this.#gridUnit) - this.#origin[0];
|
|
255
|
+
this.#offsetFromUnit[1] = this.#gridUnit * Math.round(this.#origin[1] / this.#gridUnit) - this.#origin[1];
|
|
256
|
+
this.#offsetFromUnit[2] = this.#gridUnit * Math.round(this.#origin[2] / this.#gridUnit) - this.#origin[2];
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// #endregion Private Methods (2)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// #endregion Classes (1)
|