Skip to content

Commit 33dd7f4

Browse files
florystsankhesh
authored andcommitted
feat(TransformControlsWidget): add new widget
1 parent 8f8e3c2 commit 33dd7f4

File tree

14 files changed

+1173
-0
lines changed

14 files changed

+1173
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import macro from 'vtk.js/Sources/macros';
2+
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
3+
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
4+
5+
// ----------------------------------------------------------------------------
6+
// vtkTorusSource methods
7+
// Adapted from three.js TorusGeometry
8+
// ----------------------------------------------------------------------------
9+
10+
const TAU = Math.PI * 2;
11+
12+
function vtkTorusSource(publicAPI, model) {
13+
// Set our className
14+
model.classHierarchy.push('vtkTorusSource');
15+
16+
function requestData(inData, outData) {
17+
if (model.deleted) {
18+
return;
19+
}
20+
21+
let dataset = outData[0];
22+
23+
// Points
24+
const points = macro.newTypedArray(
25+
model.pointType,
26+
3 * (model.resolution + 1) * (model.tubeResolution + 1)
27+
);
28+
let pointIdx = 0;
29+
30+
for (let ti = 0; ti <= model.tubeResolution; ti++) {
31+
const v = (ti / model.tubeResolution) * TAU;
32+
for (let ri = 0; ri <= model.resolution; ri++) {
33+
const u = (ri / model.resolution) * model.arcLength;
34+
points[pointIdx++] =
35+
(model.radius + model.tubeRadius * Math.cos(v)) * Math.cos(u);
36+
points[pointIdx++] =
37+
(model.radius + model.tubeRadius * Math.cos(v)) * Math.sin(u);
38+
points[pointIdx++] = model.tubeRadius * Math.sin(v);
39+
}
40+
}
41+
42+
// Cells
43+
const cellArraySize = 4 * 2 * (model.resolution * model.tubeResolution);
44+
let cellLocation = 0;
45+
const polys = new Uint32Array(cellArraySize);
46+
47+
for (let ti = 1; ti <= model.tubeResolution; ti++) {
48+
for (let ri = 1; ri <= model.resolution; ri++) {
49+
const a = (model.resolution + 1) * ti + ri - 1;
50+
const b = (model.resolution + 1) * (ti - 1) + ri - 1;
51+
const c = (model.resolution + 1) * (ti - 1) + ri;
52+
const d = (model.resolution + 1) * ti + ri;
53+
54+
polys[cellLocation++] = 3;
55+
polys[cellLocation++] = a;
56+
polys[cellLocation++] = b;
57+
polys[cellLocation++] = d;
58+
59+
polys[cellLocation++] = 3;
60+
polys[cellLocation++] = b;
61+
polys[cellLocation++] = c;
62+
polys[cellLocation++] = d;
63+
}
64+
}
65+
66+
// Apply transformation to the points coordinates
67+
vtkMatrixBuilder
68+
.buildFromRadian()
69+
.translate(...model.center)
70+
.rotateFromDirections([1, 0, 0], model.direction)
71+
.apply(points);
72+
73+
dataset = vtkPolyData.newInstance();
74+
dataset.getPoints().setData(points, 3);
75+
dataset.getPolys().setData(polys, 1);
76+
77+
// Update output
78+
outData[0] = dataset;
79+
}
80+
81+
// Expose methods
82+
publicAPI.requestData = requestData;
83+
}
84+
85+
// ----------------------------------------------------------------------------
86+
// Object factory
87+
// ----------------------------------------------------------------------------
88+
89+
const DEFAULT_VALUES = {
90+
radius: 0.5,
91+
tubeRadius: 0.01,
92+
resolution: 64,
93+
tubeResolution: 64,
94+
arcLength: TAU,
95+
center: [0, 0, 0],
96+
direction: [1.0, 0.0, 0.0],
97+
pointType: 'Float64Array',
98+
};
99+
100+
// ----------------------------------------------------------------------------
101+
102+
export function extend(publicAPI, model, initialValues = {}) {
103+
Object.assign(model, DEFAULT_VALUES, initialValues);
104+
105+
// Build VTK API
106+
macro.obj(publicAPI, model);
107+
macro.setGet(publicAPI, model, [
108+
'radius',
109+
'tubeRadius',
110+
'resolution',
111+
'tubeResolution',
112+
'arcLength',
113+
]);
114+
macro.setGetArray(publicAPI, model, ['center', 'direction'], 3);
115+
macro.algo(publicAPI, model, 0, 1);
116+
vtkTorusSource(publicAPI, model);
117+
}
118+
119+
// ----------------------------------------------------------------------------
120+
121+
export const newInstance = macro.newInstance(extend, 'vtkTorusSource');
122+
123+
// ----------------------------------------------------------------------------
124+
125+
export default { newInstance, extend };

