Skip to content

Commit bd97006

Browse files
committed
fix(ConcentricCylinderSource): Add new source to build concentric cylinders
1 parent df61aa4 commit bd97006

File tree

3 files changed

+287
-9
lines changed

3 files changed

+287
-9
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import 'vtk.js/Sources/favicon';
2+
3+
import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
4+
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
5+
import vtkConcentricCylinderSource from 'vtk.js/Sources/Filters/Sources/ConcentricCylinderSource';
6+
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
7+
8+
// import { ColorMode, ScalarMode } from 'vtk.js/Sources/Rendering/Core/Mapper/Constants';
9+
10+
// ----------------------------------------------------------------------------
11+
// Standard rendering code setup
12+
// ----------------------------------------------------------------------------
13+
14+
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ background: [0, 0, 0] });
15+
const renderer = fullScreenRenderer.getRenderer();
16+
const renderWindow = fullScreenRenderer.getRenderWindow();
17+
18+
// ----------------------------------------------------------------------------
19+
// Example code
20+
// ----------------------------------------------------------------------------
21+
22+
const cylinder = vtkConcentricCylinderSource.newInstance({
23+
height: 0.25,
24+
radius: [0.2, 0.3, 0.4, 0.6, 0.7, 0.8, 0.9, 1],
25+
cellFields: [0, 0.2, 0.4, 0.6, 0.7, 0.8, 0.9, 1],
26+
resolution: 120,
27+
});
28+
const actor = vtkActor.newInstance();
29+
const mapper = vtkMapper.newInstance();
30+
31+
actor.setMapper(mapper);
32+
mapper.setInputConnection(cylinder.getOutputPort());
33+
34+
const lut = mapper.getLookupTable();
35+
lut.setValueRange(0.2, 1);
36+
lut.setHueRange(0.666, 0);
37+
38+
renderer.addActor(actor);
39+
renderer.resetCamera();
40+
renderWindow.render();
41+
42+
// -----------------------------------------------------------
43+
// Make some variables global so that you can inspect and
44+
// modify objects in your browser's developer console:
45+
// -----------------------------------------------------------
46+
47+
global.cylinder = cylinder;
48+
global.renderer = renderer;
49+
global.renderWindow = renderWindow;
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
import macro from 'vtk.js/Sources/macro';
2+
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
3+
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
4+
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';
5+
6+
// ----------------------------------------------------------------------------
7+
// vtkConcentricCylinderSource methods
8+
// ----------------------------------------------------------------------------
9+
10+
function vtkConcentricCylinderSource(publicAPI, model) {
11+
// Set our className
12+
model.classHierarchy.push('vtkConcentricCylinderSource');
13+
14+
// Internal private function
15+
function validateCellFields() {
16+
while (model.cellFields.length < model.radius.length) {
17+
model.cellFields.push(model.cellFields.length);
18+
}
19+
}
20+
21+
publicAPI.clearRadius = () => {
22+
model.radius = [];
23+
model.cellFields = [];
24+
publicAPI.modified();
25+
};
26+
27+
publicAPI.addRadius = (radius, cellField) => {
28+
model.radius.push(radius);
29+
if (cellField !== undefined) {
30+
model.cellFields.push(cellField);
31+
}
32+
validateCellFields();
33+
publicAPI.modified();
34+
};
35+
36+
publicAPI.getNumberOfRadius = () => model.radius.length;
37+
publicAPI.getRadius = (index = 0) => model.radius[index];
38+
publicAPI.setRadius = (index, radius) => { model.radius[index] = radius; publicAPI.modified(); };
39+
publicAPI.setCellField = (index, field) => { model.cellFields[index] = field; publicAPI.modified(); };
40+
41+
function requestData(inData, outData) {
42+
if (model.deleted || !model.radius.length) {
43+
return;
44+
}
45+
46+
// Make sure we have concistency
47+
validateCellFields();
48+
49+
let dataset = outData[0];
50+
51+
const nbLayers = model.radius.length;
52+
const angle = 2 * Math.PI / model.resolution;
53+
const zRef = model.height / 2.0;
54+
const numberOfPoints = model.resolution * nbLayers * 2;
55+
const cellArraySize = (2 * (model.resolution + 1)) + (5 * model.resolution) + ((nbLayers - 1) * model.resolution * 20);
56+
const nbCells = 2 + model.resolution + ((nbLayers - 1) * 4 * model.resolution);
57+
58+
// Points
59+
let pointIdx = 0;
60+
const points = new window[model.pointType](numberOfPoints * 3);
61+
62+
// Cells
63+
let cellLocation = 0;
64+
const polys = new Uint32Array(cellArraySize);
65+
66+
// CellFields
67+
let fieldLocation = 0;
68+
const field = new Float32Array(nbCells);
69+
70+
// Create points
71+
for (let layer = 0; layer < nbLayers; layer++) {
72+
const radius = model.radius[layer];
73+
// Create top
74+
for (let i = 0; i < model.resolution; i++) {
75+
points[(pointIdx * 3) + 0] = radius * Math.cos(i * angle);
76+
points[(pointIdx * 3) + 1] = radius * Math.sin(i * angle);
77+
points[(pointIdx * 3) + 2] = zRef;
78+
pointIdx++;
79+
}
80+
81+
// Create bottom
82+
for (let i = 0; i < model.resolution; i++) {
83+
points[(pointIdx * 3) + 0] = radius * Math.cos(i * angle);
84+
points[(pointIdx * 3) + 1] = radius * Math.sin(i * angle);
85+
points[(pointIdx * 3) + 2] = -zRef;
86+
pointIdx++;
87+
}
88+
}
89+
90+
// Create cells for the core
91+
let currentField = model.cellFields[0];
92+
93+
// Core: Top disk
94+
field[fieldLocation++] = currentField;
95+
polys[cellLocation++] = model.resolution;
96+
for (let i = 0; i < model.resolution; i++) {
97+
polys[cellLocation++] = i;
98+
}
99+
100+
// Core: Bottom disk
101+
field[fieldLocation++] = currentField;
102+
polys[cellLocation++] = model.resolution;
103+
for (let i = 0; i < model.resolution; i++) {
104+
polys[cellLocation++] = (2 * model.resolution) - i - 1;
105+
}
106+
107+
// Core: sides
108+
for (let i = 0; i < model.resolution; i++) {
109+
polys[cellLocation++] = 4;
110+
polys[cellLocation++] = (i + 1) % model.resolution;
111+
polys[cellLocation++] = i;
112+
polys[cellLocation++] = i + model.resolution;
113+
polys[cellLocation++] = ((i + 1) % model.resolution) + model.resolution;
114+
115+
field[fieldLocation++] = currentField;
116+
}
117+
118+
// Create cells for the layers
119+
for (let layer = 1; layer < nbLayers; layer++) {
120+
const offset = model.resolution * 2 * (layer - 1);
121+
currentField = model.cellFields[layer];
122+
123+
// Create top
124+
for (let i = 0; i < model.resolution; i++) {
125+
polys[cellLocation++] = 4;
126+
polys[cellLocation++] = i + offset;
127+
polys[cellLocation++] = ((i + 1) % model.resolution) + offset;
128+
polys[cellLocation++] = ((i + 1) % model.resolution) + (2 * model.resolution) + offset;
129+
polys[cellLocation++] = i + (2 * model.resolution) + offset;
130+
131+
field[fieldLocation++] = currentField;
132+
}
133+
134+
// Create bottom
135+
for (let i = 0; i < model.resolution; i++) {
136+
polys[cellLocation++] = 4;
137+
polys[cellLocation++] = ((i + 1) % model.resolution) + offset + model.resolution;
138+
polys[cellLocation++] = i + offset + model.resolution;
139+
polys[cellLocation++] = i + (2 * model.resolution) + offset + model.resolution;
140+
polys[cellLocation++] = ((i + 1) % model.resolution) + (2 * model.resolution) + offset + model.resolution;
141+
142+
field[fieldLocation++] = currentField;
143+
}
144+
145+
// Create inner
146+
for (let i = 0; i < model.resolution; i++) {
147+
polys[cellLocation++] = 4;
148+
polys[cellLocation++] = i + offset;
149+
polys[cellLocation++] = ((i + 1) % model.resolution) + offset;
150+
polys[cellLocation++] = ((i + 1) % model.resolution) + model.resolution + offset;
151+
polys[cellLocation++] = i + model.resolution + offset;
152+
153+
field[fieldLocation++] = currentField;
154+
}
155+
156+
// Create outter
157+
for (let i = 0; i < model.resolution; i++) {
158+
polys[cellLocation++] = 4;
159+
polys[cellLocation++] = ((i + 1) % model.resolution) + offset + (2 * model.resolution);
160+
polys[cellLocation++] = i + offset + (2 * model.resolution);
161+
polys[cellLocation++] = i + model.resolution + offset + (2 * model.resolution);
162+
polys[cellLocation++] = ((i + 1) % model.resolution) + model.resolution + offset + (2 * model.resolution);
163+
164+
field[fieldLocation++] = currentField;
165+
}
166+
}
167+
168+
// Apply tranformation to the points coordinates
169+
vtkMatrixBuilder
170+
.buildFromRadian()
171+
.translate(...model.center)
172+
.rotateFromDirections([0, 0, 1], model.direction)
173+
.apply(points);
174+
175+
dataset = vtkPolyData.newInstance();
176+
dataset.getPoints().setData(points, 3);
177+
dataset.getPolys().setData(polys, 1);
178+
dataset.getCellData().setScalars(vtkDataArray.newInstance({ name: 'layer', values: field }));
179+
180+
// Update output
181+
outData[0] = dataset;
182+
}
183+
184+
// Expose methods
185+
publicAPI.requestData = requestData;
186+
}
187+
188+
// ----------------------------------------------------------------------------
189+
// Object factory
190+
// ----------------------------------------------------------------------------
191+
192+
const DEFAULT_VALUES = {
193+
height: 1.0,
194+
radius: [0.5],
195+
cellFields: [1],
196+
resolution: 6,
197+
center: [0, 0, 0],
198+
direction: [0.0, 0.0, 1.0],
199+
pointType: 'Float32Array',
200+
};
201+
202+
// ----------------------------------------------------------------------------
203+
204+
export function extend(publicAPI, model, initialValues = {}) {
205+
Object.assign(model, DEFAULT_VALUES, initialValues);
206+
207+
// Build VTK API
208+
macro.obj(publicAPI, model);
209+
macro.setGet(publicAPI, model, [
210+
'height',
211+
'resolution',
212+
]);
213+
macro.setGetArray(publicAPI, model, [
214+
'center',
215+
'direction',
216+
], 3);
217+
macro.algo(publicAPI, model, 0, 1);
218+
vtkConcentricCylinderSource(publicAPI, model);
219+
}
220+
221+
// ----------------------------------------------------------------------------
222+
223+
export const newInstance = macro.newInstance(extend, 'vtkConcentricCylinderSource');
224+
225+
// ----------------------------------------------------------------------------
226+
227+
export default { newInstance, extend };

