From deb14caae86f764603f3f5e0418733a707106fac Mon Sep 17 00:00:00 2001 From: Ibrahim <93064150+IbrahimCSAE@users.noreply.github.com> Date: Tue, 14 Mar 2023 08:26:35 -0230 Subject: [PATCH 1/4] better fix for elliptical roi --- .../src/tools/annotation/EllipticalROITool.ts | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/tools/src/tools/annotation/EllipticalROITool.ts b/packages/tools/src/tools/annotation/EllipticalROITool.ts index d0c92ed196..da5287f273 100644 --- a/packages/tools/src/tools/annotation/EllipticalROITool.ts +++ b/packages/tools/src/tools/annotation/EllipticalROITool.ts @@ -214,6 +214,7 @@ class EllipticalROITool extends AnnotationTool { activeHandleIndex: null, }, cachedStats: {}, + initialRotation: viewport.getRotation(), }, }; @@ -765,9 +766,22 @@ class EllipticalROITool extends AnnotationTool { const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p) ) as [Types.Point2, Types.Point2, Types.Point2, Types.Point2]; - const canvasCorners = >( - getCanvasEllipseCorners(canvasCoordinates) - ); + + const rotation = Math.abs(viewport.getRotation() - data.initialRotation); + let canvasCorners; + + if (rotation == 90 || rotation == 270) { + canvasCorners = >getCanvasEllipseCorners([ + canvasCoordinates[2], // bottom + canvasCoordinates[3], // top + canvasCoordinates[0], // left + canvasCoordinates[1], // right + ]); + } else { + canvasCorners = >( + getCanvasEllipseCorners(canvasCoordinates) // bottom, top, left, right, keep as is + ); + } const { centerPointRadius } = this.configuration; From 331e044447c0e91c2de14baf23cc6703cb384cfe Mon Sep 17 00:00:00 2001 From: IbrahimCSAE Date: Tue, 14 Mar 2023 08:44:11 -0230 Subject: [PATCH 2/4] type and tools.api --- common/reviews/api/tools.api.md | 1 + packages/tools/src/types/ToolSpecificAnnotationTypes.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/common/reviews/api/tools.api.md b/common/reviews/api/tools.api.md index fc8969e24d..e3bb111950 100644 --- a/common/reviews/api/tools.api.md +++ b/common/reviews/api/tools.api.md @@ -1527,6 +1527,7 @@ interface EllipticalROIAnnotation extends Annotation { }; label: string; cachedStats?: ROICachedStats; + initialRotation: number; }; } diff --git a/packages/tools/src/types/ToolSpecificAnnotationTypes.ts b/packages/tools/src/types/ToolSpecificAnnotationTypes.ts index bb6bae73fa..a946074ec2 100644 --- a/packages/tools/src/types/ToolSpecificAnnotationTypes.ts +++ b/packages/tools/src/types/ToolSpecificAnnotationTypes.ts @@ -96,6 +96,7 @@ export interface EllipticalROIAnnotation extends Annotation { }; label: string; cachedStats?: ROICachedStats; + initialRotation: number; }; } From e8869718f044e9cabe243a900773693599a2e22a Mon Sep 17 00:00:00 2001 From: IbrahimCSAE Date: Fri, 17 Mar 2023 04:59:29 -0230 Subject: [PATCH 3/4] save/restore compatible --- .../adapters/Cornerstone3D/EllipticalROI.ts | 20 +++++++++++++------ .../src/tools/annotation/EllipticalROITool.ts | 4 +++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/adapters/src/adapters/Cornerstone3D/EllipticalROI.ts b/packages/adapters/src/adapters/Cornerstone3D/EllipticalROI.ts index 30a4013c96..07242d3031 100644 --- a/packages/adapters/src/adapters/Cornerstone3D/EllipticalROI.ts +++ b/packages/adapters/src/adapters/Cornerstone3D/EllipticalROI.ts @@ -137,7 +137,7 @@ class EllipticalROI { static getTID300RepresentationArguments(tool, worldToImageCoords) { const { data, finding, findingSites, metadata } = tool; const { cachedStats = {}, handles } = data; - + const rotation = data.initialRotation || 0; const { referencedImageId } = metadata; if (!referencedImageId) { @@ -145,11 +145,19 @@ class EllipticalROI { "EllipticalROI.getTID300RepresentationArguments: referencedImageId is not defined" ); } - - const top = worldToImageCoords(referencedImageId, handles.points[0]); - const bottom = worldToImageCoords(referencedImageId, handles.points[1]); - const left = worldToImageCoords(referencedImageId, handles.points[2]); - const right = worldToImageCoords(referencedImageId, handles.points[3]); + let top, bottom, left, right; + // this way when it's restored we can assume the initial rotation is 0. + if (rotation == 90 || rotation == 270) { + bottom = worldToImageCoords(referencedImageId, handles.points[2]); + top = worldToImageCoords(referencedImageId, handles.points[3]); + left = worldToImageCoords(referencedImageId, handles.points[0]); + right = worldToImageCoords(referencedImageId, handles.points[1]); + } else { + top = worldToImageCoords(referencedImageId, handles.points[0]); + bottom = worldToImageCoords(referencedImageId, handles.points[1]); + left = worldToImageCoords(referencedImageId, handles.points[2]); + right = worldToImageCoords(referencedImageId, handles.points[3]); + } // find the major axis and minor axis const topBottomLength = Math.abs(top[1] - bottom[1]); diff --git a/packages/tools/src/tools/annotation/EllipticalROITool.ts b/packages/tools/src/tools/annotation/EllipticalROITool.ts index da5287f273..bdf7ace412 100644 --- a/packages/tools/src/tools/annotation/EllipticalROITool.ts +++ b/packages/tools/src/tools/annotation/EllipticalROITool.ts @@ -767,7 +767,9 @@ class EllipticalROITool extends AnnotationTool { viewport.worldToCanvas(p) ) as [Types.Point2, Types.Point2, Types.Point2, Types.Point2]; - const rotation = Math.abs(viewport.getRotation() - data.initialRotation); + const rotation = Math.abs( + viewport.getRotation() - (data.initialRotation || 0) + ); let canvasCorners; if (rotation == 90 || rotation == 270) { From 4d562694fc9caa8f0400d33ac0d46d5a527220e0 Mon Sep 17 00:00:00 2001 From: IbrahimCSAE Date: Wed, 22 Mar 2023 14:22:15 -0230 Subject: [PATCH 4/4] add flip h/flip v/ and rotation 90 buttons --- .../examples/stackAnnotationTools/index.ts | 103 +++++++++++++++++- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/packages/tools/examples/stackAnnotationTools/index.ts b/packages/tools/examples/stackAnnotationTools/index.ts index 83bcabb5da..0720a77eb8 100644 --- a/packages/tools/examples/stackAnnotationTools/index.ts +++ b/packages/tools/examples/stackAnnotationTools/index.ts @@ -1,9 +1,15 @@ -import { RenderingEngine, Types, Enums } from '@cornerstonejs/core'; +import { + RenderingEngine, + Types, + Enums, + getRenderingEngine, +} from '@cornerstonejs/core'; import { initDemo, createImageIdsAndCacheMetaData, setTitleAndDescription, addDropdownToToolbar, + addButtonToToolbar, } from '../../../../utils/demo/helpers'; import * as cornerstoneTools from '@cornerstonejs/tools'; @@ -25,8 +31,10 @@ const { Enums: csToolsEnums, } = cornerstoneTools; -const { ViewportType } = Enums; +const { ViewportType, Events } = Enums; const { MouseBindings } = csToolsEnums; +const renderingEngineId = 'myRenderingEngine'; +const viewportId = 'CT_STACK'; // ======== Set up page ======== // setTitleAndDescription( @@ -46,10 +54,42 @@ element.style.height = '500px'; content.appendChild(element); +const info = document.createElement('div'); +content.appendChild(info); + const instructions = document.createElement('p'); instructions.innerText = 'Left Click to use selected tool'; +info.appendChild(instructions); + +const rotationInfo = document.createElement('div'); +info.appendChild(rotationInfo); + +const flipHorizontalInfo = document.createElement('div'); +info.appendChild(flipHorizontalInfo); + +const flipVerticalInfo = document.createElement('div'); +info.appendChild(flipVerticalInfo); + +element.addEventListener(Events.CAMERA_MODIFIED, (_) => { + // Get the rendering engine + const renderingEngine = getRenderingEngine(renderingEngineId); + + // Get the stack viewport + const viewport = ( + renderingEngine.getViewport(viewportId) + ); + + if (!viewport) { + return; + } + + const { flipHorizontal, flipVertical } = viewport.getCamera(); + const { rotation } = viewport.getProperties(); -content.append(instructions); + rotationInfo.innerText = `Rotation: ${Math.round(rotation)}`; + flipHorizontalInfo.innerText = `Flip horizontal: ${flipHorizontal}`; + flipVerticalInfo.innerText = `Flip vertical: ${flipVertical}`; +}); // ============================= // const toolGroupId = 'STACK_TOOL_GROUP_ID'; @@ -88,6 +128,61 @@ addDropdownToToolbar({ }, }); +addButtonToToolbar({ + title: 'Flip H', + onClick: () => { + // Get the rendering engine + const renderingEngine = getRenderingEngine(renderingEngineId); + + // Get the stack viewport + const viewport = ( + renderingEngine.getViewport(viewportId) + ); + + const { flipHorizontal } = viewport.getCamera(); + viewport.setCamera({ flipHorizontal: !flipHorizontal }); + + viewport.render(); + }, +}); + +addButtonToToolbar({ + title: 'Flip V', + onClick: () => { + // Get the rendering engine + const renderingEngine = getRenderingEngine(renderingEngineId); + + // Get the stack viewport + const viewport = ( + renderingEngine.getViewport(viewportId) + ); + + const { flipVertical } = viewport.getCamera(); + + viewport.setCamera({ flipVertical: !flipVertical }); + + viewport.render(); + }, +}); + +addButtonToToolbar({ + title: 'Rotate Delta 90', + onClick: () => { + // Get the rendering engine + const renderingEngine = getRenderingEngine(renderingEngineId); + + // Get the stack viewport + const viewport = ( + renderingEngine.getViewport(viewportId) + ); + + const { rotation } = viewport.getProperties(); + viewport.setProperties({ rotation: rotation + 90 }); + + viewport.render(); + }, +}); + /** * Runs the demo */ @@ -148,11 +243,9 @@ async function run() { }); // Instantiate a rendering engine - const renderingEngineId = 'myRenderingEngine'; const renderingEngine = new RenderingEngine(renderingEngineId); // Create a stack viewport - const viewportId = 'CT_STACK'; const viewportInput = { viewportId, type: ViewportType.STACK,