feat: create memo when manually adding and removing annotations (#5051)

This commit is contained in:
Pedro Köhler 2025-05-29 09:26:16 -03:00 committed by GitHub
parent 9afded1720
commit 5891505c51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 95 additions and 14 deletions

View File

@ -6,6 +6,7 @@ import {
Enums as CoreEnums, Enums as CoreEnums,
Types as CoreTypes, Types as CoreTypes,
BaseVolumeViewport, BaseVolumeViewport,
getRenderingEngines,
} from '@cornerstonejs/core'; } from '@cornerstonejs/core';
import { import {
ToolGroupManager, ToolGroupManager,
@ -1882,6 +1883,31 @@ function commandsModule({
const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId);
viewportInfo.setOrientation(orientation); viewportInfo.setOrientation(orientation);
}, },
triggerCreateAnnotationMemo: ({
annotation,
FrameOfReferenceUID,
options,
}: {
annotation: ToolTypes.Annotation;
FrameOfReferenceUID: string;
options: { newAnnotation?: boolean; deleting?: boolean };
}): void => {
const { newAnnotation, deleting } = options;
const renderingEngines = getRenderingEngines();
const viewports = renderingEngines.flatMap(re => re.getViewports());
const validViewport = viewports.find(
vp => vp.getFrameOfReferenceUID() === FrameOfReferenceUID
);
if (!validViewport) {
return;
}
cornerstoneTools.AnnotationTool.createAnnotationMemo(validViewport.element, annotation, {
newAnnotation,
deleting,
});
},
}; };
const definitions = { const definitions = {
@ -2165,6 +2191,7 @@ function commandsModule({
setViewportOrientation: actions.setViewportOrientation, setViewportOrientation: actions.setViewportOrientation,
hydrateSecondaryDisplaySet: actions.hydrateSecondaryDisplaySet, hydrateSecondaryDisplaySet: actions.hydrateSecondaryDisplaySet,
getVolumeIdForDisplaySet: actions.getVolumeIdForDisplaySet, getVolumeIdForDisplaySet: actions.getVolumeIdForDisplaySet,
triggerCreateAnnotationMemo: actions.triggerCreateAnnotationMemo,
}; };
return { return {

View File

@ -179,7 +179,11 @@ export default async function init({
initWADOImageLoader(userAuthenticationService, appConfig, extensionManager); initWADOImageLoader(userAuthenticationService, appConfig, extensionManager);
/* Measurement Service */ /* Measurement Service */
this.measurementServiceSource = connectToolsToMeasurementService(servicesManager); this.measurementServiceSource = connectToolsToMeasurementService({
servicesManager,
commandsManager,
extensionManager,
});
initCineService(servicesManager); initCineService(servicesManager);
initStudyPrefetcherService(servicesManager); initStudyPrefetcherService(servicesManager);

View File

@ -188,13 +188,20 @@ const initMeasurementService = (
return csTools3DVer1MeasurementSource; return csTools3DVer1MeasurementSource;
}; };
const connectToolsToMeasurementService = (servicesManager: AppTypes.ServicesManager) => { const connectToolsToMeasurementService = ({
commandsManager,
servicesManager,
extensionManager,
}: {
commandsManager: AppTypes.CommandsManager;
servicesManager: AppTypes.ServicesManager;
extensionManager: AppTypes.ExtensionManager;
}) => {
const { const {
measurementService, measurementService,
displaySetService, displaySetService,
cornerstoneViewportService, cornerstoneViewportService,
customizationService, customizationService,
viewportGridService,
} = servicesManager.services; } = servicesManager.services;
const csTools3DVer1MeasurementSource = initMeasurementService( const csTools3DVer1MeasurementSource = initMeasurementService(
measurementService, measurementService,
@ -202,11 +209,7 @@ const connectToolsToMeasurementService = (servicesManager: AppTypes.ServicesMana
cornerstoneViewportService, cornerstoneViewportService,
customizationService customizationService
); );
connectMeasurementServiceToTools( connectMeasurementServiceToTools({ servicesManager, commandsManager, extensionManager });
measurementService,
cornerstoneViewportService,
viewportGridService
);
const { annotationToMeasurement, remove } = csTools3DVer1MeasurementSource; const { annotationToMeasurement, remove } = csTools3DVer1MeasurementSource;
// //
@ -332,11 +335,13 @@ const connectToolsToMeasurementService = (servicesManager: AppTypes.ServicesMana
return csTools3DVer1MeasurementSource; return csTools3DVer1MeasurementSource;
}; };
const connectMeasurementServiceToTools = ( const connectMeasurementServiceToTools = ({
measurementService, servicesManager,
cornerstoneViewportService, commandsManager,
viewportGridService extensionManager,
) => { }) => {
const { measurementService, cornerstoneViewportService, viewportGridService } =
servicesManager.services;
const { MEASUREMENT_REMOVED, MEASUREMENTS_CLEARED, MEASUREMENT_UPDATED, RAW_MEASUREMENT_ADDED } = const { MEASUREMENT_REMOVED, MEASUREMENTS_CLEARED, MEASUREMENT_UPDATED, RAW_MEASUREMENT_ADDED } =
measurementService.EVENTS; measurementService.EVENTS;
@ -350,7 +355,13 @@ const connectMeasurementServiceToTools = (
if (source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) { if (source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {
continue; continue;
} }
const removedAnnotation = annotation.state.getAnnotation(uid);
removeAnnotation(uid); removeAnnotation(uid);
commandsManager.run('triggerCreateAnnotationMemo', {
annotation: removedAnnotation,
FrameOfReferenceUID: removedAnnotation.metadata.FrameOfReferenceUID,
options: { deleting: true },
});
} }
// trigger a render // trigger a render
@ -441,7 +452,7 @@ const connectMeasurementServiceToTools = (
* This is not the read-only annotation rendered by the SR viewport. * This is not the read-only annotation rendered by the SR viewport.
*/ */
const annotationManager = annotation.state.getAnnotationManager(); const annotationManager = annotation.state.getAnnotationManager();
annotationManager.addAnnotation({ const newAnnotation = {
annotationUID: measurement.uid, annotationUID: measurement.uid,
highlighted: false, highlighted: false,
isLocked: false, isLocked: false,
@ -463,6 +474,12 @@ const connectMeasurementServiceToTools = (
label: data.annotation.data.label, label: data.annotation.data.label,
frameNumber, frameNumber,
}, },
};
annotationManager.addAnnotation(newAnnotation);
commandsManager.run('triggerCreateAnnotationMemo', {
annotation: newAnnotation,
FrameOfReferenceUID: newAnnotation.metadata.FrameOfReferenceUID,
options: { newAnnotation: true },
}); });
} }
); );
@ -473,7 +490,13 @@ const connectMeasurementServiceToTools = (
if (source?.name && source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) { if (source?.name && source.name !== CORNERSTONE_3D_TOOLS_SOURCE_NAME) {
return; return;
} }
const removedAnnotation = annotation.state.getAnnotation(removedMeasurementId);
removeAnnotation(removedMeasurementId); removeAnnotation(removedMeasurementId);
commandsManager.run('triggerCreateAnnotationMemo', {
annotation: removedAnnotation,
FrameOfReferenceUID: removedAnnotation.metadata.FrameOfReferenceUID,
options: { deleting: true },
});
const renderingEngine = cornerstoneViewportService.getRenderingEngine(); const renderingEngine = cornerstoneViewportService.getRenderingEngine();
// Note: We could do a better job by triggering the render on the // Note: We could do a better job by triggering the render on the
// viewport itself, but the removeAnnotation does not include that info... // viewport itself, but the removeAnnotation does not include that info...

View File

@ -0,0 +1,27 @@
---
sidebar_position: 2
sidebar_label: Other Changes
summary: Migration guide for OHIF 3.11 additional changes
---
**Key Changes:**
* **`connectToolsToMeasurementService` parameters:** The `connectToolsToMeasurementService` function from the `@ohif/cornerstone-extensions` now take different arguments.
**Migration Steps:**
1. **Update `connectToolsToMeasurementService` Method Calls:**
* Now the connectToolsToMeasurementService receives all service object arguments (servicesManager, commandsManager and extensionManager).
```diff
// Before
- connectToolsToMeasurementService(servicesManager);
// After
+ connectToolsToMeasurementService({
+ servicesManager,
+ commandsManager,
+ extensionsManager
+ });
```