diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.cpp index 6dbca7e573..095153cb34 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.cpp @@ -1,619 +1,584 @@ /*============================================================================ 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 "QmitkDeformableClippingPlaneView.h" -#include "mitkClippingPlaneInteractor3D.h" -#include "mitkHeightFieldSurfaceClipImageFilter.h" -#include -#include "mitkImageToSurfaceFilter.h" -#include "mitkInteractionConst.h" -#include "mitkLabeledImageLookupTable.h" -#include "mitkLabeledImageVolumeCalculator.h" -#include "mitkLevelWindowProperty.h" -#include "mitkLookupTableProperty.h" -#include "mitkNodePredicateProperty.h" -#include "mitkNodePredicateDataType.h" -#include "mitkRenderingModeProperty.h" -#include "mitkRotationOperation.h" -#include "mitkSurfaceDeformationDataInteractor3D.h" -#include "mitkSurfaceVtkMapper3D.h" -#include "mitkVtkRepresentationProperty.h" -#include "mitkVtkResliceInterpolationProperty.h" -#include "usModuleRegistry.h" - -#include "vtkFloatArray.h" -#include "vtkPointData.h" -#include "vtkProperty.h" +#include + +// mitk core +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include #include +#include + +#include +#include const std::string QmitkDeformableClippingPlaneView::VIEW_ID = "org.mitk.views.deformableclippingplane"; QmitkDeformableClippingPlaneView::QmitkDeformableClippingPlaneView() : QmitkAbstractView() - , m_ReferenceNode(nullptr) + , m_Controls(new Ui::QmitkDeformableClippingPlaneViewControls) , m_WorkingNode(nullptr) { + auto isImage = mitk::TNodePredicateDataType::New(); + auto isNotHelperObject = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); + + m_IsImagePredicate = mitk::NodePredicateAnd::New(isImage, isNotHelperObject); + + m_IsClippingPlanePredicate = mitk::NodePredicateProperty::New("clippingPlane", mitk::BoolProperty::New(true)); } QmitkDeformableClippingPlaneView::~QmitkDeformableClippingPlaneView() { if (m_WorkingNode.IsNotNull()) m_WorkingNode->SetDataInteractor(nullptr); } +void QmitkDeformableClippingPlaneView::SetFocus() +{ + m_Controls->createNewPlanePushButton->setFocus(); +} + void QmitkDeformableClippingPlaneView::CreateQtPartControl(QWidget *parent) { - m_Controls.setupUi(parent); + m_Controls->setupUi(parent); - auto isClippingPlane = mitk::NodePredicateProperty::New("clippingPlane", mitk::BoolProperty::New(true)); + m_Controls->imageSelectionWidget->SetDataStorage(GetDataStorage()); + m_Controls->imageSelectionWidget->SetNodePredicate(m_IsImagePredicate); + m_Controls->imageSelectionWidget->SetSelectionIsOptional(false); + m_Controls->imageSelectionWidget->SetInvalidInfo("Select an image or segmentation."); + m_Controls->imageSelectionWidget->SetPopUpTitel("Select an image or segmentation."); - m_Controls.clippingPlaneSelector->SetDataStorage(this->GetDataStorage()); - m_Controls.clippingPlaneSelector->SetPredicate(isClippingPlane); + m_Controls->clippingPlaneSelector->SetDataStorage(this->GetDataStorage()); + m_Controls->clippingPlaneSelector->SetPredicate(m_IsClippingPlanePredicate); - m_Controls.volumeGroupBox->setEnabled(false); - m_Controls.interactionSelectionBox->setEnabled(false); - m_Controls.noSelectedImageLabel->show(); - m_Controls.planesWarningLabel->hide(); + m_Controls->volumeGroupBox->setEnabled(false); + m_Controls->interactionSelectionBox->setEnabled(false); + m_Controls->planesWarningLabel->hide(); this->CreateConnections(); -} -void QmitkDeformableClippingPlaneView::SetFocus() -{ - m_Controls.createNewPlanePushButton->setFocus(); + m_Controls->imageSelectionWidget->SetAutoSelectNewNodes(true); } -void QmitkDeformableClippingPlaneView::CreateConnections() +void QmitkDeformableClippingPlaneView::OnCurrentSelectionChanged(const QList& /*nodes*/) { - connect(m_Controls.translationPushButton, SIGNAL(toggled(bool)), this, SLOT(OnTranslationMode(bool))); - connect(m_Controls.rotationPushButton, SIGNAL(toggled(bool)), this, SLOT(OnRotationMode(bool))); - connect(m_Controls.deformationPushButton, SIGNAL(toggled(bool)), this, SLOT(OnDeformationMode(bool))); - connect(m_Controls.createNewPlanePushButton, SIGNAL(clicked()), this, SLOT(OnCreateNewClippingPlane())); - connect(m_Controls.updateVolumePushButton, SIGNAL(clicked()), this, SLOT(OnCalculateClippingVolume())); - connect(m_Controls.clippingPlaneSelector, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), - this, SLOT(OnComboBoxSelectionChanged(const mitk::DataNode*))); + this->UpdateView(); } void QmitkDeformableClippingPlaneView::OnComboBoxSelectionChanged(const mitk::DataNode* node) { this->DeactivateInteractionButtons(); auto selectedNode = const_cast(node); - - if(selectedNode != nullptr) + if(nullptr != selectedNode) { if(m_WorkingNode.IsNotNull()) selectedNode->SetDataInteractor(m_WorkingNode->GetDataInteractor()); m_WorkingNode = selectedNode; } this->UpdateView(); } -void QmitkDeformableClippingPlaneView::OnSelectionChanged(mitk::DataNode* node) -{ - berry::IWorkbenchPart::Pointer nullPart; - QList nodes; - nodes.push_back(node); - - this->OnSelectionChanged(nullPart, nodes); -} - -void QmitkDeformableClippingPlaneView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) -{ - bool isClippingPlane = false; - - for (auto node : nodes) - { - node->GetBoolProperty("clippingPlane", isClippingPlane); - - if (isClippingPlane) - { - m_Controls.clippingPlaneSelector->setCurrentIndex(m_Controls.clippingPlaneSelector->Find(node)); - } - else - { - if(node.IsNotNull() && dynamic_cast(node->GetData()) != nullptr) - { - if(m_ReferenceNode.IsNotNull() && node->GetData() == m_ReferenceNode->GetData()) - return; - - m_ReferenceNode = node; - } - } - } - - this->UpdateView(); -} - -void::QmitkDeformableClippingPlaneView::NodeChanged(const mitk::DataNode*) -{ - this->UpdateView(); -} - -void QmitkDeformableClippingPlaneView::NodeRemoved(const mitk::DataNode* node) -{ - bool isClippingPlane(false); - node->GetBoolProperty("clippingPlane", isClippingPlane); - - if (isClippingPlane) - { - if (this->GetAllClippingPlanes()->Size() <= 1) - { - m_WorkingNode = nullptr; - this->UpdateView(); - } - else - { - this->OnSelectionChanged(this->GetAllClippingPlanes()->front() == node - ? this->GetAllClippingPlanes()->ElementAt(1) - : this->GetAllClippingPlanes()->front()); - } - } - else - { - if(m_ReferenceNode.IsNotNull()) - { - if(node->GetData() == m_ReferenceNode->GetData()) - { - m_ReferenceNode = nullptr; - m_Controls.volumeList->clear(); - } - - this->UpdateView(); - } - } -} - -void QmitkDeformableClippingPlaneView::UpdateView() -{ - if (m_ReferenceNode.IsNotNull()) - { - m_Controls.noSelectedImageLabel->hide(); - - m_Controls.selectedImageLabel->setText(QString::fromUtf8(m_ReferenceNode->GetName().c_str())); - - if (m_WorkingNode.IsNotNull()) - { - bool isSegmentation = false; - m_ReferenceNode->GetBoolProperty("binary", isSegmentation); - m_Controls.interactionSelectionBox->setEnabled(true); - - m_Controls.volumeGroupBox->setEnabled(isSegmentation); - - //clear list --> than search for all shown clipping plans (max 7 planes) - m_Controls.selectedVolumePlanesLabel->setText(""); - m_Controls.planesWarningLabel->hide(); - int volumePlanes=0; - - mitk::DataStorage::SetOfObjects::ConstPointer allClippingPlanes = this->GetAllClippingPlanes(); - for (mitk::DataStorage::SetOfObjects::ConstIterator itPlanes = allClippingPlanes->Begin(); itPlanes != allClippingPlanes->End(); itPlanes++) - { - bool isVisible = false; - itPlanes.Value()->GetBoolProperty("visible", isVisible); - if (isVisible) - { - if (volumePlanes < 7) - { - ++volumePlanes; - m_Controls.selectedVolumePlanesLabel->setText(m_Controls.selectedVolumePlanesLabel->text().append(QString::fromStdString(itPlanes.Value()->GetName()+"\n"))); - } - else - { - m_Controls.planesWarningLabel->show(); - return; - } - } - } - } - else - { - m_Controls.volumeGroupBox->setEnabled(false); - m_Controls.interactionSelectionBox->setEnabled(false); - m_Controls.selectedVolumePlanesLabel->setText(""); - m_Controls.volumeList->clear(); - } - } - else - { - m_Controls.volumeGroupBox->setEnabled(false); - m_Controls.noSelectedImageLabel->show(); - m_Controls.selectedImageLabel->setText(""); - m_Controls.selectedVolumePlanesLabel->setText(""); - m_Controls.planesWarningLabel->hide(); - - if (m_WorkingNode.IsNull()) - { - m_Controls.interactionSelectionBox->setEnabled(false); - } - else - { - m_Controls.interactionSelectionBox->setEnabled(true); - } - } -} - void QmitkDeformableClippingPlaneView::OnCreateNewClippingPlane() { this->DeactivateInteractionButtons(); auto plane = mitk::Surface::New(); - auto referenceImage = mitk::Image::New(); auto planeSource = vtkSmartPointer::New(); planeSource->SetOrigin(-32.0, -32.0, 0.0); - planeSource->SetPoint1( 32.0, -32.0, 0.0); - planeSource->SetPoint2(-32.0, 32.0, 0.0); + planeSource->SetPoint1(32.0, -32.0, 0.0); + planeSource->SetPoint2(-32.0, 32.0, 0.0); planeSource->SetResolution(128, 128); planeSource->Update(); plane->SetVtkPolyData(planeSource->GetOutput()); - double imageDiagonal = 200; + mitk::ScalarType imageDiagonal = 200.0; - if (m_ReferenceNode.IsNotNull()) + auto selectedNode = m_Controls->imageSelectionWidget->GetSelectedNode(); + if (selectedNode.IsNotNull()) { - referenceImage = dynamic_cast(m_ReferenceNode->GetData()); - - if (referenceImage.IsNotNull()) + auto selectedImage = dynamic_cast(selectedNode->GetData()); + if (nullptr != selectedImage) { // check if user wants a surface model - if(m_Controls.surfaceModelCheckBox->isChecked()) + if (m_Controls->surfaceModelCheckBox->isChecked()) { //Check if there is a surface node from the image. If not, create one - bool createSurfaceFromImage(true); - mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); - mitk::NodePredicateDataType::Pointer isSurface = mitk::NodePredicateDataType::New("Surface"); - mitk::DataStorage::SetOfObjects::ConstPointer childNodes = GetDataStorage()->GetDerivations(m_ReferenceNode,isSurface, true); + bool createSurfaceFromImage = true; + auto isSurface = mitk::NodePredicateDataType::New("Surface"); + auto childNodes = GetDataStorage()->GetDerivations(selectedNode, isSurface, true); - for (mitk::DataStorage::SetOfObjects::ConstIterator itChildNodes = childNodes->Begin(); - itChildNodes != childNodes->End(); itChildNodes++) + for (mitk::DataStorage::SetOfObjects::ConstIterator it = childNodes->Begin(); + it != childNodes->End(); it++) { - if (itChildNodes.Value().IsNotNull() && itChildNodes->Value()->GetName().compare(m_ReferenceNode->GetName()) == 0) + if (it.Value().IsNotNull() && it->Value()->GetName() == selectedNode->GetName()) { createSurfaceFromImage = false; - itChildNodes.Value()->SetVisibility(true); + it.Value()->SetVisibility(true); } } - if(createSurfaceFromImage) + if (createSurfaceFromImage) { //Lsg 2: Surface for the 3D-perspective - mitk::ImageToSurfaceFilter::Pointer surfaceFilter = mitk::ImageToSurfaceFilter::New(); - surfaceFilter->SetInput(referenceImage); + auto surfaceFilter = mitk::ImageToSurfaceFilter::New(); + surfaceFilter->SetInput(selectedImage); surfaceFilter->SetThreshold(1); surfaceFilter->SetSmooth(true); //Downsampling surfaceFilter->SetDecimate(mitk::ImageToSurfaceFilter::DecimatePro); - mitk::DataNode::Pointer surfaceNode = mitk::DataNode::New(); + auto surfaceNode = mitk::DataNode::New(); surfaceNode->SetData(surfaceFilter->GetOutput()); - surfaceNode->SetProperty("color", m_ReferenceNode->GetProperty("color")); + surfaceNode->SetProperty("color", selectedNode->GetProperty("color")); surfaceNode->SetOpacity(0.5); - surfaceNode->SetName(m_ReferenceNode->GetName()); - GetDataStorage()->Add(surfaceNode, m_ReferenceNode); + surfaceNode->SetName(selectedNode->GetName()); + this->GetDataStorage()->Add(surfaceNode, selectedNode); } } //If an image is selected trim the plane to this. - imageDiagonal = referenceImage->GetGeometry()->GetDiagonalLength(); - plane->SetOrigin( referenceImage->GetGeometry()->GetCenter()); + imageDiagonal = selectedImage->GetGeometry()->GetDiagonalLength(); + plane->SetOrigin(selectedImage->GetGeometry()->GetCenter()); // Rotate plane mitk::Vector3D rotationAxis; mitk::FillVector3D(rotationAxis, 0.0, 1.0, 0.0); - mitk::RotationOperation op(mitk::OpROTATE, referenceImage->GetGeometry()->GetCenter(), rotationAxis, 90.0); + mitk::RotationOperation op(mitk::OpROTATE, selectedImage->GetGeometry()->GetCenter(), rotationAxis, 90.0); plane->GetGeometry()->ExecuteOperation(&op); } } - //set some properties for the clipping plane - // plane->SetExtent(imageDiagonal * 0.9, imageDiagonal * 0.9); - // plane->SetResolution(64, 64); - - // eequivalent to the extent and resolution function of the clipping plane - const double x = imageDiagonal * 0.9; - planeSource->SetOrigin( -x / 2.0, -x / 2.0, 0.0 ); - planeSource->SetPoint1( x / 2.0, -x / 2.0, 0.0 ); - planeSource->SetPoint2( -x / 2.0, x / 2.0, 0.0 ); - planeSource->SetResolution( 64, 64 ); + // equivalent to the extent and resolution function of the clipping plane + const auto x = imageDiagonal * 0.9; + planeSource->SetOrigin(-x / 2.0, -x / 2.0, 0.0); + planeSource->SetPoint1(x / 2.0, -x / 2.0, 0.0); + planeSource->SetPoint2(-x / 2.0, x / 2.0, 0.0); + planeSource->SetResolution(64, 64); planeSource->Update(); plane->SetVtkPolyData(planeSource->GetOutput()); // Set scalars (for colorization of plane) vtkFloatArray *scalars = vtkFloatArray::New(); scalars->SetName("Distance"); scalars->SetNumberOfComponents(1); - for ( unsigned int i = 0; i < plane->GetVtkPolyData(0)->GetNumberOfPoints(); ++i) + const auto numerOfPoints = plane->GetVtkPolyData(0)->GetNumberOfPoints(); + for (std::remove_const_t i = 0; i < plane->GetVtkPolyData(0)->GetNumberOfPoints(); ++i) { scalars->InsertNextValue(-1.0); } plane->GetVtkPolyData(0)->GetPointData()->SetScalars(scalars); plane->GetVtkPolyData(0)->GetPointData()->Update(); - mitk::DataNode::Pointer planeNode = mitk::DataNode::New(); + auto planeNode = mitk::DataNode::New(); planeNode->SetData(plane); std::stringstream planeName; planeName << "ClippingPlane "; planeName << this->GetAllClippingPlanes()->Size() + 1; planeNode->SetName(planeName.str()); - planeNode->AddProperty("clippingPlane",mitk::BoolProperty::New(true)); + planeNode->AddProperty("clippingPlane", mitk::BoolProperty::New(true)); // Make plane pickable planeNode->SetBoolProperty("pickable", true); mitk::SurfaceVtkMapper3D::SetDefaultProperties(planeNode); // Don't include plane in bounding box! planeNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); // Set lookup table for plane surface visualization - vtkSmartPointer lookupTable = vtkSmartPointer::New(); - lookupTable->SetHueRange(0.6, 0.0); - lookupTable->SetSaturationRange(1.0, 1.0); - lookupTable->SetValueRange(1.0, 1.0); - lookupTable->SetTableRange(-1.0, 1.0); - lookupTable->Build(); + auto lookupTablevtk = vtkSmartPointer::New(); + lookupTablevtk->SetHueRange(0.6, 0.0); + lookupTablevtk->SetSaturationRange(1.0, 1.0); + lookupTablevtk->SetValueRange(1.0, 1.0); + lookupTablevtk->SetTableRange(-1.0, 1.0); + lookupTablevtk->Build(); - mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); - lut->SetVtkLookupTable(lookupTable); + auto lookupTable = mitk::LookupTable::New(); + lookupTable->SetVtkLookupTable(lookupTablevtk); - mitk::LookupTableProperty::Pointer prop = mitk::LookupTableProperty::New(lut); + auto prop = mitk::LookupTableProperty::New(lookupTable); planeNode->SetProperty("LookupTable", prop); planeNode->SetBoolProperty("scalar visibility", true); planeNode->SetBoolProperty("color mode", true); planeNode->SetFloatProperty("ScalarsRangeMinimum", -1.0); planeNode->SetFloatProperty("ScalarsRangeMaximum", 1.0); // Configure material so that only scalar colors are shown - planeNode->SetColor(0.0f,0.0f,0.0f); + planeNode->SetColor(0.0f, 0.0f, 0.0f); planeNode->SetOpacity(1.0f); - planeNode->SetFloatProperty("material.wireframeLineWidth",2.0f); + planeNode->SetFloatProperty("material.wireframeLineWidth", 2.0f); //Set view of plane to wireframe planeNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); - //Set the plane as working data for the tools and selected it - this->OnSelectionChanged (planeNode); - //Add the plane to data storage this->GetDataStorage()->Add(planeNode); //Change the index of the selector to the new generated node - m_Controls.clippingPlaneSelector->setCurrentIndex( m_Controls.clippingPlaneSelector->Find(planeNode) ); + m_Controls->clippingPlaneSelector->setCurrentIndex(m_Controls->clippingPlaneSelector->Find(planeNode)); - m_Controls.interactionSelectionBox->setEnabled(true); + m_Controls->interactionSelectionBox->setEnabled(true); if (auto renderWindowPart = dynamic_cast(this->GetRenderWindowPart())) { renderWindowPart->EnableSlicingPlanes(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDeformableClippingPlaneView::OnCalculateClippingVolume() { - bool isSegmentation(false); - m_ReferenceNode->GetBoolProperty("binary", isSegmentation); + auto selectedNode = m_Controls->imageSelectionWidget->GetSelectedNode(); + if (selectedNode.IsNull()) + { + MITK_ERROR << "No segmentation selected! Can't calculate volume"; + return; + } - if(m_ReferenceNode.IsNull() || !isSegmentation) + bool isSegmentation = false; + selectedNode->GetBoolProperty("binary", isSegmentation); + if (!isSegmentation) { MITK_ERROR << "No segmentation selected! Can't calculate volume"; return; } std::vector clippingPlanes; mitk::DataStorage::SetOfObjects::ConstPointer allClippingPlanes = this->GetAllClippingPlanes(); for (mitk::DataStorage::SetOfObjects::ConstIterator itPlanes = allClippingPlanes->Begin(); itPlanes != allClippingPlanes->End(); itPlanes++) { - bool isVisible(false); - itPlanes.Value()->GetBoolProperty("visible",isVisible); - mitk::Surface* plane = dynamic_cast(itPlanes.Value()->GetData()); + bool isVisible = false; + itPlanes.Value()->GetBoolProperty("visible", isVisible); + auto plane = dynamic_cast(itPlanes.Value()->GetData()); - if (isVisible && plane) + if (isVisible && nullptr != plane) clippingPlanes.push_back(plane); } if (clippingPlanes.empty()) { MITK_ERROR << "No clipping plane selected! Can't calculate volume"; return; } // deactivate Tools this->DeactivateInteractionButtons(); //Clear the list of volumes, before calculating the new values - m_Controls.volumeList->clear(); + m_Controls->volumeList->clear(); - m_ReferenceNode->SetBoolProperty("visible", false); + selectedNode->SetBoolProperty("visible", false); //set some properties for clipping the image-->Output: labled Image mitk::HeightFieldSurfaceClipImageFilter::Pointer surfaceClipFilter = mitk::HeightFieldSurfaceClipImageFilter::New(); - surfaceClipFilter->SetInput(dynamic_cast (m_ReferenceNode->GetData())); + surfaceClipFilter->SetInput(dynamic_cast(selectedNode->GetData())); surfaceClipFilter->SetClippingModeToMultiPlaneValue(); surfaceClipFilter->SetClippingSurfaces(clippingPlanes); surfaceClipFilter->Update(); //delete the old clipped image node mitk::DataStorage::SetOfObjects::ConstPointer oldClippedNode = this->GetDataStorage()->GetSubset(mitk::NodePredicateProperty::New("name", mitk::StringProperty::New("Clipped Image"))); if (oldClippedNode.IsNotNull()) this->GetDataStorage()->Remove(oldClippedNode); //add the new clipped image node - mitk::DataNode::Pointer clippedNode = mitk::DataNode::New(); + auto clippedNode = mitk::DataNode::New(); mitk::Image::Pointer clippedImage = surfaceClipFilter->GetOutput(); clippedImage->DisconnectPipeline(); clippedNode->SetData(clippedImage); - //clippedNode->SetProperty("helper object", mitk::BoolProperty::New(true)); clippedNode->SetName("Clipped Image"); - clippedNode->SetColor(1.0,1.0,1.0); // color property will not be used, labeled image lookuptable will be used instead - clippedNode->SetProperty ("use color", mitk::BoolProperty::New(false)); + clippedNode->SetColor(1.0, 1.0, 1.0); // color property will not be used, labeled image lookuptable will be used instead + clippedNode->SetProperty("use color", mitk::BoolProperty::New(false)); clippedNode->SetProperty("reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_NEAREST)); clippedNode->SetOpacity(0.4); this->GetDataStorage()->Add(clippedNode); - mitk::LabeledImageVolumeCalculator::Pointer volumeCalculator = mitk::LabeledImageVolumeCalculator::New(); + auto volumeCalculator = mitk::LabeledImageVolumeCalculator::New(); volumeCalculator->SetImage(clippedImage); volumeCalculator->Calculate(); - std::vector volumes = volumeCalculator->GetVolumes(); + auto volumes = volumeCalculator->GetVolumes(); - mitk::LabeledImageLookupTable::Pointer lut = mitk::LabeledImageLookupTable::New(); - int lablesWithVolume=0; - - for(unsigned int i = 1; i < volumes.size(); ++i) + auto lookupTable = mitk::LabeledImageLookupTable::New(); + int lablesWithVolume = 0; + const auto numberOfVolumes = volumes.size(); + for (std::remove_const_t i = 1; i < numberOfVolumes; ++i) { - if(volumes.at(i)!=0) + if (0 != volumes[0]) { lablesWithVolume++; - mitk::Color color (GetLabelColor(lablesWithVolume)); - lut->SetColorForLabel(i,color.GetRed(), color.GetGreen(), color.GetBlue(), 1.0); + mitk::Color color(GetLabelColor(lablesWithVolume)); + lookupTable->SetColorForLabel(i, color.GetRed(), color.GetGreen(), color.GetBlue(), 1.0); QColor qcolor; qcolor.setRgbF(color.GetRed(), color.GetGreen(), color.GetBlue(), 0.7); //output volume as string "x.xx ml" std::stringstream stream; - stream<< std::fixed << std::setprecision(2)<setText(QString::fromStdString(stream.str())); item->setBackgroundColor(qcolor); - m_Controls.volumeList->addItem(item); + m_Controls->volumeList->addItem(item); } } //set the rendering mode to use the lookup table and level window clippedNode->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR)); - mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New(lut.GetPointer()); + mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New(lookupTable.GetPointer()); clippedNode->SetProperty("LookupTable", lutProp); // it is absolutely important, to use the LevelWindow settings provided by // the LUT generator, otherwise, it is not guaranteed, that colors show // up correctly. - clippedNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(lut->GetLevelWindow())); -} - -mitk::DataStorage::SetOfObjects::ConstPointer QmitkDeformableClippingPlaneView::GetAllClippingPlanes() -{ - mitk::NodePredicateProperty::Pointer clipPredicate= mitk::NodePredicateProperty::New("clippingPlane",mitk::BoolProperty::New(true)); - mitk::DataStorage::SetOfObjects::ConstPointer allPlanes = GetDataStorage()->GetSubset(clipPredicate); - return allPlanes; -} - -mitk::Color QmitkDeformableClippingPlaneView::GetLabelColor(int label) -{ - float red, green, blue; - switch ( label % 6 ) - { - case 0: - {red = 1.0; green = 0.0; blue = 0.0; break;} - case 1: - {red = 0.0; green = 1.0; blue = 0.0; break;} - case 2: - {red = 0.0; green = 0.0; blue = 1.0;break;} - case 3: - {red = 1.0; green = 1.0; blue = 0.0;break;} - case 4: - {red = 1.0; green = 0.0; blue = 1.0;break;} - case 5: - {red = 0.0; green = 1.0; blue = 1.0;break;} - default: - {red = 0.0; green = 0.0; blue = 0.0;} - } - - float tmp[3] = { red, green, blue }; - - double factor; - - int outerCycleNr = label / 6; - int cycleSize = pow(2.0,(int)(log((double)(outerCycleNr))/log( 2.0 ))); - if (cycleSize==0) - cycleSize = 1; - int insideCycleCounter = outerCycleNr % cycleSize; - - if ( outerCycleNr == 0) - factor = 255; - else - factor = ( 256 / ( 2 * cycleSize ) ) + ( insideCycleCounter * ( 256 / cycleSize ) ); - - tmp[0]= tmp[0]/256*factor; - tmp[1]= tmp[1]/256*factor; - tmp[2]= tmp[2]/256*factor; - - return mitk::Color(tmp); + clippedNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(lookupTable->GetLevelWindow())); } void QmitkDeformableClippingPlaneView::OnTranslationMode(bool check) { - if(check) + if (check) { //uncheck all other buttons - m_Controls.rotationPushButton->setChecked(false); - m_Controls.deformationPushButton->setChecked(false); + m_Controls->rotationPushButton->setChecked(false); + m_Controls->deformationPushButton->setChecked(false); mitk::ClippingPlaneInteractor3D::Pointer affineDataInteractor = mitk::ClippingPlaneInteractor3D::New(); affineDataInteractor->LoadStateMachine("ClippingPlaneInteraction3D.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); affineDataInteractor->SetEventConfig("ClippingPlaneTranslationConfig.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); affineDataInteractor->SetDataNode(m_WorkingNode); } else m_WorkingNode->SetDataInteractor(nullptr); } void QmitkDeformableClippingPlaneView::OnRotationMode(bool check) { - if(check) + if (check) { //uncheck all other buttons - m_Controls.translationPushButton->setChecked(false); - m_Controls.deformationPushButton->setChecked(false); + m_Controls->translationPushButton->setChecked(false); + m_Controls->deformationPushButton->setChecked(false); mitk::ClippingPlaneInteractor3D::Pointer affineDataInteractor = mitk::ClippingPlaneInteractor3D::New(); affineDataInteractor->LoadStateMachine("ClippingPlaneInteraction3D.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); affineDataInteractor->SetEventConfig("ClippingPlaneRotationConfig.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); affineDataInteractor->SetDataNode(m_WorkingNode); } else m_WorkingNode->SetDataInteractor(nullptr); } void QmitkDeformableClippingPlaneView::OnDeformationMode(bool check) { - if(check) + if (check) { //uncheck all other buttons - m_Controls.translationPushButton->setChecked(false); - m_Controls.rotationPushButton->setChecked(false); + m_Controls->translationPushButton->setChecked(false); + m_Controls->rotationPushButton->setChecked(false); mitk::SurfaceDeformationDataInteractor3D::Pointer surfaceDataInteractor = mitk::SurfaceDeformationDataInteractor3D::New(); surfaceDataInteractor->LoadStateMachine("ClippingPlaneInteraction3D.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); surfaceDataInteractor->SetEventConfig("ClippingPlaneDeformationConfig.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); surfaceDataInteractor->SetDataNode(m_WorkingNode); } else m_WorkingNode->SetDataInteractor(nullptr); } +void QmitkDeformableClippingPlaneView::CreateConnections() +{ + connect(m_Controls->imageSelectionWidget, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, + this, &QmitkDeformableClippingPlaneView::OnCurrentSelectionChanged); + connect(m_Controls->translationPushButton, &QPushButton::toggled, + this, &QmitkDeformableClippingPlaneView::OnTranslationMode); + connect(m_Controls->rotationPushButton, &QPushButton::toggled, + this, &QmitkDeformableClippingPlaneView::OnRotationMode); + connect(m_Controls->deformationPushButton, &QPushButton::toggled, + this, &QmitkDeformableClippingPlaneView::OnDeformationMode); + connect(m_Controls->createNewPlanePushButton, &QPushButton::clicked, + this, &QmitkDeformableClippingPlaneView::OnCreateNewClippingPlane); + connect(m_Controls->updateVolumePushButton, &QPushButton::clicked, + this, &QmitkDeformableClippingPlaneView::OnCalculateClippingVolume); + connect(m_Controls->clippingPlaneSelector, &QmitkDataStorageComboBox::OnSelectionChanged, + this, &QmitkDeformableClippingPlaneView::OnComboBoxSelectionChanged); +} + +void QmitkDeformableClippingPlaneView::NodeRemoved(const mitk::DataNode* node) +{ + if (m_IsClippingPlanePredicate->CheckNode(node)) + { + if (this->GetAllClippingPlanes()->Size() <= 1) + { + m_WorkingNode = nullptr; + this->UpdateView(); + } + } +} + +void::QmitkDeformableClippingPlaneView::NodeChanged(const mitk::DataNode*) +{ + this->UpdateView(); +} + +void QmitkDeformableClippingPlaneView::UpdateView() +{ + auto selectedNode = m_Controls->imageSelectionWidget->GetSelectedNode(); + if (selectedNode.IsNotNull()) + { + m_Controls->selectedReferenceImageLabel->setText(QString::fromUtf8(selectedNode->GetName().c_str())); + if (m_WorkingNode.IsNotNull()) + { + bool isSegmentation = false; + selectedNode->GetBoolProperty("binary", isSegmentation); + m_Controls->interactionSelectionBox->setEnabled(true); + + m_Controls->volumeGroupBox->setEnabled(isSegmentation); + + //clear list --> than search for all shown clipping plans (max 7 planes) + m_Controls->selectedClippingPlanesLabel->setText(""); + m_Controls->planesWarningLabel->hide(); + int volumePlanes = 0; + + auto allClippingPlanes = this->GetAllClippingPlanes(); + for (mitk::DataStorage::SetOfObjects::ConstIterator itPlanes = allClippingPlanes->Begin(); itPlanes != allClippingPlanes->End(); itPlanes++) + { + bool isVisible = false; + itPlanes.Value()->GetBoolProperty("visible", isVisible); + if (isVisible) + { + if (volumePlanes < 7) + { + ++volumePlanes; + m_Controls->selectedClippingPlanesLabel->setText(m_Controls->selectedClippingPlanesLabel->text().append(QString::fromStdString(itPlanes.Value()->GetName()+"\n"))); + } + else + { + m_Controls->planesWarningLabel->show(); + return; + } + } + } + } + else + { + m_Controls->volumeGroupBox->setEnabled(false); + m_Controls->interactionSelectionBox->setEnabled(false); + m_Controls->selectedClippingPlanesLabel->setText(""); + m_Controls->volumeList->clear(); + } + } + else + { + m_Controls->volumeGroupBox->setEnabled(false); + m_Controls->selectedReferenceImageLabel->setText(""); + m_Controls->selectedClippingPlanesLabel->setText(""); + m_Controls->planesWarningLabel->hide(); + + m_Controls->interactionSelectionBox->setEnabled(m_WorkingNode.IsNotNull()); + } +} + +mitk::DataStorage::SetOfObjects::ConstPointer QmitkDeformableClippingPlaneView::GetAllClippingPlanes() +{ + auto allPlanes = GetDataStorage()->GetSubset(m_IsClippingPlanePredicate); + return allPlanes; +} + +mitk::Color QmitkDeformableClippingPlaneView::GetLabelColor(int label) +{ + std::array color = { 0.0f, 0.0f, 0.0f }; + + switch (label % 6) + { + case 0: // red + color[0] = 1.0f; + break; + case 1: // green + color[1] = 1.0f; + break; + case 2: // blue + color[2] = 1.0f; + break; + case 3: // yellow + color[0] = 1.0f; + color[1] = 1.0f; + break; + case 4: // magenta + color[0] = 1.0f; + color[2] = 1.0f; + break; + case 5: // cyan + color[1] = 1.0f; + color[2] = 1.0f; + default: // black + break; + } + + int outerCycleNr = label / 6; + int cycleSize = std::min(1, static_cast(std::pow(2.0, std::log(outerCycleNr) / std::log(2.0)))); + int insideCycleCounter = outerCycleNr % cycleSize; + + float factor; + if (0 == outerCycleNr) + { + factor = 255.0f; + } + else + { + factor = 256.0f / (2.0f * cycleSize) + insideCycleCounter * (256.0f / cycleSize); + } + + color = { + std::min(1.0f, color[0] / 256.0f * factor), + std::min(1.0f, color[1] / 256.0f * factor), + std::min(1.0f, color[2] / 256.0f * factor) + }; + + return mitk::Color(color.data()); +} + void QmitkDeformableClippingPlaneView::DeactivateInteractionButtons() { - m_Controls.translationPushButton->setChecked(false); - m_Controls.rotationPushButton->setChecked(false); - m_Controls.deformationPushButton->setChecked(false); + m_Controls->translationPushButton->setChecked(false); + m_Controls->rotationPushButton->setChecked(false); + m_Controls->deformationPushButton->setChecked(false); } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.h index 6bad16198b..5cc022e7f4 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.h +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneView.h @@ -1,81 +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 _QMITKDEFORMABLECLIPPINGPLANEVIEW_H_INCLUDED -#define _QMITKDEFORMABLECLIPPINGPLANEVIEW_H_INCLUDED - +#ifndef QMITKDEFORMABLECLIPPINGPLANEVIEW_H +#define QMITKDEFORMABLECLIPPINGPLANEVIEW_H #include + #include +#include +#include #include typedef itk::RGBPixel< float > Color; -/*! -* \ingroup org_mitk_gui_qt_deformableSurface -* -* \brief QmitkDeformableClippingPlaneView -* -* Document your class here. -*/ +/** + * @brief + */ class QmitkDeformableClippingPlaneView : public QmitkAbstractView { Q_OBJECT public: static const std::string VIEW_ID; QmitkDeformableClippingPlaneView(); ~QmitkDeformableClippingPlaneView() override; - void CreateQtPartControl(QWidget *parent) override; - - /// \brief Creation of the connections of main and control widget - virtual void CreateConnections(); - - /// - /// Sets the focus to an internal widget. - /// void SetFocus() override; -protected slots: +private Q_SLOTS: + void OnCurrentSelectionChanged(const QList& nodes); void OnComboBoxSelectionChanged(const mitk::DataNode* node); void OnCreateNewClippingPlane(); void OnCalculateClippingVolume(); void OnTranslationMode(bool check); void OnRotationMode(bool check); void OnDeformationMode(bool check); -protected: +private: + + void CreateQtPartControl(QWidget *parent) override; + virtual void CreateConnections(); - virtual void OnSelectionChanged(mitk::DataNode* node); - void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; void NodeRemoved(const mitk::DataNode* node) override; void NodeChanged(const mitk::DataNode* node) override; void UpdateView(); - Ui::QmitkDeformableClippingPlaneViewControls m_Controls; - -private: mitk::DataStorage::SetOfObjects::ConstPointer GetAllClippingPlanes(); mitk::Color GetLabelColor(int label); void DeactivateInteractionButtons(); - mitk::DataNode::Pointer m_ReferenceNode; + Ui::QmitkDeformableClippingPlaneViewControls* m_Controls; + + mitk::NodePredicateAnd::Pointer m_IsImagePredicate; + mitk::NodePredicateProperty::Pointer m_IsClippingPlanePredicate; + mitk::DataNode::Pointer m_WorkingNode; + }; #endif diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneViewControls.ui b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneViewControls.ui index 8507259989..0130bd6153 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneViewControls.ui +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkDeformableClippingPlaneViewControls.ui @@ -1,611 +1,431 @@ QmitkDeformableClippingPlaneViewControls 0 0 - 422 - 642 + 300 + 600 0 0 - QmitkDeformableSurface + Deformable surface - + - - - - 0 - 0 - - - - - - - - - 197 - 0 - 0 - - - - - - - 191 - 0 - 0 - - - - - - - 189 - 0 - 0 - - - - - - - - - 197 - 0 - 0 - - - - - - - 191 - 0 - 0 - - - - - - - 189 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - Please select an image! - - + + + + + Selected image + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + - - - false false - + 0 0 Create new clipping plane Qt::RightToLeft ...with surface model true - + 0 0 0 0 16777215 16777215 Plane 0 0 QComboBox::AdjustToMinimumContentsLength true 50 false 0 0 20 50 Translation - + :/org.mitk.gui.qt.segmentation/resources/clipping_plane_translate_48x48.png:/org.mitk.gui.qt.segmentation/resources/clipping_plane_translate_48x48.png 32 32 true false false 0 0 20 50 Rotation - + :/org.mitk.gui.qt.segmentation/resources/clipping_plane_rotate48x48.png:/org.mitk.gui.qt.segmentation/resources/clipping_plane_rotate48x48.png 32 32 true false 0 0 20 50 Deformation - + :/org.mitk.gui.qt.segmentation/resources/clipping_plane_deform48x48.png:/org.mitk.gui.qt.segmentation/resources/clipping_plane_deform48x48.png 32 32 true false Qt::Vertical QSizePolicy::Preferred 20 20 0 0 - - - - - - - 197 - 0 - 0 - - - - - - - 191 - 0 - 0 - - - - - - - 189 - 0 - 0 - - - - - - - - - 197 - 0 - 0 - - - - - - - 191 - 0 - 0 - - - - - - - 189 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - Please select less or equal 6 clipping planes! 0 0 - + 0 0 Referenced image - + 0 0 - Clipping planes + Clipping planes Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - + true 0 0 - - - MS Shell Dlg 2 - 8 - 50 - false - - - - - - + 8 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Update Volumina Qt::Vertical QSizePolicy::Preferred 20 20 true 0 0 + + QmitkSingleNodeSelectionWidget + QWidget +
QmitkSingleNodeSelectionWidget.h
+
QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h