All files / tools/src/utilities/segmentation createLabelmapMemo.ts

93.1% Statements 27/29
62.5% Branches 5/8
100% Functions 6/6
93.1% Lines 27/29

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          428x                                                   234x                 4x   4x 4x 24476x   4x 4x                         234x     234x                 234x               374x     374x 166x   208x 208x       208x 208x 2758x   208x 208x     208x 208x 6448566x 6448566x     6448566x   208x    
import { utilities, eventTarget } from '@cornerstonejs/core';
import { triggerSegmentationDataModified } from '../../stateManagement/segmentation/triggerSegmentationEvents';
import type { Types } from '@cornerstonejs/core';
import Events from '../../enums/Events';
 
const { VoxelManager, RLEVoxelMap } = utilities;
 
/**
 * The labelmap memo state, extending from the base Memo state
 */
export type LabelmapMemo = Types.Memo & {
  /** The base segmentation voxel manager */
  segmentationVoxelManager: Types.IVoxelManager<number>;
  /** The history remembering voxel manager */
  voxelManager: Types.IVoxelManager<number>;
  /** The redo and undo voxel managers */
  redoVoxelManager?: Types.IVoxelManager<number>;
  undoVoxelManager?: Types.IVoxelManager<number>;
  memo?: LabelmapMemo;
  /** A unique identifier for this memo */
  id: string;
};
 
/**
 * Creates a labelmap memo instance.  Does not push it to the
 * stack, which is handled externally.
 */
export function createLabelmapMemo<T>(
  segmentationId: string,
  segmentationVoxelManager: Types.IVoxelManager<T>
) {
  return createRleMemo(segmentationId, segmentationVoxelManager);
}
 
/**
 * A restore memo function.  This simply copies either the redo or the base
 * voxel manager data to the segmentation state and triggers segmentation data
 * modified.
 */
export function restoreMemo(isUndo?: boolean) {
  const { segmentationVoxelManager, undoVoxelManager, redoVoxelManager } = this;
  const useVoxelManager =
    isUndo === false ? redoVoxelManager : undoVoxelManager;
  useVoxelManager.forEach(({ value, pointIJK }) => {
    segmentationVoxelManager.setAtIJKPoint(pointIJK, value);
  });
  const slices = useVoxelManager.getArrayOfModifiedSlices();
  triggerSegmentationDataModified(this.segmentationId, slices);
 
  // Event dispatch moved to historyMemo/index.ts
}
 
/**
 * Creates an RLE memo state that stores additional changes to the voxel
 * map.
 */
export function createRleMemo<T>(
  segmentationId: string,
  segmentationVoxelManager: Types.IVoxelManager<T>
) {
  const voxelManager = VoxelManager.createRLEHistoryVoxelManager(
    segmentationVoxelManager
  );
  const state = {
    segmentationId,
    restoreMemo,
    commitMemo,
    segmentationVoxelManager,
    voxelManager,
    id: utilities.uuidv4(),
    operationType: 'labelmap',
  };
  return state;
}
 
/**
 * This is a member function of a memo that causes the completion of the
 * storage - that is, it copies the RLE data and creates a reverse RLE map
 */
function commitMemo() {
  Iif (this.redoVoxelManager) {
    return true;
  }
  if (!this.voxelManager.modifiedSlices.size) {
    return false;
  }
  const { segmentationVoxelManager } = this;
  const undoVoxelManager = VoxelManager.createRLEHistoryVoxelManager(
    segmentationVoxelManager
  );
  // @ts-expect-error
  RLEVoxelMap.copyMap(undoVoxelManager.map, this.voxelManager.map);
  for (const key of this.voxelManager.modifiedSlices.keys()) {
    undoVoxelManager.modifiedSlices.add(key);
  }
  this.undoVoxelManager = undoVoxelManager;
  const redoVoxelManager = VoxelManager.createRLEVolumeVoxelManager({
    dimensions: this.segmentationVoxelManager.dimensions,
  });
  this.redoVoxelManager = redoVoxelManager;
  undoVoxelManager.forEach(({ index, pointIJK, value }) => {
    const currentValue = segmentationVoxelManager.getAtIJKPoint(pointIJK);
    Iif (currentValue === value) {
      return;
    }
    redoVoxelManager.setAtIndex(index, currentValue);
  });
  return true;
}