@kitware/vtk.js 34.8.1 → 34.10.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/Common/DataModel/Planes.d.ts +120 -0
- package/Common/DataModel/Planes.js +281 -0
- package/Common/DataModel.js +2 -0
- package/Interaction/Manipulators/MouseCameraTrackballPanManipulatorAutoCenter.js +120 -0
- package/Interaction/Style/InteractorStyleManipulator.js +1 -73
- package/README.md +2 -3
- package/Rendering/Core/Camera.d.ts +16 -2
- package/Rendering/Core/Camera.js +14 -1
- package/Widgets/Core/WidgetManager.js +11 -0
- package/index.d.ts +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Bounds, Vector3 } from './../../types';
|
|
2
|
+
import vtkDataArray from './../Core/DataArray';
|
|
3
|
+
import vtkImplicitFunction, {
|
|
4
|
+
IImplicitFunctionInitialValues,
|
|
5
|
+
} from './ImplicitFunction';
|
|
6
|
+
import vtkPlane from './Plane';
|
|
7
|
+
import vtkPoints from './../Core/Points';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
export interface IPlanesInitialValues extends IImplicitFunctionInitialValues {
|
|
13
|
+
points?: vtkPoints;
|
|
14
|
+
normals?: vtkDataArray;
|
|
15
|
+
bounds?: Bounds;
|
|
16
|
+
planes?: number[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface vtkPlanes extends vtkImplicitFunction {
|
|
20
|
+
/**
|
|
21
|
+
* Evaluate the function at a point x
|
|
22
|
+
* @param x The point at which to evaluate the function
|
|
23
|
+
* @returns The function value at the point x
|
|
24
|
+
*/
|
|
25
|
+
evaluateFunction(x: Vector3): number;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Evaluate the gradient at a point x
|
|
29
|
+
* @param x The point at which to evaluate the gradient
|
|
30
|
+
* @returns The gradient at the point x
|
|
31
|
+
*/
|
|
32
|
+
evaluateGradient(x: Vector3): Vector3;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get the bounds of the planes.
|
|
36
|
+
* @returns {Bounds} The bounds of the planes.
|
|
37
|
+
*/
|
|
38
|
+
getBounds(): Bounds;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the number of planes in the set of planes.
|
|
42
|
+
*/
|
|
43
|
+
getNumberOfPlanes(): number;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get the normals of the plane.
|
|
47
|
+
* @returns {vtkDataArray} The normals of the plane.
|
|
48
|
+
*/
|
|
49
|
+
getNormals(): vtkDataArray;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the points of the plane.
|
|
53
|
+
* @returns {vtkPoints} The points of the plane.
|
|
54
|
+
*/
|
|
55
|
+
getPoints(): vtkPoints;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get the i-th plane
|
|
59
|
+
* @param {Number} i The index of the plane to get.
|
|
60
|
+
* @param {vtkPlane} [plane] The vtkPlane instance to fill (optional).
|
|
61
|
+
* @returns {vtkPlane} The plane instance at the specified index.
|
|
62
|
+
* If no plane is provided, a new vtkPlane instance will be created.
|
|
63
|
+
*/
|
|
64
|
+
getPlane(i: number, plane?: vtkPlane): vtkPlane;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set the bounds of the planes.
|
|
68
|
+
* @param {Bounds} bounds The bounds to set.
|
|
69
|
+
* @returns {Boolean} true if bounds were set, false if they were already set
|
|
70
|
+
* @see getBounds
|
|
71
|
+
*/
|
|
72
|
+
setBounds(bounds: Bounds): boolean;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Set the Frustum planes.
|
|
76
|
+
* @param {Vector3[]} planes The coordinates of the frustum planes.
|
|
77
|
+
*/
|
|
78
|
+
setFrustumPlanes(planes: Vector3[]): boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Set the normals of the plane.
|
|
82
|
+
* @param {vtkDataArray} normals The normals to set.
|
|
83
|
+
*/
|
|
84
|
+
setNormals(normals: vtkDataArray): boolean;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Set the points of the plane.
|
|
88
|
+
* @param points The points to set.
|
|
89
|
+
*/
|
|
90
|
+
setPoints(points: vtkPoints): boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Method used to decorate a given object (publicAPI+model) with vtkPlane characteristics.
|
|
95
|
+
*
|
|
96
|
+
* @param publicAPI object on which methods will be bounds (public)
|
|
97
|
+
* @param model object on which data structure will be bounds (protected)
|
|
98
|
+
* @param {IPlanesInitialValues} [initialValues] (default: {})
|
|
99
|
+
*/
|
|
100
|
+
export function extend(
|
|
101
|
+
publicAPI: object,
|
|
102
|
+
model: object,
|
|
103
|
+
initialValues?: IPlanesInitialValues
|
|
104
|
+
): void;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Method used to create a new instance of vtkPlane.
|
|
108
|
+
* @param {IPlanesInitialValues} [initialValues] for pre-setting some of its content
|
|
109
|
+
*/
|
|
110
|
+
export function newInstance(initialValues?: IPlanesInitialValues): vtkPlanes;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* vtkPlanes computes the implicit function and function gradient for a set of
|
|
114
|
+
* planes. The planes must define a convex space.
|
|
115
|
+
*/
|
|
116
|
+
export declare const vtkPlanes: {
|
|
117
|
+
newInstance: typeof newInstance;
|
|
118
|
+
extend: typeof extend;
|
|
119
|
+
};
|
|
120
|
+
export default vtkPlanes;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { m as macro, T as TYPED_ARRAYS } from '../../macros2.js';
|
|
2
|
+
import vtkDataArray from '../Core/DataArray.js';
|
|
3
|
+
import vtkImplicitFunction from './ImplicitFunction.js';
|
|
4
|
+
import { f as vtkMath } from '../Core/Math/index.js';
|
|
5
|
+
import vtkPlane from './Plane.js';
|
|
6
|
+
import vtkPoints from '../Core/Points.js';
|
|
7
|
+
import { VtkDataTypes } from '../Core/DataArray/Constants.js';
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
vtkErrorMacro,
|
|
11
|
+
vtkWarningMacro
|
|
12
|
+
} = macro;
|
|
13
|
+
|
|
14
|
+
// ----------------------------------------------------------------------------
|
|
15
|
+
// vtkPlanes methods
|
|
16
|
+
// ----------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
function vtkPlanes(publicAPI, model) {
|
|
19
|
+
// Set our className
|
|
20
|
+
model.classHierarchy.push('vtkPlanes');
|
|
21
|
+
|
|
22
|
+
// Initialize internal variables
|
|
23
|
+
model.planes = model.planes || macro.newTypedArray(TYPED_ARRAYS.Float64Array, 24);
|
|
24
|
+
model.bounds = model.bounds || macro.newTypedArray(TYPED_ARRAYS.Float64Array, 6);
|
|
25
|
+
model.plane = vtkPlane.newInstance();
|
|
26
|
+
|
|
27
|
+
// Public API methods
|
|
28
|
+
publicAPI.setNormals = normals => {
|
|
29
|
+
if (normals && normals.getNumberOfComponents() !== 3) {
|
|
30
|
+
vtkWarningMacro('This array does not have 3 components. Ignoring normals.');
|
|
31
|
+
}
|
|
32
|
+
model.normals = normals;
|
|
33
|
+
publicAPI.modified();
|
|
34
|
+
return true;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Evaluate the function at a point x
|
|
39
|
+
* @param {*} x The point at which to evaluate the function
|
|
40
|
+
* @returns The function value at the point x
|
|
41
|
+
*/
|
|
42
|
+
publicAPI.evaluateFunction = x => {
|
|
43
|
+
if (!model.points || !model.normals) {
|
|
44
|
+
vtkErrorMacro('Please define points and/or normals!');
|
|
45
|
+
return Number.MAX_VALUE;
|
|
46
|
+
}
|
|
47
|
+
const numPlanes = model.points.getNumberOfPoints();
|
|
48
|
+
if (numPlanes !== model.normals.getNumberOfTuples()) {
|
|
49
|
+
vtkErrorMacro('Number of normals/points inconsistent!');
|
|
50
|
+
return Number.MAX_VALUE;
|
|
51
|
+
}
|
|
52
|
+
let maxVal = -Number.MAX_VALUE;
|
|
53
|
+
const normal = [];
|
|
54
|
+
const point = [];
|
|
55
|
+
for (let i = 0; i < numPlanes; i++) {
|
|
56
|
+
model.normals.getTuple(i, normal);
|
|
57
|
+
model.points.getPoint(i, point);
|
|
58
|
+
const val = vtkPlane.evaluate(normal, point, x);
|
|
59
|
+
if (val > maxVal) {
|
|
60
|
+
maxVal = val;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return maxVal;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Evaluate the gradient at a point x
|
|
68
|
+
* @param {*} x The point at which to evaluate the gradient
|
|
69
|
+
* @returns The gradient at the point x
|
|
70
|
+
*/
|
|
71
|
+
publicAPI.evaluateGradient = x => {
|
|
72
|
+
const retVal = [0, 0, 0];
|
|
73
|
+
if (!model.points || !model.normals) {
|
|
74
|
+
vtkErrorMacro('Define points and/or normals first!');
|
|
75
|
+
return retVal;
|
|
76
|
+
}
|
|
77
|
+
const numPlanes = model.points.getNumberOfPoints();
|
|
78
|
+
if (numPlanes !== model.normals.getNumberOfTuples()) {
|
|
79
|
+
vtkErrorMacro('The number of normals/points is inconsistent!');
|
|
80
|
+
return retVal;
|
|
81
|
+
}
|
|
82
|
+
let maxVal = -Number.MAX_VALUE;
|
|
83
|
+
const nTemp = [];
|
|
84
|
+
const pTemp = [];
|
|
85
|
+
for (let i = 0; i < numPlanes; i++) {
|
|
86
|
+
model.normals.getTuple(i, nTemp);
|
|
87
|
+
model.points.getPoint(i, pTemp);
|
|
88
|
+
const val = vtkPlane.evaluate(nTemp, pTemp, x);
|
|
89
|
+
if (val > maxVal) {
|
|
90
|
+
maxVal = val;
|
|
91
|
+
retVal[0] = nTemp[0];
|
|
92
|
+
retVal[1] = nTemp[1];
|
|
93
|
+
retVal[2] = nTemp[2];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return retVal;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Set the frustum planes
|
|
101
|
+
* @param {Number[]} planes The planes to set
|
|
102
|
+
* @returns {Boolean} true if planes were set, false if they were already set
|
|
103
|
+
*/
|
|
104
|
+
publicAPI.setFrustumPlanes = planes => {
|
|
105
|
+
if (vtkMath.areEquals(model.planes, planes)) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
model.planes = [...planes];
|
|
109
|
+
const pts = vtkPoints.newInstance({
|
|
110
|
+
dataType: VtkDataTypes.DOUBLE
|
|
111
|
+
});
|
|
112
|
+
const normals = vtkDataArray.newInstance({
|
|
113
|
+
numberOfComponents: 3,
|
|
114
|
+
size: 6 * 3,
|
|
115
|
+
// 6 planes, each with a normal
|
|
116
|
+
dataType: VtkDataTypes.DOUBLE
|
|
117
|
+
});
|
|
118
|
+
pts.setNumberOfPoints(6);
|
|
119
|
+
publicAPI.setPoints(pts);
|
|
120
|
+
publicAPI.setNormals(normals);
|
|
121
|
+
const n = [];
|
|
122
|
+
const x = [];
|
|
123
|
+
for (let i = 0; i < 6; i++) {
|
|
124
|
+
const planeOffset = 4 * i;
|
|
125
|
+
n[0] = -planes[planeOffset];
|
|
126
|
+
n[1] = -planes[planeOffset + 1];
|
|
127
|
+
n[2] = -planes[planeOffset + 2];
|
|
128
|
+
x[0] = 0.0;
|
|
129
|
+
x[1] = 0.0;
|
|
130
|
+
x[2] = 0.0;
|
|
131
|
+
if (n[0] !== 0.0) {
|
|
132
|
+
x[0] = planes[planeOffset + 3] / n[0];
|
|
133
|
+
} else if (n[1] !== 0.0) {
|
|
134
|
+
x[1] = planes[planeOffset + 3] / n[1];
|
|
135
|
+
} else {
|
|
136
|
+
x[2] = planes[planeOffset + 3] / n[2];
|
|
137
|
+
}
|
|
138
|
+
pts.setPoint(i, ...x);
|
|
139
|
+
normals.setTuple(i, n);
|
|
140
|
+
}
|
|
141
|
+
publicAPI.modified();
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Set the bounds of the planes
|
|
147
|
+
* @param {*} bounds The bounds to set
|
|
148
|
+
* @returns {Boolean} true if bounds were set, false if they were already set
|
|
149
|
+
*/
|
|
150
|
+
publicAPI.setBounds = bounds => {
|
|
151
|
+
if (vtkMath.areEquals(model.bounds, bounds)) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
model.bounds = [...bounds];
|
|
155
|
+
const pts = vtkPoints.newInstance();
|
|
156
|
+
const normals = vtkDataArray.newInstance({
|
|
157
|
+
numberOfComponents: 3,
|
|
158
|
+
size: 6 * 3,
|
|
159
|
+
// 6 planes, each with a normal
|
|
160
|
+
dataType: VtkDataTypes.DOUBLE
|
|
161
|
+
});
|
|
162
|
+
pts.setNumberOfPoints(6);
|
|
163
|
+
publicAPI.setPoints(pts);
|
|
164
|
+
publicAPI.setNormals(normals);
|
|
165
|
+
const n = [];
|
|
166
|
+
const x = [];
|
|
167
|
+
|
|
168
|
+
// The x planes
|
|
169
|
+
n[0] = -1.0;
|
|
170
|
+
n[1] = 0.0;
|
|
171
|
+
n[2] = 0.0;
|
|
172
|
+
x[0] = bounds[0];
|
|
173
|
+
x[1] = 0.0;
|
|
174
|
+
x[2] = 0.0;
|
|
175
|
+
pts.setPoint(0, ...x);
|
|
176
|
+
normals.setTuple(0, n);
|
|
177
|
+
n[0] = 1.0;
|
|
178
|
+
x[0] = bounds[1];
|
|
179
|
+
pts.setPoint(1, ...x);
|
|
180
|
+
normals.setTuple(1, n);
|
|
181
|
+
|
|
182
|
+
// The y planes
|
|
183
|
+
n[0] = 0.0;
|
|
184
|
+
n[1] = -1.0;
|
|
185
|
+
n[2] = 0.0;
|
|
186
|
+
x[0] = 0.0;
|
|
187
|
+
x[1] = bounds[2];
|
|
188
|
+
x[2] = 0.0;
|
|
189
|
+
pts.setPoint(2, ...x);
|
|
190
|
+
normals.setTuple(2, n);
|
|
191
|
+
n[1] = 1.0;
|
|
192
|
+
x[1] = bounds[3];
|
|
193
|
+
pts.setPoint(3, ...x);
|
|
194
|
+
normals.setTuple(3, n);
|
|
195
|
+
|
|
196
|
+
// The z planes
|
|
197
|
+
n[0] = 0.0;
|
|
198
|
+
n[1] = 0.0;
|
|
199
|
+
n[2] = -1.0;
|
|
200
|
+
x[0] = 0.0;
|
|
201
|
+
x[1] = 0.0;
|
|
202
|
+
x[2] = bounds[4];
|
|
203
|
+
pts.setPoint(4, ...x);
|
|
204
|
+
normals.setTuple(4, n);
|
|
205
|
+
n[2] = 1.0;
|
|
206
|
+
x[2] = bounds[5];
|
|
207
|
+
pts.setPoint(5, ...x);
|
|
208
|
+
normals.setTuple(5, n);
|
|
209
|
+
publicAPI.modified();
|
|
210
|
+
return true;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Get the number of planes
|
|
215
|
+
* @returns {Number} the number of planes
|
|
216
|
+
*/
|
|
217
|
+
publicAPI.getNumberOfPlanes = () => {
|
|
218
|
+
if (model.points && model.normals) {
|
|
219
|
+
const npts = model.points.getNumberOfPoints();
|
|
220
|
+
const nnormals = model.normals.getNumberOfTuples();
|
|
221
|
+
return Math.min(npts, nnormals);
|
|
222
|
+
}
|
|
223
|
+
return 0;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get the i-th plane
|
|
228
|
+
* @param {*} i
|
|
229
|
+
* @param {vtkPlane} plane the vtkPlane instance to fill
|
|
230
|
+
* @returns {vtkPlane} the plane instance
|
|
231
|
+
*/
|
|
232
|
+
publicAPI.getPlane = function (i) {
|
|
233
|
+
let plane = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : model.plane;
|
|
234
|
+
if (i >= 0 && i < publicAPI.getNumberOfPlanes()) {
|
|
235
|
+
const normal = model.normals.getTuple(i);
|
|
236
|
+
const point = model.points.getPoint(i);
|
|
237
|
+
plane.setNormal(normal);
|
|
238
|
+
plane.setOrigin(point);
|
|
239
|
+
}
|
|
240
|
+
return plane;
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// ----------------------------------------------------------------------------
|
|
245
|
+
// Object factory
|
|
246
|
+
// ----------------------------------------------------------------------------
|
|
247
|
+
|
|
248
|
+
const DEFAULT_VALUES = {
|
|
249
|
+
points: null,
|
|
250
|
+
normals: null,
|
|
251
|
+
planes: null,
|
|
252
|
+
bounds: null
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// ----------------------------------------------------------------------------
|
|
256
|
+
|
|
257
|
+
function extend(publicAPI, model) {
|
|
258
|
+
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
259
|
+
Object.assign(model, DEFAULT_VALUES, initialValues);
|
|
260
|
+
|
|
261
|
+
// Build VTK API
|
|
262
|
+
vtkImplicitFunction.extend(publicAPI, model, initialValues);
|
|
263
|
+
macro.setGet(publicAPI, model, ['points', 'normals']);
|
|
264
|
+
macro.get(publicAPI, model, ['bounds', 'planes']);
|
|
265
|
+
|
|
266
|
+
// Object methods
|
|
267
|
+
vtkPlanes(publicAPI, model);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ----------------------------------------------------------------------------
|
|
271
|
+
|
|
272
|
+
const newInstance = macro.newInstance(extend, 'vtkPlanes');
|
|
273
|
+
|
|
274
|
+
// ----------------------------------------------------------------------------
|
|
275
|
+
|
|
276
|
+
var vtkPlanes$1 = {
|
|
277
|
+
newInstance,
|
|
278
|
+
extend
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export { vtkPlanes$1 as default, extend, newInstance };
|
package/Common/DataModel.js
CHANGED
|
@@ -12,6 +12,7 @@ import vtkLine from './DataModel/Line.js';
|
|
|
12
12
|
import vtkMolecule from './DataModel/Molecule.js';
|
|
13
13
|
import vtkPiecewiseFunction from './DataModel/PiecewiseFunction.js';
|
|
14
14
|
import vtkPlane from './DataModel/Plane.js';
|
|
15
|
+
import vtkPlanes from './DataModel/Planes.js';
|
|
15
16
|
import vtkPointSet from './DataModel/PointSet.js';
|
|
16
17
|
import vtkPolyData from './DataModel/PolyData.js';
|
|
17
18
|
import vtkSelectionNode from './DataModel/SelectionNode.js';
|
|
@@ -35,6 +36,7 @@ var DataModel = {
|
|
|
35
36
|
vtkMolecule,
|
|
36
37
|
vtkPiecewiseFunction,
|
|
37
38
|
vtkPlane,
|
|
39
|
+
vtkPlanes,
|
|
38
40
|
vtkPointSet,
|
|
39
41
|
vtkPolyData,
|
|
40
42
|
vtkSelectionNode,
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { m as macro } from '../../macros2.js';
|
|
2
|
+
import vtkMouseCameraTrackballPanManipulator from './MouseCameraTrackballPanManipulator.js';
|
|
3
|
+
import { mat4, vec3 } from 'gl-matrix';
|
|
4
|
+
|
|
5
|
+
// ----------------------------------------------------------------------------
|
|
6
|
+
// Helper functions for center of rotation adjustment
|
|
7
|
+
// ----------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Transforms a vector by the transformation delta between two matrices.
|
|
11
|
+
*
|
|
12
|
+
* @param {Object} tempObjects - Temporary matrices/vectors for computation
|
|
13
|
+
* @param {mat4} beforeMatrix - Matrix before transformation
|
|
14
|
+
* @param {mat4} afterMatrix - Matrix after transformation
|
|
15
|
+
* @param {Array} vector - Vector to transform [x, y, z]
|
|
16
|
+
* @returns {Array} Transformed vector [x, y, z]
|
|
17
|
+
*/
|
|
18
|
+
function transformVectorByTransformation(tempObjects, beforeMatrix, afterMatrix, vector) {
|
|
19
|
+
const {
|
|
20
|
+
matrixA,
|
|
21
|
+
matrixB,
|
|
22
|
+
newCenter
|
|
23
|
+
} = tempObjects;
|
|
24
|
+
|
|
25
|
+
// The view matrix from vtk.js is row-major, but gl-matrix expects column-major.
|
|
26
|
+
// We need to transpose them before use.
|
|
27
|
+
mat4.transpose(matrixA, beforeMatrix);
|
|
28
|
+
mat4.transpose(matrixB, afterMatrix);
|
|
29
|
+
mat4.invert(matrixB, matrixB);
|
|
30
|
+
|
|
31
|
+
// Compute delta transformation matrix
|
|
32
|
+
mat4.multiply(matrixA, matrixB, matrixA);
|
|
33
|
+
vec3.transformMat4(newCenter, vector, matrixA);
|
|
34
|
+
return newCenter;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Computes the new center of rotation based on camera movement.
|
|
39
|
+
* When the camera moves (pan), the center of rotation should move
|
|
40
|
+
* by the same transformation.
|
|
41
|
+
*
|
|
42
|
+
* @param {Object} tempObjects - Temporary matrices/vectors for computation
|
|
43
|
+
* @param {Object} renderer - VTK renderer
|
|
44
|
+
* @param {mat4} beforeCameraMatrix - Camera view matrix before movement
|
|
45
|
+
* @param {Array} oldCenterOfRotation - Previous center of rotation [x, y, z]
|
|
46
|
+
* @returns {Array} New center of rotation [x, y, z]
|
|
47
|
+
*/
|
|
48
|
+
function computeNewCenterOfRotation(tempObjects, renderer, beforeCameraMatrix, oldCenterOfRotation) {
|
|
49
|
+
const cam = renderer.getActiveCamera();
|
|
50
|
+
if (!cam || !beforeCameraMatrix) {
|
|
51
|
+
return oldCenterOfRotation;
|
|
52
|
+
}
|
|
53
|
+
const afterMatrixRowMajor = cam.getViewMatrix();
|
|
54
|
+
return transformVectorByTransformation(tempObjects, beforeCameraMatrix, afterMatrixRowMajor, oldCenterOfRotation);
|
|
55
|
+
}
|
|
56
|
+
function getCameraMatrix(renderer, tempMatrix) {
|
|
57
|
+
const cam = renderer.getActiveCamera();
|
|
58
|
+
if (cam) {
|
|
59
|
+
mat4.copy(tempMatrix, cam.getViewMatrix());
|
|
60
|
+
return tempMatrix;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function vtkMouseCameraTrackballPanManipulatorAutoCenter(publicAPI, model) {
|
|
65
|
+
model.classHierarchy.push('vtkMouseCameraTrackballPanManipulatorAutoCenter');
|
|
66
|
+
const tempCameraMatrix = mat4.create();
|
|
67
|
+
const tempComputeObjects = {
|
|
68
|
+
matrixA: mat4.create(),
|
|
69
|
+
matrixB: mat4.create(),
|
|
70
|
+
newCenter: vec3.create()
|
|
71
|
+
};
|
|
72
|
+
const superOnMouseMove = publicAPI.onMouseMove;
|
|
73
|
+
publicAPI.onMouseMove = (interactor, renderer, position) => {
|
|
74
|
+
if (!position) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
|
|
78
|
+
superOnMouseMove(interactor, renderer, position);
|
|
79
|
+
if (beforeCameraMatrix && model.center) {
|
|
80
|
+
const newCenter = computeNewCenterOfRotation(tempComputeObjects, renderer, beforeCameraMatrix, model.center);
|
|
81
|
+
publicAPI.setCenter(newCenter);
|
|
82
|
+
const style = interactor.getInteractorStyle();
|
|
83
|
+
if (style && style.setCenterOfRotation) {
|
|
84
|
+
style.setCenterOfRotation(newCenter);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ----------------------------------------------------------------------------
|
|
91
|
+
// Object factory
|
|
92
|
+
// ----------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
const DEFAULT_VALUES = {};
|
|
95
|
+
|
|
96
|
+
// ----------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
function extend(publicAPI, model) {
|
|
99
|
+
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
100
|
+
Object.assign(model, DEFAULT_VALUES, initialValues);
|
|
101
|
+
|
|
102
|
+
// Inheritance
|
|
103
|
+
vtkMouseCameraTrackballPanManipulator.extend(publicAPI, model, initialValues);
|
|
104
|
+
|
|
105
|
+
// Object specific methods
|
|
106
|
+
vtkMouseCameraTrackballPanManipulatorAutoCenter(publicAPI, model);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ----------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
const newInstance = macro.newInstance(extend, 'vtkMouseCameraTrackballPanManipulatorAutoCenter');
|
|
112
|
+
|
|
113
|
+
// ----------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
var index = {
|
|
116
|
+
newInstance,
|
|
117
|
+
extend
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export { index as default, extend, newInstance };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { m as macro } from '../../macros2.js';
|
|
2
2
|
import { MouseButton } from '../../Rendering/Core/RenderWindowInteractor/Constants.js';
|
|
3
3
|
import vtkInteractorStyle from '../../Rendering/Core/InteractorStyle.js';
|
|
4
|
-
import { mat4, vec3 } from 'gl-matrix';
|
|
5
4
|
|
|
6
5
|
const {
|
|
7
6
|
vtkDebugMacro
|
|
@@ -102,62 +101,6 @@ function dollyByFactor(interactor, renderer, factor) {
|
|
|
102
101
|
renderer.updateLightsGeometryToFollowCamera();
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
|
-
function getCameraMatrix(renderer, tempMatrix) {
|
|
106
|
-
const cam = renderer.getActiveCamera();
|
|
107
|
-
if (cam) {
|
|
108
|
-
mat4.copy(tempMatrix, cam.getViewMatrix());
|
|
109
|
-
return tempMatrix;
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Transforms a vector by the transformation delta between two matrices.
|
|
116
|
-
*
|
|
117
|
-
* @param {Object} tempObjects - Temporary matrices/vectors for computation
|
|
118
|
-
* @param {mat4} beforeMatrix - Matrix before transformation
|
|
119
|
-
* @param {mat4} afterMatrix - Matrix after transformation
|
|
120
|
-
* @param {Array} vector - Vector to transform [x, y, z]
|
|
121
|
-
* @returns {Array} Transformed vector [x, y, z]
|
|
122
|
-
*/
|
|
123
|
-
function transformVectorByTransformation(tempObjects, beforeMatrix, afterMatrix, vector) {
|
|
124
|
-
const {
|
|
125
|
-
matrixA,
|
|
126
|
-
matrixB,
|
|
127
|
-
newCenter
|
|
128
|
-
} = tempObjects;
|
|
129
|
-
|
|
130
|
-
// The view matrix from vtk.js is row-major, but gl-matrix expects column-major.
|
|
131
|
-
// We need to transpose them before use.
|
|
132
|
-
mat4.transpose(matrixA, beforeMatrix);
|
|
133
|
-
mat4.transpose(matrixB, afterMatrix);
|
|
134
|
-
mat4.invert(matrixB, matrixB);
|
|
135
|
-
|
|
136
|
-
// Compute delta transformation matrix
|
|
137
|
-
mat4.multiply(matrixA, matrixB, matrixA);
|
|
138
|
-
vec3.transformMat4(newCenter, vector, matrixA);
|
|
139
|
-
return newCenter;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Computes the new center of rotation based on camera movement.
|
|
144
|
-
* When the camera moves (pan), the center of rotation should move
|
|
145
|
-
* by the same transformation to maintain consistent rotation behavior.
|
|
146
|
-
*
|
|
147
|
-
* @param {Object} tempObjects - Temporary matrices/vectors for computation
|
|
148
|
-
* @param {Object} renderer - VTK renderer
|
|
149
|
-
* @param {mat4} beforeCameraMatrix - Camera view matrix before movement
|
|
150
|
-
* @param {Array} oldCenterOfRotation - Previous center of rotation [x, y, z]
|
|
151
|
-
* @returns {Array} New center of rotation [x, y, z]
|
|
152
|
-
*/
|
|
153
|
-
function computeNewCenterOfRotation(tempObjects, renderer, beforeCameraMatrix, oldCenterOfRotation) {
|
|
154
|
-
const cam = renderer.getActiveCamera();
|
|
155
|
-
if (!cam || !beforeCameraMatrix) {
|
|
156
|
-
return oldCenterOfRotation;
|
|
157
|
-
}
|
|
158
|
-
const afterMatrixRowMajor = cam.getViewMatrix();
|
|
159
|
-
return transformVectorByTransformation(tempObjects, beforeCameraMatrix, afterMatrixRowMajor, oldCenterOfRotation);
|
|
160
|
-
}
|
|
161
104
|
|
|
162
105
|
// ----------------------------------------------------------------------------
|
|
163
106
|
// Static API
|
|
@@ -176,14 +119,6 @@ const STATIC = {
|
|
|
176
119
|
function vtkInteractorStyleManipulator(publicAPI, model) {
|
|
177
120
|
// Set our className
|
|
178
121
|
model.classHierarchy.push('vtkInteractorStyleManipulator');
|
|
179
|
-
|
|
180
|
-
// Initialize temporary objects to reduce garbage collection
|
|
181
|
-
const tempCameraMatrix = mat4.create();
|
|
182
|
-
const tempComputeObjects = {
|
|
183
|
-
matrixA: mat4.create(),
|
|
184
|
-
matrixB: mat4.create(),
|
|
185
|
-
newCenter: vec3.create()
|
|
186
|
-
};
|
|
187
122
|
model.currentVRManipulators = new Map();
|
|
188
123
|
model.mouseManipulators = [];
|
|
189
124
|
model.keyboardManipulators = [];
|
|
@@ -480,11 +415,7 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
|
|
|
480
415
|
publicAPI.handleMouseMove = callData => {
|
|
481
416
|
model.cachedMousePosition = callData.position;
|
|
482
417
|
if (model.currentManipulator && model.currentManipulator.onMouseMove) {
|
|
483
|
-
|
|
484
|
-
const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
|
|
485
|
-
model.currentManipulator.onMouseMove(model._interactor, renderer, callData.position);
|
|
486
|
-
const newCenter = computeNewCenterOfRotation(tempComputeObjects, renderer, beforeCameraMatrix, model.centerOfRotation);
|
|
487
|
-
publicAPI.setCenterOfRotation(newCenter);
|
|
418
|
+
model.currentManipulator.onMouseMove(model._interactor, model.getRenderer(callData), callData.position);
|
|
488
419
|
publicAPI.invokeInteractionEvent(INTERACTION_EVENT);
|
|
489
420
|
}
|
|
490
421
|
};
|
|
@@ -627,7 +558,6 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
|
|
|
627
558
|
//----------------------------------------------------------------------------
|
|
628
559
|
publicAPI.handlePan = callData => {
|
|
629
560
|
const renderer = model.getRenderer(callData);
|
|
630
|
-
const beforeCameraMatrix = getCameraMatrix(renderer, tempCameraMatrix);
|
|
631
561
|
let count = model.gestureManipulators.length;
|
|
632
562
|
let actionCount = 0;
|
|
633
563
|
while (count--) {
|
|
@@ -638,8 +568,6 @@ function vtkInteractorStyleManipulator(publicAPI, model) {
|
|
|
638
568
|
}
|
|
639
569
|
}
|
|
640
570
|
if (actionCount) {
|
|
641
|
-
const newCenter = computeNewCenterOfRotation(tempComputeObjects, renderer, beforeCameraMatrix, model.centerOfRotation);
|
|
642
|
-
publicAPI.setCenterOfRotation(newCenter);
|
|
643
571
|
publicAPI.invokeInteractionEvent(INTERACTION_EVENT);
|
|
644
572
|
}
|
|
645
573
|
};
|
package/README.md
CHANGED
|
@@ -48,8 +48,8 @@ In general VTK tries to be as portable as possible; the specific configurations
|
|
|
48
48
|
|
|
49
49
|
vtk.js supports the following development environments:
|
|
50
50
|
|
|
51
|
-
- Node
|
|
52
|
-
- NPM
|
|
51
|
+
- Node 22+
|
|
52
|
+
- NPM 10+
|
|
53
53
|
|
|
54
54
|
and we use [@babel/preset-env](https://www.npmjs.com/package/@babel/preset-env) with the [defaults](https://github.com/Kitware/vtk-js/blob/master/.browserslistrc) set of [browsers target](https://browserl.ist/?q=defaults).
|
|
55
55
|
But when built from source this could be adjusted to support any browser as long they provide WebGL.
|
|
@@ -78,4 +78,3 @@ See [Copyright.txt][] for details.
|
|
|
78
78
|
## Contributing
|
|
79
79
|
|
|
80
80
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for instructions on how to contribute.
|
|
81
|
-
|
|
@@ -301,10 +301,17 @@ export interface vtkCamera extends vtkObject {
|
|
|
301
301
|
getViewAngle(): number;
|
|
302
302
|
|
|
303
303
|
/**
|
|
304
|
-
*
|
|
304
|
+
* Get the view transform
|
|
305
305
|
*/
|
|
306
306
|
getViewMatrix(): mat4;
|
|
307
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Get the model transform matrix for the camera.
|
|
310
|
+
* This matrix could be used for model related transformations such as scale, shear, rotations and translations.
|
|
311
|
+
* @returns {mat4} mat The value of the model transform matrix.
|
|
312
|
+
*/
|
|
313
|
+
getModelTransformMatrix(): mat4;
|
|
314
|
+
|
|
308
315
|
/**
|
|
309
316
|
* Get the ViewPlaneNormal.
|
|
310
317
|
* This vector will point opposite to the direction of projection,
|
|
@@ -674,7 +681,14 @@ export interface vtkCamera extends vtkObject {
|
|
|
674
681
|
* Set the view matrix for the camera.
|
|
675
682
|
* @param {mat4} mat The value of the view matrix.
|
|
676
683
|
*/
|
|
677
|
-
setViewMatrix(mat: mat4):
|
|
684
|
+
setViewMatrix(mat: mat4): void;
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Set the model transform matrix for the camera.
|
|
688
|
+
* This matrix could be used for model related transformations such as scale, shear, rotations and translations.
|
|
689
|
+
* @param {mat4} mat The value of the model transform matrix.
|
|
690
|
+
*/
|
|
691
|
+
setModelTransformMatrixMatrix(mat: mat4): void;
|
|
678
692
|
|
|
679
693
|
/**
|
|
680
694
|
* Set the view up direction for the camera.
|
package/Rendering/Core/Camera.js
CHANGED
|
@@ -402,6 +402,10 @@ function vtkCamera(publicAPI, model) {
|
|
|
402
402
|
mat4.multiply(tmpMatrix, mat, tmpMatrix);
|
|
403
403
|
publicAPI.computeViewParametersFromViewMatrix(tmpMatrix);
|
|
404
404
|
};
|
|
405
|
+
publicAPI.setModelTransformMatrix = mat => {
|
|
406
|
+
model.modelTransformMatrix = mat;
|
|
407
|
+
};
|
|
408
|
+
publicAPI.getModelTransformMatrix = () => model.modelTransformMatrix;
|
|
405
409
|
publicAPI.setViewMatrix = mat => {
|
|
406
410
|
model.viewMatrix = mat;
|
|
407
411
|
if (model.viewMatrix) {
|
|
@@ -412,6 +416,10 @@ function vtkCamera(publicAPI, model) {
|
|
|
412
416
|
};
|
|
413
417
|
publicAPI.getViewMatrix = () => {
|
|
414
418
|
if (model.viewMatrix) {
|
|
419
|
+
if (model.modelTransformMatrix) {
|
|
420
|
+
mat4.multiply(tmpMatrix, model.viewMatrix, model.modelTransformMatrix);
|
|
421
|
+
return tmpMatrix;
|
|
422
|
+
}
|
|
415
423
|
return model.viewMatrix;
|
|
416
424
|
}
|
|
417
425
|
mat4.lookAt(tmpMatrix, model.position,
|
|
@@ -423,7 +431,11 @@ function vtkCamera(publicAPI, model) {
|
|
|
423
431
|
|
|
424
432
|
mat4.transpose(tmpMatrix, tmpMatrix);
|
|
425
433
|
const result = new Float64Array(16);
|
|
426
|
-
|
|
434
|
+
if (model.modelTransformMatrix) {
|
|
435
|
+
mat4.multiply(result, tmpMatrix, model.modelTransformMatrix);
|
|
436
|
+
} else {
|
|
437
|
+
mat4.copy(result, tmpMatrix);
|
|
438
|
+
}
|
|
427
439
|
return result;
|
|
428
440
|
};
|
|
429
441
|
publicAPI.setProjectionMatrix = mat => {
|
|
@@ -613,6 +625,7 @@ const DEFAULT_VALUES = {
|
|
|
613
625
|
freezeFocalPoint: false,
|
|
614
626
|
projectionMatrix: null,
|
|
615
627
|
viewMatrix: null,
|
|
628
|
+
modelTransformMatrix: null,
|
|
616
629
|
cameraLightTransform: mat4.create(),
|
|
617
630
|
// used for world to physical transformations
|
|
618
631
|
physicalTranslation: [0, 0, 0],
|
|
@@ -186,12 +186,23 @@ function vtkWidgetManager(publicAPI, model) {
|
|
|
186
186
|
model._interactor.render();
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
const deactivateAllWidgets = () => {
|
|
190
|
+
let wantRender = false;
|
|
191
|
+
for (let i = 0; i < model.widgets.length; i++) {
|
|
192
|
+
const w = model.widgets[i];
|
|
193
|
+
wantRender ||= !!w.getActiveState();
|
|
194
|
+
w.deactivateAllHandles();
|
|
195
|
+
}
|
|
196
|
+
if (wantRender) model._interactor.render();
|
|
197
|
+
};
|
|
189
198
|
const handleEvent = async function (callData) {
|
|
190
199
|
let fromTouchEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
191
200
|
if (!model.isAnimating && model.pickingEnabled && callData.pokedRenderer === model._renderer) {
|
|
192
201
|
const callID = Symbol('UpdateSelection');
|
|
193
202
|
model._currentUpdateSelectionCallID = callID;
|
|
194
203
|
await updateSelection(callData, fromTouchEvent, callID);
|
|
204
|
+
} else {
|
|
205
|
+
deactivateAllWidgets();
|
|
195
206
|
}
|
|
196
207
|
};
|
|
197
208
|
function updateWidgetForRender(w) {
|
package/index.d.ts
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
/// <reference path="./Common/DataModel/Locator.d.ts" />
|
|
40
40
|
/// <reference path="./Common/DataModel/PiecewiseFunction.d.ts" />
|
|
41
41
|
/// <reference path="./Common/DataModel/Plane.d.ts" />
|
|
42
|
+
/// <reference path="./Common/DataModel/Planes.d.ts" />
|
|
42
43
|
/// <reference path="./Common/DataModel/PointSet.d.ts" />
|
|
43
44
|
/// <reference path="./Common/DataModel/PolyData/Constants.d.ts" />
|
|
44
45
|
/// <reference path="./Common/DataModel/PolyData.d.ts" />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitware/vtk.js",
|
|
3
|
-
"version": "34.
|
|
3
|
+
"version": "34.10.0",
|
|
4
4
|
"description": "Visualization Toolkit for the Web",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"3d",
|
|
@@ -238,5 +238,6 @@
|
|
|
238
238
|
"publishConfig": {
|
|
239
239
|
"access": "public"
|
|
240
240
|
},
|
|
241
|
+
"type": "module",
|
|
241
242
|
"types": "./index.d.ts"
|
|
242
243
|
}
|