Skip to content

Commit 602c9e8

Browse files
finetjulfloryst
authored andcommitted
feat(polydatanormals): add option to compute cell normals
fix #2434
1 parent 0f6d364 commit 602c9e8

File tree

2 files changed

+132
-29
lines changed

2 files changed

+132
-29
lines changed

Sources/Filters/Core/PolyDataNormals/index.js

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,24 @@ function vtkPolyDataNormals(publicAPI, model) {
1313
// Set our className
1414
model.classHierarchy.push('vtkPolyDataNormals');
1515

16-
publicAPI.vtkPolyDataNormalsExecute = (pointsData, polysData) => {
16+
publicAPI.vtkPolyDataNormalsExecute = (
17+
numberOfPolys,
18+
polysData,
19+
pointsData
20+
) => {
1721
if (!pointsData) {
1822
return null;
1923
}
2024

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

2329
let numberOfPoints = 0;
2430
const polysDataLength = polysData.length;
2531

2632
const cellPointIds = [0, 0, 0];
33+
const cellNormal = [0, 0, 0];
2734

2835
for (let c = 0; c < polysDataLength; c += numberOfPoints + 1) {
2936
numberOfPoints = polysData[c];
@@ -36,37 +43,46 @@ function vtkPolyDataNormals(publicAPI, model) {
3643
cellPointIds[i - 1] = 3 * polysData[c + i];
3744
}
3845

39-
const cellNormal = [];
40-
4146
vtkTriangle.computeNormal(
4247
pointsData.slice(cellPointIds[0], cellPointIds[0] + 3),
4348
pointsData.slice(cellPointIds[1], cellPointIds[1] + 3),
4449
pointsData.slice(cellPointIds[2], cellPointIds[2] + 3),
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];
56+
57+
if (model.computePointNormals) {
58+
for (let i = 1; i <= numberOfPoints; ++i) {
59+
let pointId = 3 * polysData[c + i];
5060

51-
normalsData[pointId] += cellNormal[0];
52-
normalsData[++pointId] += cellNormal[1];
53-
normalsData[++pointId] += cellNormal[2];
61+
pointNormals[pointId] += cellNormal[0];
62+
pointNormals[++pointId] += cellNormal[1];
63+
pointNormals[++pointId] += cellNormal[2];
64+
}
5465
}
5566
}
5667

57-
/* Normalize normals */
68+
// Normalize point normals.
69+
// A point normal is the sum of all the cell normals the point belongs to
70+
if (model.computePointNormals) {
71+
const pointNormal = [0, 0, 0];
72+
for (let i = 0; i < pointsData.length; ) {
73+
pointNormal[0] = pointNormals[i];
74+
pointNormal[1] = pointNormals[i + 1];
75+
pointNormal[2] = pointNormals[i + 2];
5876

59-
for (let i = 0; i < pointsData.length; ) {
60-
const pointNormal = normalsData.slice(i, i + 3);
77+
vtkMath.normalize(pointNormal);
6178

62-
vtkMath.normalize(pointNormal);
63-
64-
normalsData[i++] = pointNormal[0];
65-
normalsData[i++] = pointNormal[1];
66-
normalsData[i++] = pointNormal[2];
79+
pointNormals[i++] = pointNormal[0];
80+
pointNormals[i++] = pointNormal[1];
81+
pointNormals[i++] = pointNormal[2];
82+
}
6783
}
6884

69-
return normalsData;
85+
return [cellNormals, pointNormals];
7086
};
7187

7288
publicAPI.requestData = (inData, outData) => {
@@ -82,18 +98,8 @@ function vtkPolyDataNormals(publicAPI, model) {
8298
return;
8399
}
84100

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

92-
const outputNormals = vtkDataArray.newInstance({
93-
numberOfComponents: 3,
94-
values: outputNormalsData,
95-
});
96-
97103
output.setPoints(input.getPoints());
98104
output.setVerts(input.getVerts());
99105
output.setLines(input.getLines());
@@ -104,7 +110,29 @@ function vtkPolyDataNormals(publicAPI, model) {
104110
output.getCellData().passData(input.getCellData());
105111
output.getFieldData().passData(input.getFieldData());
106112

107-
output.getPointData().setNormals(outputNormals);
113+
const [cellNormals, pointNormals] = publicAPI.vtkPolyDataNormalsExecute(
114+
input.getNumberOfPolys(),
115+
input.getPolys().getData(),
116+
input.getPoints().getData()
117+
);
118+
119+
if (model.computePointNormals) {
120+
const outputPointNormals = vtkDataArray.newInstance({
121+
numberOfComponents: 3,
122+
name: 'Normals',
123+
values: pointNormals,
124+
});
125+
output.getPointData().setNormals(outputPointNormals);
126+
}
127+
128+
if (model.computeCellNormals) {
129+
const outputCellNormals = vtkDataArray.newInstance({
130+
numberOfComponents: 3,
131+
name: 'Normals',
132+
values: cellNormals,
133+
});
134+
output.getCellData().setNormals(outputCellNormals);
135+
}
108136

109137
outData[0] = output;
110138
};
@@ -115,6 +143,8 @@ function vtkPolyDataNormals(publicAPI, model) {
115143
// ----------------------------------------------------------------------------
116144
function defaultValues(initialValues) {
117145
return {
146+
computeCellNormals: false,
147+
computePointNormals: true,
118148
...initialValues,
119149
};
120150
}
@@ -131,6 +161,8 @@ export function extend(publicAPI, model, initialValues = {}) {
131161

132162
macro.algo(publicAPI, model, 1, 1);
133163

164+
macro.setGet(publicAPI, model, ['computeCellNormals', 'computePointNormals']);
165+
134166
/* Object specific methods */
135167

136168
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)