Sources/Filters/Sources/index.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import vtkConeSource from './ConeSource';
2-
import vtkCubeSource from './CubeSource';
3-
import vtkImageGridSource from './ImageGridSource';
4-
import vtkLineSource from './LineSource';
5-
import vtkPlaneSource from './PlaneSource';
6-
import vtkPointSource from './PointSource';
7-
import vtkRTAnalyticSource from './RTAnalyticSource';
8-
import vtkSLICSource from './SLICSource';
9-
import vtkSphereSource from './SphereSource';
1+
import vtkConcentricCylinderSource from './ConcentricCylinderSource';
2+
import vtkConeSource from './ConeSource';
3+
import vtkCubeSource from './CubeSource';
4+
import vtkImageGridSource from './ImageGridSource';
5+
import vtkLineSource from './LineSource';
6+
import vtkPlaneSource from './PlaneSource';
7+
import vtkPointSource from './PointSource';
8+
import vtkRTAnalyticSource from './RTAnalyticSource';
9+
import vtkSLICSource from './SLICSource';
10+
import vtkSphereSource from './SphereSource';
1011

1112
export default {
13+
vtkConcentricCylinderSource,
1214
vtkConeSource,
1315
vtkCubeSource,
1416
vtkImageGridSource,

0 commit comments

Comments
 (0)