From df7d307463c16bb109b59cc8cf6361fbd2339958 Mon Sep 17 00:00:00 2001 From: Adnane Belmadiaf Date: Mon, 21 Jul 2025 14:43:17 +0200 Subject: [PATCH] feat(ShrinkPolyData): add vtkShrinkPolyData --- .../content/docs/gallery/ShrinkPolyData.jpg | Bin 0 -> 37701 bytes Documentation/content/examples/index.md | 3 +- Sources/Common/DataModel/Polygon/index.d.ts | 13 + Sources/Common/DataModel/Polygon/index.js | 26 ++ .../ShrinkPolyData/example/controlPanel.html | 8 + .../General/ShrinkPolyData/example/index.js | 52 +++ .../Filters/General/ShrinkPolyData/index.d.ts | 85 ++++ .../Filters/General/ShrinkPolyData/index.js | 384 ++++++++++++++++++ .../ShrinkPolyData/test/testShrinkPolyData.js | 73 ++++ .../test/testShrinkPolyData.png | Bin 0 -> 38697 bytes Sources/Filters/General/index.js | 2 + 11 files changed, 645 insertions(+), 1 deletion(-) create mode 100644 Documentation/content/docs/gallery/ShrinkPolyData.jpg create mode 100644 Sources/Filters/General/ShrinkPolyData/example/controlPanel.html create mode 100644 Sources/Filters/General/ShrinkPolyData/example/index.js create mode 100644 Sources/Filters/General/ShrinkPolyData/index.d.ts create mode 100644 Sources/Filters/General/ShrinkPolyData/index.js create mode 100644 Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.js create mode 100644 Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.png diff --git a/Documentation/content/docs/gallery/ShrinkPolyData.jpg b/Documentation/content/docs/gallery/ShrinkPolyData.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1b16f9f7bb66f86eab27f058844a064b1e909523 GIT binary patch literal 37701 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 literal 0 HcmV?d00001 diff --git a/Documentation/content/examples/index.md b/Documentation/content/examples/index.md index 4e81c621d59..3789ff72f00 100644 --- a/Documentation/content/examples/index.md +++ b/Documentation/content/examples/index.md @@ -108,7 +108,7 @@ This will allow you to see the some live code running in your browser. Just pick [![Cutter Example][Cutter]](./Cutter.html "Cutter") [![PolyDataNormals Example][PolyDataNormals]](./PolyDataNormals.html "PolyDataNormals") [![ThresholdPoints Example][ThresholdPoints]](./ThresholdPoints.html "Cut/Treshold points with point data criteria") - +[![ShrinkPolyData Example][ShrinkPolyData]](./ShrinkPolyData.html "ShrinkPolyData") @@ -128,6 +128,7 @@ This will allow you to see the some live code running in your browser. Just pick [Cutter]: ../docs/gallery/Cutter.jpg [PolyDataNormals]: ../docs/gallery/PolyDataNormals.jpg [ThresholdPoints]: ../docs/gallery/ThresholdPoints.jpg +[ShrinkPolyData]: ../docs/gallery/ShrinkPolyData.jpg # Sources diff --git a/Sources/Common/DataModel/Polygon/index.d.ts b/Sources/Common/DataModel/Polygon/index.d.ts index 625ff29a82e..9cc230eb419 100644 --- a/Sources/Common/DataModel/Polygon/index.d.ts +++ b/Sources/Common/DataModel/Polygon/index.d.ts @@ -60,6 +60,19 @@ export function pointInPolygon( normal: Vector3 ): PolygonIntersectionState; +/** + * Compute the centroid of a polygon. + * @param {Array} poly - Array of point indices for the polygon + * @param {vtkPoints} points - vtkPoints instance + * @param {Vector3} [centroid] - Optional output array (length 3) + * @returns {Vector3} The centroid as [x, y, z] + */ +export function computeCentroid( + poly: Array, + points: TypedArray, + centroid?: Vector3 +): Vector3; + /** * Method used to decorate a given object (publicAPI+model) with vtkPolygon characteristics. * diff --git a/Sources/Common/DataModel/Polygon/index.js b/Sources/Common/DataModel/Polygon/index.js index ca6c82ad47f..ca636ac6d74 100644 --- a/Sources/Common/DataModel/Polygon/index.js +++ b/Sources/Common/DataModel/Polygon/index.js @@ -215,6 +215,31 @@ export function getNormal(poly, points, normal) { return vtkMath.normalize(normal); } +/** + * Compute the centroid of a polygon. + * @param {Array} poly - Array of point indices for the polygon + * @param {vtkPoints} points - vtkPoints instance + * @param {Vector3} [centroid] - Optional output array (length 3) + * @returns {Vector3} The centroid as [x, y, z] + */ +export function computeCentroid(poly, points, centroid = [0, 0, 0]) { + centroid[0] = 0; + centroid[1] = 0; + centroid[2] = 0; + const n = poly.length; + const p = []; + for (let i = 0; i < n; i++) { + points.getPoint(poly[i], p); + centroid[0] += p[0]; + centroid[1] += p[1]; + centroid[2] += p[2]; + } + centroid[0] /= n; + centroid[1] /= n; + centroid[2] /= n; + return centroid; +} + // ---------------------------------------------------------------------------- // Static API // ---------------------------------------------------------------------------- @@ -224,6 +249,7 @@ const STATIC = { pointInPolygon, getBounds, getNormal, + computeCentroid, }; // ---------------------------------------------------------------------------- diff --git a/Sources/Filters/General/ShrinkPolyData/example/controlPanel.html b/Sources/Filters/General/ShrinkPolyData/example/controlPanel.html new file mode 100644 index 00000000000..3f2c8153b9c --- /dev/null +++ b/Sources/Filters/General/ShrinkPolyData/example/controlPanel.html @@ -0,0 +1,8 @@ + + + + + +
Shrink Factor + +
diff --git a/Sources/Filters/General/ShrinkPolyData/example/index.js b/Sources/Filters/General/ShrinkPolyData/example/index.js new file mode 100644 index 00000000000..836c2974b60 --- /dev/null +++ b/Sources/Filters/General/ShrinkPolyData/example/index.js @@ -0,0 +1,52 @@ +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/IO/Core/DataAccessHelper/HttpDataAccessHelper'; + +import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow'; +import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor'; +import vtkHttpDataSetReader from '@kitware/vtk.js/IO/Core/HttpDataSetReader'; +import vtkShrinkPolyData from '@kitware/vtk.js/Filters/General/ShrinkPolyData'; +import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper'; +import controlPanel from './controlPanel.html'; + +// ---------------------------------------------------------------------------- +// Standard rendering code setup +// ---------------------------------------------------------------------------- + +const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance(); +const renderer = fullScreenRenderer.getRenderer(); +const renderWindow = fullScreenRenderer.getRenderWindow(); + +fullScreenRenderer.addController(controlPanel); + +// ---------------------------------------------------------------------------- +// Example code +// ---------------------------------------------------------------------------- +const shrinkPolyData = vtkShrinkPolyData.newInstance(); +shrinkPolyData.setShrinkFactor(0.25); + +const actor = vtkActor.newInstance(); +const mapper = vtkMapper.newInstance(); +mapper.setInputConnection(shrinkPolyData.getOutputPort()); +actor.setMapper(mapper); + +const reader = vtkHttpDataSetReader.newInstance({ fetchGzip: true }); +shrinkPolyData.setInputConnection(reader.getOutputPort()); + +reader.setUrl(`${__BASE_PATH__}/data/cow.vtp`).then(() => { + reader.loadData().then(() => { + renderer.addActor(actor); + renderer.resetCamera(); + renderWindow.render(); + }); +}); + +['shrinkFactor'].forEach((propertyName) => { + document.querySelector(`.${propertyName}`).addEventListener('input', (e) => { + const value = Number(e.target.value); + shrinkPolyData.set({ [propertyName]: value }); + renderWindow.render(); + }); +}); diff --git a/Sources/Filters/General/ShrinkPolyData/index.d.ts b/Sources/Filters/General/ShrinkPolyData/index.d.ts new file mode 100644 index 00000000000..a62578bebc7 --- /dev/null +++ b/Sources/Filters/General/ShrinkPolyData/index.d.ts @@ -0,0 +1,85 @@ +import { DesiredOutputPrecision } from '../../../Common/DataModel/DataSetAttributes'; +import { vtkAlgorithm, vtkObject } from '../../../interfaces'; +import { Vector3 } from '../../../types'; + +/** + * + */ +export interface IShrinkPolyDataInitialValues { + shrinkFactor?: number; +} + +type vtkShrinkPolyDataBase = vtkObject & vtkAlgorithm; + +export interface vtkShrinkPolyData extends vtkShrinkPolyDataBase { + /** + * Expose methods + * @param inData + * @param outData + */ + requestData(inData: any, outData: any): void; + + /** + * Get the shrink factor. + */ + getShrinkFactor(): number; + + /** + * Set the shrink factor. + * @param {Number} shrinkFactor + */ + setShrinkFactor(shrinkFactor: number): boolean; + + /** + * Shrink two points towards their midpoint by a shrink factor. + * @param {Vector3} p1 - The [x, y, z] coordinates of the first point + * @param {Vector3} p2 - The [x, y, z] coordinates of the second point + * @param {number} shrinkFactor - The shrink factor (0.0 to 1.0) + * @param {Number[]} [shrunkPoints] - Optional array to store the shrunk points + * @returns {Number[]} Array containing the two new points + */ + shrinkLine( + p1: Vector3, + p2: Vector3, + shrinkFactor: number, + shrunkPoints?: Number[] + ): Number[]; +} + +/** + * Method used to decorate a given object (publicAPI+model) with vtkShrinkPolyData characteristics. + * + * @param publicAPI object on which methods will be bounds (public) + * @param model object on which data structure will be bounds (protected) + * @param {IShrinkPolyDataInitialValues} [initialValues] (default: {}) + */ +export function extend( + publicAPI: object, + model: object, + initialValues?: IShrinkPolyDataInitialValues +): void; + +/** + * Method used to create a new instance of vtkShrinkPolyData. + * @param {IShrinkPolyDataInitialValues} [initialValues] for pre-setting some of its content + */ +export function newInstance( + initialValues?: IShrinkPolyDataInitialValues +): vtkShrinkPolyData; + +/** + * vtkShrinkPolyData shrinks cells composing a polygonal dataset (e.g., + * vertices, lines, polygons, and triangle strips) towards their centroid. The + * centroid of a cell is computed as the average position of the cell points. + * Shrinking results in disconnecting the cells from one another. The output + * dataset type of this filter is polygonal data. + * + * During execution the filter passes its input cell data to its output. Point + * data attributes are copied to the points created during the shrinking + * process. + */ +export declare const vtkShrinkPolyData: { + newInstance: typeof newInstance; + extend: typeof extend; +}; +export default vtkShrinkPolyData; diff --git a/Sources/Filters/General/ShrinkPolyData/index.js b/Sources/Filters/General/ShrinkPolyData/index.js new file mode 100644 index 00000000000..f0cf3471eb1 --- /dev/null +++ b/Sources/Filters/General/ShrinkPolyData/index.js @@ -0,0 +1,384 @@ +import macro from 'vtk.js/Sources/macros'; +import vtkCellArray from 'vtk.js/Sources/Common/Core/CellArray'; +import vtkPolyData from 'vtk.js/Sources/Common/DataModel/PolyData'; +import vtkPoints from 'vtk.js/Sources/Common/Core/Points'; +import vtkPolygon from 'vtk.js/Sources/Common/DataModel/Polygon'; + +const { vtkErrorMacro } = macro; + +// ---------------------------------------------------------------------------- +// vtkShrinkPolyData methods +// ---------------------------------------------------------------------------- + +function vtkShrinkPolyData(publicAPI, model) { + // Set our className + model.classHierarchy.push('vtkShrinkPolyData'); + + /** + * Shrink a point towards a given center by a shrink factor. + * @param {Vector3} point - The [x, y, z] coordinates of the point to shrink + * @param {Vector3} center - The [x, y, z] coordinates of the center + * @param {number} shrinkFactor - The shrink factor (0.0 to 1.0) + * @param {Vector3} [shrunkPoint] - Optional array to store the shrunk point + * @returns {Vector3} The shrunk point [x, y, z] coordinates + */ + function shrinkTowardsPoint(point, center, shrinkFactor, shrunkPoint = []) { + shrunkPoint[0] = center[0] + shrinkFactor * (point[0] - center[0]); + shrunkPoint[1] = center[1] + shrinkFactor * (point[1] - center[1]); + shrunkPoint[2] = center[2] + shrinkFactor * (point[2] - center[2]); + return shrunkPoint; + } + + /** + * Shrinks a cell towards its center by a shrink factor. + * @param {number[]} cellPointIds - Array of point indices that define the cell + * @param {vtkPoints} inPoints - Input points + * @param {number} shrinkFactor - The shrink factor (0.0 to 1.0) + * @param {Float32Array} newPointsData - Output array to store new point coordinates + * @param {number} outCount - Current index in the output points array + * @returns {Object} Object containing newPointIds array and updated outCount + */ + function shrinkCell( + cellPointIds, + inPoints, + shrinkFactor, + newPointsData, + outCount + ) { + const inPts = inPoints.getData(); + const center = [0, 0, 0]; + const newPointIds = []; + const shrunkPoint = [0, 0, 0]; + const currentPoint = [0, 0, 0]; + + let nextOutCount = outCount; + + const numPoints = cellPointIds.length; + + if (numPoints === 0) { + return { newPointIds, outCount: nextOutCount }; + } + + if (numPoints === 1) { + // vertex - no shrinking needed, just copy the point + const ptId = cellPointIds[0]; + newPointsData[nextOutCount * 3] = inPts[ptId * 3]; + newPointsData[nextOutCount * 3 + 1] = inPts[ptId * 3 + 1]; + newPointsData[nextOutCount * 3 + 2] = inPts[ptId * 3 + 2]; + newPointIds.push(nextOutCount); + nextOutCount++; + } else if (numPoints === 2) { + // line - shrink towards midpoint + + // Calculate midpoint as center + vtkPolygon.computeCentroid(cellPointIds, inPoints, center); + + // Shrink both points towards center + for (let i = 0; i < 2; i++) { + const ptId = cellPointIds[i]; + currentPoint[0] = inPts[ptId * 3]; + currentPoint[1] = inPts[ptId * 3 + 1]; + currentPoint[2] = inPts[ptId * 3 + 2]; + + shrinkTowardsPoint(currentPoint, center, shrinkFactor, shrunkPoint); + + newPointsData[nextOutCount * 3] = shrunkPoint[0]; + newPointsData[nextOutCount * 3 + 1] = shrunkPoint[1]; + newPointsData[nextOutCount * 3 + 2] = shrunkPoint[2]; + newPointIds.push(nextOutCount); + nextOutCount++; + } + } else { + // polygon/triangle - shrink towards centroid + vtkPolygon.computeCentroid(cellPointIds, inPoints, center); + + // Shrink each point towards centroid + for (let i = 0; i < numPoints; i++) { + const ptId = cellPointIds[i]; + currentPoint[0] = inPts[ptId * 3]; + currentPoint[1] = inPts[ptId * 3 + 1]; + currentPoint[2] = inPts[ptId * 3 + 2]; + + shrinkTowardsPoint(currentPoint, center, shrinkFactor, shrunkPoint); + + newPointsData[nextOutCount * 3] = shrunkPoint[0]; + newPointsData[nextOutCount * 3 + 1] = shrunkPoint[1]; + newPointsData[nextOutCount * 3 + 2] = shrunkPoint[2]; + newPointIds.push(nextOutCount); + nextOutCount++; + } + } + + return { newPointIds, outCount: nextOutCount }; + } + + // Internal method to process the shrinking + function shrinkData(input, output) { + const inPoints = input.getPoints(); + const inVerts = input.getVerts(); + const inLines = input.getLines(); + const inPolys = input.getPolys(); + const inStrips = input.getStrips(); + + const shrinkFactor = model.shrinkFactor; + + let numNewPts = 0; + + if (inVerts) { + const cellSizes = inVerts.getCellSizes(); + for (let i = 0; i < cellSizes.length; i++) { + numNewPts += cellSizes[i]; + } + } + + if (inLines) { + const cellSizes = inLines.getCellSizes(); + for (let i = 0; i < cellSizes.length; i++) { + numNewPts += (cellSizes[i] - 1) * 2; + } + } + + if (inPolys) { + const cellSizes = inPolys.getCellSizes(); + for (let i = 0; i < cellSizes.length; i++) { + numNewPts += cellSizes[i]; + } + } + + if (inStrips) { + const cellSizes = inStrips.getCellSizes(); + for (let i = 0; i < cellSizes.length; i++) { + numNewPts += (cellSizes[i] - 2) * 3; + } + } + + const newPointsData = new Float32Array(numNewPts * 3); + const newPoints = vtkPoints.newInstance(); + newPoints.setData(newPointsData, 3); + + const newVerts = vtkCellArray.newInstance(); + const newLines = vtkCellArray.newInstance(); + const newPolys = vtkCellArray.newInstance(); + + let outCount = 0; + + // Process vertices + if (inVerts) { + const vertData = inVerts.getData(); + const newVertData = []; + const cellPointIds = []; + + for (let i = 0; i < vertData.length; ) { + cellPointIds.length = 0; // Clear previous point IDs + const npts = vertData[i]; + for (let j = 1; j <= npts; j++) { + cellPointIds.push(vertData[i + j]); + } + + const result = shrinkCell( + cellPointIds, + inPoints, + shrinkFactor, + newPointsData, + outCount + ); + outCount = result.outCount; + + newVertData.push(npts); + newVertData.push(...result.newPointIds); + + i += npts + 1; + } + + newVerts.setData(new Uint32Array(newVertData)); + } + + // Process lines + if (inLines) { + const lineData = inLines.getData(); + const newLineData = []; + + for (let i = 0; i < lineData.length; ) { + const npts = lineData[i]; + + // Process each line segment + for (let j = 0; j < npts - 1; j++) { + const cellPointIds = [lineData[i + j + 1], lineData[i + j + 2]]; + + const result = shrinkCell( + cellPointIds, + inPoints, + shrinkFactor, + newPointsData, + outCount + ); + outCount = result.outCount; + + newLineData.push(2, result.newPointIds[0], result.newPointIds[1]); + } + + i += npts + 1; + } + + newLines.setData(new Uint32Array(newLineData)); + } + + // Process polygons + if (inPolys) { + const polyData = inPolys.getData(); + const newPolyData = []; + const cellPointIds = []; + + for (let i = 0; i < polyData.length; ) { + cellPointIds.length = 0; // Clear previous point IDs + const npts = polyData[i]; + + for (let j = 1; j <= npts; j++) { + cellPointIds.push(polyData[i + j]); + } + + const result = shrinkCell( + cellPointIds, + inPoints, + shrinkFactor, + newPointsData, + outCount + ); + outCount = result.outCount; + + newPolyData.push(npts); + newPolyData.push(...result.newPointIds); + + i += npts + 1; + } + + newPolys.setData(new Uint32Array(newPolyData)); + } + + // Process triangle strips (convert to triangles and shrink) + if (inStrips) { + const stripData = inStrips.getData(); + const newPolyData = []; + + for (let i = 0; i < stripData.length; ) { + const npts = stripData[i]; + + for (let j = 0; j < npts - 2; j++) { + const cellPointIds = [ + stripData[i + j + 1], + stripData[i + j + 2], + stripData[i + j + 3], + ]; + + const result = shrinkCell( + cellPointIds, + inPoints, + shrinkFactor, + newPointsData, + outCount + ); + outCount = result.outCount; + + // Triangle strips alternate the winding order of each triangle as you + // move along the strip. This means that the orientation + // (clockwise/counter-clockwise) flips for every new triangle. To + // ensure consistent face orientation (so normals and rendering are + // correct), we reverse the vertex order for every odd triangle. + // Example strip with vertices [0,1,2,3,4,5] produces these triangles: + // + // 0───2───4 Triangle 0: (0,1,2) [CCW] + // │ ╱ │ ╱ │ Triangle 1: (1,3,2) [CW -> reversed to (2,3,1) for CCW] + // │╱ │╱ │ Triangle 2: (2,3,4) [CCW] + // 1───3───5 Triangle 3: (3,5,4) [CW -> reversed to (4,5,3) for CCW] + const newIds = [...result.newPointIds]; + if (j % 2) { + const tmp = newIds[0]; + newIds[0] = newIds[2]; + newIds[2] = tmp; + } + + newPolyData.push(3, newIds[0], newIds[1], newIds[2]); + } + i += npts + 1; + } + + if (newPolyData.length > 0) { + const existingPolyData = newPolys.getData(); + const combinedPolyData = new Uint32Array( + existingPolyData.length + newPolyData.length + ); + combinedPolyData.set(existingPolyData); + combinedPolyData.set(newPolyData, existingPolyData.length); + newPolys.setData(combinedPolyData); + } + } + + // Set output + output.setPoints(newPoints); + output.setVerts(newVerts); + output.setLines(newLines); + output.setPolys(newPolys); + + // Copy cell data + output.getCellData().passData(input.getCellData()); + } + + publicAPI.requestData = (inData, outData) => { + const input = inData[0]; + const output = outData[0] || vtkPolyData.newInstance(); + + if (!input) { + vtkErrorMacro('No input!'); + return; + } + + if (!input.getPoints()) { + vtkErrorMacro('Input has no points!'); + return; + } + + shrinkData(input, output); + + outData[0] = output; + }; + + // Set the shrink factor + publicAPI.setShrinkFactor = (shrinkFactor) => { + if (shrinkFactor !== model.shrinkFactor) { + model.shrinkFactor = Math.max(0.0, Math.min(1.0, shrinkFactor)); + publicAPI.modified(); + } + }; +} + +// ---------------------------------------------------------------------------- +// Object factory +// ---------------------------------------------------------------------------- + +const DEFAULT_VALUES = { + shrinkFactor: 0.5, +}; + +// ---------------------------------------------------------------------------- + +export function extend(publicAPI, model, initialValues = {}) { + Object.assign(model, DEFAULT_VALUES, initialValues); + + // Build VTK API + macro.obj(publicAPI, model); + + // Also make it an algorithm with one input and one output + macro.algo(publicAPI, model, 1, 1); + + macro.setGet(publicAPI, model, ['shrinkFactor']); + + vtkShrinkPolyData(publicAPI, model); +} + +// ---------------------------------------------------------------------------- + +export const newInstance = macro.newInstance(extend, 'vtkShrinkPolyData'); + +// ---------------------------------------------------------------------------- + +export default { newInstance, extend }; diff --git a/Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.js b/Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.js new file mode 100644 index 00000000000..ba5bc7a73cb --- /dev/null +++ b/Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.js @@ -0,0 +1,73 @@ +import test from 'tape'; +import testUtils from 'vtk.js/Sources/Testing/testUtils'; + +import 'vtk.js/Sources/Rendering/Misc/RenderingAPIs'; +import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow'; +import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer'; +import vtkShrinkPolyData from 'vtk.js/Sources/Filters/General/ShrinkPolyData'; +import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor'; +import vtkMapper from 'vtk.js/Sources/Rendering/Core/Mapper'; +import vtkSphereSource from 'vtk.js/Sources/Filters/Sources/SphereSource'; + +import baseline from './testShrinkPolyData.png'; + +test.onlyIfWebGL('Test vtkShrinkPolyData Rendering', (t) => { + const gc = testUtils.createGarbageCollector(); + t.ok('rendering', 'vtkShrinkPolyData Rendering'); + + // Create some control UI + const container = document.querySelector('body'); + const renderWindowContainer = gc.registerDOMElement( + document.createElement('div') + ); + container.appendChild(renderWindowContainer); + + // create what we will view + const renderWindow = gc.registerResource(vtkRenderWindow.newInstance()); + const renderer = gc.registerResource(vtkRenderer.newInstance()); + renderWindow.addRenderer(renderer); + renderer.setBackground(0.32, 0.34, 0.43); + + const actor = gc.registerResource(vtkActor.newInstance()); + renderer.addActor(actor); + + const mapper = gc.registerResource(vtkMapper.newInstance()); + actor.setMapper(mapper); + + const sphere = gc.registerResource( + vtkSphereSource.newInstance({ + radius: 1.0, + thetaResolution: 20, + phiResolution: 20, + }) + ); + + const shrink = gc.registerResource( + vtkShrinkPolyData.newInstance({ + shrinkFactor: 0.5, + }) + ); + shrink.setInputConnection(sphere.getOutputPort()); + mapper.setInputConnection(shrink.getOutputPort()); + + // now create something to view it, in this case webgl + const glwindow = gc.registerResource(renderWindow.newAPISpecificView()); + glwindow.setContainer(renderWindowContainer); + renderWindow.addView(glwindow); + glwindow.setSize(400, 400); + + const promise = glwindow + .captureNextImage() + .then((image) => + testUtils.compareImages( + image, + [baseline], + 'Filters/General/ShrinkPolyData/testShrinkPolyData', + t, + 2.5 + ) + ) + .finally(gc.releaseResources); + renderWindow.render(); + return promise; +}); diff --git a/Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.png b/Sources/Filters/General/ShrinkPolyData/test/testShrinkPolyData.png new file mode 100644 index 0000000000000000000000000000000000000000..66f81e2247a95bc873d0f0c3548f0f40f1c631cc GIT binary patch literal 38697 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 literal 0 HcmV?d00001 diff --git a/Sources/Filters/General/index.js b/Sources/Filters/General/index.js index 7c7b1873dd8..ea7f760f34c 100644 --- a/Sources/Filters/General/index.js +++ b/Sources/Filters/General/index.js @@ -15,6 +15,7 @@ import vtkOBBTree from './OBBTree'; import vtkOutlineFilter from './OutlineFilter'; import vtkPaintFilter from './PaintFilter'; import vtkScalarToRGBA from './ScalarToRGBA'; +import vtkShrinkPolyData from './ShrinkPolyData'; import vtkTransformPolyDataFilter from './TransformPolyDataFilter'; import vtkTriangleFilter from './TriangleFilter'; import vtkTubeFilter from './TubeFilter'; @@ -39,6 +40,7 @@ export default { vtkOutlineFilter, vtkPaintFilter, vtkScalarToRGBA, + vtkShrinkPolyData, vtkTransformPolyDataFilter, vtkTriangleFilter, vtkTubeFilter,