All files / packages/tools/src/stateManagement/segmentation/polySeg/Contour/utils createAndAddContourSegmentationsFromClippedSurfaces.ts

2.94% Statements 1/34
0% Branches 0/6
0% Functions 0/2
3.22% Lines 1/31

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                                                                                                                                                                        1x                                      
import { PlanarFreehandContourSegmentationTool } from '../../../../../tools';
import { addAnnotation } from '../../../../annotation/annotationState';
import { RawContourData } from '../contourComputationStrategies';
import { utilities, type Types } from '@cornerstonejs/core';
 
/**
 * Creates and adds contour segmentations from a clipped surface.
 *
 * @param rawContourData - The raw contour data.
 * @param viewport - The viewport.
 * @param segmentationId - The segmentation ID.
 */
export function createAndAddContourSegmentationsFromClippedSurfaces(
  rawContourData: RawContourData,
  viewport: Types.IViewport,
  segmentationId: string
) {
  const annotationUIDsMap = new Map<number, Set<string>>();
 
  for (const [segmentIndex, contoursData] of rawContourData) {
    for (const contourData of contoursData) {
      const { points } = contourData;
 
      const { lineSegments, linesNumberOfPoints } =
        _extractLineSegments(contourData);
 
      // There may be a few lines as the surface might not be closed and could have holes in it.
      // Currently, we simply render the generated contour as empty fill to indicate
      // the presence of holes. However, filling the proper area with
      //  fillAlpha requires further work.
      for (let i = 0; i < lineSegments.length; i++) {
        const line = lineSegments[i];
        const polyline = [];
 
        for (let j = 0; j < linesNumberOfPoints[i]; j++) {
          const pointIndex = line[j];
          polyline.push([
            points[3 * pointIndex],
            points[3 * pointIndex + 1],
            points[3 * pointIndex + 2],
          ]);
        }
 
        if (polyline.length < 3) {
          continue;
        }
 
        const contourSegmentationAnnotation = {
          annotationUID: utilities.uuidv4(),
          data: {
            contour: {
              closed: true,
              polyline,
            },
            segmentation: {
              segmentationId,
              segmentIndex,
            },
            handles: {},
          },
          handles: {},
          highlighted: false,
          autoGenerated: false,
          invalidated: false,
          isLocked: false,
          isVisible: true,
          metadata: {
            toolName: PlanarFreehandContourSegmentationTool.toolName,
            ...viewport.getViewReference(),
          },
        };
 
        addAnnotation(contourSegmentationAnnotation, viewport.element);
 
        const currentSet = annotationUIDsMap.get(segmentIndex) || new Set();
        currentSet.add(contourSegmentationAnnotation.annotationUID);
        annotationUIDsMap.set(segmentIndex, currentSet);
      }
    }
  }
 
  return annotationUIDsMap;
}
 
const _extractLineSegments = (contourData) => {
  const { numberOfCells, lines } = contourData;
 
  const lineSegments = [];
  const linesNumberOfPoints = [];
 
  for (let i = 0; i < lines.length; ) {
    const pointsInLine = lines[i];
    linesNumberOfPoints.push(pointsInLine);
    lineSegments.push(lines.slice(i + 1, i + pointsInLine + 1));
    i += pointsInLine + 1;
 
    if (lineSegments.length === numberOfCells) {
      break;
    }
  }
 
  return { lineSegments, linesNumberOfPoints };
};