All files / packages/tools/src/utilities/math/polyline getSubPixelSpacingAndXYDirections.ts

4.25% Statements 2/47
0% Branches 0/14
0% Functions 0/1
4.54% Lines 2/44

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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100        1x                           1x                                                                                                                                                                  
import { StackViewport } from '@cornerstonejs/core';
import type { Types } from '@cornerstonejs/core';
import { vec3 } from 'gl-matrix';
 
const EPSILON = 1e-3;
 
/**
 * Gets the desired spacing for points in the polyline for the
 * `PlanarFreehandROITool` in the x and y canvas directions, as well as
 * returning these canvas directions in world space.
 *
 * @param viewport - The Cornerstone3D `StackViewport` or `VolumeViewport`.
 * @param subPixelResolution - The number to divide the image pixel spacing by
 * to get the sub pixel spacing. E.g. `10` will return spacings 10x smaller than
 * the native image spacing.
 * @returns The spacings of the X and Y directions, and the 3D directions of the
 * x and y directions.
 */
const getSubPixelSpacingAndXYDirections = (
  viewport: Types.IStackViewport | Types.IVolumeViewport,
  subPixelResolution: number
): { spacing: Types.Point2; xDir: Types.Point3; yDir: Types.Point3 } => {
  let spacing;
  let xDir;
  let yDir;
 
  if (viewport instanceof StackViewport) {
    // Check XY directions
    const imageData = viewport.getImageData();
 
    xDir = imageData.direction.slice(0, 3);
    yDir = imageData.direction.slice(3, 6);
 
    spacing = imageData.spacing;
  } else {
    // Check volume directions
    const imageData = viewport.getImageData();
    const { direction, spacing: volumeSpacing } = imageData;
    const { viewPlaneNormal, viewUp } = viewport.getCamera();
 
    // Calculate size of spacing vector in normal direction
    const iVector = direction.slice(0, 3) as Types.Point3;
    const jVector = direction.slice(3, 6) as Types.Point3;
    const kVector = direction.slice(6, 9) as Types.Point3;
 
    const viewRight = vec3.create(); // Get the X direction of the viewport
 
    vec3.cross(viewRight, <vec3>viewUp, <vec3>viewPlaneNormal);
 
    const absViewRightDotI = Math.abs(vec3.dot(viewRight, iVector));
    const absViewRightDotJ = Math.abs(vec3.dot(viewRight, jVector));
    const absViewRightDotK = Math.abs(vec3.dot(viewRight, kVector));
 
    // Get X spacing
    let xSpacing;
    if (Math.abs(1 - absViewRightDotI) < EPSILON) {
      xSpacing = volumeSpacing[0];
      xDir = iVector;
    } else if (Math.abs(1 - absViewRightDotJ) < EPSILON) {
      xSpacing = volumeSpacing[1];
      xDir = jVector;
    } else if (Math.abs(1 - absViewRightDotK) < EPSILON) {
      xSpacing = volumeSpacing[2];
      xDir = kVector;
    } else {
      throw new Error('No support yet for oblique plane planar contours');
    }
 
    const absViewPlaneNormalDotI = Math.abs(vec3.dot(viewPlaneNormal, iVector));
    const absViewPlaneNormalDotJ = Math.abs(vec3.dot(viewPlaneNormal, jVector));
    const absViewPlaneNormalDotK = Math.abs(vec3.dot(viewPlaneNormal, kVector));
 
    // Get Y spacing
    let ySpacing;
    if (Math.abs(1 - absViewPlaneNormalDotI) < EPSILON) {
      ySpacing = volumeSpacing[0];
      yDir = iVector;
    } else if (Math.abs(1 - absViewPlaneNormalDotJ) < EPSILON) {
      ySpacing = volumeSpacing[1];
      yDir = jVector;
    } else if (Math.abs(1 - absViewPlaneNormalDotK) < EPSILON) {
      ySpacing = volumeSpacing[2];
      yDir = kVector;
    } else {
      throw new Error('No support yet for oblique plane planar contours');
    }
 
    spacing = [xSpacing, ySpacing];
  }
 
  const subPixelSpacing: Types.Point2 = [
    spacing[0] / subPixelResolution,
    spacing[1] / subPixelResolution,
  ];
 
  return { spacing: subPixelSpacing, xDir, yDir };
};
 
export default getSubPixelSpacingAndXYDirections;