diff --git a/Documentation/Doxygen/3-DeveloperManual/Concepts/MITKROIs.md b/Documentation/Doxygen/3-DeveloperManual/Concepts/MITKROIs.md index 2dac2c9742..85199dbef5 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Concepts/MITKROIs.md +++ b/Documentation/Doxygen/3-DeveloperManual/Concepts/MITKROIs.md @@ -1,154 +1,190 @@ # MITK ROI {#MITKROIPage} [TOC] ## Disclaimer Until the MITK ROI file format is going to be officially announced in a 2024 release of MITK, the file format must be considered experimental and is prone to change without any prior warning. ## Overview MITK ROI is a JSON-based file format defining a collection of region of interests (ROIs). ROIs must have an ID (unsigned integer) and their shape is currently considered to be an axis-aligned bounding box. Its bounds are defined by minimum and maximum index coordinates, typically relative to an image. Custom properties of various known types can be optionally attached to a ROI. A few of these properties are used by MITK to define the appearance of a rendered ROI, for example: - "color" (mitk::ColorProperty): Color/RGB triplet of the rendered ROI (default: white \[1.0, 1.0, 1.0\]) - "opacity" (mitk::FloatProperty): Opacity of the rendered ROI (default: 100% \[1.0\]) - "lineWidth" (mitk::FloatProperty): Line width of the egdes of the rendered ROI (default: 1px \[1.0\]) ROIs can be optionally time-resolved and define both coordinates and properties per time step, allowing for a dynamic appearance, position, and size over time. ROIs also display a caption at their bottom-left corner (supporting multiple lines), that can be set once per MITK ROI file for all contained ROIs. Placeholders enclosed by braces in the caption are substituted by their corresponding ROI property values at runtime. The default caption is "{name} ({ID})", where ``{ID}`` is a special placeholder for the ID of a ROI (technically not a ROI property), and ``{name}`` refers to the ROI property "name" (typically an mitk::StringProperty). Last but not least the reference (image) geometry of the ROIs in an MITK ROI file must be specified to be able to map all index coordinates to actual world coordinates. A geometry is defined by an origin, the pixel/voxel spacing, a size, and optionally the number of time steps in case of a time-resolved MITK ROI file. ## File format As all features are explained in the overview above, the JSON-based file format is defined here by two examples with minimal additional notes: one example for a static MITK ROI file and one example for a time-resolved MITK ROI file. ### Static MITK ROI file This example contains two ROIs for detected tumors in an image with certain confidence. Names and confidence values will be displayed in separate lines for each ROI. ~~~{.json} { "FileFormat": "MITK ROI", "Version": 1, "Name": "Static example", "Caption": "{name}\nConfidence: {confidence}", "Geometry": { "Origin": [0, 0, 0], "Spacing": [1, 1, 3], "Size": [256, 256, 49] }, "ROIs": [ { "ID": 0, "Min": [4, 4, 1], "Max": [124, 124, 31], "Properties": { "StringProperty": { "name": "tumor", "comment": "Detected a tumor with 95% confidence.", "note": "Properties are grouped by their type to reduce verbosity." }, "ColorProperty": { "color": [0, 1, 0] }, "FloatProperty": { "confidence": 0.95 } } }, { "ID": 1, "Min": [132, 4, 1], "Max": [252, 60, 15], "Properties": { "StringProperty": { "name": "Another tumor", "comment": "Maybe another tumor (confidence only 25%)." }, "ColorProperty": { "color": [1, 0, 0] }, "FloatProperty": { "confidence": 0.25 } } } ] } ~~~ Further hints: - "FileFormat" ("MITK ROI"), "Version" (1), and "Geometry" are mandatory. - "Name" is optional. If not set, the file name is used by MITK instead. - ROIs are defined by JSON objects in the "ROIs" JSON array. - See the derived classes of mitk::BaseProperty for an overview of known property types. ### Time-resolved MITK ROI file This example only contains a single ROI but it is defined for several time steps. Fallbacks of time step properties to default properties are demonstrated as well. ~~~{.json} { "FileFormat": "MITK ROI", "Version": 1, "Name": "Time-resolved example", "Geometry": { "Origin": [0, 0, 0], "Spacing": [1, 1, 3], "Size": [256, 256, 49], "TimeSteps": 3 }, "ROIs": [ { "ID": 0, "Properties": { "ColorProperty": { "color": [1, 0, 0] }, "StringProperty": { "name": "Color-changing ROI" } }, "TimeSteps": [ { "t": 0, "Min": [4, 4, 1], "Max": [124, 124, 31] }, { "t": 2, "Min": [14, 14, 11], "Max": [121, 121, 28], "Properties": { "ColorProperty": { "color": [0, 1, 0] } } } ] } ] } ~~~ Further hints: - The geometry defines 3 time steps. - The "Properties" directly in the ROI function as fallbacks, if they are not defined for a certain time step. - Time time step indices "t" are mandatory. The ROI is only present at time steps 0 and 2. - The ROI is red (fallback) at time step 0 and green at time step 2. - Its extents are larger at time step 0 than at time step 2. + +### New features in version 2 + +In version 2 of the file format, geometries can be optionally defined by a linear transformation instead of origin and spacing. +Such a transformation is written as 4x4 matrix in the form of a contiguous array of 16 elements. +For example, the following two geometries are identical: + +~~~{.json} +"Geometry": { + "Origin": [10, 20, 30], + "Spacing": [1, 2, 3], + "Size": [100, 100, 100] +} +~~~ + +~~~{.json} +"Geometry": { + "Transform": [ + 1, 0, 0, 0, + 0, 2, 0, 0, + 0, 0, 3, 0, + 10, 20, 30, 1 + ], + "Size": [100, 100, 100] +} +~~~ + +The latter format is more powerful as it is able to express rotated geometries. + +Further hints: + + - The upper left 3x3 matrix is a rotation matrix. + - The column vectors of the rotation matrix represent the three space directions. + - The norms of the space directions are equivalent to the spacing values. + - The rightmost column vector is always `[0, 0, 0, 1]`. + - The bottom row vector corresonds to the origin (with 1 as fourth element). diff --git a/Modules/Core/files.cmake b/Modules/Core/files.cmake index e9f3daabdf..f1bd7b5ec4 100644 --- a/Modules/Core/files.cmake +++ b/Modules/Core/files.cmake @@ -1,329 +1,330 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkCoreActivator.cpp mitkCoreObjectFactoryBase.cpp mitkCoreObjectFactory.cpp mitkCoreServices.cpp mitkException.cpp Algorithms/mitkBaseDataSource.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkCompareImageDataFilter.cpp Algorithms/mitkCompositePixelValueToString.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkExtractSliceFilter.cpp Algorithms/mitkExtractSliceFilter2.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkImageToSurfaceFilter.cpp Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToImageFilter.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkTemporalJoinImagesFilter.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkCrosshairManager.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSliceNavigationHelper.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkTimeNavigationController.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkLayerController.cpp + DataManagement/mitkAffineTransform3D.cpp DataManagement/mitkAnatomicalStructureColorPresets.cpp DataManagement/mitkArbitraryTimeGeometry.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkApplyTransformMatrixOperation.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseGeometry.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkCrosshairData.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataStorage.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkFloatPropertyExtension.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGeometryTransformHolder.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkGenericIDRelationRule.cpp DataManagement/mitkIdentifiable.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageReadAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageVtkReadAccessor.cpp DataManagement/mitkImageVtkWriteAccessor.cpp DataManagement/mitkImageWriteAccessor.cpp DataManagement/mitkIntPropertyExtension.cpp DataManagement/mitkIPersistenceService.cpp DataManagement/mitkIPropertyAliases.cpp DataManagement/mitkIPropertyDescriptions.cpp DataManagement/mitkIPropertyDeserialization.cpp DataManagement/mitkIPropertyExtensions.cpp DataManagement/mitkIPropertyFilters.cpp DataManagement/mitkIPropertyOwner.cpp DataManagement/mitkIPropertyPersistence.cpp DataManagement/mitkIPropertyProvider.cpp DataManagement/mitkITKEventObserverGuard.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTableProperty.cpp DataManagement/mitkLookupTables.cpp DataManagement/mitkMaterial.cpp DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModifiedLock.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDataUID.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFunction.cpp DataManagement/mitkNodePredicateGeometry.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateDataProperty.cpp DataManagement/mitkNodePredicateSubGeometry.cpp DataManagement/mitkNumericConstants.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneGeometryData.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkPointSetShapeProperty.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyAliases.cpp DataManagement/mitkPropertyDescriptions.cpp DataManagement/mitkPropertyDeserialization.cpp DataManagement/mitkPropertyExtension.cpp DataManagement/mitkPropertyExtensions.cpp DataManagement/mitkPropertyFilter.cpp DataManagement/mitkPropertyFilters.cpp DataManagement/mitkPropertyKeyPath.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkPropertyListReplacedObserver.cpp DataManagement/mitkPropertyNameHelper.cpp DataManagement/mitkPropertyObserver.cpp DataManagement/mitkPropertyPersistence.cpp DataManagement/mitkPropertyPersistenceInfo.cpp DataManagement/mitkPropertyRelationRuleBase.cpp DataManagement/mitkProportionalTimeGeometry.cpp DataManagement/mitkRenderingModeProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkScaleOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkSourceImageRelationRule.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTemporoSpatialStringProperty.cpp DataManagement/mitkUIDManipulator.cpp DataManagement/mitkVectorProperty.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkIPropertyRelations.cpp DataManagement/mitkPropertyRelations.cpp Interactions/mitkAction.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayActionEventBroadcast.cpp Interactions/mitkDisplayActionEventFunctions.cpp Interactions/mitkDisplayActionEventHandler.cpp Interactions/mitkDisplayActionEventHandlerDesynchronized.cpp Interactions/mitkDisplayActionEventHandlerStd.cpp Interactions/mitkDisplayActionEventHandlerSynchronized.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventFactory.cpp Interactions/mitkEventRecorder.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkInteractionEventConst.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionEventHandler.cpp Interactions/mitkInteractionEventObserver.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInteractionSchemeSwitcher.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkMouseDoubleClickEvent.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkSinglePointDataInteractor.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineCondition.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkXML2EventParser.cpp IO/mitkAbstractFileIO.cpp IO/mitkAbstractFileReader.cpp IO/mitkAbstractFileWriter.cpp IO/mitkCustomMimeType.cpp IO/mitkFileReader.cpp IO/mitkFileReaderRegistry.cpp IO/mitkFileReaderSelector.cpp IO/mitkFileReaderWriterBase.cpp IO/mitkFileWriter.cpp IO/mitkFileWriterRegistry.cpp IO/mitkFileWriterSelector.cpp IO/mitkGeometry3DToXML.cpp IO/mitkIFileIO.cpp IO/mitkIFileReader.cpp IO/mitkIFileWriter.cpp IO/mitkGeometryDataReaderService.cpp IO/mitkGeometryDataWriterService.cpp IO/mitkImageVtkLegacyIO.cpp IO/mitkImageVtkXmlIO.cpp IO/mitkIMimeTypeProvider.cpp IO/mitkIOConstants.cpp IO/mitkIOMimeTypes.cpp IO/mitkIOUtil.cpp IO/mitkItkImageIO.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkLegacyFileReaderService.cpp IO/mitkLegacyFileWriterService.cpp IO/mitkLocaleSwitch.cpp IO/mitkLogBackend.cpp IO/mitkMimeType.cpp IO/mitkMimeTypeProvider.cpp IO/mitkOperation.cpp IO/mitkPixelType.cpp IO/mitkPointSetReaderService.cpp IO/mitkPointSetWriterService.cpp IO/mitkProportionalTimeGeometryToXML.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSurfaceStlIO.cpp IO/mitkSurfaceVtkIO.cpp IO/mitkSurfaceVtkLegacyIO.cpp IO/mitkSurfaceVtkXmlIO.cpp IO/mitkUtf8Util.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkPreferenceListReaderOptionsFunctor.cpp IO/mitkIOMetaInformationPropertyConstants.cpp IO/mitkIPreferences.cpp IO/mitkPreferences.cpp IO/mitkIPreferencesService.cpp IO/mitkPreferencesService.cpp IO/mitkIPreferencesStorage.cpp IO/mitkXMLPreferencesStorage.cpp Rendering/mitkAbstractAnnotationRenderer.cpp Rendering/mitkAnnotationUtils.cpp Rendering/mitkBaseRenderer.cpp Rendering/mitkBaseRendererHelper.cpp Rendering/mitkCrosshairVtkMapper2D.cpp Rendering/mitkGradientBackground.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/mitkMapper.cpp Rendering/mitkAnnotation.cpp Rendering/mitkPlaneGeometryDataMapper2D.cpp Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp Rendering/mitkPointSetVtkMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowFrame.cpp Rendering/mitkSurfaceVtkMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVideoRecorder.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkVtkMapper.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp ) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfigMITKBase.xml Interactions/DisplayConfigPACSBase.xml Interactions/DisplayConfigCrosshair.xml Interactions/DisplayConfigRotation.xml Interactions/DisplayConfigActivateCoupling.xml Interactions/DisplayConfigSwivel.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigBlockLMB.xml Interactions/PointSet.xml Interactions/PointSetConfig.xml mitkLevelWindowPresets.xml mitkAnatomicalStructureColorPresets.xml ) diff --git a/Modules/Core/include/mitkAffineTransform3D.h b/Modules/Core/include/mitkAffineTransform3D.h index e6f535cd75..840fd8f6ac 100644 --- a/Modules/Core/include/mitkAffineTransform3D.h +++ b/Modules/Core/include/mitkAffineTransform3D.h @@ -1,24 +1,34 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkAffineTransform3D_h #define mitkAffineTransform3D_h #include #include +#include +#include namespace mitk { using AffineTransform3D = itk::ScalableAffineTransform; + + /** \brief Write transform (4x4 matrix) as JSON array with 16 elements. + */ + MITKCORE_EXPORT void ToJSON(nlohmann::json& j, AffineTransform3D::ConstPointer transform); + + /** \brief Read transform from JSON array (16 elements, resp. 4x4 matrix). + */ + MITKCORE_EXPORT void FromJSON(const nlohmann::json& j, AffineTransform3D::Pointer transform); } #endif diff --git a/Modules/Core/src/DataManagement/mitkAffineTransform3D.cpp b/Modules/Core/src/DataManagement/mitkAffineTransform3D.cpp new file mode 100644 index 0000000000..24677b60d7 --- /dev/null +++ b/Modules/Core/src/DataManagement/mitkAffineTransform3D.cpp @@ -0,0 +1,58 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include + +void mitk::ToJSON(nlohmann::json& j, AffineTransform3D::ConstPointer transform) +{ + const auto& matrix = transform->GetMatrix().GetVnlMatrix(); + + for (int row = 0; row < 3; ++row) + { + for (int column = 0; column < 3; ++column) + { + j.push_back(matrix[row][column]); + } + + j.push_back(0); + } + + const auto& offset = transform->GetOffset(); + + for (int column = 0; column < 3; ++column) + j.push_back(offset[column]); + + j.push_back(1); +} + +void mitk::FromJSON(const nlohmann::json& j, AffineTransform3D::Pointer transform) +{ + size_t i = 0; + itk::Matrix matrix; + + for (int row = 0; row < 3; ++row) + { + for (int column = 0; column < 3; ++column) + j.at(i++).get_to(matrix[row][column]); + + ++i; + } + + transform->SetMatrix(matrix); + + itk::Vector offset; + + for (int column = 0; column < 3; ++column) + j.at(i++).get_to(offset[column]); + + transform->SetOffset(offset); +} diff --git a/Modules/ROI/autoload/IO/src/mitkROIIO.cpp b/Modules/ROI/autoload/IO/src/mitkROIIO.cpp index ade9c8016d..9817496d05 100644 --- a/Modules/ROI/autoload/IO/src/mitkROIIO.cpp +++ b/Modules/ROI/autoload/IO/src/mitkROIIO.cpp @@ -1,213 +1,236 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkROIIO.h" #include #include #include #include #include namespace { int CheckFileFormat(const nlohmann::json& json) { if ("MITK ROI" != json["FileFormat"].get()) mitkThrow() << "Unknown file format (expected \"MITK ROI\")!"; auto version = json["Version"].get(); - if (1 != version) - mitkThrow() << "Unknown file format version (expected version 1)!"; + if (version < 1 || version > 2) + mitkThrow() << "Unknown file format version (expected version 1 or 2)!"; return version; } mitk::Vector3D GetSize(const mitk::BaseGeometry* geometry) { auto bounds = geometry->GetBounds(); mitk::Vector3D result; result[0] = bounds[1]; result[1] = bounds[3]; result[2] = bounds[5]; return result; } void SetSize(mitk::BaseGeometry* geometry, const mitk::Vector3D& size) { mitk::BaseGeometry::BoundsArrayType bounds({ 0.0, size[0], 0.0, size[1], 0.0, size[2] }); geometry->SetBounds(bounds); } - mitk::TimeGeometry::Pointer ReadGeometry(const nlohmann::json& jGeometry) + mitk::TimeGeometry::Pointer ReadGeometry(const nlohmann::json& jGeometry, int version) { auto geometry = mitk::Geometry3D::New(); geometry->ImageGeometryOn(); if (!jGeometry.is_object()) mitkThrow() << "Geometry is expected to be a JSON object."; + bool hasTransform = false; + + if (jGeometry.contains("Transform")) + { + if (version < 2) + mitkThrow() << "Transforms are not supported in MITK ROI file format version 1."; + + auto transform = mitk::AffineTransform3D::New(); + mitk::FromJSON(jGeometry["Transform"], transform); + geometry->SetIndexToWorldTransform(transform); + + hasTransform = true; + } + if (jGeometry.contains("Origin")) + { + if (hasTransform) + mitkThrow() << "Origin is already defined by Transform."; + geometry->SetOrigin(jGeometry["Origin"].get()); + } if (jGeometry.contains("Spacing")) + { + if (hasTransform) + mitkThrow() << "Spacing is already defined by Transform."; + geometry->SetSpacing(jGeometry["Spacing"].get()); + } if (jGeometry.contains("Size")) SetSize(geometry, jGeometry["Size"].get()); auto timeSteps = jGeometry.contains("TimeSteps") ? jGeometry["TimeSteps"].get() : 1; auto result = mitk::ProportionalTimeGeometry::New(); result->Initialize(geometry, timeSteps); return result; } nlohmann::json WriteGeometry(const mitk::TimeGeometry* timeGeometry) { auto geometry = timeGeometry->GetGeometryForTimeStep(0); - nlohmann::json result = { - { "Origin", geometry->GetOrigin() }, - { "Spacing", geometry->GetSpacing() }, - { "Size", GetSize(geometry) } - }; + nlohmann::json result; + + mitk::ToJSON(result["Transform"], geometry->GetIndexToWorldTransform()); + result["Size"] = GetSize(geometry); auto timeSteps = timeGeometry->CountTimeSteps(); if (timeSteps > 1) result["TimeSteps"] = timeSteps; return result; } } mitk::ROIIO::ROIIO() : AbstractFileIO(ROI::GetStaticNameOfClass(), MitkROIIOMimeTypes::ROI_MIMETYPE(), "MITK ROI") { this->RegisterService(); } std::vector mitk::ROIIO::DoRead() { auto *stream = this->GetInputStream(); std::ifstream fileStream; if (nullptr == stream) { auto filename = this->GetInputLocation(); if (filename.empty() || !std::filesystem::exists(filename)) mitkThrow() << "Invalid or nonexistent filename: \"" << filename << "\"!"; fileStream.open(filename); if (!fileStream.is_open()) mitkThrow() << "Could not open file \"" << filename << "\" for reading!"; stream = &fileStream; } auto result = ROI::New(); try { auto j = nlohmann::json::parse(*stream); - CheckFileFormat(j); + auto version = CheckFileFormat(j); - auto geometry = ReadGeometry(j["Geometry"]); + auto geometry = ReadGeometry(j["Geometry"], version); result->SetTimeGeometry(geometry); if (j.contains("Name")) result->SetProperty("name", mitk::StringProperty::New(j["Name"].get())); if (j.contains("Caption")) result->SetProperty("caption", mitk::StringProperty::New(j["Caption"].get())); for (const auto& roi : j["ROIs"]) result->AddElement(roi.get()); } catch (const nlohmann::json::exception &e) { mitkThrow() << e.what(); } return { result }; } void mitk::ROIIO::Write() { auto input = dynamic_cast(this->GetInput()); if (input == nullptr) mitkThrow() << "Invalid input for writing!"; if (input->GetNumberOfElements() == 0) mitkThrow() << "No ROIs found!"; auto* stream = this->GetOutputStream(); std::ofstream fileStream; if (stream == nullptr) { auto filename = this->GetOutputLocation(); if (filename.empty()) mitkThrow() << "Neither an output stream nor an output filename was specified!"; fileStream.open(filename); if (!fileStream.is_open()) mitkThrow() << "Could not open file \"" << filename << "\" for writing!"; stream = &fileStream; } if (!stream->good()) mitkThrow() << "Stream for writing is not good!"; nlohmann::ordered_json j = { { "FileFormat", "MITK ROI" }, - { "Version", 1 } + { "Version", 2 } }; if (auto name = input->GetProperty("name"); name.IsNotNull()) j["Name"] = name->GetValueAsString(); j["Geometry"] = WriteGeometry(input->GetTimeGeometry()); auto caption = input->GetConstProperty("caption"); if (caption.IsNotNull()) j["Caption"] = caption->GetValueAsString(); nlohmann::json rois; for (const auto& roi : *input) rois.push_back(roi.second); j["ROIs"] = rois; *stream << std::setw(2) << j << std::endl; } mitk::ROIIO* mitk::ROIIO::IOClone() const { return new ROIIO(*this); } diff --git a/Modules/ROI/autoload/IO/src/mitkROIIOMimeTypes.cpp b/Modules/ROI/autoload/IO/src/mitkROIIOMimeTypes.cpp index 91b8032fe5..40d8697186 100644 --- a/Modules/ROI/autoload/IO/src/mitkROIIOMimeTypes.cpp +++ b/Modules/ROI/autoload/IO/src/mitkROIIOMimeTypes.cpp @@ -1,75 +1,77 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include #include #include #include mitk::MitkROIIOMimeTypes::MitkROIMimeType::MitkROIMimeType() : CustomMimeType(ROI_MIMETYPE_NAME()) { this->AddExtension("json"); this->SetCategory("MITK ROI"); this->SetComment("MITK ROI"); } bool mitk::MitkROIIOMimeTypes::MitkROIMimeType::AppliesTo(const std::string& path) const { bool result = CustomMimeType::AppliesTo(path); if (!std::filesystem::exists(path)) // T18572 return result; std::ifstream file(path); if (!file.is_open()) return false; auto json = nlohmann::json::parse(file, nullptr, false); if (json.is_discarded() || !json.is_object()) return false; if ("MITK ROI" != json.value("FileFormat", "")) return false; - if (1 != json.value("Version", 0)) + auto version = json.value("Version", 0); + + if (version < 1 || version > 2) return false; return true; } mitk::MitkROIIOMimeTypes::MitkROIMimeType* mitk::MitkROIIOMimeTypes::MitkROIMimeType::Clone() const { return new MitkROIMimeType(*this); } mitk::MitkROIIOMimeTypes::MitkROIMimeType mitk::MitkROIIOMimeTypes::ROI_MIMETYPE() { return MitkROIMimeType(); } std::string mitk::MitkROIIOMimeTypes::ROI_MIMETYPE_NAME() { return IOMimeTypes::DEFAULT_BASE_NAME() + ".roi"; } std::vector mitk::MitkROIIOMimeTypes::Get() { std::vector mimeTypes; mimeTypes.push_back(ROI_MIMETYPE().Clone()); return mimeTypes; } diff --git a/Modules/ROI/src/mitkROIMapper2D.cpp b/Modules/ROI/src/mitkROIMapper2D.cpp index 1435d4c6d7..035249e7e8 100644 --- a/Modules/ROI/src/mitkROIMapper2D.cpp +++ b/Modules/ROI/src/mitkROIMapper2D.cpp @@ -1,187 +1,186 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include "mitkROIMapperHelper.h" #include #include #include #include #include +#include #include #include namespace { mitk::Point3D GetBottomLeftPoint(vtkPoints* points, mitk::BaseRenderer* renderer) { mitk::Point3D point = points->GetPoint(0); mitk::Point2D bottomLeftDisplayPoint; renderer->WorldToDisplay(point, bottomLeftDisplayPoint); auto numPoints = points->GetNumberOfPoints(); mitk::Point2D displayPoint; for (decltype(numPoints) i = 1; i < numPoints; ++i) { point.FillPoint(points->GetPoint(i)); renderer->WorldToDisplay(point, displayPoint); bottomLeftDisplayPoint[0] = std::min(bottomLeftDisplayPoint[0], displayPoint[0]); bottomLeftDisplayPoint[1] = std::min(bottomLeftDisplayPoint[1], displayPoint[1]); } renderer->DisplayToWorld(bottomLeftDisplayPoint, point); return point; } } mitk::ROIMapper2D::LocalStorage::LocalStorage() { } mitk::ROIMapper2D::LocalStorage::~LocalStorage() { } const mitk::PlaneGeometry* mitk::ROIMapper2D::LocalStorage::GetLastPlaneGeometry() const { return m_LastPlaneGeometry; } void mitk::ROIMapper2D::LocalStorage::SetLastPlaneGeometry(const PlaneGeometry* planeGeometry) { m_LastPlaneGeometry = planeGeometry; } void mitk::ROIMapper2D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool override) { Superclass::SetDefaultProperties(node, renderer, override); ROIMapperHelper::SetDefaultProperties(node, renderer, override); } mitk::ROIMapper2D::ROIMapper2D() { } mitk::ROIMapper2D::~ROIMapper2D() { } void mitk::ROIMapper2D::GenerateDataForRenderer(BaseRenderer* renderer) { const auto timePoint = renderer->GetWorldTimeGeometry()->TimeStepToTimePoint(renderer->GetTimeStep()); const auto* planeGeometry = renderer->GetCurrentWorldPlaneGeometry(); auto* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); const auto* dataNode = this->GetDataNode(); if (localStorage->GetLastPlaneGeometry() != nullptr && localStorage->GetLastPlaneGeometry()->IsOnPlane(planeGeometry) && localStorage->GetLastGenerateDataTime() >= dataNode->GetMTime() && localStorage->GetLastTimePoint() == timePoint) { return; } localStorage->SetLastPlaneGeometry(planeGeometry->Clone()); localStorage->SetLastTimePoint(timePoint); auto data = static_cast(this->GetData()); if (!data->GetTimeGeometry()->IsValidTimePoint(timePoint)) return; const auto t = data->GetTimeGeometry()->TimePointToTimeStep(timePoint); auto propAssembly = vtkSmartPointer::New(); if (dataNode->IsVisible(renderer)) { const auto* geometry = data->GetGeometry(t); - const auto halfSpacing = geometry->GetSpacing() * 0.5f; auto plane = vtkSmartPointer::New(); plane->SetOrigin(planeGeometry->GetOrigin().data()); plane->SetNormal(planeGeometry->GetNormal().data()); for (const auto& [id, roi] : *data) { if (!roi.HasTimeStep(t)) continue; - Point3D min; - geometry->IndexToWorld(roi.GetMin(t), min); - min -= halfSpacing; - - Point3D max; - geometry->IndexToWorld(roi.GetMax(t), max); - max += halfSpacing; + Point3D min = roi.GetMin(t); + Point3D max = roi.GetMax(t); auto cube = vtkSmartPointer::New(); cube->SetBounds(min[0], max[0], min[1], max[1], min[2], max[2]); + auto transform = vtkSmartPointer::New(); + transform->SetTransform(geometry->GetVtkTransform()); + transform->SetInputConnection(cube->GetOutputPort()); + auto cutter = vtkSmartPointer::New(); - cutter->SetInputConnection(cube->GetOutputPort()); + cutter->SetInputConnection(transform->GetOutputPort()); cutter->SetPlane(plane); cutter->Update(); auto* slicePolyData = cutter->GetOutput(); if (slicePolyData->GetNumberOfLines() == 0) continue; auto mapper = vtkSmartPointer::New(); mapper->SetInputConnection(cutter->GetOutputPort()); auto actor = vtkSmartPointer::New(); actor->SetMapper(mapper); this->ApplyColorAndOpacityProperties(renderer, actor); ROIMapperHelper::ApplyIndividualProperties(roi, t, actor); propAssembly->AddPart(actor); if (std::string caption; dataNode->GetStringProperty("caption", caption, renderer)) { caption = ROIMapperHelper::ParseCaption(caption, roi, t); if (!caption.empty()) { auto bottomLeftPoint = GetBottomLeftPoint(slicePolyData->GetPoints(), renderer); auto captionActor = ROIMapperHelper::CreateCaptionActor(caption, bottomLeftPoint, actor->GetProperty(), dataNode, renderer); propAssembly->AddPart(captionActor); } } } } localStorage->SetPropAssembly(propAssembly); localStorage->UpdateGenerateDataTime(); } void mitk::ROIMapper2D::ApplyColorAndOpacityProperties(BaseRenderer* renderer, vtkActor* actor) { auto* property = actor->GetProperty(); float opacity = 1.0f; this->GetDataNode()->GetOpacity(opacity, renderer); property->SetOpacity(opacity); } vtkProp* mitk::ROIMapper2D::GetVtkProp(BaseRenderer* renderer) { return m_LocalStorageHandler.GetLocalStorage(renderer)->GetPropAssembly(); } diff --git a/Modules/ROI/src/mitkROIMapper3D.cpp b/Modules/ROI/src/mitkROIMapper3D.cpp index e8120de0e3..06425a8cdc 100644 --- a/Modules/ROI/src/mitkROIMapper3D.cpp +++ b/Modules/ROI/src/mitkROIMapper3D.cpp @@ -1,118 +1,116 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include #include "mitkROIMapperHelper.h" #include #include #include #include +#include mitk::ROIMapper3D::LocalStorage::LocalStorage() { } mitk::ROIMapper3D::LocalStorage::~LocalStorage() { } void mitk::ROIMapper3D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool override) { Superclass::SetDefaultProperties(node, renderer, override); ROIMapperHelper::SetDefaultProperties(node, renderer, override); } mitk::ROIMapper3D::ROIMapper3D() { } mitk::ROIMapper3D::~ROIMapper3D() { } void mitk::ROIMapper3D::GenerateDataForRenderer(BaseRenderer* renderer) { const auto timePoint = renderer->GetWorldTimeGeometry()->TimeStepToTimePoint(renderer->GetTimeStep()); auto* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); const auto* dataNode = this->GetDataNode(); if (localStorage->GetLastGenerateDataTime() >= dataNode->GetMTime() && localStorage->GetLastTimePoint() == timePoint) { return; } localStorage->SetLastTimePoint(timePoint); auto data = static_cast(this->GetData()); if (!data->GetTimeGeometry()->IsValidTimePoint(timePoint)) return; const auto t = data->GetTimeGeometry()->TimePointToTimeStep(timePoint); auto propAssembly = vtkSmartPointer::New(); if (dataNode->IsVisible(renderer)) { const auto* geometry = data->GetGeometry(); - const auto halfSpacing = geometry->GetSpacing() * 0.5f; for (const auto& [id, roi] : *data) { if (!roi.HasTimeStep(t)) continue; - Point3D min; - geometry->IndexToWorld(roi.GetMin(t), min); - min -= halfSpacing; - - Point3D max; - geometry->IndexToWorld(roi.GetMax(t), max); - max += halfSpacing; + Point3D min = roi.GetMin(t); + Point3D max = roi.GetMax(t); auto cube = vtkSmartPointer::New(); cube->SetBounds(min[0], max[0], min[1], max[1], min[2], max[2]); - cube->Update(); + + auto transform = vtkSmartPointer::New(); + transform->SetTransform(geometry->GetVtkTransform()); + transform->SetInputConnection(cube->GetOutputPort()); auto mapper = vtkSmartPointer::New(); - mapper->SetInputConnection(cube->GetOutputPort()); + mapper->SetInputConnection(transform->GetOutputPort()); auto actor = vtkSmartPointer::New(); actor->SetMapper(mapper); this->ApplyColorAndOpacityProperties(renderer, actor); ROIMapperHelper::ApplyIndividualProperties(roi, t, actor); propAssembly->AddPart(actor); } } localStorage->SetPropAssembly(propAssembly); localStorage->UpdateGenerateDataTime(); } void mitk::ROIMapper3D::ApplyColorAndOpacityProperties(BaseRenderer* renderer, vtkActor* actor) { auto* property = actor->GetProperty(); float opacity = 1.0f; this->GetDataNode()->GetOpacity(opacity, renderer); property->SetOpacity(opacity); } vtkProp* mitk::ROIMapper3D::GetVtkProp(BaseRenderer* renderer) { return m_LocalStorageHandler.GetLocalStorage(renderer)->GetPropAssembly(); } diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp index f982b5807e..33fe0dd3f5 100644 --- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp +++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp @@ -1,189 +1,139 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkConvertGeometryDataToROIAction.h" #include #include #include #include #include namespace { void HandleInvalidNodeSelection() { auto message = QStringLiteral( - "All selected bounding boxes must be child nodes of a single common reference image " - "with a non-rotated geometry!"); + "All selected bounding boxes must be child nodes of a single common reference image!"); MITK_ERROR << message; QMessageBox::warning(nullptr, QStringLiteral("Convert to ROI"), message); } - bool IsRotated(const mitk::BaseGeometry* geometry) - { - auto matrix = geometry->GetVtkMatrix(); - - for (int j = 0; j < 3; ++j) - { - for (int i = 0; i < 3; ++i) - { - if (i != j && std::abs(matrix->GetElement(i, j)) > mitk::eps) - return true; - } - } - - return false; - } - - void FlipAxis(mitk::BaseGeometry* geometry, int axis) - { - auto matrix = geometry->GetVtkMatrix(); - matrix->SetElement(axis, axis, -matrix->GetElement(axis, axis)); - matrix->SetElement(axis, 3, matrix->GetElement(axis, 3) - geometry->GetExtentInMM(axis)); - - geometry->SetIndexToWorldTransformByVtkMatrix(matrix); - - auto bounds = geometry->GetBounds(); - int minIndex = 2 * axis; - bounds[minIndex] *= -1; - bounds[minIndex + 1] += 2 * bounds[minIndex]; - - geometry->SetBounds(bounds); - } - - mitk::BaseGeometry::Pointer RectifyGeometry(const mitk::BaseGeometry* geometry) - { - auto rectifiedGeometry = geometry->Clone(); - auto matrix = rectifiedGeometry->GetVtkMatrix(); - - for (int axis = 0; axis < 3; ++axis) - { - if (matrix->GetElement(axis, axis) < 0.0) - FlipAxis(rectifiedGeometry, axis); - } - - return rectifiedGeometry; - } - std::pair, mitk::DataNode*> GetValidInput(const QList& selectedNodes, const mitk::DataStorage* dataStorage) { std::pair, mitk::DataNode*> result; result.first.reserve(selectedNodes.size()); std::copy_if(selectedNodes.cbegin(), selectedNodes.cend(), std::back_inserter(result.first), [](const mitk::DataNode* node) { return node != nullptr && dynamic_cast(node->GetData()) != nullptr; }); for (auto node : result.first) { auto sourceNodes = dataStorage->GetSources(node, mitk::TNodePredicateDataType::New()); if (sourceNodes->size() != 1) mitkThrow(); if (result.second == nullptr) { - auto geometry = sourceNodes->front()->GetData()->GetGeometry(); - - if (IsRotated(geometry)) - mitkThrow(); - result.second = sourceNodes->front(); } else if (result.second != sourceNodes->front()) { mitkThrow(); } } return result; } } QmitkConvertGeometryDataToROIAction::QmitkConvertGeometryDataToROIAction() { } QmitkConvertGeometryDataToROIAction::~QmitkConvertGeometryDataToROIAction() { } void QmitkConvertGeometryDataToROIAction::Run(const QList& selectedNodes) { try { auto [nodes, referenceNode] = GetValidInput(selectedNodes, m_DataStorage); auto roi = mitk::ROI::New(); - roi->SetGeometry(RectifyGeometry(referenceNode->GetData()->GetGeometry())); + roi->SetGeometry(referenceNode->GetData()->GetGeometry()); unsigned int id = 0; for (auto node : nodes) { mitk::ROI::Element element(id++); element.SetProperty("name", mitk::StringProperty::New(node->GetName())); if (auto* color = node->GetProperty("Bounding Shape.Deselected Color"); color != nullptr) element.SetProperty("color", color); - auto geometry = RectifyGeometry(node->GetData()->GetGeometry()); - const auto origin = geometry->GetOrigin() - roi->GetGeometry()->GetOrigin(); - const auto spacing = geometry->GetSpacing(); + const auto* geometry = node->GetData()->GetGeometry(); + + mitk::Vector3D origin = geometry->GetOrigin() - roi->GetGeometry()->GetOrigin(); + geometry->WorldToIndex(origin, origin); + const auto bounds = geometry->GetBounds(); mitk::Point3D min; mitk::Point3D max; for (size_t i = 0; i < 3; ++i) { - min[i] = origin[i] / spacing[i] + bounds[2 * i]; - max[i] = origin[i] / spacing[i] + bounds[2 * i + 1] - 1; + min[i] = origin[i] + bounds[2 * i] - 0.5; + max[i] = origin[i] + bounds[2 * i + 1] - 1 + 0.5; } element.SetMin(min); element.SetMax(max); roi->AddElement(element); } auto roiNode = mitk::DataNode::New(); roiNode->SetName(referenceNode->GetName() + " ROI" + (roi->GetNumberOfElements() > 1 ? "s" : "")); roiNode->SetData(roi); m_DataStorage->Add(roiNode, referenceNode); } catch (const mitk::Exception&) { HandleInvalidNodeSelection(); } } void QmitkConvertGeometryDataToROIAction::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkConvertGeometryDataToROIAction::SetFunctionality(berry::QtViewPart*) { } void QmitkConvertGeometryDataToROIAction::SetSmoothed(bool) { } void QmitkConvertGeometryDataToROIAction::SetDecimated(bool) { }