Skip to content

Commit 7f8a960

Browse files
committed
perf(vtkcutter): improve vtkCutter performances
Avoid using subarray that is costly
1 parent d20b2c4 commit 7f8a960

File tree

3 files changed

+138
-106
lines changed

3 files changed

+138
-106
lines changed
Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,74 @@
1-
<table>
2-
<tr>
3-
<td><b>Origin<b></td>
4-
</tr>
5-
<tr>
6-
<td>X</td>
7-
<td>
8-
<form name='originXForm'>
9-
<input class='originX' id="originXInputId" type="range"
10-
min="-0.5" max="0.5" step="0.01" value="0"
11-
oninput="originXOutputId.value = originXInputId.value"/>
12-
<output id="originXOutputId">0</output>
13-
</form>
14-
</td>
15-
</tr>
16-
<tr>
17-
<td>Y</td>
18-
<td>
19-
<form name='originYForm'>
20-
<input class='originY' id="originYInputId" type="range"
21-
min="-0.5" max="0.5" step="0.01" value="0"
22-
oninput="originYOutputId.value = originYInputId.value"/>
23-
<output id="originYOutputId">0</output>
24-
</form>
25-
</td>
26-
</tr>
27-
<tr>
28-
<td>Z</td>
29-
<td>
30-
<form name='originZForm'>
31-
<input class='originZ' id="originZInputId" type="range"
32-
min="-0.5" max="0.5" step="0.01" value="0"
33-
oninput="originZOutputId.value = originZInputId.value"/>
34-
<output id="originZOutputId">0</output>
35-
</form>
36-
</td>
37-
</tr>
38-
<tr>
39-
<td><b>Normal<b></td>
40-
</tr>
41-
<tr>
42-
<td>X</td>
43-
<td>
44-
<form name='normalXForm'>
45-
<input class='normalX' id="normalXInputId" type="range"
46-
min="-1" max="1" step="0.01" value="1"
47-
oninput="normalXOutputId.value = normalXInputId.value"/>
48-
<output id="normalXOutputId">1</output>
49-
</form>
50-
</td>
51-
</tr>
52-
<tr>
53-
<td>Y</td>
54-
<td>
55-
<form name='normalYForm'>
56-
<input class='normalY' id="normalYInputId" type="range"
57-
min="-1" max="1" step="0.01" value="0"
58-
oninput="normalYOutputId.value = normalYInputId.value"/>
59-
<output id="normalYOutputId">0</output>
60-
</form>
61-
</td>
62-
</tr>
63-
<tr>
64-
<td>Z</td>
65-
<td>
66-
<form name='normalZForm'>
67-
<input class='normalZ' id="normalZInputId" type="range"
68-
min="-1" max="1" step="0.01" value="0"
69-
oninput="normalZOutputId.value = normalZInputId.value"/>
70-
<output id="normalZOutputId">0</output>
71-
</form>
72-
</td>
73-
</tr>
74-
</table>
1+
<table>
2+
<tr>
3+
<td><b>Origin<b></td>
4+
</tr>
5+
<tr>
6+
<td>X</td>
7+
<td>
8+
<form name='originXForm'>
9+
<input class='originX' id="originXInputId" type="range"
10+
min="-6" max="6" step="0.01" value="0"
11+
oninput="originXOutputId.value = originXInputId.value"/>
12+
<output id="originXOutputId">0</output>
13+
</form>
14+
</td>
15+
</tr>
16+
<tr>
17+
<td>Y</td>
18+
<td>
19+
<form name='originYForm'>
20+
<input class='originY' id="originYInputId" type="range"
21+
min="-0.5" max="0.5" step="0.01" value="0"
22+
oninput="originYOutputId.value = originYInputId.value"/>
23+
<output id="originYOutputId">0</output>
24+
</form>
25+
</td>
26+
</tr>
27+
<tr>
28+
<td>Z</td>
29+
<td>
30+
<form name='originZForm'>
31+
<input class='originZ' id="originZInputId" type="range"
32+
min="-0.5" max="0.5" step="0.01" value="0"
33+
oninput="originZOutputId.value = originZInputId.value"/>
34+
<output id="originZOutputId">0</output>
35+
</form>
36+
</td>
37+
</tr>
38+
<tr>
39+
<td><b>Normal<b></td>
40+
</tr>
41+
<tr>
42+
<td>X</td>
43+
<td>
44+
<form name='normalXForm'>
45+
<input class='normalX' id="normalXInputId" type="range"
46+
min="-1" max="1" step="0.01" value="1"
47+
oninput="normalXOutputId.value = normalXInputId.value"/>
48+
<output id="normalXOutputId">1</output>
49+
</form>
50+
</td>
51+
</tr>
52+
<tr>
53+
<td>Y</td>
54+
<td>
55+
<form name='normalYForm'>
56+
<input class='normalY' id="normalYInputId" type="range"
57+
min="-1" max="1" step="0.01" value="0"
58+
oninput="normalYOutputId.value = normalYInputId.value"/>
59+
<output id="normalYOutputId">0</output>
60+
</form>
61+
</td>
62+
</tr>
63+
<tr>
64+
<td>Z</td>
65+
<td>
66+
<form name='normalZForm'>
67+
<input class='normalZ' id="normalZInputId" type="range"
68+
min="-1" max="1" step="0.01" value="0"
69+
oninput="normalZOutputId.value = normalZInputId.value"/>
70+
<output id="normalZOutputId">0</output>
71+
</form>
72+
</td>
73+
</tr>
74+
</table>

