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 | 67x 67x | import { vec3 } from 'gl-matrix';
import { Enums } from '@cornerstonejs/core';
import OrientationAxis = Enums.OrientationAxis;
export const isReferenceViewable = (servicesManager, viewportId, reference, viewportOptions?) => {
const { cornerstoneViewportService, displaySetService } = servicesManager.services;
Iif (!viewportOptions) {
const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
// we can make a customization for this to allow specific settings
// The annotation can be seen either via navigation or by changing to a volume
const isViewable = viewport.isReferenceViewable(reference, {
withNavigation: true,
asVolume: true,
});
return isViewable;
}
Iif (viewportOptions.viewportType === 'stack') {
// we only need the viewport to include the referenced imageId
const displaySet = displaySetService.getDisplaySetByUID(reference.displaySetInstanceUID);
const imageIds = displaySet.instances.map(instance => instance.imageId);
return imageIds.includes(reference.referencedImageId);
}
// for the volume viewports, we need to check orientation
const { orientation } = viewportOptions;
// Todo: handle hanging protocols that have acquisition orientation
const closestOrientation = getClosestOrientationFromIOP(
displaySetService,
reference.displaySetInstanceUID
);
return closestOrientation === orientation;
};
/**
* Get the plane (orientation) to which the ImageOrientationPatient is most closely aligned
*
* @param displaySetService
* @param displaySetInstanceUID
* @returns orientation
*/
export default function getClosestOrientationFromIOP(
displaySetService,
displaySetInstanceUID
): OrientationAxis {
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
const imageOrientationPatient = displaySet.instances[0].ImageOrientationPatient as Array<number>;
// ImageOrientationPatient must be an array of length 6.
Iif (imageOrientationPatient?.length !== 6) {
return;
}
// Take cross product to get vector coming "out" of image plane
const rowCosineVec = vec3.fromValues(
imageOrientationPatient[0],
imageOrientationPatient[1],
imageOrientationPatient[2]
);
const colCosineVec = vec3.fromValues(
imageOrientationPatient[3],
imageOrientationPatient[4],
imageOrientationPatient[5]
);
const scanAxisNormal = vec3.cross(vec3.create(), rowCosineVec, colCosineVec);
// Define the reference vectors for axial, coronal, and sagittal planes
const unitVectors = {
[OrientationAxis.AXIAL]: vec3.fromValues(0, 0, 1),
[OrientationAxis.CORONAL]: vec3.fromValues(0, 1, 0),
[OrientationAxis.SAGITTAL]: vec3.fromValues(1, 0, 0),
};
// Compute dot products for each reference plane
// Because all vectors are normalized, dot product is bounded between -1 and 1
let maxDot = 0;
let maxOrientation: string = '';
for (const [k, v] of Object.entries(unitVectors)) {
// Absolute value of dot product because we only care about alignment with the axis
// For example, dot product of -1 for a given axis means perfect alignment
// but the image is pointing in the "opposite" direction
const res = Math.abs(vec3.dot(scanAxisNormal, v));
Iif (res > maxDot) {
maxDot = res;
maxOrientation = k;
}
}
return maxOrientation as OrientationAxis;
}
|