diff --git a/Modules/ROI/include/mitkROIMapper2D.h b/Modules/ROI/include/mitkROIMapper2D.h index 430302e761..f7c81f61e9 100644 --- a/Modules/ROI/include/mitkROIMapper2D.h +++ b/Modules/ROI/include/mitkROIMapper2D.h @@ -1,56 +1,64 @@ /*============================================================================ 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 mitkROIMapper2D_h #define mitkROIMapper2D_h #include <mitkLocalStorageHandler.h> #include <mitkVtkMapper.h> #include <MitkROIExports.h> #include <vtkPropAssembly.h> #include <vtkSmartPointer.h> namespace mitk { class MITKROI_EXPORT ROIMapper2D : public VtkMapper { class LocalStorage : public Mapper::BaseLocalStorage { public: LocalStorage(); ~LocalStorage() override; vtkPropAssembly* GetPropAssembly() const; + void SetPropAssembly(vtkPropAssembly* propAssembly); + + const PlaneGeometry* GetLastPlaneGeometry() const; + void SetLastPlaneGeometry(const PlaneGeometry* planeGeometry); protected: vtkSmartPointer<vtkPropAssembly> m_PropAssembly; + PlaneGeometry::ConstPointer m_LastPlaneGeometry; }; public: static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool override = false); mitkClassMacro(ROIMapper2D, VtkMapper) itkFactorylessNewMacro(Self) vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; protected: ROIMapper2D(); ~ROIMapper2D() override; + void GenerateDataForRenderer(BaseRenderer* renderer) override; + void ApplyColorAndOpacityProperties(BaseRenderer* renderer, vtkActor* actor) override; + private: LocalStorageHandler<LocalStorage> m_LocalStorageHandler; }; } #endif diff --git a/Modules/ROI/src/mitkROIMapper2D.cpp b/Modules/ROI/src/mitkROIMapper2D.cpp index c2adedc3fc..9caece5caf 100644 --- a/Modules/ROI/src/mitkROIMapper2D.cpp +++ b/Modules/ROI/src/mitkROIMapper2D.cpp @@ -1,45 +1,150 @@ /*============================================================================ 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 <mitkROIMapper2D.h> +#include <mitkROI.h> + +#include <vtkActor.h> +#include <vtkCubeSource.h> +#include <vtkCutter.h> +#include <vtkPlane.h> +#include <vtkPolyDataMapper.h> +#include <vtkSmartPointer.h> + +// Implemented in mitkROIMapper3D.cpp +extern void ApplyIndividualColorAndOpacityProperties(const mitk::IPropertyProvider* properties, vtkActor* actor); mitk::ROIMapper2D::LocalStorage::LocalStorage() : m_PropAssembly(vtkSmartPointer<vtkPropAssembly>::New()) { } mitk::ROIMapper2D::LocalStorage::~LocalStorage() { } vtkPropAssembly* mitk::ROIMapper2D::LocalStorage::GetPropAssembly() const { return m_PropAssembly; } +void mitk::ROIMapper2D::LocalStorage::SetPropAssembly(vtkPropAssembly* propAssembly) +{ + m_PropAssembly = propAssembly; +} + +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); + // Implemented in ROIMapper3D } mitk::ROIMapper2D::ROIMapper2D() { } mitk::ROIMapper2D::~ROIMapper2D() { } +void mitk::ROIMapper2D::GenerateDataForRenderer(BaseRenderer* renderer) +{ + const auto* dataNode = this->GetDataNode(); + + if (dataNode == nullptr) + return; + + auto* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); + const auto* planeGeometry = renderer->GetCurrentWorldPlaneGeometry(); + + if (localStorage->GetLastPlaneGeometry() != nullptr && localStorage->GetLastPlaneGeometry()->IsOnPlane(planeGeometry) && + localStorage->GetLastGenerateDataTime() >= dataNode->GetMTime()) + { + return; + } + + localStorage->SetLastPlaneGeometry(planeGeometry->Clone()); + + const auto* data = dynamic_cast<ROI*>(this->GetData()); + + if (data == nullptr) + return; + + auto propAssembly = vtkSmartPointer<vtkPropAssembly>::New(); + + if (dataNode->IsVisible(renderer)) + { + const auto* geometry = data->GetGeometry(); + const auto halfSpacing = geometry->GetSpacing() * 0.5f; + + auto plane = vtkSmartPointer<vtkPlane>::New(); + plane->SetOrigin(planeGeometry->GetOrigin().data()); + plane->SetNormal(planeGeometry->GetNormal().data()); + + for (const auto& roi : *data) + { + Point3D min; + geometry->IndexToWorld(roi.Min, min); + min -= halfSpacing; + + Point3D max; + geometry->IndexToWorld(roi.Max, max); + max += halfSpacing; + + auto cube = vtkSmartPointer<vtkCubeSource>::New(); + cube->SetBounds(min[0], max[0], min[1], max[1], min[2], max[2]); + + auto cutter = vtkSmartPointer<vtkCutter>::New(); + cutter->SetInputConnection(cube->GetOutputPort()); + cutter->SetCutFunction(plane); + cutter->Update(); + + auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); + mapper->SetInputConnection(cutter->GetOutputPort()); + mapper->SetResolveCoincidentTopologyToPolygonOffset(); + + auto actor = vtkSmartPointer<vtkActor>::New(); + actor->SetMapper(mapper); + + this->ApplyColorAndOpacityProperties(renderer, actor); + ApplyIndividualColorAndOpacityProperties(roi.Properties, actor); + + propAssembly->AddPart(actor); + } + } + + localStorage->SetPropAssembly(propAssembly); + localStorage->UpdateGenerateDataTime(); +} + +void mitk::ROIMapper2D::ApplyColorAndOpacityProperties(BaseRenderer* renderer, vtkActor* actor) +{ + auto* property = actor->GetProperty(); + + float opacity = 1.0f; + this->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 73afe959c7..a91446f479 100644 --- a/Modules/ROI/src/mitkROIMapper3D.cpp +++ b/Modules/ROI/src/mitkROIMapper3D.cpp @@ -1,157 +1,154 @@ /*============================================================================ 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 <mitkROIMapper3D.h> #include <mitkROI.h> #include <vtkActor.h> #include <vtkCubeSource.h> #include <vtkPolyDataMapper.h> #include <vtkSmartPointer.h> -namespace +// Used by both ROIMapper2D and ROIMapper3D +void ApplyIndividualColorAndOpacityProperties(const mitk::IPropertyProvider* properties, vtkActor* actor) { - void ApplyIndividualColorAndOpacityProperties(const mitk::IPropertyProvider* properties, vtkActor* actor) + actor->GetProperty()->SetRepresentationToWireframe(); + actor->GetProperty()->LightingOff(); + + auto property = properties->GetConstProperty("color"); + + if (property.IsNotNull()) { - auto property = properties->GetConstProperty("color"); + auto colorProperty = dynamic_cast<const mitk::ColorProperty*>(property.GetPointer()); - if (property.IsNotNull()) + if (colorProperty != nullptr) { - auto colorProperty = dynamic_cast<const mitk::ColorProperty*>(property.GetPointer()); - - if (colorProperty != nullptr) - { - const auto color = colorProperty->GetColor(); - actor->GetProperty()->SetColor(color[0], color[1], color[2]); - } + const auto color = colorProperty->GetColor(); + actor->GetProperty()->SetColor(color[0], color[1], color[2]); } + } - property = properties->GetConstProperty("opacity"); + property = properties->GetConstProperty("opacity"); - if (property.IsNotNull()) - { - auto opacityProperty = dynamic_cast<const mitk::FloatProperty*>(property.GetPointer()); + if (property.IsNotNull()) + { + auto opacityProperty = dynamic_cast<const mitk::FloatProperty*>(property.GetPointer()); - if (opacityProperty != nullptr) - { - const auto opacity = opacityProperty->GetValue(); - actor->GetProperty()->SetOpacity(actor->GetProperty()->GetOpacity() * opacity); - } + if (opacityProperty != nullptr) + { + const auto opacity = opacityProperty->GetValue(); + actor->GetProperty()->SetOpacity(actor->GetProperty()->GetOpacity() * opacity); } } } mitk::ROIMapper3D::LocalStorage::LocalStorage() : m_PropAssembly(vtkSmartPointer<vtkPropAssembly>::New()) { } mitk::ROIMapper3D::LocalStorage::~LocalStorage() { } vtkPropAssembly* mitk::ROIMapper3D::LocalStorage::GetPropAssembly() const { return m_PropAssembly; } void mitk::ROIMapper3D::LocalStorage::SetPropAssembly(vtkPropAssembly* propAssembly) { m_PropAssembly = propAssembly; } void mitk::ROIMapper3D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool override) { Superclass::SetDefaultProperties(node, renderer, override); node->AddProperty("opacity", mitk::FloatProperty::New(1.0f), renderer, override); } mitk::ROIMapper3D::ROIMapper3D() { } mitk::ROIMapper3D::~ROIMapper3D() { } void mitk::ROIMapper3D::GenerateDataForRenderer(BaseRenderer* renderer) { const auto* dataNode = this->GetDataNode(); if (dataNode == nullptr) return; auto* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); if (localStorage->GetLastGenerateDataTime() >= dataNode->GetMTime()) return; const auto* data = dynamic_cast<ROI*>(this->GetData()); if (data == nullptr) return; - const auto* geometry = data->GetGeometry(); - const auto halfSpacing = geometry->GetSpacing() * 0.5f; - auto propAssembly = vtkSmartPointer<vtkPropAssembly>::New(); if (dataNode->IsVisible(renderer)) { + const auto* geometry = data->GetGeometry(); + const auto halfSpacing = geometry->GetSpacing() * 0.5f; + for (const auto& roi : *data) { Point3D min; geometry->IndexToWorld(roi.Min, min); min -= halfSpacing; Point3D max; geometry->IndexToWorld(roi.Max, max); max += halfSpacing; auto cube = vtkSmartPointer<vtkCubeSource>::New(); cube->SetBounds(min[0], max[0], min[1], max[1], min[2], max[2]); cube->Update(); auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(cube->GetOutputPort()); auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); this->ApplyColorAndOpacityProperties(renderer, actor); ApplyIndividualColorAndOpacityProperties(roi.Properties, actor); - auto* property = actor->GetProperty(); - property->SetRepresentationToWireframe(); - property->LightingOff(); - 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->GetOpacity(opacity, renderer); property->SetOpacity(opacity); } vtkProp* mitk::ROIMapper3D::GetVtkProp(BaseRenderer* renderer) { return m_LocalStorageHandler.GetLocalStorage(renderer)->GetPropAssembly(); }