All files / extensions/cornerstone-dicom-sr/src/tools SRPointTool.ts

12.5% Statements 5/40
0% Branches 0/15
0% Functions 0/2
12.5% Lines 5/40

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                  242x 242x 242x   242x             242x                                                                                                                                                                                                      
import type { Types } from '@cornerstonejs/core';
import { ProbeTool, drawing, annotation } from '@cornerstonejs/tools';
 
import type { SVGDrawingHelper } from '@cornerstonejs/tools';
import type { StyleSpecifier } from '@cornerstonejs/tools';
import type { ProbeAnnotation } from '@cornerstonejs/tools';
 
import { getSRPointTextLines } from '../utils/srToolGetTextLines';
 
const { drawPath, drawTextBox } = drawing;
const { getAnnotations } = annotation.state;
const { isAnnotationVisible } = annotation.visibility;
 
const CROSS_SIZE = 6;
 
/**
 * SRPoint: sub-type of Probe for hydrated DICOM SR SCOORD/SCOORD3D points.
 * Renders a cross (plus) marker per medical imaging convention;
 * shows label only, no intensity/coordinates.
 */
class SRPointTool extends ProbeTool {
  static toolName = 'SRPoint';
 
  constructor(toolProps, defaultToolProps) {
    super(toolProps, {
      ...defaultToolProps,
      configuration: {
        ...defaultToolProps?.configuration,
        getTextLines: getSRPointTextLines,
        handleRadius: 6,
        textCanvasOffset: { x: 4, y: 4 },
      },
    });
  }
 
  renderAnnotation = (
    enabledElement: Types.IEnabledElement,
    svgDrawingHelper: SVGDrawingHelper
  ): boolean => {
    let renderStatus = false;
    const { viewport } = enabledElement;
    const { element } = viewport;
 
    const annotations = getAnnotations(this.getToolName(), element) as ProbeAnnotation[];
    Iif (!annotations?.length) {
      return renderStatus;
    }
 
    const filteredAnnotations = this.filterInteractableAnnotationsForElement(
      element,
      annotations
    );
    Iif (!filteredAnnotations?.length) {
      return renderStatus;
    }
 
    const styleSpecifier: StyleSpecifier = {
      toolGroupId: this.toolGroupId,
      toolName: this.getToolName(),
      viewportId: enabledElement.viewport.id,
    };
 
    for (const annotation of filteredAnnotations) {
      const annotationUID = annotation.annotationUID;
      const data = annotation.data;
      const point = data.handles.points[0];
      const [canvasX, canvasY] = viewport.worldToCanvas(point);
 
      Iif (!isAnnotationVisible(annotationUID)) {
        continue;
      }
 
      styleSpecifier.annotationUID = annotationUID;
      const { color, lineWidth, lineDash } = this.getAnnotationStyle({
        annotation,
        styleSpecifier,
      });
 
      const size = Number(this.configuration?.handleRadius) || CROSS_SIZE;
      const cx = Number(canvasX);
      const cy = Number(canvasY);
      const crossPaths: [number, number][][] = [
        [[cx, cy - size], [cx, cy + size]],
        [[cx - size, cy], [cx + size, cy]],
      ];
      drawPath(svgDrawingHelper, annotationUID, 'cross', crossPaths, {
        color,
        lineWidth: lineWidth || 2,
        lineDash,
      });
 
      renderStatus = true;
 
      const options = this.getLinkedTextBoxStyle(styleSpecifier, annotation);
      Iif (options?.visibility !== false) {
        const targetId = this.getTargetId(viewport, data);
        const textLines = this.configuration.getTextLines(data, targetId);
        Iif (textLines?.length) {
          const textCanvasCoordinates = [
            cx + (this.configuration?.textCanvasOffset?.x ?? 4),
            cy + (this.configuration?.textCanvasOffset?.y ?? 4),
          ];
          drawTextBox(
            svgDrawingHelper,
            annotationUID,
            '0',
            textLines,
            [textCanvasCoordinates[0], textCanvasCoordinates[1]],
            { ...options, padding: options.padding ?? 4 }
          );
        }
      }
    }
 
    return renderStatus;
  };
}
 
export default SRPointTool;