All files / packages/core/src/utilities snapFocalPointToSlice.ts

88.23% Statements 15/17
50% Branches 2/4
100% Functions 1/1
88.23% Lines 15/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                                                    1x     1x   1x     1x     1x 1x 1x     1x                   1x     1x   1x         1x   1x           1x           1x    
import { vec3 } from 'gl-matrix';
import { ActorSliceRange, Point3 } from '../types';
 
/**
 * Given a number of frames, `deltaFrames`,
 * move the `focalPoint` and camera `position` so that it moves forward/backwards
 * `deltaFrames` in the camera's normal direction, and snaps to the nearest frame.
 *
 * @param focalPoint - The focal point to move.
 * @param position - The camera position to move.
 * @param sliceRange - The scroll range used to find the current
 * position in the stack, as well as prevent scrolling past the extent of the volume.
 * @param viewPlaneNormal - The normal direction of the camera.
 * @param spacingInNormalDirection - The spacing of frames the normal direction of the camera.
 * @param deltaFrames - The number of frames to jump.
 *
 * @returns The `newFocalPoint` and `newPosition` of the camera.
 */
export default function snapFocalPointToSlice(
  focalPoint: Point3,
  position: Point3,
  sliceRange: ActorSliceRange,
  viewPlaneNormal: Point3,
  spacingInNormalDirection: number,
  deltaFrames: number
): { newFocalPoint: Point3; newPosition: Point3 } {
  const { min, max, current } = sliceRange;
 
  // Get the current offset off the camera position so we can add it on at the end.
  const posDiffFromFocalPoint = vec3.create();
 
  vec3.sub(posDiffFromFocalPoint, <vec3>position, <vec3>focalPoint);
 
  // Now we can see how many steps there are in this direction
  const steps = Math.round((max - min) / spacingInNormalDirection);
 
  // Find out current frameIndex
  const fraction = (current - min) / (max - min);
  const floatingStepNumber = fraction * steps;
  let frameIndex = Math.round(floatingStepNumber);
 
  // Dolly the focal point back to min slice focal point.
  let newFocalPoint = <Point3>[
    focalPoint[0] -
      viewPlaneNormal[0] * floatingStepNumber * spacingInNormalDirection,
    focalPoint[1] -
      viewPlaneNormal[1] * floatingStepNumber * spacingInNormalDirection,
    focalPoint[2] -
      viewPlaneNormal[2] * floatingStepNumber * spacingInNormalDirection,
  ];
 
  // Increment the slice number by deltaFrames.
  frameIndex += deltaFrames;
 
  // Clamp sliceNumber to volume.
  Iif (frameIndex > steps) {
    frameIndex = steps;
  } else Iif (frameIndex < 0) {
    frameIndex = 0;
  }
 
  // Dolly the focal towards to the correct frame focal point.
  const newSlicePosFromMin = frameIndex * spacingInNormalDirection;
 
  newFocalPoint = <Point3>[
    newFocalPoint[0] + viewPlaneNormal[0] * newSlicePosFromMin,
    newFocalPoint[1] + viewPlaneNormal[1] * newSlicePosFromMin,
    newFocalPoint[2] + viewPlaneNormal[2] * newSlicePosFromMin,
  ];
 
  const newPosition = <Point3>[
    newFocalPoint[0] + posDiffFromFocalPoint[0],
    newFocalPoint[1] + posDiffFromFocalPoint[1],
    newFocalPoint[2] + posDiffFromFocalPoint[2],
  ];
 
  return { newFocalPoint, newPosition };
}