204 lines
5.9 KiB
TypeScript
204 lines
5.9 KiB
TypeScript
import { Types, metaData, utilities as csUtils } from '@cornerstonejs/core';
|
|
import {
|
|
annotation,
|
|
drawing,
|
|
utilities,
|
|
Types as cs3DToolsTypes,
|
|
AnnotationDisplayTool,
|
|
} from '@cornerstonejs/tools';
|
|
import toolNames from './toolNames';
|
|
import { Annotation } from '@cornerstonejs/tools/dist/types/types';
|
|
|
|
export default class SCOORD3DPointTool extends AnnotationDisplayTool {
|
|
static toolName = toolNames.SRSCOORD3DPoint;
|
|
|
|
constructor(
|
|
toolProps = {},
|
|
defaultToolProps = {
|
|
configuration: {},
|
|
}
|
|
) {
|
|
super(toolProps, defaultToolProps);
|
|
}
|
|
|
|
_getTextBoxLinesFromLabels(labels) {
|
|
// TODO -> max 5 for now (label + shortAxis + longAxis), need a generic solution for this!
|
|
|
|
const labelLength = Math.min(labels.length, 5);
|
|
const lines = [];
|
|
|
|
return lines;
|
|
}
|
|
|
|
// This tool should not inherit from AnnotationTool and we should not need
|
|
// to add the following lines.
|
|
isPointNearTool = () => null;
|
|
getHandleNearImagePoint = () => null;
|
|
|
|
renderAnnotation = (enabledElement: Types.IEnabledElement, svgDrawingHelper: any): void => {
|
|
const { viewport } = enabledElement;
|
|
const { element } = viewport;
|
|
|
|
const annotations = annotation.state.getAnnotations(this.getToolName(), element);
|
|
|
|
// Todo: We don't need this anymore, filtering happens in triggerAnnotationRender
|
|
if (!annotations?.length) {
|
|
return;
|
|
}
|
|
|
|
// Filter toolData to only render the data for the active SR.
|
|
const filteredAnnotations = annotations;
|
|
if (!viewport._actors?.size) {
|
|
return;
|
|
}
|
|
|
|
const styleSpecifier: cs3DToolsTypes.AnnotationStyle.StyleSpecifier = {
|
|
toolGroupId: this.toolGroupId,
|
|
toolName: this.getToolName(),
|
|
viewportId: enabledElement.viewport.id,
|
|
};
|
|
|
|
for (let i = 0; i < filteredAnnotations.length; i++) {
|
|
const annotation = filteredAnnotations[i];
|
|
|
|
const annotationUID = annotation.annotationUID;
|
|
const { renderableData } = annotation.data;
|
|
const { POINT: points } = renderableData;
|
|
|
|
styleSpecifier.annotationUID = annotationUID;
|
|
|
|
const lineWidth = this.getStyle('lineWidth', styleSpecifier, annotation);
|
|
const lineDash = this.getStyle('lineDash', styleSpecifier, annotation);
|
|
const color = this.getStyle('color', styleSpecifier, annotation);
|
|
|
|
const options = {
|
|
color,
|
|
lineDash,
|
|
lineWidth,
|
|
};
|
|
|
|
const point = points[0][0];
|
|
|
|
// check if viewport can render it
|
|
const viewable = viewport.isReferenceViewable(
|
|
{ FrameOfReferenceUID: annotation.metadata.FrameOfReferenceUID, cameraFocalPoint: point },
|
|
{ asNearbyProjection: true }
|
|
);
|
|
|
|
if (!viewable) {
|
|
continue;
|
|
}
|
|
|
|
// render the point
|
|
const arrowPointCanvas = viewport.worldToCanvas(point);
|
|
// Todo: configure this
|
|
const arrowEndCanvas = [arrowPointCanvas[0] + 20, arrowPointCanvas[1] + 20];
|
|
const canvasCoordinates = [arrowPointCanvas, arrowEndCanvas];
|
|
|
|
drawing.drawArrow(
|
|
svgDrawingHelper,
|
|
annotationUID,
|
|
'1',
|
|
canvasCoordinates[1],
|
|
canvasCoordinates[0],
|
|
{
|
|
color: options.color,
|
|
width: options.lineWidth,
|
|
}
|
|
);
|
|
|
|
this.renderTextBox(
|
|
svgDrawingHelper,
|
|
viewport,
|
|
canvasCoordinates,
|
|
annotation,
|
|
styleSpecifier,
|
|
options
|
|
);
|
|
}
|
|
};
|
|
|
|
renderTextBox(
|
|
svgDrawingHelper,
|
|
viewport,
|
|
canvasCoordinates,
|
|
annotation,
|
|
styleSpecifier,
|
|
options = {}
|
|
) {
|
|
if (!canvasCoordinates || !annotation) {
|
|
return;
|
|
}
|
|
|
|
const { annotationUID, data = {} } = annotation;
|
|
const { labels } = data;
|
|
|
|
const textLines = [];
|
|
|
|
for (const label of labels) {
|
|
// make this generic
|
|
// fix this
|
|
if (label.label === '363698007') {
|
|
textLines.push(`Finding Site: ${label.value}`);
|
|
}
|
|
}
|
|
|
|
const { color } = options;
|
|
|
|
const adaptedCanvasCoordinates = canvasCoordinates;
|
|
// adapt coordinates if there is an adapter
|
|
const canvasTextBoxCoords = utilities.drawing.getTextBoxCoordsCanvas(adaptedCanvasCoordinates);
|
|
|
|
if (!annotation.data?.handles?.textBox?.worldPosition) {
|
|
annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
|
|
}
|
|
|
|
const textBoxPosition = viewport.worldToCanvas(annotation.data.handles.textBox.worldPosition);
|
|
|
|
const textBoxUID = '1';
|
|
const textBoxOptions = this.getLinkedTextBoxStyle(styleSpecifier, annotation);
|
|
|
|
const boundingBox = drawing.drawLinkedTextBox(
|
|
svgDrawingHelper,
|
|
annotationUID,
|
|
textBoxUID,
|
|
textLines,
|
|
textBoxPosition,
|
|
canvasCoordinates,
|
|
{},
|
|
{
|
|
...textBoxOptions,
|
|
color,
|
|
}
|
|
);
|
|
|
|
const { x: left, y: top, width, height } = boundingBox;
|
|
|
|
annotation.data.handles.textBox.worldBoundingBox = {
|
|
topLeft: viewport.canvasToWorld([left, top]),
|
|
topRight: viewport.canvasToWorld([left + width, top]),
|
|
bottomLeft: viewport.canvasToWorld([left, top + height]),
|
|
bottomRight: viewport.canvasToWorld([left + width, top + height]),
|
|
};
|
|
}
|
|
|
|
public getLinkedTextBoxStyle(
|
|
specifications: cs3DToolsTypes.AnnotationStyle.StyleSpecifier,
|
|
annotation?: Annotation
|
|
): Record<string, unknown> {
|
|
// Todo: this function can be used to set different styles for different toolMode
|
|
// for the textBox.
|
|
|
|
return {
|
|
visibility: this.getStyle('textBoxVisibility', specifications, annotation),
|
|
fontFamily: this.getStyle('textBoxFontFamily', specifications, annotation),
|
|
fontSize: this.getStyle('textBoxFontSize', specifications, annotation),
|
|
color: this.getStyle('textBoxColor', specifications, annotation),
|
|
shadow: this.getStyle('textBoxShadow', specifications, annotation),
|
|
background: this.getStyle('textBoxBackground', specifications, annotation),
|
|
lineWidth: this.getStyle('textBoxLinkLineWidth', specifications, annotation),
|
|
lineDash: this.getStyle('textBoxLinkLineDash', specifications, annotation),
|
|
};
|
|
}
|
|
}
|