@kitware/vtk.js 31.0.5 → 31.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/Widgets/Representations/GlyphRepresentation.js +1 -1
- package/Widgets/Representations/LineHandleRepresentation.js +59 -1
- package/Widgets/Widgets3D/ResliceCursorWidget/behavior.d.ts +6 -0
- package/Widgets/Widgets3D/ResliceCursorWidget/helpers.js +1 -4
- package/Widgets/Widgets3D/ResliceCursorWidget/state.js +1 -3
- package/Widgets/Widgets3D/ResliceCursorWidget.d.ts +16 -0
- package/Widgets/Widgets3D/ResliceCursorWidget.js +5 -1
- package/package.json +1 -1
|
@@ -119,7 +119,7 @@ function direction(publicAPI, model) {
|
|
|
119
119
|
return (polyData, states) => {
|
|
120
120
|
model._pipeline.mapper.setOrientationArray('orientation');
|
|
121
121
|
model._pipeline.mapper.setOrientationMode(OrientationModes.MATRIX);
|
|
122
|
-
const orientation = allocateArray(polyData, 'orientation', states.length, '
|
|
122
|
+
const orientation = allocateArray(polyData, 'orientation', states.length, 'Float64Array', 9).getData();
|
|
123
123
|
for (let i = 0; i < states.length; ++i) {
|
|
124
124
|
const state = states[i];
|
|
125
125
|
const right = state.getRight ? state.getRight() : [1, 0, 0];
|
|
@@ -4,6 +4,8 @@ import vtkGlyphRepresentation from './GlyphRepresentation.js';
|
|
|
4
4
|
import vtkPixelSpaceCallbackMapper from '../../Rendering/Core/PixelSpaceCallbackMapper.js';
|
|
5
5
|
import vtkCylinderSource from '../../Filters/Sources/CylinderSource.js';
|
|
6
6
|
import { allocateArray } from './WidgetRepresentation.js';
|
|
7
|
+
import { getPixelWorldHeightAtCoord } from '../Core/WidgetManager.js';
|
|
8
|
+
import { vec3 } from 'gl-matrix';
|
|
7
9
|
|
|
8
10
|
const INFINITE_RATIO = 100000;
|
|
9
11
|
|
|
@@ -60,6 +62,61 @@ function vtkLineHandleRepresentation(publicAPI, model) {
|
|
|
60
62
|
model.displayCallback = callback;
|
|
61
63
|
model.displayMapper.setCallback(callback ? callbackProxy : null);
|
|
62
64
|
};
|
|
65
|
+
const superPublicAPI = {
|
|
66
|
+
...publicAPI
|
|
67
|
+
};
|
|
68
|
+
publicAPI.requestData = (inData, outData) => {
|
|
69
|
+
superPublicAPI.requestData(inData, outData);
|
|
70
|
+
if (!model.holeWidth) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const internalPolyData = outData[0];
|
|
74
|
+
|
|
75
|
+
// Duplicate points and point data
|
|
76
|
+
const points = internalPolyData.getPoints();
|
|
77
|
+
const dataArrays = internalPolyData.getPointData().getArrays();
|
|
78
|
+
[points, ...dataArrays].forEach(array => {
|
|
79
|
+
const oldNumberOfValues = array.getNumberOfValues();
|
|
80
|
+
array.resize(2 * array.getNumberOfTuples());
|
|
81
|
+
const arrayData = array.getData();
|
|
82
|
+
for (let i = 0; i < oldNumberOfValues; ++i) {
|
|
83
|
+
arrayData[i + oldNumberOfValues] = arrayData[i];
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Change the scale and origin of each line
|
|
88
|
+
const states = publicAPI.getRepresentationStates(inData[0]);
|
|
89
|
+
const nStates = states.length;
|
|
90
|
+
const scaleArray = internalPolyData.getPointData().getArrayByName('scale');
|
|
91
|
+
const orientationArray = internalPolyData.getPointData().getArrayByName('orientation');
|
|
92
|
+
const defaultScale = [1, 1, 1];
|
|
93
|
+
const defaultOrientation = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
|
94
|
+
for (let i = 0; i < nStates; ++i) {
|
|
95
|
+
const j = i + nStates;
|
|
96
|
+
const scale = scaleArray?.getTuple(i) ?? defaultScale;
|
|
97
|
+
const orientationMatrix = orientationArray?.getTuple(i) ?? defaultOrientation;
|
|
98
|
+
const originalPoint = points.getTuple(i);
|
|
99
|
+
|
|
100
|
+
// Divide the scale by two in the direction of the cylinder, as we duplicate the line
|
|
101
|
+
scale[2] *= 0.5;
|
|
102
|
+
scaleArray?.setTuple(i, scale);
|
|
103
|
+
scaleArray?.setTuple(j, scale);
|
|
104
|
+
|
|
105
|
+
// Add or subtract an offset to each point depending on the hole width
|
|
106
|
+
let holeWidth = model.holeWidth;
|
|
107
|
+
if (publicAPI.getScaleInPixels()) {
|
|
108
|
+
holeWidth *= getPixelWorldHeightAtCoord(originalPoint, model.displayScaleParams);
|
|
109
|
+
}
|
|
110
|
+
const offset = vec3.fromValues(0, 0, 0.5 * scale[2] + holeWidth);
|
|
111
|
+
vec3.transformMat3(offset, offset, orientationMatrix);
|
|
112
|
+
points.setTuple(i, vec3.add(vec3.create(), originalPoint, offset));
|
|
113
|
+
points.setTuple(j, vec3.sub(vec3.create(), originalPoint, offset));
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
publicAPI.getSelectedState = (prop, compositeID) => {
|
|
117
|
+
const representationStates = publicAPI.getRepresentationStates();
|
|
118
|
+
return representationStates[compositeID % representationStates.length];
|
|
119
|
+
};
|
|
63
120
|
|
|
64
121
|
/**
|
|
65
122
|
* Overwrite scale3 to optionally make lines infinite
|
|
@@ -84,6 +141,7 @@ function defaultValues(initialValues) {
|
|
|
84
141
|
return {
|
|
85
142
|
infiniteLine: true,
|
|
86
143
|
glyphResolution: 4,
|
|
144
|
+
holeWidth: 0,
|
|
87
145
|
_pipeline: {
|
|
88
146
|
glyph: vtkCylinderSource.newInstance({
|
|
89
147
|
resolution: initialValues.glyphResolution ?? 4,
|
|
@@ -100,7 +158,7 @@ function defaultValues(initialValues) {
|
|
|
100
158
|
function extend(publicAPI, model) {
|
|
101
159
|
let initialValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
102
160
|
vtkGlyphRepresentation.extend(publicAPI, model, defaultValues(initialValues));
|
|
103
|
-
macro.setGet(publicAPI, model, ['infiniteLine', 'glyphResolution']);
|
|
161
|
+
macro.setGet(publicAPI, model, ['infiniteLine', 'glyphResolution', 'holeWidth']);
|
|
104
162
|
|
|
105
163
|
// Object specific methods
|
|
106
164
|
vtkLineHandleRepresentation(publicAPI, model);
|
|
@@ -14,6 +14,12 @@ export default interface vtkResliceCursorWidgetDefaultInstance
|
|
|
14
14
|
extends vtkAbstractWidget {
|
|
15
15
|
getActiveInteraction(): Nullable<InteractionMethodsName>;
|
|
16
16
|
|
|
17
|
+
getScaleInPixels(): boolean;
|
|
18
|
+
setScaleInPixels(scaleInPixels: boolean): boolean;
|
|
19
|
+
|
|
20
|
+
getHoleWidth(): number;
|
|
21
|
+
setHoleWidth(holeWidth: number): boolean;
|
|
22
|
+
|
|
17
23
|
setKeepOrthogonality(keepOrthogonality: boolean): boolean;
|
|
18
24
|
getKeepOrthogonality(): boolean;
|
|
19
25
|
|
|
@@ -211,10 +211,7 @@ function updateState(widgetState, scaleInPixels, rotationHandlePosition) {
|
|
|
211
211
|
lineHandle.setOrigin(center);
|
|
212
212
|
lineHandle.getManipulator()?.setHandleOrigin(center);
|
|
213
213
|
lineHandle.getManipulator()?.setHandleNormal(widgetState.getPlanes()[planeNameToViewType[planeName]].normal);
|
|
214
|
-
|
|
215
|
-
const scale3 = lineHandle.getScale3();
|
|
216
|
-
scale3[2] = 2 * scale;
|
|
217
|
-
lineHandle.setScale3(scale3);
|
|
214
|
+
normalize(direction);
|
|
218
215
|
const right = widgetState.getPlanes()[planeNameToViewType[inPlaneName]].normal;
|
|
219
216
|
const up = cross(direction, right, []);
|
|
220
217
|
lineHandle.setRight(right);
|
|
@@ -68,9 +68,7 @@ function generateState() {
|
|
|
68
68
|
// Line handle
|
|
69
69
|
axisState.addStateFromMixin({
|
|
70
70
|
labels: ['handles', 'line', `lineIn${view}`, `${axis}in${view}`],
|
|
71
|
-
mixins: ['origin', 'color3', 'scale3',
|
|
72
|
-
// scale3[2] will be automatically overwritten
|
|
73
|
-
'orientation', 'visible', 'manipulator'],
|
|
71
|
+
mixins: ['origin', 'color3', 'scale3', 'orientation', 'visible', 'manipulator'],
|
|
74
72
|
name: `axis${axis}in${view}`,
|
|
75
73
|
initialValues: {
|
|
76
74
|
scale3: [4, 4, 4],
|
|
@@ -70,6 +70,22 @@ export interface vtkResliceCursorWidget<
|
|
|
70
70
|
|
|
71
71
|
getScaleInPixels(): boolean;
|
|
72
72
|
|
|
73
|
+
setHoleWidth(holeWidth: number): boolean;
|
|
74
|
+
|
|
75
|
+
getHoleWidth(): number;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Defines the length of the line
|
|
79
|
+
* The scaling of each line representation always define the dimensions of the circle / elipse (X and Y axes)
|
|
80
|
+
* The unit of this scaling is either in world coordinates or in pixels depending in scaleInPixels
|
|
81
|
+
* When the line is finite, this scaling on the Z axis also defines the length of the line
|
|
82
|
+
* When the line is infinite, the scaling on the Z axis is automatically huge
|
|
83
|
+
* @param infiniteLine
|
|
84
|
+
*/
|
|
85
|
+
setInfiniteLine(infiniteLine: boolean): boolean;
|
|
86
|
+
|
|
87
|
+
getInfiniteLine(): boolean;
|
|
88
|
+
|
|
73
89
|
setRotationHandlePosition(position: number): boolean;
|
|
74
90
|
|
|
75
91
|
getRotationHandlePosition(): number;
|
|
@@ -27,7 +27,11 @@ const {
|
|
|
27
27
|
|
|
28
28
|
function vtkResliceCursorWidget(publicAPI, model) {
|
|
29
29
|
model.classHierarchy.push('vtkResliceCursorWidget');
|
|
30
|
-
model.methodsToLink = [
|
|
30
|
+
model.methodsToLink = [
|
|
31
|
+
// For all representations
|
|
32
|
+
'scaleInPixels',
|
|
33
|
+
// For line representations
|
|
34
|
+
'holeWidth', 'infiniteLine'];
|
|
31
35
|
|
|
32
36
|
// --------------------------------------------------------------------------
|
|
33
37
|
// Private methods
|