diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp index 5061ffbc81..27b5819b9b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp @@ -1,1015 +1,1121 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkFiberGenerationView.h" // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RAPIDXML_NO_EXCEPTIONS #include #include #include #include #include "usModuleRegistry.h" #include #include #include #include #include #include #include #include #include #include "mitkNodePredicateDataType.h" #include #include #include #include #define _USE_MATH_DEFINES #include const std::string QmitkFiberGenerationView::VIEW_ID = "org.mitk.views.fibergenerationview"; QmitkFiberGenerationView::QmitkFiberGenerationView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImageNode( nullptr ) { } // Destructor QmitkFiberGenerationView::~QmitkFiberGenerationView() { } void QmitkFiberGenerationView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkFiberGenerationViewControls; m_Controls->setupUi( parent ); m_ParameterFile = QDir::currentPath()+"/param.ffp"; - connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); - connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); - connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); - connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); - connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); - connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); - connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); - connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnFiberSamplingChanged(double))); - connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); - connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); - connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); - - connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); - connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); - connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform())); - connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); - - - connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); - - connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters())); - connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters())); + connect(static_cast(m_Controls->m_GenerateFibersButton), SIGNAL(clicked()), static_cast(this), SLOT(GenerateFibers())); + connect(static_cast(m_Controls->m_CircleButton), SIGNAL(clicked()), static_cast(this), SLOT(OnDrawROI())); + connect(static_cast(m_Controls->m_FlipButton), SIGNAL(clicked()), static_cast(this), SLOT(OnFlipButton())); + connect(static_cast(m_Controls->m_JoinBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(JoinBundles())); + connect(static_cast(m_Controls->m_VarianceBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnVarianceChanged(double))); + connect(static_cast(m_Controls->m_DistributionBox), SIGNAL(currentIndexChanged(int)), static_cast(this), SLOT(OnDistributionChanged(int))); + connect(static_cast(m_Controls->m_FiberDensityBox), SIGNAL(valueChanged(int)), static_cast(this), SLOT(OnFiberDensityChanged(int))); + connect(static_cast(m_Controls->m_FiberSamplingBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnFiberSamplingChanged(double))); + connect(static_cast(m_Controls->m_TensionBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnTensionChanged(double))); + connect(static_cast(m_Controls->m_ContinuityBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnContinuityChanged(double))); + connect(static_cast(m_Controls->m_BiasBox), SIGNAL(valueChanged(double)), static_cast(this), SLOT(OnBiasChanged(double))); + + connect(static_cast(m_Controls->m_ConstantRadiusBox), SIGNAL(stateChanged(int)), static_cast(this), SLOT(OnConstantRadius(int))); + connect(static_cast(m_Controls->m_CopyBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(CopyBundles())); + connect(static_cast(m_Controls->m_TransformBundlesButton), SIGNAL(clicked()), static_cast(this), SLOT(ApplyTransform())); + connect(static_cast(m_Controls->m_AlignOnGrid), SIGNAL(clicked()), static_cast(this), SLOT(AlignOnGrid())); + connect(static_cast(m_Controls->m_FidAxis1), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); + connect(static_cast(m_Controls->m_FidAxis2), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); + connect(static_cast(m_Controls->m_FidPosX), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); + connect(static_cast(m_Controls->m_FidPosY), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); + connect(static_cast(m_Controls->m_FidPosZ), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); + connect(static_cast(m_Controls->m_FidTwist), SIGNAL(editingFinished()), static_cast(this), SLOT(UpdateFiducialPosition())); + + connect(static_cast(m_Controls->m_AdvancedOptionsBox), SIGNAL( stateChanged(int)), static_cast(this), SLOT(ShowAdvancedOptions(int))); + + connect(static_cast(m_Controls->m_SaveParametersButton), SIGNAL(clicked()), static_cast(this), SLOT(SaveParameters())); + connect(static_cast(m_Controls->m_LoadParametersButton), SIGNAL(clicked()), static_cast(this), SLOT(LoadParameters())); } UpdateGui(); } void QmitkFiberGenerationView::UpdateParametersFromGui() { m_Parameters.ClearFiberParameters(); m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); switch(m_Controls->m_DistributionBox->currentIndex()) { case 0: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; break; case 1: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN; break; default: m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM; } m_Parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value(); m_Parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value(); m_Parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value(); m_Parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value(); m_Parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value(); m_Parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value(); m_Parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value(); m_Parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value(); m_Parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value(); m_Parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value(); m_Parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value(); m_Parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value(); m_Parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value(); m_Parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value(); m_Parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value(); m_Parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked(); m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked(); m_Parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked(); m_Parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked(); } void QmitkFiberGenerationView::SaveParameters(QString filename) { UpdateParametersFromGui(); m_Parameters.SaveParameters(filename.toStdString()); m_ParameterFile = filename; } void QmitkFiberGenerationView::SaveParameters() { QString filename = QFileDialog::getSaveFileName( 0, tr("Save Parameters"), m_ParameterFile, tr("Fiberfox Parameters (*.ffp)") ); SaveParameters(filename); } void QmitkFiberGenerationView::LoadParameters() { QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") ); if(filename.isEmpty() || filename.isNull()) return; m_ParameterFile = filename; m_Parameters.LoadParameters(filename.toStdString()); if (m_Parameters.m_MissingTags.size()>0) { QString missing("Parameter file might be corrupted. The following parameters could not be read: "); missing += QString(m_Parameters.m_MissingTags.c_str()); missing += "\nDefault values have been assigned to the missing parameters."; QMessageBox::information( nullptr, "Warning!", missing); } m_Controls->m_RealTimeFibers->setChecked(m_Parameters.m_Misc.m_CheckRealTimeFibersBox); m_Controls->m_AdvancedOptionsBox->setChecked(m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox); m_Controls->m_IncludeFiducials->setChecked(m_Parameters.m_Misc.m_CheckIncludeFiducialsBox); m_Controls->m_ConstantRadiusBox->setChecked(m_Parameters.m_Misc.m_CheckConstantRadiusBox); m_Controls->m_DistributionBox->setCurrentIndex(m_Parameters.m_FiberGen.m_Distribution); m_Controls->m_VarianceBox->setValue(m_Parameters.m_FiberGen.m_Variance); m_Controls->m_FiberDensityBox->setValue(m_Parameters.m_FiberGen.m_Density); m_Controls->m_FiberSamplingBox->setValue(m_Parameters.m_FiberGen.m_Sampling); m_Controls->m_TensionBox->setValue(m_Parameters.m_FiberGen.m_Tension); m_Controls->m_ContinuityBox->setValue(m_Parameters.m_FiberGen.m_Continuity); m_Controls->m_BiasBox->setValue(m_Parameters.m_FiberGen.m_Bias); m_Controls->m_XrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[0]); m_Controls->m_YrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[1]); m_Controls->m_ZrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[2]); m_Controls->m_XtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[0]); m_Controls->m_YtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[1]); m_Controls->m_ZtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[2]); m_Controls->m_XscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[0]); m_Controls->m_YscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[1]); m_Controls->m_ZscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[2]); } void QmitkFiberGenerationView::ShowAdvancedOptions(int state) { if (state) { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); m_Controls->m_AdvancedOptionsBox->setChecked(true); } else { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); m_Controls->m_AdvancedOptionsBox->setChecked(false); } } void QmitkFiberGenerationView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnVarianceChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFiberDensityChanged(int) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFiberSamplingChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnTensionChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnContinuityChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnBiasChanged(double) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } +void QmitkFiberGenerationView::UpdateFiducialPosition() +{ + if (m_SelectedFiducials.size()!=1) + return; + + mitk::PlanarEllipse* pe = dynamic_cast(m_SelectedFiducials.at(0)->GetData()); + mitk::BaseGeometry* geom = pe->GetGeometry(); + + // translate + mitk::Point3D origin; + origin[0] = m_Controls->m_FidPosX->value(); + origin[1] = m_Controls->m_FidPosY->value(); + origin[2] = m_Controls->m_FidPosZ->value(); + + // transform control point coordinate into geometry translation + auto p0 = pe->GetControlPoint(0); + auto p1 = pe->GetControlPoint(1); + auto p2 = pe->GetControlPoint(2); + auto p3 = pe->GetControlPoint(3); + + auto v1 = p1 - p0; + auto v2 = p2 - p0; + auto angle_deg = m_Controls->m_FidTwist->value(); + auto dot = std::cos(itk::Math::pi*angle_deg/180.0); + + vnl_matrix_fixed tRot; + tRot[0][0] = dot; + tRot[1][1] = tRot[0][0]; + tRot[1][0] = sin(acos(tRot[0][0])); + tRot[0][1] = -tRot[1][0]; + if (angle_deg<0) + tRot = tRot.transpose(); + vnl_vector_fixed vt; vt[0]=1; vt[1]=0; + vnl_vector_fixed v3 = tRot*vt; + + if (v1.GetNorm()<0.0001 || v2.GetNorm()<0.0001) + { + QMessageBox::information( nullptr, "", "Please select exactly one fiducial."); + return; + } + + v1.Normalize(); + v2.Normalize(); + + p1 = p0 + v1*m_Controls->m_FidAxis1->value(); + p2 = p0 + v2*m_Controls->m_FidAxis2->value(); + p3 = p0 + mitk::Vector2D(v3); + pe->SetControlPoint(1, p1); + pe->SetControlPoint(2, p2); + pe->SetControlPoint(3, p3); + geom->SetOrigin(origin); + + pe->Modified(); + + if (m_Controls->m_RealTimeFibers->isChecked()) + GenerateFibers(); + + UpdateGui(); +} + void QmitkFiberGenerationView::AlignOnGrid() { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for(unsigned int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for(unsigned int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::BaseGeometry::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::OnAddBundle() { if (m_SelectedImageNode.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode); mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImageNode); } void QmitkFiberGenerationView::OnDrawROI() { if (m_SelectedBundles.empty()) OnAddBundle(); if (m_SelectedBundles.empty()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0)); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); node->SetBoolProperty("planarfigure.3drendering", true); node->SetBoolProperty("planarfigure.3drendering.fill", true); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( node ); } UpdateGui(); GetDataStorage()->Add(node, m_SelectedBundles.at(0)); } bool QmitkFiberGenerationView::CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } UpdateParametersFromGui(); for (unsigned int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); std::sort(childVector.begin(), childVector.end(), CompareLayer); std::vector< mitk::PlanarEllipse::Pointer > fib; std::vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); ellipse->Modified(); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); ellipse->Modified(); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { m_Parameters.m_FiberGen.m_Fiducials.push_back(fib); m_Parameters.m_FiberGen.m_FlipList.push_back(flip); } else if (fib.size()>0) m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetParameters(m_Parameters.m_FiberGen); filter->Update(); std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles(); for (unsigned int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::ApplyTransform() { std::vector< mitk::DataNode::Pointer > selectedBundles; for(unsigned int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { for (std::vector::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it) { mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*itk::Math::pi/180; double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; double z = m_Controls->m_ZrotBox->value()*itk::Math::pi/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); pe->Modified(); } } } } } else { for (unsigned int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::BaseGeometry* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*itk::Math::pi/180; double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180; double z = m_Controls->m_ZrotBox->value()*itk::Math::pi/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); pe->Modified(); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberGenerationView") << "Select at least one fiber bundle!"; return; } for (std::vector::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } mitk::FiberBundle::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundle::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData())->Clone(); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); newNode->SetBoolProperty("planarfigure.3drendering", true); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberGenerationView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); mitk::FiberBundle::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (; it!=m_SelectedBundles.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberGenerationView::UpdateGui() { m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); + m_Controls->m_FiducialAttributeBox->setEnabled(false); // Fiber generation gui if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } + if (m_SelectedFiducials.size()==1) + { + m_Controls->m_FiducialAttributeBox->setEnabled(true); + mitk::PlanarEllipse* pe = dynamic_cast(m_SelectedFiducials.at(0)->GetData()); + auto origin = pe->GetGeometry()->GetOrigin(); + m_Controls->m_FidPosX->setValue(origin[0]); + m_Controls->m_FidPosY->setValue(origin[1]); + m_Controls->m_FidPosZ->setValue(origin[2]); + + + auto p0 = pe->GetControlPoint(0); + auto p1 = pe->GetControlPoint(1); + auto p2 = pe->GetControlPoint(2); + auto p3 = pe->GetControlPoint(3); + + auto v1 = p1 - p0; + auto v2 = p2 - p0; + + m_Controls->m_FidAxis1->setValue(v1.GetNorm()); + m_Controls->m_FidAxis2->setValue(v2.GetNorm()); + + vnl_vector_fixed vt; vt[0]=1; vt[1]=0; + auto v3 = p3-p0; v3.Normalize(); + auto angle = dot_product(vt, v3.GetVnlVector()); + angle = std::acos(angle)*180.0/itk::Math::pi; + if (v3[1]<0) + angle *= -1; + m_Controls->m_FidTwist->setValue(angle); + } + else + { + m_Controls->m_FidPosX->setValue(0); + m_Controls->m_FidPosY->setValue(0); + m_Controls->m_FidPosZ->setValue(0); + m_Controls->m_FidAxis1->setValue(1); + m_Controls->m_FidAxis2->setValue(1); + m_Controls->m_FidTwist->setValue(0); + } + if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty()) { m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); } if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty()) m_Controls->m_AlignOnGrid->setEnabled(true); if (!m_SelectedBundles.empty()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } } void QmitkFiberGenerationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = nullptr; m_SelectedBundles.clear(); m_SelectedImageNode = nullptr; // iterate all selected objects, adjust warning visibility for( int i=0; i(node->GetData()) ) { m_SelectedImages.push_back(node); m_SelectedImageNode = node; } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked()) { m_SelectedBundles.push_back(node); mitk::FiberBundle::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=static_cast(m_Controls->m_FiberDensityBox->value())) GenerateFibers(); } else m_SelectedBundles.push_back(node); } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) m_SelectedBundles.push_back(pNode); } } } UpdateGui(); } void QmitkFiberGenerationView::EnableCrosshairNavigation() { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberGenerationView::DisableCrosshairNavigation() { } void QmitkFiberGenerationView::NodeRemoved(const mitk::DataNode* node) { mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if (dynamic_cast(node->GetData())) { m_SelectedBundles.clear(); m_SelectedBundles2.clear(); } else if (dynamic_cast(node->GetData())) m_SelectedImages.clear(); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberGenerationView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetDataInteractor().GetPointer()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New(); us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" ); figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule ); figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule ); figureInteractor->SetDataNode( nonConstNode ); } MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberGenerationView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberGenerationView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberGenerationView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberGenerationView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h index adbff9b243..c7637d763b 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h @@ -1,146 +1,147 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "ui_QmitkFiberGenerationViewControls.h" #include #include #include #ifndef Q_MOC_RUN #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include #include #include #include class QmitkFiberGenerationView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkFiberGenerationView(); virtual ~QmitkFiberGenerationView(); virtual void CreateQtPartControl(QWidget *parent) override; void SetFocus() override; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; protected slots: void LoadParameters(); ///< load FiberGeneration parameters void SaveParameters(); ///< save FiberGeneration parameters void OnDrawROI(); ///< adds new ROI, handles interactors etc. void OnAddBundle(); ///< adds new fiber bundle to datastorage void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists void GenerateFibers(); ///< generate fibers from the selected ROIs void JoinBundles(); ///< merges selcted fiber bundles into one void CopyBundles(); ///< add copy of the selected bundle to the datamanager void ApplyTransform(); ///< rotate and shift selected bundles void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center void ShowAdvancedOptions(int state); /** update fibers if any parameter changes */ void OnFiberDensityChanged(int value); void OnFiberSamplingChanged(double value); void OnTensionChanged(double value); void OnContinuityChanged(double value); void OnBiasChanged(double value); void OnVarianceChanged(double value); void OnDistributionChanged(int value); void OnConstantRadius(int value); + void UpdateFiducialPosition(); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; Ui::QmitkFiberGenerationViewControls* m_Controls; void UpdateParametersFromGui(); void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection void PlanarFigureSelected( itk::Object* object, const itk::EventObject& ); void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts void NodeAdded( const mitk::DataNode* node ) override; ///< add observers void NodeRemoved(const mitk::DataNode* node) override; ///< remove observers void SaveParameters(QString filename); static bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j); /** structure to keep track of planar figures and observers */ struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_Figure(0) , m_EndPlacementObserverTag(0) , m_SelectObserverTag(0) , m_StartInteractionObserverTag(0) , m_EndInteractionObserverTag(0) , m_Flipped(0) { } mitk::PlanarFigure* m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; unsigned int m_Flipped; }; std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse mitk::DataNode::Pointer m_SelectedImageNode; std::vector< mitk::DataNode::Pointer > m_SelectedBundles; std::vector< mitk::DataNode::Pointer > m_SelectedBundles2; std::vector< mitk::DataNode::Pointer > m_SelectedFiducials; std::vector< mitk::DataNode::Pointer > m_SelectedImages; QString m_ParameterFile; ///< parameter file name FiberfoxParameters m_Parameters; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui index 948e38eaac..ed6ff1f5bc 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationViewControls.ui @@ -1,1154 +1,1403 @@ QmitkFiberGenerationViewControls 0 0 - 463 - 1017 + 413 + 1282 Form - - + + - QGroupBox { - background-color: transparent; -} + color: rgb(255, 0, 0); - - Fiducial Options + + Please select an image or an existing fiber bundle to draw the fiber fiducials. If you can't provide a suitable image, generate one using the Fiberfox View. - + + Qt::AutoText + + + Qt::AlignJustify|Qt::AlignVCenter + + + true + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + - 6 + 0 - 6 + 0 - 6 + 0 - 6 + 0 - + + + false + + + + 30 + 30 + + - All fiducials are treated as circles with the same radius as the first fiducial. + Draw elliptical fiducial. - Use Constant Fiducial Radius + - + + + :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png + + + + 32 + 32 + + + false + + true + - - + + false - - Align selected fiducials with voxel grid. Shifts selected fiducials to nearest voxel center. + + + 30 + 30 + - - QCommandLinkButton:disabled { - border: none; -} + + Flip fiber waypoints of selcted fiducial around one axis. - Align With Grid + - :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico + :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico + + + + 32 + 32 + + + + false + + + true + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - - - color: rgb(255, 0, 0); - - - Please select an image or an existing fiber bundle to draw the fiber fiducials. If you can't provide a suitable image, generate one using the Fiberfox View. - - - Qt::AutoText - - - Qt::AlignJustify|Qt::AlignVCenter - - - true - - - QGroupBox { background-color: transparent; } Fiber Options 6 6 6 6 QFrame::NoFrame QFrame::Raised 0 0 0 0 QFrame::NoFrame QFrame::Raised 0 0 0 0 Tension: false Fiber Sampling: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Bias: false Continuity: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Distance of fiber sampling points (in mm) 1 0.100000000000000 0.100000000000000 1.000000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 6 #Fibers: false Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 false QCommandLinkButton:disabled { border: none; } Generate Fibers :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico QFrame::NoFrame QFrame::Raised 0 0 0 0 Select fiber distribution inside of the fiducials. Uniform Gaussian Fiber Distribution: false Variance of the gaussian 3 0.001000000000000 10.000000000000000 0.010000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 0 0 0 Disable to only generate fibers if "Generate Fibers" button is pressed. Real Time Fibers true Disable to only generate fibers if "Generate Fibers" button is pressed. Advanced Options false - - - - QFrame::NoFrame + + + + QGroupBox { + background-color: transparent; +} - - QFrame::Raised + + Operations - + - 0 + 6 - 0 + 6 - 0 + 6 - 0 + 6 - - - - false - - - - 30 - 30 - - - - Draw elliptical fiducial. - - - - - - - :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png - - - - 32 - 32 - - - - false - - - true - - - - - + + false - - - 30 - 30 - - - - Flip fiber waypoints of selcted fiducial around one axis. + + QCommandLinkButton:disabled { + border: none; +} - + Join Bundles - :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico - - - - 32 - 32 - - - - false - - - true + :/QmitkDiffusionImaging/general_icons/plus.ico:/QmitkDiffusionImaging/general_icons/plus.ico - - - - Qt::Horizontal + + + + QFrame::NoFrame - - - 40 - 20 - - - - - - - - - - - - - - Load Parameters - - - - :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico - - - - - - - - - - Save Parameters - - - - :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico - - - - - - - QGroupBox { - background-color: transparent; -} - - - Operations - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - false - - - QCommandLinkButton:disabled { - border: none; -} - - - Join Bundles - - - - :/QmitkDiffusionImaging/general_icons/plus.ico:/QmitkDiffusionImaging/general_icons/plus.ico - - - - - - - QFrame::NoFrame - - - QFrame::Raised + + QFrame::Raised 0 0 0 0 Y false Rotation angle (in degree) around x-axis. - 3 + 2 -360.000000000000000 360.000000000000000 0.100000000000000 Axis: false Rotation angle (in degree) around y-axis. - 3 + 2 -360.000000000000000 360.000000000000000 0.100000000000000 Translation: false Translation (in mm) in direction of the z-axis. - 3 + 2 -1000.000000000000000 1000.000000000000000 0.100000000000000 Translation (in mm) in direction of the y-axis. - 3 + 2 -1000.000000000000000 1000.000000000000000 0.100000000000000 X false Rotation: false Z false Rotation angle (in degree) around z-axis. - 3 + 2 -360.000000000000000 360.000000000000000 0.100000000000000 Translation (in mm) in direction of the x-axis. - 3 + 2 -1000.000000000000000 1000.000000000000000 0.100000000000000 Scaling: false Scaling factor for selected fiber bundle along the x-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the y-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the z-axis. 0.010000000000000 10.000000000000000 0.010000000000000 1.000000000000000 false QCommandLinkButton:disabled { border: none; } Copy Bundles :/QmitkDiffusionImaging/general_icons/copy2.ico:/QmitkDiffusionImaging/general_icons/copy2.ico false QCommandLinkButton:disabled { border: none; } Transform Selection :/QmitkDiffusionImaging/general_icons/refresh.ico:/QmitkDiffusionImaging/general_icons/refresh.ico If checked, the fiducials belonging to the modified bundle are also modified. Include Fiducials true Qt::Vertical 20 40 + + + + + + + Save Parameters + + + + :/QmitkDiffusionImaging/general_icons/download.ico:/QmitkDiffusionImaging/general_icons/download.ico + + + + + + + QGroupBox { + background-color: transparent; +} + + + Fiducial Options + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Fiducial Attributes + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Length of fiducial axis 2 + + + 2 + + + 0.000000000000000 + + + 9999.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Axis 1: + + + false + + + + + + + + + + + + + + + + Position X: + + + false + + + + + + + World Position in mm + + + 2 + + + -99999.000000000000000 + + + 99999.000000000000000 + + + 0.100000000000000 + + + + + + + World Position in mm + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + World Position in mm + + + 2 + + + -360.000000000000000 + + + 360.000000000000000 + + + 0.100000000000000 + + + + + + + Length of fiducial axis 1 + + + 2 + + + 0.000000000000000 + + + 9999.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + + + Position Z: + + + false + + + + + + + + + + + + + + + + Position Y: + + + false + + + + + + + + + + + + + + + + Axis 2: + + + false + + + + + + + + + + + + + + + + Twist: + + + false + + + + + + + Twist in degree + + + 2 + + + -180.000000000000000 + + + 180.000000000000000 + + + 0.100000000000000 + + + + + + + + + + All fiducials are treated as circles with the same radius as the first fiducial. + + + Use Constant Fiducial Radius + + + false + + + + + + + false + + + Align selected fiducials with voxel grid. Shifts selected fiducials to nearest voxel center. + + + QCommandLinkButton:disabled { + border: none; +} + + + Align With Grid + + + + :/QmitkDiffusionImaging/general_icons/right.ico:/QmitkDiffusionImaging/general_icons/right.ico + + + + + + + + + + + + + Load Parameters + + + + :/QmitkDiffusionImaging/general_icons/upload.ico:/QmitkDiffusionImaging/general_icons/upload.ico + + + m_CircleButton m_FlipButton m_RealTimeFibers m_AdvancedOptionsBox m_DistributionBox m_VarianceBox m_FiberDensityBox m_FiberSamplingBox m_TensionBox m_ContinuityBox m_BiasBox m_GenerateFibersButton m_ConstantRadiusBox m_AlignOnGrid m_XrotBox m_YrotBox m_ZrotBox m_XtransBox m_YtransBox m_ZtransBox m_XscaleBox m_YscaleBox m_ZscaleBox m_TransformBundlesButton m_CopyBundlesButton m_JoinBundlesButton m_IncludeFiducials m_SaveParametersButton m_LoadParametersButton