diff --git a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp index 86ca564d52..9f6367a8f9 100644 --- a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp +++ b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp @@ -1,167 +1,166 @@ /*============================================================================ 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 "mitkIOExtObjectFactory.h" #include "mitkCoreObjectFactory.h" #include "mitkParRecFileIOFactory.h" //#include "mitkObjFileIOFactory.h" #include "mitkStlVolumeTimeSeriesIOFactory.h" #include "mitkVtkVolumeTimeSeriesIOFactory.h" #include "mitkUnstructuredGridVtkWriter.h" #include "mitkUnstructuredGridVtkWriterFactory.h" #include "mitkVolumeMapperVtkSmart3D.h" #include "mitkUnstructuredGridMapper2D.h" #include "mitkUnstructuredGridVtkMapper3D.h" #include "mitkVtkGLMapperWrapper.h" #include #include #include mitk::IOExtObjectFactory::IOExtObjectFactory() : CoreObjectFactoryBase(), m_ParRecFileIOFactory(ParRecFileIOFactory::New().GetPointer()) //, m_ObjFileIOFactory(ObjFileIOFactory::New().GetPointer()) , m_StlVolumeTimeSeriesIOFactory(StlVolumeTimeSeriesIOFactory::New().GetPointer()), m_VtkVolumeTimeSeriesIOFactory(VtkVolumeTimeSeriesIOFactory::New().GetPointer()), m_UnstructuredGridVtkWriterFactory(UnstructuredGridVtkWriterFactory::New().GetPointer()) { static bool alreadyDone = false; if (!alreadyDone) { MITK_DEBUG << "IOExtObjectFactory c'tor" << std::endl; itk::ObjectFactoryBase::RegisterFactory(m_ParRecFileIOFactory); itk::ObjectFactoryBase::RegisterFactory(m_StlVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::RegisterFactory(m_VtkVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::RegisterFactory(m_UnstructuredGridVtkWriterFactory); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); CreateFileExtensionsMap(); alreadyDone = true; } } mitk::IOExtObjectFactory::~IOExtObjectFactory() { itk::ObjectFactoryBase::UnRegisterFactory(m_ParRecFileIOFactory); itk::ObjectFactoryBase::UnRegisterFactory(m_StlVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::UnRegisterFactory(m_VtkVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::UnRegisterFactory(m_UnstructuredGridVtkWriterFactory); } mitk::Mapper::Pointer mitk::IOExtObjectFactory::CreateMapper(mitk::DataNode *node, MapperSlotId id) { mitk::Mapper::Pointer newMapper = nullptr; mitk::BaseData *data = node->GetData(); if (id == mitk::BaseRenderer::Standard2D) { if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::VtkGLMapperWrapper::New(mitk::UnstructuredGridMapper2D::New().GetPointer()); newMapper->SetDataNode(node); } } else if (id == mitk::BaseRenderer::Standard3D) { if ((dynamic_cast(data) != nullptr) && std::string("Image").compare(node->GetData()->GetNameOfClass())==0) { - newMapper = mitk::VolumeMapperVtkSmart3D::New(); - newMapper->SetDataNode(node); + newMapper = mitk::VolumeMapperVtkSmart3D::New(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::UnstructuredGridVtkMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } void mitk::IOExtObjectFactory::SetDefaultProperties(mitk::DataNode *node) { if (node == nullptr) return; mitk::DataNode::Pointer nodePointer = node; mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { mitk::VolumeMapperVtkSmart3D::SetDefaultProperties(node); } if (dynamic_cast(node->GetData())) { mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(node); } } std::string mitk::IOExtObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::IOExtObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } mitk::CoreObjectFactoryBase::MultimapType mitk::IOExtObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::IOExtObjectFactory::CreateFileExtensionsMap() { m_FileExtensionsMap.insert(std::pair("*.vtu", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.vtk", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.pvtu", "VTK Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.pvtu", "VTK Parallel XML Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.vtu", "VTK XML Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.vtk", "VTK Legacy Unstructured Grid")); } std::string mitk::IOExtObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } struct RegisterIOExtObjectFactory { RegisterIOExtObjectFactory() : m_Factory(mitk::IOExtObjectFactory::New()) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(m_Factory); } ~RegisterIOExtObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory(m_Factory); } mitk::IOExtObjectFactory::Pointer m_Factory; }; static RegisterIOExtObjectFactory registerIOExtObjectFactory; diff --git a/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h b/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h index 34731725da..4ac917f499 100644 --- a/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h +++ b/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h @@ -1,75 +1,75 @@ /*============================================================================ 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 MITKVTKSMARTVOLUMEMAPPER_H_HEADER_INCLUDED #define MITKVTKSMARTVOLUMEMAPPER_H_HEADER_INCLUDED // MITK #include "MitkMapperExtExports.h" #include "mitkBaseRenderer.h" #include "mitkCommon.h" #include "mitkImage.h" #include "mitkVtkMapper.h" // VTK #include #include #include #include #include #include #include namespace mitk { //##Documentation //## @brief Vtk-based mapper for VolumeData //## //## @ingroup Mapper class MITKMAPPEREXT_EXPORT VolumeMapperVtkSmart3D : public VtkMapper { public: mitkClassMacro(VolumeMapperVtkSmart3D, VtkMapper); - itkFactorylessNewMacro(Self); + mitkNewMacro1Param(Self, mitk::DataNode::Pointer); itkCloneMacro(Self); vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; void ApplyProperties(vtkActor *actor, mitk::BaseRenderer *renderer) override; static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); protected: - VolumeMapperVtkSmart3D(); + VolumeMapperVtkSmart3D(mitk::DataNode::Pointer datanode); ~VolumeMapperVtkSmart3D() override; void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; void createMapper(vtkImageData*); void createVolume(); void createVolumeProperty(); vtkImageData* GetInputImage(); - vtkSmartPointer m_Volume; - vtkSmartPointer m_ImageChangeInformation; - vtkSmartPointer m_SmartVolumeMapper; - vtkSmartPointer m_VolumeProperty; + std::vector> m_Volume; + std::vector> m_ImageChangeInformation; + std::vector> m_SmartVolumeMapper; + std::vector> m_VolumeProperty; void UpdateTransferFunctions(mitk::BaseRenderer *renderer); void UpdateRenderMode(mitk::BaseRenderer *renderer); }; } // namespace mitk #endif /* MITKVTKSMARTVOLUMEMAPPER_H_HEADER_INCLUDED */ diff --git a/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp b/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp index ee9a32ef57..e4580ddf6d 100644 --- a/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp +++ b/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp @@ -1,237 +1,251 @@ /*============================================================================ 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 "mitkVolumeMapperVtkSmart3D.h" #include "mitkTransferFunctionProperty.h" #include "mitkTransferFunctionInitializer.h" #include "mitkLevelWindowProperty.h" #include #include #include #include void mitk::VolumeMapperVtkSmart3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { bool value; this->GetDataNode()->GetBoolProperty("volumerendering", value, renderer); + auto timestep = this->GetTimestep(); if (!value) { - m_Volume->VisibilityOff(); + m_Volume[timestep]->VisibilityOff(); return; } else { - m_Volume->VisibilityOn(); + m_Volume[timestep]->VisibilityOn(); } UpdateTransferFunctions(renderer); UpdateRenderMode(renderer); this->Modified(); } vtkProp* mitk::VolumeMapperVtkSmart3D::GetVtkProp(mitk::BaseRenderer *) { - if (!m_Volume->GetMapper()) + auto timestep = this->GetTimestep(); + if (!m_Volume[timestep]->GetMapper()) { createMapper(GetInputImage()); createVolume(); createVolumeProperty(); } - return m_Volume; + return m_Volume[timestep]; } void mitk::VolumeMapperVtkSmart3D::ApplyProperties(vtkActor *, mitk::BaseRenderer *) { } void mitk::VolumeMapperVtkSmart3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { // GPU_INFO << "SetDefaultProperties"; node->AddProperty("volumerendering", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.usemip", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.cpu.ambient", mitk::FloatProperty::New(0.10f), renderer, overwrite); node->AddProperty("volumerendering.cpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.cpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.cpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("volumerendering.usegpu", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.useray", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.gpu.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); node->AddProperty("volumerendering.gpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.gpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.gpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { if ((overwrite) || (node->GetProperty("TransferFunction", renderer) == nullptr)) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); tfInit->SetTransferFunctionMode(0); node->SetProperty("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkImageData* mitk::VolumeMapperVtkSmart3D::GetInputImage() { auto input = dynamic_cast(this->GetDataNode()->GetData()); return input->GetVtkImageData(this->GetTimestep()); } void mitk::VolumeMapperVtkSmart3D::createMapper(vtkImageData* imageData) { Vector3D spacing; FillVector3D(spacing, 1.0, 1.0, 1.0); + auto timestep = this->GetTimestep(); - m_ImageChangeInformation->SetInputData(imageData); - m_ImageChangeInformation->SetOutputSpacing(spacing.GetDataPointer()); + m_ImageChangeInformation[timestep]->SetInputData(imageData); + m_ImageChangeInformation[timestep]->SetOutputSpacing(spacing.GetDataPointer()); - m_SmartVolumeMapper->SetBlendModeToComposite(); - m_SmartVolumeMapper->SetInputConnection(m_ImageChangeInformation->GetOutputPort()); + m_SmartVolumeMapper[timestep]->SetBlendModeToComposite(); + m_SmartVolumeMapper[timestep]->SetInputConnection(m_ImageChangeInformation[timestep]->GetOutputPort()); } void mitk::VolumeMapperVtkSmart3D::createVolume() { - m_Volume->VisibilityOff(); - m_Volume->SetMapper(m_SmartVolumeMapper); - m_Volume->SetProperty(m_VolumeProperty); + auto timestep = this->GetTimestep(); + m_Volume[timestep]->SetMapper(m_SmartVolumeMapper[timestep]); + m_Volume[timestep]->SetProperty(m_VolumeProperty[timestep]); } void mitk::VolumeMapperVtkSmart3D::createVolumeProperty() { - m_VolumeProperty->ShadeOn(); - m_VolumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION); + auto timestep = this->GetTimestep(); + m_VolumeProperty[timestep]->ShadeOn(); + m_VolumeProperty[timestep]->SetInterpolationType(VTK_LINEAR_INTERPOLATION); } void mitk::VolumeMapperVtkSmart3D::UpdateTransferFunctions(mitk::BaseRenderer *renderer) { vtkSmartPointer opacityTransferFunction; vtkSmartPointer gradientTransferFunction; vtkSmartPointer colorTransferFunction; bool isBinary = false; this->GetDataNode()->GetBoolProperty("binary", isBinary, renderer); if (isBinary) { colorTransferFunction = vtkSmartPointer::New(); float rgb[3]; if (!GetDataNode()->GetColor(rgb, renderer)) rgb[0] = rgb[1] = rgb[2] = 1; colorTransferFunction->AddRGBPoint(0, rgb[0], rgb[1], rgb[2]); colorTransferFunction->Modified(); opacityTransferFunction = vtkSmartPointer::New(); gradientTransferFunction = vtkSmartPointer::New(); } else { auto *transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction", renderer)); if (transferFunctionProp) { opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); } else { opacityTransferFunction = vtkSmartPointer::New(); gradientTransferFunction = vtkSmartPointer::New(); colorTransferFunction = vtkSmartPointer::New(); } } - - m_VolumeProperty->SetColor(colorTransferFunction); - m_VolumeProperty->SetScalarOpacity(opacityTransferFunction); - m_VolumeProperty->SetGradientOpacity(gradientTransferFunction); + auto timestep = this->GetTimestep(); + m_VolumeProperty[timestep]->SetColor(colorTransferFunction); + m_VolumeProperty[timestep]->SetScalarOpacity(opacityTransferFunction); + m_VolumeProperty[timestep]->SetGradientOpacity(gradientTransferFunction); } void mitk::VolumeMapperVtkSmart3D::UpdateRenderMode(mitk::BaseRenderer *renderer) { bool usegpu = false; bool useray = false; bool usemip = false; this->GetDataNode()->GetBoolProperty("volumerendering.usegpu", usegpu); this->GetDataNode()->GetBoolProperty("volumerendering.useray", useray); this->GetDataNode()->GetBoolProperty("volumerendering.usemip", usemip); + auto timestep = this->GetTimestep(); if (usegpu) - m_SmartVolumeMapper->SetRequestedRenderModeToGPU(); + m_SmartVolumeMapper[timestep]->SetRequestedRenderModeToGPU(); else if (useray) - m_SmartVolumeMapper->SetRequestedRenderModeToRayCast(); + m_SmartVolumeMapper[timestep]->SetRequestedRenderModeToRayCast(); else - m_SmartVolumeMapper->SetRequestedRenderModeToDefault(); + m_SmartVolumeMapper[timestep]->SetRequestedRenderModeToDefault(); int blendMode; if (this->GetDataNode()->GetIntProperty("volumerendering.blendmode", blendMode)) - m_SmartVolumeMapper->SetBlendMode(blendMode); + m_SmartVolumeMapper[timestep]->SetBlendMode(blendMode); else if (usemip) - m_SmartVolumeMapper->SetBlendMode(vtkSmartVolumeMapper::MAXIMUM_INTENSITY_BLEND); + m_SmartVolumeMapper[timestep]->SetBlendMode(vtkSmartVolumeMapper::MAXIMUM_INTENSITY_BLEND); // shading parameter - if (m_SmartVolumeMapper->GetRequestedRenderMode() == vtkSmartVolumeMapper::GPURenderMode) + if (m_SmartVolumeMapper[timestep]->GetRequestedRenderMode() == vtkSmartVolumeMapper::GPURenderMode) { float value = 0; if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.ambient", value, renderer)) - m_VolumeProperty->SetAmbient(value); + m_VolumeProperty[timestep]->SetAmbient(value); if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.diffuse", value, renderer)) - m_VolumeProperty->SetDiffuse(value); + m_VolumeProperty[timestep]->SetDiffuse(value); if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.specular", value, renderer)) - m_VolumeProperty->SetSpecular(value); + m_VolumeProperty[timestep]->SetSpecular(value); if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.specular.power", value, renderer)) - m_VolumeProperty->SetSpecularPower(value); + m_VolumeProperty[timestep]->SetSpecularPower(value); } else { float value = 0; if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient", value, renderer)) - m_VolumeProperty->SetAmbient(value); + m_VolumeProperty[timestep]->SetAmbient(value); if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse", value, renderer)) - m_VolumeProperty->SetDiffuse(value); + m_VolumeProperty[timestep]->SetDiffuse(value); if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.specular", value, renderer)) - m_VolumeProperty->SetSpecular(value); + m_VolumeProperty[timestep]->SetSpecular(value); if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power", value, renderer)) - m_VolumeProperty->SetSpecularPower(value); + m_VolumeProperty[timestep]->SetSpecularPower(value); } } -mitk::VolumeMapperVtkSmart3D::VolumeMapperVtkSmart3D() +mitk::VolumeMapperVtkSmart3D::VolumeMapperVtkSmart3D(mitk::DataNode::Pointer datanode) { - m_SmartVolumeMapper = vtkSmartPointer::New(); - m_SmartVolumeMapper->SetBlendModeToComposite(); - m_ImageChangeInformation = vtkSmartPointer::New(); - m_VolumeProperty = vtkSmartPointer::New(); - m_Volume = vtkSmartPointer::New(); + this->SetDataNode(datanode); + int timesteps = this->GetDataNode()->GetData()->GetTimeSteps(); + for (int i = 0; i < timesteps; i++) + { + auto volumeMapper = vtkSmartPointer::New(); + volumeMapper->SetBlendModeToComposite(); + m_SmartVolumeMapper.push_back(volumeMapper); + auto imageChangeInformation = vtkSmartPointer::New(); + m_ImageChangeInformation.push_back(imageChangeInformation); + auto volumeProperty = vtkSmartPointer::New(); + m_VolumeProperty.push_back(volumeProperty); + auto volume = vtkSmartPointer::New(); + m_Volume.push_back(volume); + } } mitk::VolumeMapperVtkSmart3D::~VolumeMapperVtkSmart3D() { } diff --git a/Modules/QtWidgetsExt/include/QmitkTransferFunctionGeneratorWidget.h b/Modules/QtWidgetsExt/include/QmitkTransferFunctionGeneratorWidget.h index 5bf7ea8d64..e766708959 100644 --- a/Modules/QtWidgetsExt/include/QmitkTransferFunctionGeneratorWidget.h +++ b/Modules/QtWidgetsExt/include/QmitkTransferFunctionGeneratorWidget.h @@ -1,80 +1,80 @@ /*============================================================================ 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 QMITKTRANSFERFUNCTIONGENERATORWIDGET_H #define QMITKTRANSFERFUNCTIONGENERATORWIDGET_H #include "MitkQtWidgetsExtExports.h" #include "ui_QmitkTransferFunctionGeneratorWidget.h" #include #include #include #include class MITKQTWIDGETSEXT_EXPORT QmitkTransferFunctionGeneratorWidget : public QWidget, public Ui::QmitkTransferFunctionGeneratorWidget { Q_OBJECT public: QmitkTransferFunctionGeneratorWidget(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); ~QmitkTransferFunctionGeneratorWidget() override; - void SetDataNode(mitk::DataNode *node); + void SetDataNode(mitk::DataNode *node, int timestep = 0); int AddPreset(const QString &presetName); void SetPresetsTabEnabled(bool enable); void SetThresholdTabEnabled(bool enable); void SetBellTabEnabled(bool enable); public slots: void OnSavePreset(); void OnLoadPreset(); void OnDeltaLevelWindow(int dx, int dy); void OnDeltaThreshold(int dx, int dy); signals: void SignalTransferFunctionModeChanged(int); void SignalUpdateCanvas(); protected slots: void OnPreset(int mode); protected: mitk::TransferFunctionProperty::Pointer tfpToChange; double histoMinimum; double histoMaximum; double thPos; double thDelta; double deltaScale; double deltaMax; double deltaMin; const mitk::Image::HistogramType *histoGramm; QString presetFileName; double ScaleDelta(int d) const; }; #endif diff --git a/Modules/QtWidgetsExt/include/QmitkTransferFunctionWidget.h b/Modules/QtWidgetsExt/include/QmitkTransferFunctionWidget.h index d1d5a901d4..9e73f53443 100755 --- a/Modules/QtWidgetsExt/include/QmitkTransferFunctionWidget.h +++ b/Modules/QtWidgetsExt/include/QmitkTransferFunctionWidget.h @@ -1,79 +1,79 @@ /*============================================================================ 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 QMITKTRANSFERFUNCTIONWIDGET_H #define QMITKTRANSFERFUNCTIONWIDGET_H #include "MitkQtWidgetsExtExports.h" #include "ui_QmitkTransferFunctionWidget.h" #include #include #include #include #include #include #include namespace mitk { class BaseRenderer; } class MITKQTWIDGETSEXT_EXPORT QmitkTransferFunctionWidget : public QWidget, public Ui::QmitkTransferFunctionWidget { Q_OBJECT public: QmitkTransferFunctionWidget(QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); ~QmitkTransferFunctionWidget() override; - void SetDataNode(mitk::DataNode *node, const mitk::BaseRenderer *renderer = nullptr); + void SetDataNode(mitk::DataNode *node, int timestep = 0, const mitk::BaseRenderer *renderer = nullptr); void SetScalarLabel(const QString &scalarLabel); void ShowScalarOpacityFunction(bool show); void ShowColorFunction(bool show); void ShowGradientOpacityFunction(bool show); void SetScalarOpacityFunctionEnabled(bool enable); void SetColorFunctionEnabled(bool enable); void SetGradientOpacityFunctionEnabled(bool enable); public slots: void SetXValueScalar(const QString text); void SetYValueScalar(const QString text); void SetXValueGradient(const QString text); void SetYValueGradient(const QString text); void SetXValueColor(const QString text); void OnUpdateCanvas(); void UpdateRanges(); void OnResetSlider(); void OnSpanChanged(int lower, int upper); protected: mitk::TransferFunctionProperty::Pointer tfpToChange; int m_RangeSliderMin; int m_RangeSliderMax; mitk::SimpleHistogramCache histogramCache; }; #endif diff --git a/Modules/QtWidgetsExt/src/QmitkTransferFunctionGeneratorWidget.cpp b/Modules/QtWidgetsExt/src/QmitkTransferFunctionGeneratorWidget.cpp index e244bb77a1..9acb8d8e44 100644 --- a/Modules/QtWidgetsExt/src/QmitkTransferFunctionGeneratorWidget.cpp +++ b/Modules/QtWidgetsExt/src/QmitkTransferFunctionGeneratorWidget.cpp @@ -1,353 +1,367 @@ /*============================================================================ 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 "QmitkTransferFunctionGeneratorWidget.h" #include #include #include #include #include #include #include #include #include QmitkTransferFunctionGeneratorWidget::QmitkTransferFunctionGeneratorWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), deltaScale(1.0), deltaMax(1024), deltaMin(1) { histoGramm = nullptr; this->setupUi(this); // LevelWindow Tab { connect(m_CrossLevelWindow, SIGNAL(SignalDeltaMove(int, int)), this, SLOT(OnDeltaLevelWindow(int, int))); } // Threshold Tab { connect(m_CrossThreshold, SIGNAL(SignalDeltaMove(int, int)), this, SLOT(OnDeltaThreshold(int, int))); thDelta = 100; } // Presets Tab { m_TransferFunctionComboBox->setVisible(false); connect(m_TransferFunctionComboBox, SIGNAL(activated(int)), this, SIGNAL(SignalTransferFunctionModeChanged(int))); connect(m_TransferFunctionComboBox, SIGNAL(activated(int)), this, SLOT(OnPreset(int))); connect(m_SavePreset, SIGNAL(clicked()), this, SLOT(OnSavePreset())); connect(m_LoadPreset, SIGNAL(clicked()), this, SLOT(OnLoadPreset())); } presetFileName = "."; } int QmitkTransferFunctionGeneratorWidget::AddPreset(const QString &presetName) { m_TransferFunctionComboBox->setVisible(true); m_TransferFunctionComboBox->addItem(presetName); return m_TransferFunctionComboBox->count() - 1; } void QmitkTransferFunctionGeneratorWidget::SetPresetsTabEnabled(bool enable) { m_PresetTab->setEnabled(enable); } void QmitkTransferFunctionGeneratorWidget::SetThresholdTabEnabled(bool enable) { m_ThresholdTab->setEnabled(enable); } void QmitkTransferFunctionGeneratorWidget::SetBellTabEnabled(bool enable) { m_BellTab->setEnabled(enable); } void QmitkTransferFunctionGeneratorWidget::OnSavePreset() { if (tfpToChange.IsNull()) return; mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); presetFileName = QFileDialog::getSaveFileName( this, "Choose a filename to save the transfer function", presetFileName, "Transferfunction (*.xml)"); if (!presetFileName.endsWith(".xml")) presetFileName.append(".xml"); MITK_INFO << "Saving Transferfunction under path: " << presetFileName.toStdString(); if (mitk::TransferFunctionPropertySerializer::SerializeTransferFunction(presetFileName.toLatin1(), tf)) { QFontMetrics metrics(m_InfoPreset->font()); QString text = metrics.elidedText(presetFileName, Qt::ElideMiddle, m_InfoPreset->width()); m_InfoPreset->setText(QString("saved ") + text); } else { m_InfoPreset->setText(QString("saving failed")); } } void QmitkTransferFunctionGeneratorWidget::OnLoadPreset() { if (tfpToChange.IsNull()) return; presetFileName = QFileDialog::getOpenFileName( this, "Choose a file to open the transfer function from", presetFileName, "Transferfunction (*.xml)"); MITK_INFO << "Loading Transferfunction from path: " << presetFileName.toStdString(); mitk::TransferFunction::Pointer tf = mitk::TransferFunctionPropertySerializer::DeserializeTransferFunction(presetFileName.toLatin1()); if (tf.IsNotNull()) { tfpToChange->SetValue(tf); QFontMetrics metrics(m_InfoPreset->font()); QString text = metrics.elidedText(presetFileName, Qt::ElideMiddle, m_InfoPreset->width()); m_InfoPreset->setText(QString("loaded ") + text); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); emit SignalUpdateCanvas(); } } void QmitkTransferFunctionGeneratorWidget::OnPreset(int mode) { // first item is only information if (--mode == -1) return; m_InfoPreset->setText(QString("selected ") + m_TransferFunctionComboBox->currentText()); // revert to first item m_TransferFunctionComboBox->setCurrentIndex(0); } static double transformationGlocke(double x) { double z = 0.1; double a = 2 - 2 * z; double b = 2 * z - 1; x = a * x + b; return x; } static double stepFunctionGlocke(double x) { x = 1 - (2 * x - 1.0); // map [0.5;1] to [0,1] x = x * (3 * x - 2 * x * x); // apply smoothing function x = x * x; return x; } double QmitkTransferFunctionGeneratorWidget::ScaleDelta(int d) const { return deltaScale * (double)d; } void QmitkTransferFunctionGeneratorWidget::OnDeltaLevelWindow(int dx, int dy) // bell { if (tfpToChange.IsNull()) return; thPos += ScaleDelta(dx); thDelta -= ScaleDelta(dy); if (thDelta < deltaMin) thDelta = deltaMin; if (thDelta > deltaMax) thDelta = deltaMax; if (thPos < histoMinimum) thPos = histoMinimum; if (thPos > histoMaximum) thPos = histoMaximum; std::stringstream ss; ss << "Click on the cross and move the mouse" << "\n" << "\n" << "center at " << thPos << "\n" << "width " << thDelta * 2; m_InfoLevelWindow->setText(QString(ss.str().c_str())); mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); // grayvalue->opacity { vtkPiecewiseFunction *f = tf->GetScalarOpacityFunction(); f->RemoveAllPoints(); for (int r = 0; r <= 6; r++) { double relPos = (r / 6.0) * 0.5 + 0.5; f->AddPoint(thPos + thDelta * (-transformationGlocke(relPos)), stepFunctionGlocke(relPos)); f->AddPoint(thPos + thDelta * (transformationGlocke(relPos)), stepFunctionGlocke(relPos)); } f->Modified(); } // gradient at grayvalue->opacity { vtkPiecewiseFunction *f = tf->GetGradientOpacityFunction(); f->RemoveAllPoints(); f->AddPoint(0, 1.0); f->Modified(); } tf->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); emit SignalUpdateCanvas(); } static double stepFunctionThreshold(double x) { x = 0.5 * x + 0.5; // map [-1;1] to [0,1] x = x * (3 * x - 2 * x * x); // apply smoothing function x = x * x; return x; } void QmitkTransferFunctionGeneratorWidget::OnDeltaThreshold(int dx, int dy) // LEVELWINDOW { if (tfpToChange.IsNull()) return; thPos += ScaleDelta(dx); thDelta += ScaleDelta(dy); if (thDelta < deltaMin) thDelta = deltaMin; if (thDelta > deltaMax) thDelta = deltaMax; if (thPos < histoMinimum) thPos = histoMinimum; if (thPos > histoMaximum) thPos = histoMaximum; std::stringstream ss; ss << "Click on the cross and move the mouse" << "\n" << "\n" << "threshold at " << thPos << "\n" << "width " << thDelta * 2; m_InfoThreshold->setText(QString(ss.str().c_str())); mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); // grayvalue->opacity { vtkPiecewiseFunction *f = tf->GetScalarOpacityFunction(); f->RemoveAllPoints(); for (int r = 1; r <= 4; r++) { double relPos = r / 4.0; f->AddPoint(thPos + thDelta * (-relPos), stepFunctionThreshold(-relPos)); f->AddPoint(thPos + thDelta * (relPos), stepFunctionThreshold(relPos)); } f->Modified(); } // gradient at grayvalue->opacity { vtkPiecewiseFunction *f = tf->GetGradientOpacityFunction(); f->RemoveAllPoints(); f->AddPoint(0, 1.0); f->Modified(); } tf->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); emit SignalUpdateCanvas(); } QmitkTransferFunctionGeneratorWidget::~QmitkTransferFunctionGeneratorWidget() { } -void QmitkTransferFunctionGeneratorWidget::SetDataNode(mitk::DataNode *node) +void QmitkTransferFunctionGeneratorWidget::SetDataNode(mitk::DataNode *node, int timestep) { histoGramm = nullptr; if (node) { tfpToChange = dynamic_cast(node->GetProperty("TransferFunction")); if (!tfpToChange) node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New()); mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); if (mitk::Image *image = dynamic_cast(node->GetData())) { - mitk::ImageStatisticsHolder *statistics = image->GetStatistics(); - histoMinimum = statistics->GetScalarValueMin(); - histoMaximum = statistics->GetScalarValueMax(); + if (image->GetTimeSteps() > 1) + { + mitk::ImageTimeSelector::Pointer timeselector = mitk::ImageTimeSelector::New(); + timeselector->SetInput(image); + timeselector->SetTimeNr(timestep); + timeselector->UpdateLargestPossibleRegion(); + auto inputImage = timeselector->GetOutput(); + mitk::ImageStatisticsHolder *statistics = inputImage->GetStatistics(); + histoMinimum = statistics->GetScalarValueMin(); + histoMaximum = statistics->GetScalarValueMax(); + } + else + { + mitk::ImageStatisticsHolder *statistics = image->GetStatistics(); + histoMinimum = statistics->GetScalarValueMin(); + histoMaximum = statistics->GetScalarValueMax(); + } } else if (mitk::UnstructuredGrid *grid = dynamic_cast(node->GetData())) { double *range = grid->GetVtkUnstructuredGrid()->GetScalarRange(); histoMinimum = range[0]; histoMaximum = range[1]; double histoRange = histoMaximum - histoMinimum; deltaMax = histoRange / 4.0; deltaMin = histoRange / 400.0; deltaScale = histoRange / 1024.0; } else { MITK_WARN << "QmitkTransferFunctonGeneratorWidget does not support " << node->GetData()->GetNameOfClass() << " instances"; } thPos = (histoMinimum + histoMaximum) / 2.0; } else { tfpToChange = nullptr; m_InfoPreset->setText(QString("")); } } diff --git a/Modules/QtWidgetsExt/src/QmitkTransferFunctionWidget.cpp b/Modules/QtWidgetsExt/src/QmitkTransferFunctionWidget.cpp index bde5c54854..4aa40b2d62 100755 --- a/Modules/QtWidgetsExt/src/QmitkTransferFunctionWidget.cpp +++ b/Modules/QtWidgetsExt/src/QmitkTransferFunctionWidget.cpp @@ -1,246 +1,259 @@ /*============================================================================ 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 "QmitkTransferFunctionWidget.h" +#include "mitkImageTimeSelector.h" #include QmitkTransferFunctionWidget::QmitkTransferFunctionWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) { this->setupUi(this); // signals and slots connections connect(m_XEditScalarOpacity, SIGNAL(textEdited(const QString &)), this, SLOT(SetXValueScalar(const QString &))); connect(m_YEditScalarOpacity, SIGNAL(textEdited(const QString &)), this, SLOT(SetYValueScalar(const QString &))); connect(m_XEditGradientOpacity, SIGNAL(textEdited(const QString &)), this, SLOT(SetXValueGradient(const QString &))); connect(m_YEditGradientOpacity, SIGNAL(textEdited(const QString &)), this, SLOT(SetYValueGradient(const QString &))); connect(m_XEditColor, SIGNAL(textEdited(const QString &)), this, SLOT(SetXValueColor(const QString &))); m_RangeSlider->setMinimum(-2048); m_RangeSlider->setMaximum(2048); connect(m_RangeSlider, SIGNAL(valuesChanged(int, int)), this, SLOT(OnSpanChanged(int, int))); // reset button connect(m_RangeSliderReset, SIGNAL(pressed()), this, SLOT(OnResetSlider())); m_ScalarOpacityFunctionCanvas->SetQLineEdits(m_XEditScalarOpacity, m_YEditScalarOpacity); m_GradientOpacityCanvas->SetQLineEdits(m_XEditGradientOpacity, m_YEditGradientOpacity); m_ColorTransferFunctionCanvas->SetQLineEdits(m_XEditColor, nullptr); m_ScalarOpacityFunctionCanvas->SetTitle("Grayvalue -> Opacity"); m_GradientOpacityCanvas->SetTitle("Grayvalue/Gradient -> Opacity"); m_ColorTransferFunctionCanvas->SetTitle("Grayvalue -> Color"); } QmitkTransferFunctionWidget::~QmitkTransferFunctionWidget() { } void QmitkTransferFunctionWidget::SetScalarLabel(const QString &scalarLabel) { m_textLabelX->setText(scalarLabel); m_textLabelX_2->setText(scalarLabel); m_textLabelX_3->setText(scalarLabel); m_ScalarOpacityFunctionCanvas->SetTitle(scalarLabel + " -> Opacity"); m_GradientOpacityCanvas->SetTitle(scalarLabel + "/Gradient -> Opacity"); m_ColorTransferFunctionCanvas->SetTitle(scalarLabel + " -> Color"); } void QmitkTransferFunctionWidget::ShowScalarOpacityFunction(bool show) { m_ScalarOpacityWidget->setVisible(show); } void QmitkTransferFunctionWidget::ShowColorFunction(bool show) { m_ColorWidget->setVisible(show); } void QmitkTransferFunctionWidget::ShowGradientOpacityFunction(bool show) { m_GradientOpacityWidget->setVisible(show); } void QmitkTransferFunctionWidget::SetScalarOpacityFunctionEnabled(bool enable) { m_ScalarOpacityWidget->setEnabled(enable); } void QmitkTransferFunctionWidget::SetColorFunctionEnabled(bool enable) { m_ColorWidget->setEnabled(enable); } void QmitkTransferFunctionWidget::SetGradientOpacityFunctionEnabled(bool enable) { m_GradientOpacityWidget->setEnabled(enable); } -void QmitkTransferFunctionWidget::SetDataNode(mitk::DataNode *node, const mitk::BaseRenderer *renderer) +void QmitkTransferFunctionWidget::SetDataNode(mitk::DataNode *node, int timestep, const mitk::BaseRenderer *renderer) { if (node) { tfpToChange = dynamic_cast(node->GetProperty("TransferFunction", renderer)); - if (!tfpToChange) { if (!dynamic_cast(node->GetData())) { MITK_WARN << "QmitkTransferFunctionWidget::SetDataNode called with non-image node"; goto turnOff; } node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New()); } mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); - if (mitk::BaseData *data = node->GetData()) + if (mitk::Image *data = dynamic_cast(node->GetData())) { - mitk::SimpleHistogram *h = histogramCache[data]; + mitk::SimpleHistogram *h = nullptr; + if (data->GetTimeSteps() > 1) + { + mitk::ImageTimeSelector::Pointer timeselector = mitk::ImageTimeSelector::New(); + timeselector->SetInput(data); + timeselector->SetTimeNr(timestep); + timeselector->UpdateLargestPossibleRegion(); + auto inputImage = timeselector->GetOutput(); + h = histogramCache[inputImage]; + } + else + { + h = histogramCache[data]; + } m_RangeSliderMin = h->GetMin(); m_RangeSliderMax = h->GetMax(); m_RangeSlider->blockSignals(true); m_RangeSlider->setMinimum(m_RangeSliderMin); m_RangeSlider->setMaximum(m_RangeSliderMax); m_RangeSlider->setMinimumValue(m_RangeSliderMin); m_RangeSlider->setMaximumValue(m_RangeSliderMax); m_RangeSlider->blockSignals(false); m_ScalarOpacityFunctionCanvas->SetHistogram(h); m_GradientOpacityCanvas->SetHistogram(h); m_ColorTransferFunctionCanvas->SetHistogram(h); } OnUpdateCanvas(); return; } turnOff: m_ScalarOpacityFunctionCanvas->setEnabled(false); m_ScalarOpacityFunctionCanvas->SetHistogram(nullptr); m_GradientOpacityCanvas->setEnabled(false); m_GradientOpacityCanvas->SetHistogram(nullptr); m_ColorTransferFunctionCanvas->setEnabled(false); m_ColorTransferFunctionCanvas->SetHistogram(nullptr); tfpToChange = nullptr; } void QmitkTransferFunctionWidget::OnUpdateCanvas() { if (tfpToChange.IsNull()) return; mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); if (tf.IsNull()) return; m_ScalarOpacityFunctionCanvas->SetPiecewiseFunction(tf->GetScalarOpacityFunction()); m_GradientOpacityCanvas->SetPiecewiseFunction(tf->GetGradientOpacityFunction()); m_ColorTransferFunctionCanvas->SetColorTransferFunction(tf->GetColorTransferFunction()); UpdateRanges(); m_ScalarOpacityFunctionCanvas->update(); m_GradientOpacityCanvas->update(); m_ColorTransferFunctionCanvas->update(); } void QmitkTransferFunctionWidget::SetXValueScalar(const QString text) { if (!text.endsWith(".")) { m_ScalarOpacityFunctionCanvas->SetX(text.toFloat()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionWidget::SetYValueScalar(const QString text) { if (!text.endsWith(".")) { m_ScalarOpacityFunctionCanvas->SetY(text.toFloat()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionWidget::SetXValueGradient(const QString text) { if (!text.endsWith(".")) { m_GradientOpacityCanvas->SetX(text.toFloat()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionWidget::SetYValueGradient(const QString text) { if (!text.endsWith(".")) { m_GradientOpacityCanvas->SetY(text.toFloat()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionWidget::SetXValueColor(const QString text) { if (!text.endsWith(".")) { m_ColorTransferFunctionCanvas->SetX(text.toFloat()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionWidget::UpdateRanges() { int lower = m_RangeSlider->minimumValue(); int upper = m_RangeSlider->maximumValue(); m_ScalarOpacityFunctionCanvas->SetMin(lower); m_ScalarOpacityFunctionCanvas->SetMax(upper); m_GradientOpacityCanvas->SetMin(lower); m_GradientOpacityCanvas->SetMax(upper); m_ColorTransferFunctionCanvas->SetMin(lower); m_ColorTransferFunctionCanvas->SetMax(upper); } void QmitkTransferFunctionWidget::OnSpanChanged(int, int) { UpdateRanges(); m_GradientOpacityCanvas->update(); m_ColorTransferFunctionCanvas->update(); m_ScalarOpacityFunctionCanvas->update(); } void QmitkTransferFunctionWidget::OnResetSlider() { m_RangeSlider->blockSignals(true); m_RangeSlider->setMaximumValue(m_RangeSliderMax); m_RangeSlider->setMinimumValue(m_RangeSliderMin); m_RangeSlider->blockSignals(false); UpdateRanges(); m_GradientOpacityCanvas->update(); m_ColorTransferFunctionCanvas->update(); m_ScalarOpacityFunctionCanvas->update(); } diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp index 2e931cec19..c33755a5dc 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp @@ -1,293 +1,315 @@ /*============================================================================ 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 "QmitkVolumeVisualizationView.h" #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkVolumeVisualizationView::VIEW_ID = "org.mitk.views.volumevisualization"; enum { DEFAULT_RENDERMODE = 0, RAYCAST_RENDERMODE = 1, GPU_RENDERMODE = 2 }; QmitkVolumeVisualizationView::QmitkVolumeVisualizationView() : QmitkAbstractView() , m_Controls(nullptr) { } void QmitkVolumeVisualizationView::SetFocus() { UpdateInterface(); } void QmitkVolumeVisualizationView::CreateQtPartControl(QWidget* parent) { m_Controls = new Ui::QmitkVolumeVisualizationViewControls; m_Controls->setupUi(parent); m_Controls->volumeSelectionWidget->SetDataStorage(GetDataStorage()); m_Controls->volumeSelectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateOr::New(mitk::NodePredicateDimension::New(3), mitk::NodePredicateDimension::New(4)), mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object")))); m_Controls->volumeSelectionWidget->SetSelectionIsOptional(true); m_Controls->volumeSelectionWidget->SetEmptyInfo(QString("Please select a 3D / 4D image volume")); m_Controls->volumeSelectionWidget->SetPopUpTitel(QString("Select image volume")); // Fill the transfer function presets in the generator widget std::vector names; mitk::TransferFunctionInitializer::GetPresetNames(names); for (const auto& name : names) { m_Controls->transferFunctionGeneratorWidget->AddPreset(QString::fromStdString(name)); } // see enum in vtkSmartVolumeMapper m_Controls->renderMode->addItem("Default"); m_Controls->renderMode->addItem("RayCast"); m_Controls->renderMode->addItem("GPU"); // see vtkVolumeMapper::BlendModes m_Controls->blendMode->addItem("Comp"); m_Controls->blendMode->addItem("Max"); m_Controls->blendMode->addItem("Min"); m_Controls->blendMode->addItem("Avg"); m_Controls->blendMode->addItem("Add"); connect(m_Controls->volumeSelectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkVolumeVisualizationView::OnCurrentSelectionChanged); connect(m_Controls->enableRenderingCB, SIGNAL(toggled(bool)), this, SLOT(OnEnableRendering(bool))); connect(m_Controls->renderMode, SIGNAL(activated(int)), this, SLOT(OnRenderMode(int))); connect(m_Controls->blendMode, SIGNAL(activated(int)), this, SLOT(OnBlendMode(int))); connect(m_Controls->transferFunctionGeneratorWidget, SIGNAL(SignalUpdateCanvas()), m_Controls->transferFunctionWidget, SLOT(OnUpdateCanvas())); connect(m_Controls->transferFunctionGeneratorWidget, SIGNAL(SignalTransferFunctionModeChanged(int)), SLOT(OnMitkInternalPreset(int))); m_Controls->enableRenderingCB->setEnabled(false); m_Controls->blendMode->setEnabled(false); m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); m_Controls->volumeSelectionWidget->SetAutoSelectNewNodes(true); + + this->m_TimePointChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); + connect(&m_TimePointChangeListener, + &QmitkSliceNavigationListener::SelectedTimePointChanged, + this, + &QmitkVolumeVisualizationView::OnSelectedTimePointChanged); +} + +void QmitkVolumeVisualizationView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) +{ + this->m_TimePointChangeListener.RenderWindowPartActivated(renderWindowPart); +} + +void QmitkVolumeVisualizationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart) +{ + this->m_TimePointChangeListener.RenderWindowPartDeactivated(renderWindowPart); } void QmitkVolumeVisualizationView::OnMitkInternalPreset(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto node = m_SelectedNode.Lock(); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction")) { // first item is only information if (--mode == -1) return; // -- Creat new TransferFunction mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(transferFuncProp->GetValue()); tfInit->SetTransferFunctionMode(mode); RequestRenderWindowUpdate(); m_Controls->transferFunctionWidget->OnUpdateCanvas(); } } void QmitkVolumeVisualizationView::OnCurrentSelectionChanged(QList nodes) { m_SelectedNode = nullptr; if (nodes.empty() || nodes.front().IsNull()) { UpdateInterface(); return; } auto selectedNode = nodes.front(); auto image = dynamic_cast(selectedNode->GetData()); if (nullptr != image) { m_SelectedNode = selectedNode; } UpdateInterface(); } void QmitkVolumeVisualizationView::OnEnableRendering(bool state) { if (m_SelectedNode.IsExpired()) { return; } m_SelectedNode.Lock()->SetProperty("volumerendering", mitk::BoolProperty::New(state)); UpdateInterface(); RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::OnRenderMode(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto selectedNode = m_SelectedNode.Lock(); bool usegpu = false; bool useray = false; if (DEFAULT_RENDERMODE == mode) { useray = true; usegpu = true; } else if (GPU_RENDERMODE == mode) { usegpu = true; } else if (RAYCAST_RENDERMODE == mode) { useray = true; } selectedNode->SetProperty("volumerendering.usegpu", mitk::BoolProperty::New(usegpu)); selectedNode->SetProperty("volumerendering.useray", mitk::BoolProperty::New(useray)); RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::OnBlendMode(int mode) { if (m_SelectedNode.IsExpired()) { return; } auto selectedNode = m_SelectedNode.Lock(); bool usemip = false; if (vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND == mode) { usemip = true; } selectedNode->SetProperty("volumerendering.usemip", mitk::BoolProperty::New(usemip)); selectedNode->SetProperty("volumerendering.blendmode", mitk::IntProperty::New(mode)); RequestRenderWindowUpdate(); } +void QmitkVolumeVisualizationView::OnSelectedTimePointChanged(const mitk::TimePointType & /*newTimePoint*/) +{ + this->UpdateInterface(); +} + void QmitkVolumeVisualizationView::UpdateInterface() { if (m_SelectedNode.IsExpired()) { // turnoff all m_Controls->enableRenderingCB->setChecked(false); m_Controls->enableRenderingCB->setEnabled(false); m_Controls->blendMode->setCurrentIndex(0); m_Controls->blendMode->setEnabled(false); m_Controls->renderMode->setCurrentIndex(0); m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->SetDataNode(nullptr); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->SetDataNode(nullptr); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); return; } bool enabled = false; auto selectedNode = m_SelectedNode.Lock(); selectedNode->GetBoolProperty("volumerendering", enabled); m_Controls->enableRenderingCB->setEnabled(true); m_Controls->enableRenderingCB->setChecked(enabled); if (!enabled) { // turnoff all except volumerendering checkbox m_Controls->blendMode->setCurrentIndex(0); m_Controls->blendMode->setEnabled(false); m_Controls->renderMode->setCurrentIndex(0); m_Controls->renderMode->setEnabled(false); m_Controls->transferFunctionWidget->SetDataNode(nullptr); m_Controls->transferFunctionWidget->setEnabled(false); m_Controls->transferFunctionGeneratorWidget->SetDataNode(nullptr); m_Controls->transferFunctionGeneratorWidget->setEnabled(false); return; } // otherwise we can activate em all m_Controls->blendMode->setEnabled(true); m_Controls->renderMode->setEnabled(true); // Determine Combo Box mode { bool usegpu = false; bool useray = false; bool usemip = false; selectedNode->GetBoolProperty("volumerendering.usegpu", usegpu); selectedNode->GetBoolProperty("volumerendering.useray", useray); selectedNode->GetBoolProperty("volumerendering.usemip", usemip); int blendMode; if (selectedNode->GetIntProperty("volumerendering.blendmode", blendMode)) m_Controls->blendMode->setCurrentIndex(blendMode); if (usemip) m_Controls->blendMode->setCurrentIndex(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND); int mode = DEFAULT_RENDERMODE; if (useray) mode = RAYCAST_RENDERMODE; else if (usegpu) mode = GPU_RENDERMODE; m_Controls->renderMode->setCurrentIndex(mode); } - - m_Controls->transferFunctionWidget->SetDataNode(selectedNode); + auto time = this->GetRenderWindowPart()->GetTimeNavigationController()->GetSelectedTimeStep(); + MITK_INFO << time; + m_Controls->transferFunctionWidget->SetDataNode(selectedNode, time); m_Controls->transferFunctionWidget->setEnabled(true); - m_Controls->transferFunctionGeneratorWidget->SetDataNode(selectedNode); + m_Controls->transferFunctionGeneratorWidget->SetDataNode(selectedNode, time); m_Controls->transferFunctionGeneratorWidget->setEnabled(true); } diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h index 5d413576f2..658d5fc133 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h @@ -1,61 +1,69 @@ /*============================================================================ 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 QMITKVOLUMEVISUALIZATIONVIEW_H #define QMITKVOLUMEVISUALIZATIONVIEW_H #include "ui_QmitkVolumeVisualizationViewControls.h" // mitk core #include #include #include +#include +#include /** * @brief */ -class QmitkVolumeVisualizationView : public QmitkAbstractView +class QmitkVolumeVisualizationView : public QmitkAbstractView, public mitk::IRenderWindowPartListener { Q_OBJECT public: static const std::string VIEW_ID; QmitkVolumeVisualizationView(); ~QmitkVolumeVisualizationView() override = default; void SetFocus() override; private Q_SLOTS: void OnCurrentSelectionChanged(QList nodes); void OnMitkInternalPreset(int mode); void OnEnableRendering(bool state); void OnRenderMode(int mode); void OnBlendMode(int mode); + void OnSelectedTimePointChanged(const mitk::TimePointType &); + +protected: + void RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) override; + void RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart) override; private: void CreateQtPartControl(QWidget* parent) override; void UpdateInterface(); Ui::QmitkVolumeVisualizationViewControls* m_Controls; mitk::WeakPointer m_SelectedNode; + QmitkSliceNavigationListener m_TimePointChangeListener; }; #endif // QMITKVOLUMEVISUALIZATIONVIEW_H