UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

203 lines (181 loc) 6.78 kB
import { m as macro } from '../../macros2.js'; import vtkCellArray from '../../Common/Core/CellArray.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; const { vtkErrorMacro } = macro; class SegmentAgregator { constructor() { this.segmentMapping = {}; this.segments = [null]; // to force first id to be 1 this.faces = []; } addSegment(segment) { const first = segment[0]; const last = segment[segment.length - 1]; if (first === last || segment.length < 2) { return; } const mappingFirst = this.segmentMapping[first]; const mappingLast = this.segmentMapping[last]; if (mappingFirst !== undefined && mappingLast !== undefined) { if (Math.abs(mappingFirst) === Math.abs(mappingLast)) { // This make a closing loop const idx = mappingFirst < mappingLast ? mappingLast : mappingFirst; const seg = this.segments[idx]; if (mappingFirst > 0) { for (let i = 1; i < segment.length - 1; i++) { seg.push(segment[i]); } } else { for (let i = 1; i < segment.length - 1; i++) { seg.unshift(segment[segment.length - 1 - i]); } } this.faces.push(seg); this.segments[idx] = null; this.segmentMapping[first] = undefined; this.segmentMapping[last] = undefined; } else { // we need to merge segments // strategie: // => remove and add them again in special order to induce merge const idxHead = Math.abs(mappingFirst); const idxTail = Math.abs(mappingLast); const segHead = this.segments[idxHead]; const segTail = this.segments[idxTail]; this.segments[idxHead] = null; this.segments[idxTail] = null; this.segmentMapping[segHead[0]] = undefined; this.segmentMapping[segTail[0]] = undefined; this.segmentMapping[segHead[segHead.length - 1]] = undefined; this.segmentMapping[segTail[segTail.length - 1]] = undefined; // This will lead to a single segment this.addSegment(segment); this.addSegment(segHead); this.addSegment(segTail); } } else if (mappingFirst !== undefined) { if (mappingFirst > 0) { // The head of our segment match the tail of the existing one const seg = this.segments[mappingFirst]; for (let i = 1; i < segment.length; i++) { seg.push(segment[i]); } // record new tail this.segmentMapping[last] = mappingFirst; } else { // our segment should be reverted and put on the front of the existing one const seg = this.segments[-mappingFirst]; // record new head this.segmentMapping[last] = mappingFirst; for (let i = 1; i < segment.length; i++) { seg.unshift(segment[i]); } } // Erase used connection this.segmentMapping[first] = undefined; } else if (mappingLast !== undefined) { if (mappingLast > 0) { // The tail of our segment match the tail of the existing one const seg = this.segments[mappingLast]; for (let i = 1; i < segment.length; i++) { seg.push(segment[segment.length - 1 - i]); } // record new tail this.segmentMapping[first] = mappingLast; } else { // our segment should be reverted and put on the front of the existing one const seg = this.segments[-mappingLast]; // record new head this.segmentMapping[first] = mappingLast; for (let i = 1; i < segment.length; i++) { seg.unshift(segment[segment.length - i - 1]); } } // Erase used connection this.segmentMapping[last] = undefined; } else { // store segment for now const id = this.segments.length; this.segments.push(segment); this.segmentMapping[first] = -id; this.segmentMapping[last] = id; } } } // ---------------------------------------------------------------------------- // vtkClosedPolyLineToSurfaceFilter methods // ---------------------------------------------------------------------------- function vtkClosedPolyLineToSurfaceFilter(publicAPI, model) { // Set our className model.classHierarchy.push('vtkClosedPolyLineToSurfaceFilter'); // -------------------------------------------------------------------------- publicAPI.requestData = (inData, outData) => { // implement requestData const input = inData[0]; if (!input) { vtkErrorMacro('Invalid or missing input'); return; } const output = outData[0]?.initialize() || vtkPolyData.newInstance(); output.shallowCopy(input); // Extract faces const agregator = new SegmentAgregator(); const lines = input.getLines().getData(); let offset = 0; while (offset < lines.length) { const lineSize = lines[offset++]; const lineSegment = []; for (let i = 0; i < lineSize; i++) { lineSegment.push(lines[offset + i]); } agregator.addSegment(lineSegment); offset += lineSize; } // Create CellArray for polys const { faces } = agregator; let cellArraySize = faces.length; for (let i = 0; i < faces.length; i++) { cellArraySize += faces[i].length; } const cellArray = new Uint16Array(cellArraySize); offset = 0; for (let i = 0; i < faces.length; i++) { const face = faces[i]; cellArray[offset++] = face.length; for (let j = 0; j < face.length; j++) { cellArray[offset++] = face[j]; } } output.setPolys(vtkCellArray.newInstance({ values: cellArray, name: 'faces' })); outData[0] = output; }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = {}; // ---------------------------------------------------------------------------- function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); // Make this a VTK object macro.obj(publicAPI, model); // Also make it an algorithm with one input and one output macro.algo(publicAPI, model, 1, 1); // Object specific methods vtkClosedPolyLineToSurfaceFilter(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkClosedPolyLineToSurfaceFilter'); // ---------------------------------------------------------------------------- var vtkClosedPolyLineToSurfaceFilter$1 = { newInstance, extend }; export { vtkClosedPolyLineToSurfaceFilter$1 as default, extend, newInstance };