Skip to content

Commit

Permalink
feat(polydatacellnormals): programatically choose to compute cell nor…
Browse files Browse the repository at this point in the history
…mals

closes Kitware#2434
  • Loading branch information
emil-peters committed May 25, 2022
1 parent 77ee125 commit dd32dfc
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
94 changes: 94 additions & 0 deletions Sources/Filters/Core/PolyDataNormals/example/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'vtk.js/Sources/favicon';

// Load the rendering pieces we want to use (for both WebGL and WebGPU)
import 'vtk.js/Sources/Rendering/Profiles/Geometry';

import vtkFullScreenRenderWindow from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';
import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkLineSource from 'vtk.js/Sources/Filters/Sources/LineSource';
import vtkSphereSource from 'vtk.js/Sources/Filters/Sources/SphereSource';

import vtkPolyDataNormals from 'vtk.js/Sources/Filters/Core/PolyDataNormals';

// ----------------------------------------------------------------------------
// Standard rendering code setup
// ----------------------------------------------------------------------------

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();

const computeNormals = vtkPolyDataNormals.newInstance();

const sphere = vtkSphereSource.newInstance({
thetaResolution: 4,
phiResolution: 4,
});
const polydata = sphere.getOutputData();

const mapper = vtkMapper.newInstance();
const actor = vtkActor.newInstance();

actor.setMapper(mapper);
mapper.setInputData(polydata);

renderer.addActor(actor);

computeNormals.setInputData(polydata);
computeNormals.setComputeCellNormals(true);
computeNormals.update();

const cellNormals = computeNormals.getOutputData().getCellData().getNormals();

const pointsData = polydata.getPoints().getData();
const polysData = polydata.getPolys().getData();

let numberOfPoints = 0;
const cellPointIds = [0, 0, 0];
let normalId = 0;

for (let c = 0; c < polysData.length; c += numberOfPoints + 1) {
numberOfPoints = polysData[c];

if (numberOfPoints < 3) {
continue; // eslint-disable-line
}

for (let i = 1; i <= 3; ++i) {
cellPointIds[i - 1] = 3 * polysData[c + i];
}

const v1 = pointsData.slice(cellPointIds[0], cellPointIds[0] + 3);
const v2 = pointsData.slice(cellPointIds[1], cellPointIds[1] + 3);
const v3 = pointsData.slice(cellPointIds[2], cellPointIds[2] + 3);

const center = [
(v1[0] + v2[0] + v3[0]) / 3,
(v1[1] + v2[1] + v3[1]) / 3,
(v1[2] + v2[2] + v3[2]) / 3,
];

const line = vtkLineSource.newInstance({
point1: center,
point2: [
center[0] + cellNormals[normalId++],
center[1] + cellNormals[normalId++],
center[2] + cellNormals[normalId++],
],
});

const lineMapper = vtkMapper.newInstance();
const lineActor = vtkActor.newInstance();

lineActor.setMapper(lineMapper);
lineMapper.setInputData(line.getOutputData());
renderer.addActor(lineActor);
}

// Display the resulting STL
renderer.resetCamera();
renderWindow.render();

global.renderer = renderer;
global.renderWindow = renderWindow;
57 changes: 57 additions & 0 deletions Sources/Filters/Core/PolyDataNormals/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import vtkMath from 'vtk.js/Sources/Common/Core/Math/index';
import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData';
import vtkTriangle from 'vtk.js/Sources/Common/DataModel/Triangle';

export const NormalType = {
CELL: 'cell',
POINT: ' point',
};

// ----------------------------------------------------------------------------
// vtkPolyDataNormals methods
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -69,6 +74,49 @@ function vtkPolyDataNormals(publicAPI, model) {
return normalsData;
};

publicAPI.vtkPolyDataCellNormalsExecute = (polyData) => {
const pointsData = polyData.getPoints().getData();
const polysData = polyData.getPolys().getData();
const numPolys = polyData.getPolys().getNumberOfCells();

if (!pointsData || !polysData) {
return null;
}

const normalsData = new Float32Array(numPolys * 3);

let normalsIndex = 0;
let numberOfPoints = 0;
const cellPointIds = [0, 0, 0];

for (let c = 0; c < polysData.length; c += numberOfPoints + 1) {
numberOfPoints = polysData[c];

if (numberOfPoints < 3) {
continue; // eslint-disable-line
}

for (let i = 1; i <= 3; ++i) {
cellPointIds[i - 1] = 3 * polysData[c + i];
}

const cellNormal = [];

vtkTriangle.computeNormal(
pointsData.slice(cellPointIds[0], cellPointIds[0] + 3),
pointsData.slice(cellPointIds[1], cellPointIds[1] + 3),
pointsData.slice(cellPointIds[2], cellPointIds[2] + 3),
cellNormal
);

normalsData[normalsIndex++] = cellNormal[0];
normalsData[normalsIndex++] = cellNormal[1];
normalsData[normalsIndex++] = cellNormal[2];
}

return normalsData;
};

publicAPI.requestData = (inData, outData) => {
const numberOfInputs = publicAPI.getNumberOfInputPorts();

Expand Down Expand Up @@ -105,6 +153,13 @@ function vtkPolyDataNormals(publicAPI, model) {

output.getPointData().setNormals(outputNormals);

if (model.computeCellNormals) {
const outputCellNormalsData =
publicAPI.vtkPolyDataCellNormalsExecute(input);

output.getCellData().setNormals(outputCellNormalsData);
}

outData[0] = output;
};
}
Expand All @@ -130,6 +185,8 @@ export function extend(publicAPI, model, initialValues = {}) {

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

macro.setGet(publicAPI, model, ['computeCellNormals']);

/* Object specific methods */

vtkPolyDataNormals(publicAPI, model);
Expand Down

0 comments on commit dd32dfc

Please sign in to comment.