Sources/Filters/Core/Cutter/example/index.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@ import '@kitware/vtk.js/favicon';
44
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
55

66
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
7-
import vtkCubeSource from '@kitware/vtk.js/Filters/Sources/CubeSource';
87
import vtkCutter from '@kitware/vtk.js/Filters/Core/Cutter';
98
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
9+
import HttpDataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper/HttpDataAccessHelper';
10+
import DataAccessHelper from '@kitware/vtk.js/IO/Core/DataAccessHelper';
11+
12+
import vtkHttpSceneLoader from '@kitware/vtk.js/IO/Core/HttpSceneLoader';
1013
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
1114
import vtkPlane from '@kitware/vtk.js/Common/DataModel/Plane';
1215
import vtkProperty from '@kitware/vtk.js/Rendering/Core/Property';
1316

1417
import controlPanel from './controlPanel.html';
1518

19+
// Force DataAccessHelper to have access to various data source
20+
import '@kitware/vtk.js/IO/Core/DataAccessHelper/JSZipDataAccessHelper';
21+
1622
// ----------------------------------------------------------------------------
1723
// Standard rendering code setup
1824
// ----------------------------------------------------------------------------
@@ -28,11 +34,9 @@ const renderWindow = fullScreenRenderer.getRenderWindow();
2834
// ----------------------------------------------------------------------------
2935

3036
const plane = vtkPlane.newInstance();
31-
const cube = vtkCubeSource.newInstance();
3237

3338
const cutter = vtkCutter.newInstance();
3439
cutter.setCutFunction(plane);
35-
cutter.setInputConnection(cube.getOutputPort());
3640

3741
const cutMapper = vtkMapper.newInstance();
3842
cutMapper.setInputConnection(cutter.getOutputPort());
@@ -45,16 +49,15 @@ cutProperty.setColor(0, 1, 0);
4549
renderer.addActor(cutActor);
4650

4751
const cubeMapper = vtkMapper.newInstance();
48-
cubeMapper.setInputConnection(cube.getOutputPort());
52+
cubeMapper.setScalarVisibility(false);
4953
const cubeActor = vtkActor.newInstance();
5054
cubeActor.setMapper(cubeMapper);
5155
const cubeProperty = cubeActor.getProperty();
5256
cubeProperty.setRepresentation(vtkProperty.Representation.WIREFRAME);
5357
cubeProperty.setLighting(false);
58+
cubeProperty.setOpacity(0.1);
5459
renderer.addActor(cubeActor);
5560

56-
renderer.resetCamera();
57-
5861
// -----------------------------------------------------------
5962
// UI control handling
6063
// -----------------------------------------------------------
@@ -76,9 +79,6 @@ const updatePlaneFunction = () => {
7679
renderWindow.render();
7780
};
7881

79-
// Update now
80-
updatePlaneFunction();
81-
8282
// Update when changing UI
8383
['originX', 'originY', 'originZ', 'normalX', 'normalY', 'normalZ'].forEach(
8484
(propertyName) => {
@@ -90,3 +90,29 @@ updatePlaneFunction();
9090
});
9191
}
9292
);
93+
94+
HttpDataAccessHelper.fetchBinary(
95+
`${__BASE_PATH__}/data/StanfordDragon.vtkjs`,
96+
{}
97+
).then((zipContent) => {
98+
const dataAccessHelper = DataAccessHelper.get('zip', {
99+
zipContent,
100+
callback: (zip) => {
101+
const sceneImporter = vtkHttpSceneLoader.newInstance({
102+
renderer,
103+
dataAccessHelper,
104+
});
105+
sceneImporter.setUrl('index.json');
106+
sceneImporter.onReady(() => {
107+
console.log(sceneImporter.getScene());
108+
sceneImporter.getScene()[0].actor.setVisibility(false);
109+
110+
const source = sceneImporter.getScene()[0].source;
111+
cutter.setInputConnection(source.getOutputPort());
112+
cubeMapper.setInputConnection(source.getOutputPort());
113+
renderer.resetCamera();
114+
updatePlaneFunction();
115+
});
116+
},
117+
});
118+
});

