import vtkCompositeCameraManipulator from 'vtk.js/Sources/Interaction/Manipulators/CompositeCameraManipulator'; import vtkCompositeMouseManipulator from 'vtk.js/Sources/Interaction/Manipulators/CompositeMouseManipulator'; import vtkInteractorStyleConstants from 'vtk.js/Sources/Rendering/Core/InteractorStyle/Constants'; import vtkMouseCameraUnicamRotateManipulator from 'vtk.js/Sources/Interaction/Manipulators/MouseCameraUnicamRotateManipulator';
import macro from 'vtk.js/Sources/macros'; import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
const { States } = vtkInteractorStyleConstants;
function vtkMouseCameraUnicamManipulator(publicAPI, model) { model.classHierarchy.push('vtkMouseCameraUnicamManipulator');
model.state = States.IS_NONE;
model.rotateManipulator = vtkMouseCameraUnicamRotateManipulator.newInstance({ button: model.button, shift: model.shift, control: model.control, alt: model.alt, dragEnabled: model.dragEnabled, scrollEnabled: model.scrollEnabled, displayFocusSphereOnButtonDown: false, });
const normalize = (position, interactor) => { const renderer = interactor.findPokedRenderer(); const [width, height] = interactor.getView().getViewportSize(renderer);
const nx = -1.0 + (2.0 * position.x) / width; const ny = -1.0 + (2.0 * position.y) / height;
return { x: nx, y: ny }; };
const getRightVAndUpV = (downPoint, interactor) => { const camera = interactor.findPokedRenderer().getActiveCamera(); const cameraPosition = camera.getPosition(); const cameraToPointVec = [0, 0, 0];
vtkMath.subtract(downPoint, cameraPosition, cameraToPointVec); if (camera.getParallelProjection()) { vtkMath.multiplyScalar(cameraToPointVec, camera.getParallelScale()); }
const atV = camera.getViewPlaneNormal(); vtkMath.normalize(atV); const l = vtkMath.dot(cameraToPointVec, atV); const viewAngle = vtkMath.radiansFromDegrees(camera.getViewAngle()); const renderer = interactor.findPokedRenderer(); const [width, height] = interactor.getView().getViewportSize(renderer);
const scaleX = (width / height) * ((2 * l * Math.tan(viewAngle / 2)) / 2); const scaleY = (2 * l * Math.tan(viewAngle / 2)) / 2;
const upV = camera.getViewUp(); const rightV = []; vtkMath.cross(upV, atV, rightV); vtkMath.cross(atV, rightV, upV); vtkMath.normalize(rightV); vtkMath.normalize(upV);
vtkMath.multiplyScalar(rightV, scaleX); vtkMath.multiplyScalar(upV, scaleY);
return { rightV, upV }; };
const choose = (interactor, position) => { const normalizedPosition = normalize(position, interactor); const normalizedPreviousPosition = normalize( model.previousPosition, interactor ); const delta = { x: normalizedPosition.x - normalizedPreviousPosition.x, y: normalizedPosition.y - normalizedPreviousPosition.y, }; model.previousPosition = position;
const deltaT = Date.now() / 1000 - model.time; model.dist += Math.sqrt(delta.x ** 2 + delta.y ** 2); const sDelta = { x: position.x - model.startPosition.x, y: position.y - model.startPosition.y, }; const len = Math.sqrt(sDelta.x ** 2 + sDelta.y ** 2); if (Math.abs(sDelta.y) / len > 0.9 && deltaT > 0.05) { model.state = States.IS_DOLLY; } else if (deltaT >= 0.1 || model.dist >= 0.03) { if (Math.abs(sDelta.x) / len > 0.6) { model.state = States.IS_PAN; } else { model.state = States.IS_DOLLY; } } };
const pan = (interactor, position) => { const renderer = interactor.findPokedRenderer(); const normalizedPosition = normalize(position, interactor); const normalizedPreviousPosition = normalize( model.previousPosition, interactor );
const delta = { x: normalizedPosition.x - normalizedPreviousPosition.x, y: normalizedPosition.y - normalizedPreviousPosition.y, };
const camera = renderer.getActiveCamera();
model.previousPosition = position;
const { rightV, upV } = getRightVAndUpV(model.downPoint, interactor); const offset = [];
for (let index = 0; index < 3; index++) { offset[index] = delta.x * rightV[index] + delta.y * upV[index]; }
camera.translate(...offset);
renderer.resetCameraClippingRange(); interactor.render(); };
const dolly = (interactor, position) => { const renderer = interactor.findPokedRenderer(); const normalizedPosition = normalize(position, interactor); const normalizedPreviousPosition = normalize( model.previousPosition, interactor );
const delta = { x: normalizedPosition.x - normalizedPreviousPosition.x, y: normalizedPosition.y - normalizedPreviousPosition.y, };
const camera = renderer.getActiveCamera(); const cameraPosition = camera.getPosition();
if (camera.getParallelProjection()) { camera.zoom(1 - delta.y); } else { const offset1 = []; vtkMath.subtract(model.downPoint, cameraPosition, offset1); vtkMath.multiplyScalar(offset1, delta.y * -4);
camera.translate(...offset1); }
const { rightV: offset2 } = getRightVAndUpV(model.downPoint, interactor);
vtkMath.multiplyScalar(offset2, delta.x);
camera.translate(...offset2);
renderer.resetCameraClippingRange(); interactor.render(); };
publicAPI.onButtonDown = (interactor, renderer, position) => { model.buttonPressed = true; model.startPosition = position; model.previousPosition = position; model.time = Date.now() / 1000.0; model.dist = 0;
model.rotateManipulator.onButtonDown(interactor, renderer, position);
model.downPoint = model.rotateManipulator.getDownPoint(); };
publicAPI.onMouseMove = (interactor, renderer, position) => { if (!model.buttonPressed) { return; }
if (model.rotateManipulator.getState() === States.IS_ROTATE) { model.rotateManipulator.onMouseMove(interactor, renderer, position); } else { switch (model.state) { case States.IS_NONE: choose(interactor, position); break; case States.IS_PAN: pan(interactor, position); break; case States.IS_DOLLY: dolly(interactor, position); break; default: break; } }
model.previousPosition = position; };
publicAPI.onButtonUp = (interactor) => { model.buttonPressed = false; if (model.state === States.IS_NONE) { model.rotateManipulator.onButtonUp(interactor); } model.state = States.IS_NONE; };
publicAPI.getUseWorldUpVec = () => model.rotateManipulator.getUseWorldUpVec(); publicAPI.setUseWorldUpVec = (useWorldUpVec) => { model.rotateManipulator.setUseWorldUpVec(useWorldUpVec); }; publicAPI.getWorldUpVec = () => model.rotateManipulator.getWorldUpVec(); publicAPI.setWorldUpVec = (x, y, z) => { model.rotateManipulator.setWorldUpVec(x, y, z); }; publicAPI.getUseHardwareSelector = () => model.rotateManipulator.getUseHardwareSelector(); publicAPI.setUseHardwareSelector = (useHardwareSelector) => { model.rotateManipulator.setUseHardwareSelector(useHardwareSelector); }; publicAPI.getFocusSphereColor = () => { model.rotateManipulator.getFocusSphereColor(); }; publicAPI.setFocusSphereColor = (r, g, b) => { model.rotateManipulator.setFocusSphereColor(r, g, b); }; publicAPI.getFocusSphereRadiusFactor = () => model.rotateManipulator.getFocusSphereRadiusFactor(); publicAPI.setFocusSphereRadiusFactor = (focusSphereRadiusFactor) => { model.rotateManipulator.setFocusSphereRadiusFactor(focusSphereRadiusFactor); }; }
const DEFAULT_VALUES = {};
export function extend(publicAPI, model, initialValues = {}) { Object.assign(model, DEFAULT_VALUES, initialValues);
macro.obj(publicAPI, model); vtkCompositeCameraManipulator.extend(publicAPI, model, initialValues); vtkCompositeMouseManipulator.extend(publicAPI, model, initialValues);
vtkMouseCameraUnicamManipulator(publicAPI, model); }
export const newInstance = macro.newInstance( extend, 'vtkMouseCameraUnicamManipulator' );
export default { newInstance, extend };
|