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;
function vtkShrinkPolyData(publicAPI, model) { model.classHierarchy.push('vtkShrinkPolyData');
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; }
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) { 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) {
vtkPolygon.computeCentroid(cellPointIds, inPoints, 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 { vtkPolygon.computeCentroid(cellPointIds, inPoints, center);
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 }; }
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;
if (inVerts) { const vertData = inVerts.getData(); const newVertData = []; const cellPointIds = [];
for (let i = 0; i < vertData.length; ) { cellPointIds.length = 0; 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)); }
if (inLines) { const lineData = inLines.getData(); const newLineData = [];
for (let i = 0; i < lineData.length; ) { const npts = lineData[i];
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)); }
if (inPolys) { const polyData = inPolys.getData(); const newPolyData = []; const cellPointIds = [];
for (let i = 0; i < polyData.length; ) { cellPointIds.length = 0; 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)); }
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;
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); } }
output.setPoints(newPoints); output.setVerts(newVerts); output.setLines(newLines); output.setPolys(newPolys);
output.getCellData().passData(input.getCellData()); }
publicAPI.requestData = (inData, outData) => { const input = inData[0]; const output = outData[0]?.initialize() || vtkPolyData.newInstance();
if (!input) { vtkErrorMacro('No input!'); return; }
if (!input.getPoints()) { vtkErrorMacro('Input has no points!'); return; }
shrinkData(input, output);
outData[0] = output; };
publicAPI.setShrinkFactor = (shrinkFactor) => { if (shrinkFactor !== model.shrinkFactor) { model.shrinkFactor = Math.max(0.0, Math.min(1.0, shrinkFactor)); publicAPI.modified(); } }; }
const DEFAULT_VALUES = { shrinkFactor: 0.5, };
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model);
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 };
|