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; } |