UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

262 lines (238 loc) 8.68 kB
import { m as macro } from '../../macros2.js'; import vtk from '../../vtk.js'; import vtkCellArray from '../Core/CellArray.js'; import vtkCellLinks from './CellLinks.js'; import vtkCellTypes from './CellTypes.js'; import vtkLine from './Line.js'; import vtkPointSet from './PointSet.js'; import vtkPolyLine from './PolyLine.js'; import vtkPolygon from './Polygon.js'; import vtkQuad from './Quad.js'; import vtkTriangle from './Triangle.js'; import vtkTriangleStrip from './TriangleStrip.js'; import { CellType } from './CellTypes/Constants.js'; import { POLYDATA_FIELDS } from './PolyData/Constants.js'; const { vtkWarningMacro } = macro; const CELL_FACTORY = { [CellType.VTK_LINE]: vtkLine, [CellType.VTK_QUAD]: vtkQuad, [CellType.VTK_POLY_LINE]: vtkLine, [CellType.VTK_TRIANGLE]: vtkTriangle, [CellType.VTK_TRIANGLE_STRIP]: vtkTriangleStrip, [CellType.VTK_POLY_LINE]: vtkPolyLine, [CellType.VTK_POLYGON]: vtkPolygon }; // ---------------------------------------------------------------------------- // vtkPolyData methods // ---------------------------------------------------------------------------- function vtkPolyData(publicAPI, model) { // Set our className model.classHierarchy.push('vtkPolyData'); function camelize(str) { return str.replace(/(?:^\w|[A-Z]|\b\w)/g, letter => letter.toUpperCase()).replace(/\s+/g, ''); } function clearCells() { model.cells = undefined; model.links = undefined; } // build empty cell arrays and set methods POLYDATA_FIELDS.forEach(type => { publicAPI[`getNumberOf${camelize(type)}`] = () => model[type].getNumberOfCells(); if (!model[type]) { model[type] = vtkCellArray.newInstance(); } else { model[type] = vtk(model[type]); } model[`_on${camelize(type)}Changed`] = clearCells; }); publicAPI.getNumberOfCells = () => POLYDATA_FIELDS.reduce((num, cellType) => num + model[cellType].getNumberOfCells(), 0); const superShallowCopy = publicAPI.shallowCopy; publicAPI.shallowCopy = (other, debug = false) => { superShallowCopy(other, debug); POLYDATA_FIELDS.forEach(type => { model[type] = vtkCellArray.newInstance(); model[type].shallowCopy(other.getReferenceByName(type)); }); }; const superGetMTime = publicAPI.getMTime; publicAPI.getMTime = () => POLYDATA_FIELDS.reduce((mTime, type) => Math.max(mTime, model[type]?.getMTime() ?? mTime), superGetMTime()); const superInitialize = publicAPI.initialize; publicAPI.initialize = () => { POLYDATA_FIELDS.forEach(type => model[type]?.initialize()); clearCells(); return superInitialize(); }; publicAPI.buildCells = () => { // here are the number of cells we have const nVerts = publicAPI.getNumberOfVerts(); const nLines = publicAPI.getNumberOfLines(); const nPolys = publicAPI.getNumberOfPolys(); const nStrips = publicAPI.getNumberOfStrips(); // pre-allocate the space we need const nCells = nVerts + nLines + nPolys + nStrips; const types = new Uint8Array(nCells); let pTypes = types; const locs = new Uint32Array(nCells); let pLocs = locs; // record locations and type of each cell. // verts if (nVerts) { let nextCellPts = 0; model.verts.getCellSizes().forEach((numCellPts, index) => { pLocs[index] = nextCellPts; pTypes[index] = numCellPts > 1 ? CellType.VTK_POLY_VERTEX : CellType.VTK_VERTEX; nextCellPts += numCellPts + 1; }); pLocs = pLocs.subarray(nVerts); pTypes = pTypes.subarray(nVerts); } // lines if (nLines) { let nextCellPts = 0; model.lines.getCellSizes().forEach((numCellPts, index) => { pLocs[index] = nextCellPts; pTypes[index] = numCellPts > 2 ? CellType.VTK_POLY_LINE : CellType.VTK_LINE; if (numCellPts === 1) { vtkWarningMacro('Building VTK_LINE ', index, ' with only one point, but VTK_LINE needs at least two points. Check the input.'); } nextCellPts += numCellPts + 1; }); pLocs = pLocs.subarray(nLines); pTypes = pTypes.subarray(nLines); } // polys if (nPolys) { let nextCellPts = 0; model.polys.getCellSizes().forEach((numCellPts, index) => { pLocs[index] = nextCellPts; switch (numCellPts) { case 3: pTypes[index] = CellType.VTK_TRIANGLE; break; case 4: pTypes[index] = CellType.VTK_QUAD; break; default: pTypes[index] = CellType.VTK_POLYGON; break; } if (numCellPts < 3) { vtkWarningMacro('Building VTK_TRIANGLE ', index, ' with less than three points, but VTK_TRIANGLE needs at least three points. Check the input.'); } nextCellPts += numCellPts + 1; }); pLocs += pLocs.subarray(nPolys); pTypes += pTypes.subarray(nPolys); } // strips if (nStrips) { let nextCellPts = 0; pTypes.fill(CellType.VTK_TRIANGLE_STRIP, 0, nStrips); model.strips.getCellSizes().forEach((numCellPts, index) => { pLocs[index] = nextCellPts; nextCellPts += numCellPts + 1; }); } // set up the cell types data structure model.cells = vtkCellTypes.newInstance(); model.cells.setCellTypes(nCells, types, locs); }; /** * Create upward links from points to cells that use each point. Enables * topologically complex queries. */ publicAPI.buildLinks = (initialSize = 0) => { if (model.cells == null) { publicAPI.buildCells(); } model.links = vtkCellLinks.newInstance(); if (initialSize > 0) { model.links.allocate(initialSize); } else { model.links.allocate(publicAPI.getPoints().getNumberOfPoints()); } model.links.buildLinks(publicAPI); }; publicAPI.getCellType = cellId => model.cells.getCellType(cellId); publicAPI.getCellPoints = cellId => { const cellType = publicAPI.getCellType(cellId); let cells = null; switch (cellType) { case CellType.VTK_VERTEX: case CellType.VTK_POLY_VERTEX: cells = model.verts; break; case CellType.VTK_LINE: case CellType.VTK_POLY_LINE: cells = model.lines; break; case CellType.VTK_TRIANGLE: case CellType.VTK_QUAD: case CellType.VTK_POLYGON: cells = model.polys; break; case CellType.VTK_TRIANGLE_STRIP: cells = model.strips; break; default: cells = null; return { type: 0, cellPointIds: null }; } const loc = model.cells.getCellLocation(cellId); const cellPointIds = cells.getCell(loc); return { cellType, cellPointIds }; }; publicAPI.getPointCells = ptId => model.links.getCells(ptId); publicAPI.getCellEdgeNeighbors = (cellId, point1, point2) => { const link1 = model.links.getLink(point1); const link2 = model.links.getLink(point2); return link1.cells.filter(cell => cell !== cellId && link2.cells.indexOf(cell) !== -1); }; /** * If you know the type of cell, you may provide it to improve performances. */ publicAPI.getCell = (cellId, cellHint = null) => { const cellInfo = publicAPI.getCellPoints(cellId); const cell = cellHint || CELL_FACTORY[cellInfo.cellType].newInstance(); cell.initialize(publicAPI.getPoints(), cellInfo.cellPointIds); return cell; }; publicAPI.getMaxCellSize = () => POLYDATA_FIELDS.reduce((max, type) => Math.max(max, model[type]?.getMaxCellSize?.() ?? 0), 0); } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = { // verts: null, // lines: null, // polys: null, // strips: null, // cells: null, // links: null, }; // ---------------------------------------------------------------------------- function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); // Inheritance vtkPointSet.extend(publicAPI, model, initialValues); macro.get(publicAPI, model, ['cells', 'links']); macro.setGet(publicAPI, model, ['verts', 'lines', 'polys', 'strips']); // Object specific methods vtkPolyData(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkPolyData'); // ---------------------------------------------------------------------------- var vtkPolyData$1 = { newInstance, extend }; export { CELL_FACTORY, vtkPolyData$1 as default, extend, newInstance };