Sources/Filters/Core/Cutter/index.js

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,26 @@ function initPolyIterator(pd) {
77
const polys = pd.getPolys().getData();
88
const strips = pd.getStrips().getData();
99
const it = {
10+
cellSize: 0,
11+
cell: [],
1012
done: false,
1113
polyIdx: 0,
1214
stripIdx: 0,
1315
remainingStripLength: 0,
16+
1417
// returns a single poly cell
1518
next() {
16-
let ret = null;
1719
if (it.polyIdx < polys.length) {
18-
const cellSize = polys[it.polyIdx];
20+
it.cellSize = polys[it.polyIdx];
1921
const start = it.polyIdx + 1;
20-
const end = start + cellSize;
22+
const end = start + it.cellSize;
2123
it.polyIdx = end;
22-
ret = polys.subarray(start, end);
24+
let p = 0;
25+
for (let i = start; i < end; ++i) {
26+
it.cell[p++] = polys[i];
27+
}
2328
} else if (it.stripIdx < strips.length) {
29+
it.cellSize = 3;
2430
if (it.remainingStripLength === 0) {
2531
it.remainingStripLength = strips[it.stripIdx] - 2; // sliding window of 3 points
2632
// stripIdx points to the last point in a triangle 3-tuple
@@ -30,15 +36,18 @@ function initPolyIterator(pd) {
3036
const end = it.stripIdx + 1;
3137
it.stripIdx++;
3238
it.remainingStripLength--;
33-
ret = strips.subarray(start, end);
34-
} else if (it.done) {
39+
let p = 0;
40+
for (let i = start; i < end; ++i) {
41+
it.cell[p++] = strips[i];
42+
}
43+
} else if (!it.done) {
44+
it.done = true;
45+
} else {
3546
throw new Error('Iterator is done');
3647
}
37-
38-
it.done = it.polyIdx >= polys.length && it.stripIdx >= strips.length;
39-
return ret;
4048
},
4149
};
50+
it.next();
4251
return it;
4352
}
4453

@@ -89,32 +98,29 @@ function vtkCutter(publicAPI, model) {
8998
const crossedEdges = [];
9099
const x1 = new Array(3);
91100
const x2 = new Array(3);
101+
const cellPointsScalars = [];
102+
92103
// Loop over all cells; get scalar values for all cell points
93104
// and process each cell.
94105
/* eslint-disable no-continue */
95-
const it = initPolyIterator(input);
96-
while (!it.done) {
106+
for (const it = initPolyIterator(input); !it.done; it.next()) {
97107
// cell contains the point IDs/indices
98-
const cell = it.next();
99108

100109
// Check that cells have at least 3 points
101-
if (cell.length <= 2) {
110+
if (it.cellSize <= 2) {
102111
continue;
103112
}
104113

105114
// Get associated scalar of points that constitute the current cell
106-
const cellPointsScalars = [];
107-
let pointIndex;
108-
for (let i = 0; i < cell.length; i++) {
109-
pointIndex = cell[i];
110-
cellPointsScalars.push(model.cutScalars[pointIndex]);
115+
for (let i = 0; i < it.cellSize; ) {
116+
cellPointsScalars[i] = model.cutScalars[it.cell[i++]];
111117
}
112118

113119
// Check if all cell points are on same side (same side == cell not crossed by cut function)
114120
// TODO: won't work if one point scalar is = 0 ?
115121
const sideFirstPoint = cellPointsScalars[0] > 0;
116122
let allPointsSameSide = true;
117-
for (let i = 1; i < cellPointsScalars.length; i++) {
123+
for (let i = 1; i < it.cell.length; i++) {
118124
const sideCurrentPoint = cellPointsScalars[i] > 0;
119125
if (sideCurrentPoint !== sideFirstPoint) {
120126
allPointsSameSide = false;
@@ -129,8 +135,8 @@ function vtkCutter(publicAPI, model) {
129135

130136
// Find and compute edges which intersect cells
131137
const intersectedEdgesList = [];
132-
for (let i = 0; i < cell.length; i++) {
133-
const idNext = i + 1 === cell.length ? 0 : i + 1;
138+
for (let i = 0; i < it.cellSize; i++) {
139+
const idNext = i + 1 === it.cellSize ? 0 : i + 1;
134140

135141
// Go to next edge if edge is not crossed
136142
// TODO: in most come cases, (numberOfPointsInCell - 1) or 0 edges of the cell
@@ -159,8 +165,8 @@ function vtkCutter(publicAPI, model) {
159165
}
160166

161167
// points position
162-
const pointID1 = cell[e1];
163-
const pointID2 = cell[e2];
168+
const pointID1 = it.cell[e1];
169+
const pointID2 = it.cell[e2];
164170
x1[0] = pointsData[pointID1 * 3];
165171
x1[1] = pointsData[pointID1 * 3 + 1];
166172
x1[2] = pointsData[pointID1 * 3 + 2];

0 commit comments

Comments
 (0)