Sources/Filters/Sources/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import vtkPointSource from './PointSource';
1616
import vtkRTAnalyticSource from './RTAnalyticSource';
1717
import vtkSLICSource from './SLICSource';
1818
import vtkSphereSource from './SphereSource';
19+
import vtkTorusSource from './TorusSource';
1920

2021
export default {
2122
vtkArcSource,
@@ -36,4 +37,5 @@ export default {
3637
vtkRTAnalyticSource,
3738
vtkSLICSource,
3839
vtkSphereSource,
40+
vtkTorusSource,
3941
};

Sources/Rendering/Core/Prop3D/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ function vtkProp3D(publicAPI, model) {
116116
return true;
117117
};
118118

119+
publicAPI.setOrientationFromQuaternion = (q) => {
120+
mat4.fromQuat(model.rotation, q);
121+
publicAPI.modified();
122+
};
123+
119124
publicAPI.setUserMatrix = (matrix) => {
120125
if (vtkMath.areMatricesEqual(model.userMatrix, matrix)) {
121126
return false;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import macro from 'vtk.js/Sources/macros';
2+
import vtkGlyphRepresentation from 'vtk.js/Sources/Widgets/Representations/GlyphRepresentation';
3+
import vtkTorusSource from 'vtk.js/Sources/Filters/Sources/TorusSource';
4+
5+
// ----------------------------------------------------------------------------
6+
// vtkRotateTransformHandleRepresentation methods
7+
// ----------------------------------------------------------------------------
8+
9+
function vtkRotateTransformHandleRepresentation(publicAPI, model) {
10+
// Set our className
11+
model.classHierarchy.push('vtkRotateTransformHandleRepresentation');
12+
}
13+
14+
// ----------------------------------------------------------------------------
15+
// Object factory
16+
// ----------------------------------------------------------------------------
17+
18+
// ----------------------------------------------------------------------------
19+
function defaultValues(initialValues) {
20+
return {
21+
_pipeline: {
22+
glyph: vtkTorusSource.newInstance({}),
23+
},
24+
...initialValues,
25+
};
26+
}
27+
28+
export function extend(publicAPI, model, initialValues = {}) {
29+
vtkGlyphRepresentation.extend(publicAPI, model, defaultValues(initialValues));
30+
31+
// Object specific methods
32+
vtkRotateTransformHandleRepresentation(publicAPI, model);
33+
}
34+
35+
// ----------------------------------------------------------------------------
36+
37+
export const newInstance = macro.newInstance(
38+
extend,
39+
'vtkRotateTransformHandleRepresentation'
40+
);
41+
42+
// ----------------------------------------------------------------------------
43+
44+
export default { newInstance, extend };
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import macro from 'vtk.js/Sources/macros';
2+
import vtkGlyphRepresentation from 'vtk.js/Sources/Widgets/Representations/GlyphRepresentation';
3+
import vtkCubeSource from 'vtk.js/Sources/Filters/Sources/CubeSource';
4+
5+
import vtkTransformHandleSource from 'vtk.js/Sources/Widgets/Representations/TranslateTransformHandleRepresentation/TransformHandleSource';
6+
7+
// ----------------------------------------------------------------------------
8+
// vtkScaleTransformHandleRepresentation methods
9+
// ----------------------------------------------------------------------------
10+
11+
function vtkScaleTransformHandleRepresentation(publicAPI, model) {
12+
// Set our className
13+
model.classHierarchy.push('vtkScaleTransformHandleRepresentation');
14+
}
15+
16+
// ----------------------------------------------------------------------------
17+
// Object factory
18+
// ----------------------------------------------------------------------------
19+
20+
// ----------------------------------------------------------------------------
21+
function defaultValues(initialValues) {
22+
const source = vtkTransformHandleSource.newInstance({
23+
height: initialValues.height ?? 1,
24+
radius: initialValues.radius ?? 1,
25+
resolution: initialValues.glyphResolution ?? 12,
26+
direction: [0, 0, 1],
27+
});
28+
29+
const cube1 = vtkCubeSource.newInstance(initialValues.cubeSource);
30+
const cube2 = vtkCubeSource.newInstance(initialValues.cubeSource);
31+
32+
source.addInputConnection(cube1.getOutputPort());
33+
source.addInputConnection(cube2.getOutputPort());
34+
35+
return {
36+
_pipeline: {
37+
glyph: source,
38+
},
39+
...initialValues,
40+
};
41+
}
42+
43+
export function extend(publicAPI, model, initialValues = {}) {
44+
vtkGlyphRepresentation.extend(publicAPI, model, defaultValues(initialValues));
45+
46+
// Object specific methods
47+
vtkScaleTransformHandleRepresentation(publicAPI, model);
48+
}
49+
50+
// ----------------------------------------------------------------------------
51+
52+
export const newInstance = macro.newInstance(
53+
extend,
54+
'vtkScaleTransformHandleRepresentation'
55+
);
56+
57+
// ----------------------------------------------------------------------------
58+
59+
export default { newInstance, extend };
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import macro from 'vtk.js/Sources/macros';
2+
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
3+
import vtkAppendPolyData from 'vtk.js/Sources/Filters/General/AppendPolyData';
4+
import vtkCylinderSource from 'vtk.js/Sources/Filters/Sources/CylinderSource';
5+
6+
function rotatePolyData(pd, direction) {
7+
const points = pd.getPoints().getData();
8+
9+
vtkMatrixBuilder
10+
.buildFromRadian()
11+
.rotateFromDirections([0, 1, 0], direction)
12+
.apply(points);
13+
14+
pd.modified();
15+
}
16+
function translatePolyData(pd, translation) {
17+
const points = pd.getPoints().getData();
18+
19+
vtkMatrixBuilder
20+
.buildFromRadian()
21+
.translate(...translation)
22+
.apply(points);
23+
24+
pd.modified();
25+
}
26+
27+
function vtkTransformHandleSource(publicAPI, model) {
28+
// Set our className
29+
model.classHierarchy.push('vtkTransformHandleSource');
30+
31+
function requestData(inData, outData) {
32+
if (model.deleted) {
33+
return;
34+
}
35+
36+
const cylinderSource = vtkCylinderSource.newInstance({
37+
height: model.height,
38+
initAngle: model.initAngle,
39+
radius: model.radius,
40+
resolution: model.resolution,
41+
capping: model.capping,
42+
pointType: model.pointType,
43+
center: [0, 0, 0],
44+
direction: [0, 1, 0],
45+
});
46+
47+
const appendFilter = vtkAppendPolyData.newInstance();
48+
appendFilter.setInputConnection(cylinderSource.getOutputPort(), 0);
49+
50+
if (inData[0]) {
51+
translatePolyData(inData[0], [0, model.height / 2, 0]);
52+
appendFilter.addInputData(inData[0]);
53+
}
54+
if (inData[1]) {
55+
rotatePolyData(inData[1], [0, -1, 0]);
56+
translatePolyData(inData[1], [0, -model.height / 2, 0]);
57+
appendFilter.addInputData(inData[1]);
58+
}
59+
60+
const poly = appendFilter.getOutputData();
61+
const points = poly.getPoints().getData();
62+
63+
// Apply transformation to the points coordinates
64+
vtkMatrixBuilder
65+
.buildFromRadian()
66+
.translate(...model.center)
67+
.rotateFromDirections([0, 1, 0], model.direction)
68+
.translate(...model.center.map((c) => c * -1))
69+
.apply(points);
70+
71+
// Update output
72+
outData[0] = poly;
73+
}
74+
75+
// Expose methods
76+
publicAPI.requestData = requestData;
77+
}
78+
79+
// ----------------------------------------------------------------------------
80+
// Object factory
81+
// ----------------------------------------------------------------------------
82+
83+
const DEFAULT_VALUES = {
84+
capPolyData: null,
85+
};
86+
87+
// ----------------------------------------------------------------------------
88+
89+
export function extend(publicAPI, model, initialValues = {}) {
90+
Object.assign(model, DEFAULT_VALUES, initialValues);
91+
92+
vtkCylinderSource.extend(publicAPI, model, initialValues);
93+
macro.algo(publicAPI, model, 1, 1);
94+
95+
vtkTransformHandleSource(publicAPI, model);
96+
}
97+
98+
// ----------------------------------------------------------------------------
99+
100+
export const newInstance = macro.newInstance(
101+
extend,
102+
'vtkTransformHandleSource'
103+
);
104+
105+
// ----------------------------------------------------------------------------
106+
107+
export default { newInstance, extend };

0 commit comments

Comments
 (0)