UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

135 lines (121 loc) 4.04 kB
import { m as macro } from '../../macros2.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; const Dir = { Forward: 1, Backward: -1 }; const visited = new Set(); function vtkContourLoopExtraction(publicAPI, model) { publicAPI.requestData = (inData, outData) => { const [input] = inData; const output = outData[0]?.initialize() || vtkPolyData.newInstance(); outData[0] = output; publicAPI.extractContours(input, output); output.modified(); }; publicAPI.traverseLoop = (pd, dir, startLineId, startPtId, loopPoints) => { let lineId = startLineId; let lastPtId = startPtId; let terminated = false; let numInserted = 0; while (!terminated) { const { cellPointIds } = pd.getCellPoints(lineId); if (!cellPointIds) { // eslint-disable-next-line no-continue continue; } lastPtId = cellPointIds[0] !== lastPtId ? cellPointIds[0] : cellPointIds[1]; numInserted++; // parametric point value const t = dir * numInserted; loopPoints.push({ t, ptId: lastPtId }); const lineCell = pd.getPointCells(lastPtId); if (lineCell.length !== 2 || lastPtId === startPtId) { // looped return lastPtId; } if (lineCell.length === 2) { // continue along loop lineId = lineCell[0] !== lineId ? lineCell[0] : lineCell[1]; visited.add(lineId); } else { // empty or invalid cell terminated = true; } } return lastPtId; }; publicAPI.extractContours = (input, output) => { const loops = []; visited.clear(); const inLines = input.getLines(); output.getPoints().setData(Float32Array.from(input.getPoints().getData())); // TODO skip if cached input mtime hasn't changed. // iterate over input lines for (let li = 0; li < inLines.getNumberOfCells(); li++) { if (visited.has(li)) { // eslint-disable-next-line no-continue continue; } const { cellPointIds } = input.getCellPoints(li); if (!cellPointIds) { // eslint-disable-next-line no-continue continue; } visited.add(li); const startPtId = cellPointIds[0]; const loopPoints = []; loopPoints.push({ t: 0, ptId: startPtId }); const endPtId = publicAPI.traverseLoop(input, Dir.Forward, li, startPtId, loopPoints); if (startPtId !== endPtId) { // didn't find a loop. Go other direction to see where we end up publicAPI.traverseLoop(input, Dir.Backward, li, startPtId, loopPoints); loopPoints.sort((a, b) => a.t < b.t ? -1 : 1); // make closed contour if (loopPoints.length && loopPoints[0].ptId !== loopPoints[loopPoints.length - 1]?.ptId) { loopPoints.push({ ...loopPoints[loopPoints.length - 1] }); } } if (loopPoints.length) { loops.push(loopPoints); } } // clear output lines const outLines = output.getLines(); outLines.resize(0); loops.forEach(loop => { outLines.insertNextCell(loop.map(pt => pt.ptId)); }); }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = {}; // ---------------------------------------------------------------------------- function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); macro.obj(publicAPI, model); macro.algo(publicAPI, model, 1, 1); vtkContourLoopExtraction(publicAPI); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkContourLoopExtraction'); // ---------------------------------------------------------------------------- var index = { newInstance, extend }; export { index as default, extend, newInstance };