UNPKG

@kitware/vtk.js

Version:

Visualization Toolkit for the Web

220 lines (200 loc) 6.48 kB
import { m as macro } from '../../macros2.js'; import vtkBoundingBox from './BoundingBox.js'; import vtkImplicitFunction from './ImplicitFunction.js'; // ---------------------------------------------------------------------------- // Global methods // ---------------------------------------------------------------------------- //------------------------------------------------------------------------------ // Bounding box intersection code from David Gobbi. Go through the // bounding planes one at a time and compute the parametric coordinate // of each intersection and return the parametric values and the calculated points function intersectWithLine(bounds, p1, p2) { let plane1 = -1; let plane2 = -1; let t1 = 0.0; let t2 = 1.0; for (let j = 0; j < 3; j++) { for (let k = 0; k < 2; k++) { // Compute distances of p1 and p2 from the plane along the plane normal const i = 2 * j + k; const d1 = (bounds[i] - p1[j]) * (1 - 2 * k); const d2 = (bounds[i] - p2[j]) * (1 - 2 * k); // If both distances are positive, both points are outside if (d1 > 0 && d2 > 0) { return; } // If one of the distances is positive, the line crosses the plane if (d1 > 0 || d2 > 0) { // Compute fractional distance "t" of the crossing between p1 & p2 let t = 0.0; if (d1 !== 0) { t = d1 / (d1 - d2); } // If point p1 was clipped, adjust t1 if (d1 > 0) { if (t >= t1) { t1 = t; plane1 = i; } } // else point p2 was clipped, so adjust t2 else if (t <= t2) { t2 = t; plane2 = i; } // If this happens, there's no line left if (t1 > t2) { // Allow for planes that are coincident or slightly inverted if (plane1 < 0 || plane2 < 0) { return; } } } } } function getValues(plane, t) { const x = [0, 0, 0]; for (let count = 0; count < 2; count++) { for (let i = 0; i < 3; i++) { if (plane === 2 * i || plane === 2 * i + 1) { x[i] = bounds[plane]; } else { x[i] = p1[i] * (1.0 - t) + p2[i] * t; if (x[i] < bounds[2 * i]) { x[i] = bounds[2 * i]; } if (x[i] > bounds[2 * i + 1]) { x[i] = bounds[2 * i + 1]; } } } } return x; } const x1 = getValues(plane1, t1); const x2 = getValues(plane2, t2); const outObject = { t1, t2, x1, x2 }; // eslint-disable-next-line consistent-return return outObject; } // ---------------------------------------------------------------------------- // Static API // ---------------------------------------------------------------------------- const STATIC = {}; // ---------------------------------------------------------------------------- // vtkBox methods // ---------------------------------------------------------------------------- function vtkBox(publicAPI, model) { // Set our className model.classHierarchy.push('vtkBox'); // TODO: replace with macro.setArray ? publicAPI.setBounds = (...bounds) => { let boundsArray = []; if (Array.isArray(bounds[0])) { boundsArray = bounds[0]; } else { for (let i = 0; i < bounds.length; i++) { boundsArray.push(bounds[i]); } } if (boundsArray.length !== 6) { console.log('vtkBox.setBounds', boundsArray, bounds); return; } vtkBoundingBox.setBounds(model.bbox, boundsArray); }; publicAPI.getBounds = () => [...model.bbox]; publicAPI.evaluateFunction = (x, y, z) => { const point = Array.isArray(x) ? x : [x, y, z]; let diff; let dist; let t; let minDistance = -Number.MAX_VALUE; let distance = 0; const minPoint = vtkBoundingBox.getMinPoint(model.bbox); const maxPoint = vtkBoundingBox.getMaxPoint(model.bbox); let inside = 1; for (let i = 0; i < 3; i++) { diff = vtkBoundingBox.getLength(model.bbox, i); if (diff !== 0.0) { t = (point[i] - minPoint[i]) / diff; if (t < 0.0) { inside = 0; dist = minPoint[i] - point[i]; } else if (t > 1.0) { inside = 0; dist = point[i] - maxPoint[i]; } else { // want negative distance, we are inside if (t <= 0.5) { dist = minPoint[i] - point[i]; } else { dist = point[i] - maxPoint[i]; } if (dist > minDistance) { // remember, it's negative minDistance = dist; } } // end if inside } else { dist = Math.abs(point[i] - minPoint[i]); if (dist > 0.0) { inside = 0; } } if (dist > 0.0) { distance += dist * dist; } } // end for i distance = Math.sqrt(distance); if (inside) { return minDistance; } return distance; }; publicAPI.addBounds = (...bounds) => { let boundsArray = []; if (Array.isArray(bounds[0])) { boundsArray = bounds[0]; } else { for (let i = 0; i < bounds.length; i++) { boundsArray.push(bounds[i]); } } if (boundsArray.length !== 6) { return; } vtkBoundingBox.addBounds(model.bbox, ...boundsArray); publicAPI.modified(); }; publicAPI.addBox = other => publicAPI.addBounds(other.getBounds()); publicAPI.intersectWithLine = (p1, p2) => intersectWithLine(model.bbox, p1, p2); } // ---------------------------------------------------------------------------- // Object factory // ---------------------------------------------------------------------------- const DEFAULT_VALUES = { bbox: [...vtkBoundingBox.INIT_BOUNDS] }; // ---------------------------------------------------------------------------- function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues); // Object methods vtkImplicitFunction.extend(publicAPI, model, initialValues); vtkBox(publicAPI, model); } // ---------------------------------------------------------------------------- const newInstance = macro.newInstance(extend, 'vtkBox'); // ---------------------------------------------------------------------------- var vtkBox$1 = { newInstance, extend, intersectWithLine, ...STATIC }; export { STATIC, vtkBox$1 as default, extend, intersectWithLine, newInstance };