diff --git a/Sources/Filters/Core/PolyDataNormals/example/controlPanel.html b/Sources/Filters/Core/PolyDataNormals/example/controlPanel.html new file mode 100644 index 00000000000..d5b0ca6793f --- /dev/null +++ b/Sources/Filters/Core/PolyDataNormals/example/controlPanel.html @@ -0,0 +1,14 @@ + + + + + + + + + +
Compute point normals + +
Compute cell normals + +
diff --git a/Sources/Filters/Core/PolyDataNormals/example/index.js b/Sources/Filters/Core/PolyDataNormals/example/index.js new file mode 100644 index 00000000000..75256b35463 --- /dev/null +++ b/Sources/Filters/Core/PolyDataNormals/example/index.js @@ -0,0 +1,112 @@ +import '@kitware/vtk.js/favicon'; + +// Load the rendering pieces we want to use (for both WebGL and WebGPU) +import '@kitware/vtk.js/Rendering/Profiles/Geometry'; +import '@kitware/vtk.js/Rendering/Profiles/Glyph'; + +import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow'; + +import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor'; +import vtkArrowSource from '@kitware/vtk.js/Filters/Sources/ArrowSource'; +import vtkCubeSource from '@kitware/vtk.js/Filters/Sources/CubeSource'; +import vtkLookupTable from '@kitware/vtk.js/Common/Core/LookupTable'; +import vtkGlyph3DMapper from '@kitware/vtk.js/Rendering/Core/Glyph3DMapper'; +import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper'; +import vtkPolyDataNormals from '@kitware/vtk.js/Filters/Core/PolyDataNormals'; + +import controlPanel from './controlPanel.html'; + +const { ColorMode, ScalarMode } = vtkMapper; + +// ---------------------------------------------------------------------------- +// Standard rendering code setup +// ---------------------------------------------------------------------------- + +const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ + background: [0.9, 0.9, 0.9], +}); +const renderer = fullScreenRenderer.getRenderer(); +const renderWindow = fullScreenRenderer.getRenderWindow(); + +// ---------------------------------------------------------------------------- +// Example code +// ---------------------------------------------------------------------------- + +const lookupTable = vtkLookupTable.newInstance({ hueRange: [0.666, 0] }); + +const source = vtkCubeSource.newInstance(); +const inputPolyData = source.getOutputData(); +inputPolyData.getPointData().setNormals(null); + +const mapper = vtkMapper.newInstance({ + interpolateScalarsBeforeMapping: true, + colorMode: ColorMode.DEFAULT, + scalarMode: ScalarMode.DEFAULT, + useLookupTableScalarRange: true, + lookupTable, +}); +const actor = vtkActor.newInstance(); +actor.getProperty().setEdgeVisibility(true); + +const polyDataNormals = vtkPolyDataNormals.newInstance(); + +// The generated 'z' array will become the default scalars, so the plane mapper will color by 'z': +polyDataNormals.setInputData(inputPolyData); + +mapper.setInputConnection(polyDataNormals.getOutputPort()); +actor.setMapper(mapper); + +renderer.addActor(actor); + +const arrowSource = vtkArrowSource.newInstance(); + +const glyphMapper = vtkGlyph3DMapper.newInstance(); +glyphMapper.setInputConnection(polyDataNormals.getOutputPort()); +glyphMapper.setSourceConnection(arrowSource.getOutputPort()); +glyphMapper.setOrientationModeToDirection(); +glyphMapper.setOrientationArray('Normals'); +glyphMapper.setScaleModeToScaleByMagnitude(); +glyphMapper.setScaleArray('Normals'); +glyphMapper.setScaleFactor(0.1); + +const glyphActor = vtkActor.newInstance(); +glyphActor.setMapper(glyphMapper); +renderer.addActor(glyphActor); + +renderer.resetCamera(); +renderWindow.render(); + +// ---------------------------------------------------------------------------- +// UI control handling +// ---------------------------------------------------------------------------- + +fullScreenRenderer.addController(controlPanel); + +// Checkbox +document + .querySelector('.computePointNormals') + .addEventListener('change', (e) => { + polyDataNormals.setComputePointNormals(!!e.target.checked); + renderWindow.render(); + }); + +document + .querySelector('.computeCellNormals') + .addEventListener('change', (e) => { + polyDataNormals.setComputeCellNormals(!!e.target.checked); + renderWindow.render(); + }); + +// ----------------------------------------------------------- +// Make some variables global so that you can inspect and +// modify objects in your browser's developer console: +// ----------------------------------------------------------- + +global.mapper = mapper; +global.actor = actor; +global.source = source; +global.renderer = renderer; +global.renderWindow = renderWindow; +global.lookupTable = lookupTable; +global.polyDataNormals = polyDataNormals; +global.glyphMapper = glyphMapper; diff --git a/Sources/Filters/Core/PolyDataNormals/test/testPolyDataNormals.js b/Sources/Filters/Core/PolyDataNormals/test/testPolyDataNormals.js index 1d289fda32c..d1e6adcfd88 100644 --- a/Sources/Filters/Core/PolyDataNormals/test/testPolyDataNormals.js +++ b/Sources/Filters/Core/PolyDataNormals/test/testPolyDataNormals.js @@ -29,7 +29,7 @@ test('Test vtkPolyDataNormals passData', (t) => { t.end(); }); -test.only('Test vtkPolyDataNormals normals', (t) => { +test('Test vtkPolyDataNormals normals', (t) => { const cube = vtkCubeSource.newInstance(); const input = cube.getOutputData(); const pointNormalsData = input.getPointData().getNormals().getData(); diff --git a/Sources/Rendering/Core/Glyph3DMapper/index.d.ts b/Sources/Rendering/Core/Glyph3DMapper/index.d.ts index c4a47862838..6281beb9fc7 100755 --- a/Sources/Rendering/Core/Glyph3DMapper/index.d.ts +++ b/Sources/Rendering/Core/Glyph3DMapper/index.d.ts @@ -1,4 +1,4 @@ -import { Bounds } from "../../../types"; +import { Bounds, Nullable, vtkPipelineConnection } from "../../../types"; import vtkMapper, { IMapperInitialValues } from "../Mapper"; import { OrientationModes, ScaleModes } from "./Constants"; @@ -87,6 +87,12 @@ export interface vtkGlyph3DMapper extends vtkMapper { */ getPrimitiveCount(): IPrimitiveCount; + /** + * Sets the name of the array to use as orientation. + * @param {String} arrayName Name of the array + */ + setOrientationArray(arrayName: Nullable): boolean; + /** * Orientation mode indicates if the OrientationArray provides the direction * vector for the orientation or the rotations around each axes. @@ -138,6 +144,13 @@ export interface vtkGlyph3DMapper extends vtkMapper { * Set scale to `SCALE_BY_CONSTANT` */ setScaleModeToScaleByConstant(): boolean; + + /** + * Convenient method to set the source glyph connection + * @param {vtkPipelineConnection} outputPort The output port of the glyph source. + */ + setSourceConnection(outputPort: vtkPipelineConnection): void; + } /** diff --git a/Sources/Rendering/Core/Glyph3DMapper/index.js b/Sources/Rendering/Core/Glyph3DMapper/index.js index 4612ae80c33..a3d9ac232f6 100644 --- a/Sources/Rendering/Core/Glyph3DMapper/index.js +++ b/Sources/Rendering/Core/Glyph3DMapper/index.js @@ -134,6 +134,7 @@ function vtkGlyph3DMapper(publicAPI, model) { model.normalArray = new Float32Array(9 * numPts); const nbuff = model.normalArray.buffer; const tuple = []; + const orientation = []; for (let i = 0; i < numPts; ++i) { const z = new Float32Array(mbuff, i * 64, 16); trans[0] = pts[i * 3]; @@ -142,7 +143,6 @@ function vtkGlyph3DMapper(publicAPI, model) { mat4.translate(z, identity, trans); if (oArray) { - const orientation = []; oArray.getTuple(i, orientation); switch (model.orientationMode) { case OrientationModes.MATRIX: { @@ -299,6 +299,9 @@ function vtkGlyph3DMapper(publicAPI, model) { }; return pcount; }; + + publicAPI.setSourceConnection = (outputPort) => + publicAPI.setInputConnection(outputPort, 1); } // ----------------------------------------------------------------------------