Skip to content

Commit 5a6a6cd

Browse files
committed
feat(polydatanormals): add option to compute cell normals
fix #2434
1 parent 7f404e9 commit 5a6a6cd

File tree

2 files changed

+118
-32
lines changed

2 files changed

+118
-32
lines changed

Sources/Filters/Core/PolyDataNormals/index.js

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import macro from 'vtk.js/Sources/macros';
22

33
import vtkDataArray from 'vtk.js/Sources/Common/Core/DataArray';
4-
import vtkMath from 'vtk.js/Sources/Common/Core/Math/index';
54
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
65
import vtkTriangle from 'vtk.js/Sources/Common/DataModel/Triangle';
76

@@ -13,12 +12,18 @@ function vtkPolyDataNormals(publicAPI, model) {
1312
// Set our className
1413
model.classHierarchy.push('vtkPolyDataNormals');
1514

16-
publicAPI.vtkPolyDataNormalsExecute = (pointsData, polysData) => {
15+
publicAPI.vtkPolyDataNormalsExecute = (
16+
numberOfPolys,
17+
polysData,
18+
pointsData
19+
) => {
1720
if (!pointsData) {
1821
return null;
1922
}
2023

21-
const normalsData = new Float32Array(pointsData.length);
24+
const pointNormals = new Float32Array(pointsData.length);
25+
const cellNormals = new Float32Array(3 * numberOfPolys);
26+
let cellNormalComponent = 0;
2227

2328
let numberOfPoints = 0;
2429
const polysDataLength = polysData.length;
@@ -45,28 +50,22 @@ function vtkPolyDataNormals(publicAPI, model) {
4550
cellNormal
4651
);
4752

48-
for (let i = 1; i <= numberOfPoints; ++i) {
49-
let pointId = 3 * polysData[c + i];
53+
cellNormals[cellNormalComponent++] = cellNormal[0];
54+
cellNormals[cellNormalComponent++] = cellNormal[1];
55+
cellNormals[cellNormalComponent++] = cellNormal[2];
5056

51-
normalsData[pointId] += cellNormal[0];
52-
normalsData[++pointId] += cellNormal[1];
53-
normalsData[++pointId] += cellNormal[2];
54-
}
55-
}
56-
57-
/* Normalize normals */
58-
59-
for (let i = 0; i < pointsData.length; ) {
60-
const pointNormal = normalsData.slice(i, i + 3);
57+
if (model.computePointNormals) {
58+
for (let i = 1; i <= numberOfPoints; ++i) {
59+
let pointId = 3 * polysData[c + i];
6160

62-
vtkMath.normalize(pointNormal);
63-
64-
normalsData[i++] = pointNormal[0];
65-
normalsData[i++] = pointNormal[1];
66-
normalsData[i++] = pointNormal[2];
61+
pointNormals[pointId] += cellNormal[0];
62+
pointNormals[++pointId] += cellNormal[1];
63+
pointNormals[++pointId] += cellNormal[2];
64+
}
65+
}
6766
}
6867

69-
return normalsData;
68+
return [cellNormals, pointNormals];
7069
};
7170

7271
publicAPI.requestData = (inData, outData) => {
@@ -82,18 +81,8 @@ function vtkPolyDataNormals(publicAPI, model) {
8281
return;
8382
}
8483

85-
const outputNormalsData = publicAPI.vtkPolyDataNormalsExecute(
86-
input.getPoints().getData(),
87-
input.getPolys().getData()
88-
);
89-
9084
const output = vtkPolyData.newInstance();
9185

92-
const outputNormals = vtkDataArray.newInstance({
93-
numberOfComponents: 3,
94-
values: outputNormalsData,
95-
});
96-
9786
output.setPoints(input.getPoints());
9887
output.setVerts(input.getVerts());
9988
output.setLines(input.getLines());
@@ -104,7 +93,29 @@ function vtkPolyDataNormals(publicAPI, model) {
10493
output.getCellData().passData(input.getCellData());
10594
output.getFieldData().passData(input.getFieldData());
10695

107-
output.getPointData().setNormals(outputNormals);
96+
const [cellNormals, pointNormals] = publicAPI.vtkPolyDataNormalsExecute(
97+
input.getNumberOfPolys(),
98+
input.getPolys().getData(),
99+
input.getPoints().getData()
100+
);
101+
102+
if (model.computePointNormals) {
103+
const outputPointNormals = vtkDataArray.newInstance({
104+
numberOfComponents: 3,
105+
name: 'Normals',
106+
values: pointNormals,
107+
});
108+
output.getPointData().setNormals(outputPointNormals);
109+
}
110+
111+
if (model.computeCellNormals) {
112+
const outputCellNormals = vtkDataArray.newInstance({
113+
numberOfComponents: 3,
114+
name: 'Normals',
115+
values: cellNormals,
116+
});
117+
output.getCellData().setNormals(outputCellNormals);
118+
}
108119

109120
outData[0] = output;
110121
};
@@ -115,6 +126,8 @@ function vtkPolyDataNormals(publicAPI, model) {
115126
// ----------------------------------------------------------------------------
116127
function defaultValues(initialValues) {
117128
return {
129+
computeCellNormals: false,
130+
computePointNormals: true,
118131
...initialValues,
119132
};
120133
}
@@ -131,6 +144,8 @@ export function extend(publicAPI, model, initialValues = {}) {
131144

132145
macro.algo(publicAPI, model, 1, 1);
133146

147+
macro.setGet(publicAPI, model, ['computeCellNormals', 'computePointNormals']);
148+
134149
/* Object specific methods */
135150

136151
vtkPolyDataNormals(publicAPI, model);

Sources/Filters/Core/PolyDataNormals/test/testPolyDataNormals.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import test from 'tape-catch';
22

33
import vtkCubeSource from 'vtk.js/Sources/Filters/Sources/CubeSource';
4+
import vtkMath from 'vtk.js/Sources/Common/Core/Math';
45
import vtkPolyDataNormals from 'vtk.js/Sources/Filters/Core/PolyDataNormals';
6+
import vtkTriangle from 'vtk.js/Sources/Common/DataModel/Triangle';
7+
8+
const PRECISION = 4;
59

610
test('Test vtkPolyDataNormals passData', (t) => {
711
const cube = vtkCubeSource.newInstance();
@@ -24,3 +28,70 @@ test('Test vtkPolyDataNormals passData', (t) => {
2428

2529
t.end();
2630
});
31+
32+
test.only('Test vtkPolyDataNormals normals', (t) => {
33+
const cube = vtkCubeSource.newInstance();
34+
const input = cube.getOutputData();
35+
const pointNormalsData = input.getPointData().getNormals().getData();
36+
// const cellNormalsData = input.getCellData().getNormals().getData();
37+
input.getPointData().setNormals(null);
38+
input.getCellData().setNormals(null);
39+
40+
const normals = vtkPolyDataNormals.newInstance();
41+
normals.setInputData(input);
42+
normals.setComputeCellNormals(true);
43+
normals.update();
44+
const output = normals.getOutputData();
45+
46+
console.log(pointNormalsData);
47+
console.log(output.getPointData().getNormals().getData());
48+
t.deepEqual(
49+
vtkMath.roundVector(pointNormalsData, [], PRECISION),
50+
vtkMath.roundVector(
51+
output.getPointData().getNormals().getData(),
52+
[],
53+
PRECISION
54+
),
55+
'Same point normals'
56+
);
57+
58+
const pointsData = output.getPoints().getData();
59+
const polysData = output.getPolys().getData();
60+
const polysDataLength = polysData.length;
61+
const cellPointIds = [0, 0, 0];
62+
let numberOfPoints = 0;
63+
let polysId = 0;
64+
for (let c = 0; c < polysDataLength; c += numberOfPoints + 1) {
65+
numberOfPoints = polysData[c];
66+
67+
for (let i = 1; i <= 3; ++i) {
68+
cellPointIds[i - 1] = 3 * polysData[c + i];
69+
}
70+
71+
const cellNormal = [];
72+
73+
vtkTriangle.computeNormal(
74+
pointsData.slice(cellPointIds[0], cellPointIds[0] + 3),
75+
pointsData.slice(cellPointIds[1], cellPointIds[1] + 3),
76+
pointsData.slice(cellPointIds[2], cellPointIds[2] + 3),
77+
cellNormal
78+
);
79+
80+
t.deepEqual(
81+
vtkMath.roundVector(cellNormal, [], PRECISION),
82+
vtkMath.roundVector(
83+
output
84+
.getCellData()
85+
.getNormals()
86+
.getData()
87+
.slice(3 * polysId, 3 * polysId + 3),
88+
[],
89+
PRECISION
90+
),
91+
`Same cell normal #${polysId}`
92+
);
93+
++polysId;
94+
}
95+
96+
t.end();
97+
});

0 commit comments

Comments
 (0)