UNPKG

@cornerstonejs/core

Version:
111 lines (110 loc) 4.58 kB
import vtkMath from '@kitware/vtk.js/Common/Core/Math.js'; import { MPR_CAMERA_VALUES } from '../../../constants/index.js'; import { OrientationAxis } from '../../../enums/index.js'; import { getConfiguration } from '../../../init.js'; import { getCubeSizeInView } from '../../../utilities/getPlaneCubeIntersectionDimensions.js'; import { getVolumeCenterIJK } from '../../Viewport.js'; const VOLUME_3D_RADIUS_MULTIPLIER = 10; export function getInitialVolume3DCamera(ctx, imageVolume) { const imageData = imageVolume.imageData; if (!imageData) { return; } const vtkCamera = ctx.vtk.renderer.getActiveCamera(); const orientation = getOrientationVectors({ fallbackViewPlaneNormal: vtkCamera.getViewPlaneNormal(), fallbackViewUp: vtkCamera.getViewUp(), imageVolume, orientation: ctx.viewport.options.orientation, }); const { viewPlaneNormal, viewUp } = orientation; const bounds = imageData.getBounds(); const focalPoint = [0, 0, 0]; const dimensions = imageData.getDimensions(); const middleIJK = getVolumeCenterIJK(dimensions, imageData.getDirection(), viewPlaneNormal); imageData.indexToWorld(middleIJK, focalPoint); const { widthWorld, heightWorld } = getCubeSizeInView(imageData, viewPlaneNormal, viewUp); const canvasWidth = ctx.vtk.canvas.width || ctx.viewport.element.clientWidth || 1; const canvasHeight = ctx.vtk.canvas.height || ctx.viewport.element.clientHeight || 1; const boundsAspectRatio = widthWorld / heightWorld; const canvasAspectRatio = canvasWidth / canvasHeight; const scaleFactor = boundsAspectRatio / canvasAspectRatio; const insetImageMultiplier = getConfiguration().rendering?.useLegacyCameraFOV ? 1.1 : 1; const parallelScale = scaleFactor < 1 ? (insetImageMultiplier * heightWorld) / 2 : (insetImageMultiplier * heightWorld * scaleFactor) / 2; const radius = getBoundsRadius(bounds) * VOLUME_3D_RADIUS_MULTIPLIER; const distance = insetImageMultiplier * radius; const viewUpToUse = Math.abs(vtkMath.dot(viewUp, viewPlaneNormal)) > 0.999 ? [-viewUp[2], viewUp[0], viewUp[1]] : viewUp; const position = [ focalPoint[0] + distance * viewPlaneNormal[0], focalPoint[1] + distance * viewPlaneNormal[1], focalPoint[2] + distance * viewPlaneNormal[2], ]; if ('setPhysicalScale' in vtkCamera) { vtkCamera.setPhysicalScale(radius); vtkCamera.setPhysicalTranslation(-focalPoint[0], -focalPoint[1], -focalPoint[2]); } return { focalPoint, parallelProjection: ctx.viewport.options.parallelProjection ?? true, parallelScale, position, viewAngle: 90, viewPlaneNormal, viewUp: viewUpToUse, }; } function getOrientationVectors(args) { const { fallbackViewPlaneNormal, fallbackViewUp, imageVolume, orientation } = args; if (!orientation) { return { viewPlaneNormal: fallbackViewPlaneNormal, viewUp: fallbackViewUp, }; } if (typeof orientation === 'object' && orientation.viewPlaneNormal) { return { viewPlaneNormal: [...orientation.viewPlaneNormal], viewUp: orientation.viewUp ? [...orientation.viewUp] : fallbackViewUp, }; } if (orientation === OrientationAxis.ACQUISITION) { const { direction } = imageVolume; return { viewPlaneNormal: direction.slice(6, 9).map((x) => -x), viewUp: direction.slice(3, 6).map((x) => -x), }; } const cameraValues = orientation === OrientationAxis.AXIAL_REFORMAT ? MPR_CAMERA_VALUES.axial : orientation === OrientationAxis.SAGITTAL_REFORMAT ? MPR_CAMERA_VALUES.sagittal : orientation === OrientationAxis.CORONAL_REFORMAT ? MPR_CAMERA_VALUES.coronal : typeof orientation === 'string' ? MPR_CAMERA_VALUES[orientation] : undefined; if (!cameraValues) { return { viewPlaneNormal: fallbackViewPlaneNormal, viewUp: fallbackViewUp, }; } return { viewPlaneNormal: [...cameraValues.viewPlaneNormal], viewUp: [...cameraValues.viewUp], }; } function getBoundsRadius(bounds) { const width = (bounds[1] - bounds[0]) ** 2; const height = (bounds[3] - bounds[2]) ** 2; const depth = (bounds[5] - bounds[4]) ** 2; return Math.sqrt(width + height + depth || 1) * 0.5; }