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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | 1x 562x 562x 562x 246x 246x 246x 246x 318x 318x 318x 246x 1x 1x 1x 1x 1x 1x 245x 245x 245x 245x 317x 317x 317x 317x 245x 245x 245x 245x | import cache from '../cache/cache';
import { EPSILON } from '../constants';
// import type { VolumeViewport } from '../RenderingEngine'
import { ICamera, IImageVolume, IVolumeViewport } from '../types';
import getSpacingInNormalDirection from './getSpacingInNormalDirection';
import { getVolumeLoaderSchemes } from '../loaders/volumeLoader';
// One EPSILON part larger multiplier
const EPSILON_PART = 1 + EPSILON;
const startsWith = (str, starts) =>
starts === str.substring(0, Math.min(str.length, starts.length));
// Check if this is a primary volume
// For now, that means it came from some sort of image loader, but
// should be specifically designated.
const isPrimaryVolume = (volume): boolean =>
!!getVolumeLoaderSchemes().find((scheme) =>
startsWith(volume.volumeId, scheme)
);
/**
* Given a volume viewport and camera, find the target volume.
* The imageVolume is retrieved from cache for the specified targetVolumeId or
* in case it is not provided, it chooses the volumeId on the viewport (there
* might be more than one in case of fusion) that has the finest resolution in the
* direction of view (normal).
*
* @param viewport - volume viewport
* @param camera - current camera
* @param targetVolumeId - If a target volumeId is given that volume
* is forced to be used.
*
* @returns An object containing the imageVolume and spacingInNormalDirection.
*
*/
export default function getTargetVolumeAndSpacingInNormalDir(
viewport: IVolumeViewport,
camera: ICamera,
targetVolumeId?: string
): {
imageVolume: IImageVolume;
spacingInNormalDirection: number;
actorUID: string;
} {
const { viewPlaneNormal } = camera;
const volumeActors = viewport.getActors();
Iif (!volumeActors || !volumeActors.length) {
return {
spacingInNormalDirection: null,
imageVolume: null,
actorUID: null,
};
}
const imageVolumes = volumeActors
.map((va) => {
// prefer the referenceUID if it is set, since it can be a derived actor
// and the uid does not necessarily match the volumeId
const actorUID = va.referenceId ?? va.uid;
return cache.getVolume(actorUID);
})
.filter((iv) => !!iv);
// If a volumeId is defined, set that volume as the target
if (targetVolumeId) {
const imageVolumeIndex = imageVolumes.findIndex(
(iv) => iv.volumeId === targetVolumeId
);
const imageVolume = imageVolumes[imageVolumeIndex];
const { uid: actorUID } = volumeActors[imageVolumeIndex];
const spacingInNormalDirection = getSpacingInNormalDirection(
imageVolume,
viewPlaneNormal
);
return { imageVolume, spacingInNormalDirection, actorUID };
}
Iif (!imageVolumes.length) {
return {
spacingInNormalDirection: null,
imageVolume: null,
actorUID: null,
};
}
// Fetch volume actor with finest resolution in direction of projection.
const smallest = {
spacingInNormalDirection: Infinity,
imageVolume: null,
actorUID: null,
};
const hasPrimaryVolume = imageVolumes.find(isPrimaryVolume);
for (let i = 0; i < imageVolumes.length; i++) {
const imageVolume = imageVolumes[i];
Iif (hasPrimaryVolume && !isPrimaryVolume(imageVolume)) {
// Secondary volumes like segmentation don't count towards spacing
continue;
}
const spacingInNormalDirection = getSpacingInNormalDirection(
imageVolume,
viewPlaneNormal
);
// Allow for EPSILON part larger requirement to prefer earlier volumes
// when the spacing is within a factor of EPSILON. Use a factor because
// that deals with very small or very large volumes effectively.
if (
spacingInNormalDirection * EPSILON_PART <
smallest.spacingInNormalDirection
) {
smallest.spacingInNormalDirection = spacingInNormalDirection;
smallest.imageVolume = imageVolume;
smallest.actorUID = volumeActors[i].uid;
}
}
return smallest;
}
|