import macro from 'vtk.js/Sources/macros'; import vtkPlane from 'vtk.js/Sources/Common/DataModel/Plane';
import vtkAbstractManipulator from 'vtk.js/Sources/Widgets/Manipulators/AbstractManipulator'; import { mat3, mat4, vec3 } from 'gl-matrix';
export function intersectDisplayWithPlane( x, y, planeOrigin, planeNormal, renderer, glRenderWindow ) { const near = glRenderWindow.displayToWorld(x, y, 0, renderer); const far = glRenderWindow.displayToWorld(x, y, 1, renderer);
return vtkPlane.intersectWithLine(near, far, planeOrigin, planeNormal).x; }
function vtkCPRManipulator(publicAPI, model) { model.classHierarchy.push('vtkCPRManipulator');
publicAPI.handleEvent = (callData, glRenderWindow) => { const mapper = model.cprActor?.getMapper(); if (!mapper) { return model._addWorldDeltas({ worldCoords: null }); }
const cprActorMatrix = []; mat4.transpose(cprActorMatrix, model.cprActor.getMatrix());
const worldPlaneNormal = cprActorMatrix.slice(8, 11); const worldPlaneOrigin = cprActorMatrix.slice(12, 15);
const inversecprActorMatrix = []; mat4.invert(inversecprActorMatrix, cprActorMatrix); const worldPlanePicking = intersectDisplayWithPlane( callData.position.x, callData.position.y, worldPlaneOrigin, worldPlaneNormal, callData.pokedRenderer, glRenderWindow ); const modelPlanePicking = []; vec3.transformMat4( modelPlanePicking, worldPlanePicking, inversecprActorMatrix ); const height = mapper.getHeight(); const distance = height - modelPlanePicking[1];
return model._addWorldDeltas(publicAPI.distanceEvent(distance)); };
publicAPI.distanceEvent = (distance) => { const mapper = model.cprActor?.getMapper(); if (!mapper) { return { worldCoords: null }; } const height = mapper.getHeight(); const clampedDistance = Math.max(0, Math.min(height, distance)); const { position, orientation } = mapper.getCenterlinePositionAndOrientation(clampedDistance);
let worldDirection; if (orientation) { const modelDirections = mat3.fromQuat([], orientation); const baseDirections = mapper.getDirectionMatrix(); worldDirection = mat3.mul([], modelDirections, baseDirections); }
model.currentDistance = clampedDistance; return { worldCoords: position, worldDirection }; };
publicAPI.handleScroll = (nbSteps) => { const distance = model.currentDistance + publicAPI.getDistanceStep() * nbSteps; return publicAPI.distanceEvent(distance); };
publicAPI.getDistanceStep = () => { if (!model.distanceStep) { const imageSpacing = model.cprActor ?.getMapper() ?.getInputData(0) ?.getSpacing?.(); if (imageSpacing) { return Math.min(...imageSpacing); } } return model.distanceStep; }; }
function defaultValues(initialValues) { return { distanceStep: 0, currentDistance: 0, cprActor: null, ...initialValues, }; }
export function extend(publicAPI, model, initialValues = {}) { vtkAbstractManipulator.extend(publicAPI, model, defaultValues(initialValues));
macro.setGet(publicAPI, model, ['distance', 'currentDistance', 'cprActor']); macro.set(publicAPI, model, ['distanceStep']);
vtkCPRManipulator(publicAPI, model); }
export const newInstance = macro.newInstance(extend, 'vtkCPRManipulator');
export default { intersectDisplayWithPlane, extend, newInstance };
|