@cornerstonejs/core
Version:
Cornerstone3D Core
244 lines (243 loc) • 10 kB
JavaScript
import { vec3 } from 'gl-matrix';
import { ActorRenderMode } from '../../../types/index.js';
import getClosestImageId from '../../../utilities/getClosestImageId.js';
import imageIdToURI from '../../../utilities/imageIdToURI.js';
import isEqual from '../../../utilities/isEqual.js';
import getVolumeViewReferenceId from '../../../utilities/getVolumeViewReferenceId.js';
import { updatePlaneRestriction } from '../../../utilities/updatePlaneRestriction.js';
import { getDimensionGroupReferenceContext } from '../genericViewportReferenceCompatibility.js';
import { resolvePlanarViewportView } from './PlanarResolvedView.js';
export function getPlanarReferencedImageId(args) {
const { rendering, viewRefSpecifier } = args;
if (!rendering) {
return;
}
const imageIds = getImageIds(args.data);
if (!imageIds.length) {
return;
}
if (rendering.renderMode === ActorRenderMode.CPU_IMAGE ||
rendering.renderMode === ActorRenderMode.VTK_IMAGE) {
const imageIdIndex = typeof viewRefSpecifier?.sliceIndex === 'number'
? Math.min(Math.max(0, viewRefSpecifier.sliceIndex), imageIds.length - 1)
: args.viewState?.slice?.kind === 'stackIndex'
? Math.min(Math.max(0, args.viewState.slice.imageIdIndex), imageIds.length - 1)
: getCurrentSliceIndex(rendering);
return imageIds[imageIdIndex];
}
const resolvedView = getPlanarResolvedViewForReference({
viewState: args.viewState,
data: args.data,
frameOfReferenceUID: args.frameOfReferenceUID,
renderContext: args.renderContext,
rendering,
sliceIndex: viewRefSpecifier?.sliceIndex,
})?.toICamera();
if (!resolvedView?.focalPoint || !resolvedView.viewPlaneNormal) {
return imageIds[Math.min(getCurrentSliceIndex(rendering), imageIds.length - 1)];
}
return getClosestImageId(rendering.imageVolume, resolvedView.focalPoint, resolvedView.viewPlaneNormal);
}
export function getPlanarViewReference(args) {
const { frameOfReferenceUID, rendering, viewRefSpecifier } = args;
const { dimensionGroupNumber } = getDimensionGroupReferenceContext(args.data?.imageVolume);
const sliceIndex = viewRefSpecifier?.sliceIndex ??
(rendering ? getCurrentSliceIndex(rendering) : undefined);
const rangeEndSliceIndex = viewRefSpecifier?.rangeEndSliceIndex;
const targetCamera = getPlanarResolvedViewForReference({
...args,
sliceIndex,
})?.toICamera();
const cameraFocalPoint = toPoint3(targetCamera?.focalPoint);
const viewPlaneNormal = toPoint3(targetCamera?.viewPlaneNormal);
const viewUp = toPoint3(targetCamera?.viewUp);
const inPlaneVector2 = viewUp && viewPlaneNormal
? toPoint3(vec3.cross(vec3.create(), viewUp, viewPlaneNormal))
: undefined;
const viewReference = {
FrameOfReferenceUID: frameOfReferenceUID,
dataId: args.dataId,
dimensionGroupNumber,
cameraFocalPoint,
viewPlaneNormal,
viewUp,
sliceIndex,
planeRestriction: viewPlaneNormal && viewUp && cameraFocalPoint
? {
FrameOfReferenceUID: frameOfReferenceUID,
point: toPoint3(viewRefSpecifier?.points?.[0]) || cameraFocalPoint,
inPlaneVector1: viewUp,
inPlaneVector2,
}
: undefined,
};
const referencedImageId = getPlanarReferencedImageId(args);
const rangeEndReferencedImageId = typeof sliceIndex === 'number' &&
typeof rangeEndSliceIndex === 'number' &&
rangeEndSliceIndex > sliceIndex
? getPlanarReferencedImageId({
...args,
viewRefSpecifier: {
...viewRefSpecifier,
sliceIndex: rangeEndSliceIndex,
},
})
: undefined;
if (rendering &&
(rendering.renderMode === ActorRenderMode.CPU_VOLUME ||
rendering.renderMode === ActorRenderMode.VTK_VOLUME_SLICE) &&
viewRefSpecifier?.forFrameOfReference !== true) {
viewReference.volumeId = args.data?.volumeId;
}
if (referencedImageId) {
viewReference.referencedImageId = referencedImageId;
viewReference.referencedImageURI = imageIdToURI(referencedImageId);
}
if (rangeEndReferencedImageId &&
typeof rangeEndSliceIndex === 'number' &&
typeof sliceIndex === 'number' &&
rangeEndSliceIndex > sliceIndex) {
viewReference.multiSliceReference = {
FrameOfReferenceUID: frameOfReferenceUID,
referencedImageId: rangeEndReferencedImageId,
referencedImageURI: imageIdToURI(rangeEndReferencedImageId),
sliceIndex: rangeEndSliceIndex,
};
}
if (viewRefSpecifier?.points && viewReference.planeRestriction) {
updatePlaneRestriction(viewRefSpecifier.points, viewReference);
}
return viewReference;
}
export function getPlanarViewReferenceId(args) {
const { rendering, viewRefSpecifier } = args;
if (!rendering) {
return null;
}
if (rendering.renderMode === ActorRenderMode.CPU_VOLUME ||
rendering.renderMode === ActorRenderMode.VTK_VOLUME_SLICE) {
const resolvedView = getPlanarResolvedViewForReference({
...args,
sliceIndex: viewRefSpecifier?.sliceIndex,
})?.toICamera();
const sliceIndex = viewRefSpecifier?.sliceIndex ?? getCurrentSliceIndex(rendering);
const volumeId = args.data?.volumeId;
if (!volumeId || !resolvedView?.viewPlaneNormal) {
return null;
}
return getVolumeViewReferenceId({
sliceIndex,
viewPlaneNormal: resolvedView.viewPlaneNormal,
volumeId,
});
}
const referencedImageId = getPlanarReferencedImageId(args);
return referencedImageId ? `imageId:${referencedImageId}` : null;
}
export function isPlanarPlaneViewable(args) {
const { frameOfReferenceUID, options, planeRestriction } = args;
if (planeRestriction.FrameOfReferenceUID !== frameOfReferenceUID) {
return false;
}
const resolvedView = getPlanarResolvedViewForReference(args)?.toICamera();
const { focalPoint, viewPlaneNormal } = resolvedView || {};
if (!focalPoint || !viewPlaneNormal) {
return false;
}
if (options?.withOrientation) {
return true;
}
if (planeRestriction.inPlaneVector1 &&
!isEqual(0, vec3.dot(viewPlaneNormal, planeRestriction.inPlaneVector1))) {
return false;
}
if (planeRestriction.inPlaneVector2 &&
!isEqual(0, vec3.dot(viewPlaneNormal, planeRestriction.inPlaneVector2))) {
return false;
}
if (options?.withNavigation) {
return true;
}
const { point } = planeRestriction;
const pointVector = vec3.sub(vec3.create(), point, focalPoint);
return isEqual(0, vec3.dot(pointVector, viewPlaneNormal));
}
export function isPlanarReferenceViewable(args) {
const { frameOfReferenceUID, imageIds, options = {}, viewRef } = args;
if (!viewRef) {
return false;
}
if (viewRef.planeRestriction) {
return isPlanarPlaneViewable({
viewState: args.viewState,
frameOfReferenceUID,
options,
planeRestriction: viewRef.planeRestriction,
renderContext: args.renderContext,
rendering: args.rendering,
});
}
if (viewRef.FrameOfReferenceUID &&
viewRef.FrameOfReferenceUID !== frameOfReferenceUID) {
return false;
}
const resolvedView = getPlanarResolvedViewForReference(args)?.toICamera();
if (!resolvedView?.viewPlaneNormal) {
return false;
}
if (viewRef.viewPlaneNormal &&
!isEqual(viewRef.viewPlaneNormal, resolvedView.viewPlaneNormal) &&
!isEqual(vec3.negate(vec3.create(), resolvedView.viewPlaneNormal), viewRef.viewPlaneNormal)) {
return Boolean(options.withOrientation);
}
if (viewRef.referencedImageId || viewRef.referencedImageURI) {
const referencedImageURI = viewRef.referencedImageURI ||
imageIdToURI(viewRef.referencedImageId);
const currentSliceIndex = args.rendering
? getCurrentSliceIndex(args.rendering)
: 0;
const currentReferencedImageId = imageIds[currentSliceIndex];
if (currentReferencedImageId &&
imageIdToURI(currentReferencedImageId) === referencedImageURI) {
return true;
}
const foundSliceIndex = imageIds.findIndex((imageId) => imageIdToURI(imageId) === referencedImageURI);
if (foundSliceIndex === -1) {
return false;
}
if (options.withNavigation) {
return true;
}
const rangeEndSliceIndex = viewRef.multiSliceReference &&
imageIds.findIndex((imageId) => imageIdToURI(imageId) ===
imageIdToURI(viewRef.multiSliceReference.referencedImageId));
if (rangeEndSliceIndex !== undefined && rangeEndSliceIndex >= 0) {
return (foundSliceIndex <= currentSliceIndex &&
currentSliceIndex <= rangeEndSliceIndex);
}
return currentSliceIndex === foundSliceIndex;
}
const currentSliceIndex = args.rendering
? getCurrentSliceIndex(args.rendering)
: 0;
const { sliceIndex } = viewRef;
if (Array.isArray(sliceIndex)) {
return (sliceIndex[0] <= currentSliceIndex && currentSliceIndex <= sliceIndex[1]);
}
return sliceIndex === undefined || sliceIndex === currentSliceIndex;
}
function getCurrentSliceIndex(rendering) {
return rendering.currentImageIdIndex;
}
function getImageIds(payload) {
return payload?.imageVolume?.imageIds || payload?.imageIds || [];
}
function toPoint3(point) {
if (!point) {
return;
}
return [point[0], point[1], point[2]];
}
function getPlanarResolvedViewForReference(args) {
return resolvePlanarViewportView(args);
}