All files / core/src/utilities getCurrentVolumeViewportSlice.ts

0% Statements 0/19
0% Branches 0/4
0% Functions 0/1
0% Lines 0/19

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                                                                                                                                                 
import { glMatrix, vec3 } from 'gl-matrix';
import type { IVolumeViewport } from '../types';
import { transformCanvasToIJK } from './transformCanvasToIJK';
 
/**
 * Get the image data for the current slice rendered on the viewport. The image
 * data returned is the full slice and not only the region that is visible on
 * the viewport. It does not work for oblique views.
 * @param viewport - Volume viewport
 * @returns Slice image data and  matrices to convert from volume
 *   to slice and vice-versa
 */
function getCurrentVolumeViewportSlice(viewport: IVolumeViewport) {
  const { width: canvasWidth, height: canvasHeight } = viewport.getCanvas();
 
  const { sliceToIndexMatrix, indexToSliceMatrix } =
    viewport.getSliceViewInfo();
  // Get three points from the canvas to help us identify the orientation of
  // the slice. Using canvas width/height to get point far away for each other
  // because points such as (0,0), (1,0) and (0,1) may be converted to the same
  // ijk index when the image is zoomed in.
  const ijkOriginPoint = transformCanvasToIJK(viewport, [0, 0]);
  const ijkRowPoint = transformCanvasToIJK(viewport, [canvasWidth - 1, 0]);
  const ijkColPoint = transformCanvasToIJK(viewport, [0, canvasHeight - 1]);
 
  // Subtract the points to get the row and column vectors in index space
  const ijkRowVec = vec3.sub(vec3.create(), ijkRowPoint, ijkOriginPoint);
  const ijkColVec = vec3.sub(vec3.create(), ijkColPoint, ijkOriginPoint);
  const ijkSliceVec = vec3.cross(vec3.create(), ijkRowVec, ijkColVec);
 
  vec3.normalize(ijkRowVec, ijkRowVec);
  vec3.normalize(ijkColVec, ijkColVec);
  vec3.normalize(ijkSliceVec, ijkSliceVec);
 
  // Any unit vector parallel to IJK have one component equal to 1 and
  // the other two components equal to 0. If two of them are parallel
  // the third one is also parallel
  const maxIJKRowVec = Math.max(
    Math.abs(ijkRowVec[0]),
    Math.abs(ijkRowVec[1]),
    Math.abs(ijkRowVec[2])
  );
  const maxIJKColVec = Math.max(
    Math.abs(ijkColVec[0]),
    Math.abs(ijkColVec[1]),
    Math.abs(ijkColVec[2])
  );
 
  // Using glMatrix.equals() because the number may be not exactly equal to
  // 1 due to rounding issues
  if (!glMatrix.equals(1, maxIJKRowVec) || !glMatrix.equals(1, maxIJKColVec)) {
    throw new Error('Livewire is not available for rotate/oblique viewports');
  }
 
  const { voxelManager } = viewport.getImageData();
 
  const sliceViewInfo = viewport.getSliceViewInfo();
  const scalarData = voxelManager.getSliceData(sliceViewInfo);
 
  return {
    width: sliceViewInfo.width,
    height: sliceViewInfo.height,
    scalarData,
    sliceToIndexMatrix,
    indexToSliceMatrix,
  };
}
 
export {
  getCurrentVolumeViewportSlice as default,
  getCurrentVolumeViewportSlice,
};