UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

248 lines (217 loc) 7.64 kB
import { m as macro } from '../../macros2.js'; import { b as vtkMath } from '../../Common/Core/Math/index.js'; import vtkCellArray from '../../Common/Core/CellArray.js'; import vtkPoints from '../../Common/Core/Points.js'; import vtkPolyData from '../../Common/DataModel/PolyData.js'; import { DesiredOutputPrecision } from '../../Common/DataModel/DataSetAttributes/Constants.js'; import { VtkDataTypes } from '../../Common/Core/DataArray/Constants.js'; const { vtkErrorMacro } = macro; // ---------------------------------------------------------------------------- // vtkFrustumSource methods // ---------------------------------------------------------------------------- function vtkFrustumSource(publicAPI, model) { // Set our className model.classHierarchy.push('vtkFrustumSource'); function computePoint(planeIndices, pt) { // Get planes and their normals/origins const plane0 = model.planes.getPlane(planeIndices[0]); const n0 = plane0.getNormal(); const p0 = plane0.getOrigin(); const plane1 = model.planes.getPlane(planeIndices[1]); const n1 = plane1.getNormal(); const p1 = plane1.getOrigin(); const plane2 = model.planes.getPlane(planeIndices[2]); const n2 = plane2.getNormal(); const p2 = plane2.getOrigin(); // Dot products const d0 = vtkMath.dot(p0, n0); const d1 = vtkMath.dot(p1, n1); const d2 = vtkMath.dot(p2, n2); // Cross products const c12 = [0, 0, 0]; vtkMath.cross(n1, n2, c12); const c20 = [0, 0, 0]; vtkMath.cross(n2, n0, c20); const c01 = [0, 0, 0]; vtkMath.cross(n0, n1, c01); // Determinant const d = vtkMath.determinant3x3([...n0, ...n1, ...n2]); // Intersection point for (let i = 0; i < 3; ++i) { pt[i] = (d0 * c12[i] + d1 * c20[i] + d2 * c01[i]) / d; } } publicAPI.requestData = (inData, outData) => { const output = outData[0] || vtkPolyData.newInstance(); if (!model.planes || model.planes.getNumberOfPlanes() !== 6) { vtkErrorMacro('vtkFrustum requires 6 planes.'); return; } let nbPts = 8; let leftRightNull = false; let bottomTopNull = false; let parallelFrustum = false; // angle between left and right planes const n0 = model.planes.getPlane(0).getNormal().slice(); const n1 = model.planes.getPlane(1).getNormal().slice(); const c = [0, 0, 0]; vtkMath.normalize(n0); vtkMath.normalize(n1); vtkMath.dot(n0, n1); vtkMath.cross(n0, n1, c); vtkMath.norm(c); // angle between bottom and top planes n0.splice(0, 3, ...model.planes.getPlane(2).getNormal()); n1.splice(0, 3, ...model.planes.getPlane(3).getNormal()); vtkMath.normalize(n0); vtkMath.normalize(n1); vtkMath.dot(n0, n1); vtkMath.cross(n0, n1, c); vtkMath.norm(c); if (model.showLines) { const left = model.planes.getPlane(0).getNormal(); const right = model.planes.getPlane(1).getNormal(); const bottom = model.planes.getPlane(2).getNormal(); const top = model.planes.getPlane(3).getNormal(); const leftRight = [0, 0, 0]; vtkMath.cross(left, right, leftRight); leftRightNull = leftRight[0] === 0.0 && leftRight[1] === 0.0 && leftRight[2] === 0.0; const bottomTop = [0, 0, 0]; vtkMath.cross(bottom, top, bottomTop); bottomTopNull = bottomTop[0] === 0.0 && bottomTop[1] === 0.0 && bottomTop[2] === 0.0; parallelFrustum = leftRightNull && bottomTopNull; if (parallelFrustum) { // start at near points, just add the 4 extra far points. nbPts += 4; } else if (leftRightNull || bottomTopNull) { // two extra starting points, and 4 extra far points. nbPts += 6; } else { // there is an apex, and 4 extra far points nbPts += 5; } } let pointType = 0; if (model.outputPointsPrecision === DesiredOutputPrecision.SINGLE) { pointType = VtkDataTypes.FLOAT; } else if (model.outputPointsPrecision === DesiredOutputPrecision.DOUBLE) { pointType = VtkDataTypes.DOUBLE; } const newPoints = vtkPoints.newInstance({ dataType: pointType }); newPoints.setNumberOfPoints(nbPts); const pt = [0.0, 0.0, 0.0]; const planes = [0, 0, 0]; planes[0] = 0; // left planes[1] = 2; // bottom planes[2] = 5; // near computePoint(planes, pt); newPoints.setPoint(0, ...pt); planes[0] = 1; computePoint(planes, pt); newPoints.setPoint(1, ...pt); planes[1] = 3; computePoint(planes, pt); newPoints.setPoint(2, ...pt); planes[0] = 0; computePoint(planes, pt); newPoints.setPoint(3, ...pt); planes[1] = 2; planes[2] = 4; // far computePoint(planes, pt); newPoints.setPoint(4, ...pt); planes[0] = 1; computePoint(planes, pt); newPoints.setPoint(5, ...pt); planes[1] = 3; computePoint(planes, pt); newPoints.setPoint(6, ...pt); planes[0] = 0; computePoint(planes, pt); newPoints.setPoint(7, ...pt); const numPolys = 6; const newPolys = vtkCellArray.newInstance(); newPolys.allocate(numPolys * 5); // left newPolys.insertNextCell([4, 0, 3, 7]); // right newPolys.insertNextCell([1, 5, 6, 2]); // bottom newPolys.insertNextCell([0, 4, 5, 1]); // top newPolys.insertNextCell([3, 2, 6, 7]); // near newPolys.insertNextCell([0, 1, 2, 3]); // far newPolys.insertNextCell([4, 7, 6, 5]); let newLines = null; if (model.showLines) { const numLines = 4; newLines = vtkCellArray.newInstance(); newLines.allocate(numLines * 3); const pts = [12, 8]; // apex, or first of the two extra near points. // line from lower-left corner if (parallelFrustum) { pts[0] = 0; } newLines.insertNextCell(pts); // line from lower-right corner if (parallelFrustum) { pts[0]++; } else if (leftRightNull) { pts[0] = 13; } pts[1]++; newLines.insertNextCell(pts); // line from upper-right corner if (parallelFrustum) { pts[0]++; } else if (bottomTopNull) { pts[0] = 13; } pts[1]++; newLines.insertNextCell(pts); // line from upper-left corner if (parallelFrustum) { pts[0]++; } else if (leftRightNull) { pts[0] = 12; } pts[1]++; newLines.insertNextCell(pts); output.setLines(newLines); } output.setPoints(newPoints); output.setPolys(newPolys); outData[0] = output; }; } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = { planes: null, showLines: true, outputPointsPrecision: DesiredOutputPrecision.DEFAULT }; // ---------------------------------------------------------------------------- function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); // Build VTK API macro.obj(publicAPI, model); // Also make it an algorithm with no input and one output macro.algo(publicAPI, model, 0, 1); macro.setGet(publicAPI, model, ['showLines', 'outputPointsPrecision', 'planes']); vtkFrustumSource(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkFrustumSource'); // ---------------------------------------------------------------------------- var index = { newInstance, extend }; export { index as default, extend, newInstance };