All files / core/src/RenderingEngine/helpers createVolumeActor.ts

91.66% Statements 22/24
72.72% Branches 8/11
100% Functions 2/2
91.66% Lines 22/24

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                                                                                  384x   384x   384x           384x   384x   384x 170x     384x 384x     384x       384x 384x   384x       384x   384x 110x     384x 214x     384x                 214x         214x                 214x        
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
 
import type { VolumeActor } from './../../types/IActor';
import type { VoiModifiedEventDetail } from './../../types/EventTypes';
import { loadVolume } from '../../loaders/volumeLoader';
import createVolumeMapper from './createVolumeMapper';
import type BlendModes from '../../enums/BlendModes';
import triggerEvent from '../../utilities/triggerEvent';
import { Events } from '../../enums';
import setDefaultVolumeVOI from './setDefaultVolumeVOI';
import type { BlendMode } from '@kitware/vtk.js/Rendering/Core/VolumeMapper/Constants';
 
interface createVolumeActorInterface {
  volumeId: string;
  callback?: ({
    volumeActor,
    volumeId,
  }: {
    volumeActor: VolumeActor;
    volumeId: string;
  }) => void;
  blendMode?: BlendModes;
}
 
/**
 * Creates a volume actor based on the provided properties.
 *
 * @param props - The properties for creating the volume actor.
 * @param element - The HTMLDivElement where the volume actor will be rendered.
 * @param viewportId - The ID of the viewport where the volume actor will be displayed.
 * @param suppressEvents - Optional. Specifies whether to suppress triggering events. Default is false.
 * @param useNativeDataType - Optional. Specifies whether to use the native data type. Default is false.
 * @returns A promise that resolves to the created volume actor.
 * @throws An error if the imageVolume with the specified ID does not exist.
 */
async function createVolumeActor(
  props: createVolumeActorInterface,
  element: HTMLDivElement,
  viewportId: string,
  suppressEvents = false
): Promise<VolumeActor> {
  const { volumeId, callback, blendMode } = props;
 
  const imageVolume = await loadVolume(volumeId);
 
  Iif (!imageVolume) {
    throw new Error(
      `imageVolume with id: ${imageVolume.volumeId} does not exist`
    );
  }
 
  const { imageData, vtkOpenGLTexture } = imageVolume;
 
  const volumeMapper = createVolumeMapper(imageData, vtkOpenGLTexture);
 
  if (blendMode) {
    volumeMapper.setBlendMode(blendMode as unknown as BlendMode);
  }
 
  const volumeActor = vtkVolume.newInstance();
  volumeActor.setMapper(volumeMapper);
 
  // Todo: fix this for 3D RGB
  const { numberOfComponents } = imageData.get('numberOfComponents') as {
    numberOfComponents: number;
  };
 
  const volumeProperty = volumeActor.getProperty();
  volumeProperty.set({ viewportId: viewportId }, true);
 
  Iif (numberOfComponents === 3) {
    volumeActor.getProperty().setIndependentComponents(false);
  }
 
  await setDefaultVolumeVOI(volumeActor, imageVolume);
 
  if (callback) {
    callback({ volumeActor, volumeId });
  }
 
  if (!suppressEvents) {
    triggerVOIModified(element, viewportId, volumeActor, volumeId);
  }
 
  return volumeActor;
}
 
function triggerVOIModified(
  element: HTMLDivElement,
  viewportId: string,
  volumeActor: VolumeActor,
  volumeId: string
) {
  const voiRange = volumeActor
    .getProperty()
    .getRGBTransferFunction(0)
    .getRange();
 
  const voiModifiedEventDetail: VoiModifiedEventDetail = {
    viewportId,
    range: {
      lower: voiRange[0],
      upper: voiRange[1],
    },
    volumeId,
  };
 
  triggerEvent(element, Events.VOI_MODIFIED, voiModifiedEventDetail);
}
 
export default createVolumeActor;