diff --git a/Modules/FiberDissection/CMakeLists.txt b/Modules/FiberDissection/CMakeLists.txt new file mode 100644 index 0000000..14605b9 --- /dev/null +++ b/Modules/FiberDissection/CMakeLists.txt @@ -0,0 +1,5 @@ +MITK_CREATE_MODULE( + SUBPROJECTS MITK-Diffusion + INCLUDE_DIRS Interactor ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS MitkDiffusionCore +) diff --git a/Modules/FiberDissection/Interactor/mitkStreamlineInteractor.cpp b/Modules/FiberDissection/Interactor/mitkStreamlineInteractor.cpp new file mode 100644 index 0000000..20011f4 --- /dev/null +++ b/Modules/FiberDissection/Interactor/mitkStreamlineInteractor.cpp @@ -0,0 +1,231 @@ +# include + +/*============================================================================ + +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 "mitkStreamlineInteractor.h" +#include "mitkStreamlineMapper2D.h" + +// MITK includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VTK includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +mitk::StreamlineInteractor::StreamlineInteractor() +{ + m_ColorForHighlight[0] = 1.0; + m_ColorForHighlight[1] = 0.5; + m_ColorForHighlight[2] = 0.0; + m_ColorForHighlight[3] = 1.0; + + // TODO if we want to get this configurable, the this is the recipe: + // - make the 2D mapper add corresponding properties to control "enabled" and "color" + // - make the interactor evaluate those properties + // - in an ideal world, modify the state machine on the fly and skip mouse move handling +} + +mitk::StreamlineInteractor::~StreamlineInteractor() +{ +} + +void mitk::StreamlineInteractor::ConnectActionsAndFunctions() +{ + CONNECT_CONDITION("PickedHandle", HasPickedHandle); + + CONNECT_FUNCTION("FeedUndoStack", FeedUndoStack); +} + +void mitk::StreamlineInteractor::SetStreamlineNode(DataNode *node) +{ + DataInteractor::SetDataNode(node); + + m_Streamline = dynamic_cast(node->GetData()); + + // setup picking from just this object + m_Picker.clear(); +} + +void mitk::StreamlineInteractor::SetManipulatedObjectNode(DataNode *node) +{ + if (node && node->GetData()) + { + m_ManipulatedObjectGeometry = node->GetData()->GetGeometry(); + } +} + +bool mitk::StreamlineInteractor::HasPickedHandle(const InteractionEvent *interactionEvent) +{ + auto positionEvent = dynamic_cast(interactionEvent); + if (positionEvent == nullptr || + m_Streamline.IsNull() || + m_ManipulatedObjectGeometry.IsNull() || + interactionEvent->GetSender()->GetRenderWindow()->GetNeverRendered()) + { + return false; + } + + if (interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D) + { + m_PickedHandle = PickFrom2D(positionEvent); + } + else + { + m_PickedHandle = PickFrom3D(positionEvent); + } + + UpdateHandleHighlight(); + + return m_PickedHandle != Streamline::NoHandle; +} + +void mitk::StreamlineInteractor::FeedUndoStack(StateMachineAction *, InteractionEvent *) +{ + if (m_UndoEnabled) + { + OperationEvent *operationEvent = new OperationEvent(m_ManipulatedObjectGeometry, + // OperationEvent will destroy operations! + // --> release() and not get() + m_FinalDoOperation.release(), + m_FinalUndoOperation.release(), + "Direct geometry manipulation"); + mitk::OperationEvent::IncCurrObjectEventId(); // save each modification individually + m_UndoController->SetOperationEvent(operationEvent); + } +} + +mitk::Streamline::HandleType mitk::StreamlineInteractor::PickFrom2D(const InteractionPositionEvent *positionEvent) +{ + BaseRenderer *renderer = positionEvent->GetSender(); + + auto mapper = GetDataNode()->GetMapper(BaseRenderer::Standard2D); + auto Streamline_mapper = dynamic_cast(mapper); + auto &picker = m_Picker[renderer]; + + if (picker == nullptr) + { + picker = vtkSmartPointer::New(); + picker->SetTolerance(0.005); + + if (Streamline_mapper) + { // doing this each time is bizarre + picker->AddPickList(Streamline_mapper->GetVtkProp(renderer)); + picker->PickFromListOn(); + } + } + + auto displayPosition = positionEvent->GetPointerPositionOnScreen(); + picker->Pick(displayPosition[0], displayPosition[1], 0, positionEvent->GetSender()->GetVtkRenderer()); + + vtkIdType pickedPointID = picker->GetPointId(); + if (pickedPointID == -1) + { + return Streamline::NoHandle; + } + + vtkPolyData *polydata = Streamline_mapper->GetVtkPolyData(renderer); + + if (polydata && polydata->GetPointData() && polydata->GetPointData()->GetScalars()) + { + double dataValue = polydata->GetPointData()->GetScalars()->GetTuple1(pickedPointID); + return m_Streamline->GetHandleFromPointDataValue(dataValue); + } + + return Streamline::NoHandle; +} + +mitk::Streamline::HandleType mitk::StreamlineInteractor::PickFrom3D(const InteractionPositionEvent *positionEvent) +{ + BaseRenderer *renderer = positionEvent->GetSender(); + auto &picker = m_Picker[renderer]; + if (picker == nullptr) + { + picker = vtkSmartPointer::New(); + picker->SetTolerance(0.005); + auto mapper = GetDataNode()->GetMapper(BaseRenderer::Standard3D); + auto vtk_mapper = dynamic_cast(mapper); + if (vtk_mapper) + { // doing this each time is bizarre + picker->AddPickList(vtk_mapper->GetVtkProp(renderer)); + picker->PickFromListOn(); + } + } + + auto displayPosition = positionEvent->GetPointerPositionOnScreen(); + picker->Pick(displayPosition[0], displayPosition[1], 0, positionEvent->GetSender()->GetVtkRenderer()); + + vtkIdType pickedPointID = picker->GetPointId(); + if (pickedPointID == -1) + { + return Streamline::NoHandle; + } + + // _something_ picked + return m_Streamline->GetHandleFromPointID(pickedPointID); +} + +void mitk::StreamlineInteractor::UpdateHandleHighlight() +{ + if (m_HighlightedHandle != m_PickedHandle) { + + auto node = GetDataNode(); + if (node == nullptr) return; + + auto base_prop = node->GetProperty("LookupTable"); + if (base_prop == nullptr) return; + + auto lut_prop = dynamic_cast(base_prop); + if (lut_prop == nullptr) return; + + auto lut = lut_prop->GetLookupTable(); + if (lut == nullptr) return; + + // Table size is expected to constructed as one entry per Streamline-part enum value + assert(lut->GetVtkLookupTable()->GetNumberOfTableValues() > std::max(m_PickedHandle, m_HighlightedHandle)); + + // Reset previously overwritten color + if (m_HighlightedHandle != Streamline::NoHandle) + { + lut->SetTableValue(m_HighlightedHandle, m_ColorReplacedByHighlight); + } + + // Overwrite currently highlighted color + if (m_PickedHandle != Streamline::NoHandle) + { + lut->GetTableValue(m_PickedHandle, m_ColorReplacedByHighlight); + lut->SetTableValue(m_PickedHandle, m_ColorForHighlight); + } + + // Mark node modified to allow repaint + node->Modified(); + RenderingManager::GetInstance()->RequestUpdateAll(RenderingManager::REQUEST_UPDATE_ALL); + + m_HighlightedHandle = m_PickedHandle; + } +} diff --git a/Modules/FiberDissection/Interactor/mitkStreamlineInteractor.h b/Modules/FiberDissection/Interactor/mitkStreamlineInteractor.h new file mode 100644 index 0000000..e507164 --- /dev/null +++ b/Modules/FiberDissection/Interactor/mitkStreamlineInteractor.h @@ -0,0 +1,117 @@ +/*============================================================================ + +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 mitkStreamlineInteractor_h +#define mitkStreamlineInteractor_h + + +// MITK includes +#include +#include +#include + +// VTK includes +#include +#include + +// System includes +#include + +#include "MitkStreamlineExports.h" + +namespace mitk +{ + class InteractionPositionEvent; + + //! Data interactor to pick streamlines via interaction + //! with a mitk::Streamline. + //! + //! + //! To determine what parts of the object are clicked during interaction, + //! the mappers (2D: custom mapper, 3D: regular surface mapper) are asked + //! for their VTK objects, picking is performed, and the picked point is + //! forwarded to the Streamline object for interpretation. + //! + //! The interactor fills the undo/redo stack with operations on the modified geometry. + //! + //! \sa Streamline + class MITKStreamline_EXPORT StreamlineInteractor : public DataInteractor + { + public: + mitkClassMacro(StreamlineInteractor, DataInteractor); + itkFactorylessNewMacro(Self); + itkCloneMacro(Self); + + //! The node holding the Streamline for visual feedback. + //! This is the node that the interactor is primarily working on + //! (calls DataInteractor::SetDataNode). + void SetStreamlineNode(DataNode *node); + + private: + StreamlineInteractor(); + ~StreamlineInteractor() override; + + //! Setup the relation between the XML state machine and this object's methods. + void ConnectActionsAndFunctions() override; + + //! State machine condition: successful Streamline picking + //! \return true when any part of the Streamline has been picked. + bool HasPickedHandle(const InteractionEvent *); + + //! Pick a Streamline handle from a 2D event (passing by the 2D mapper) + Streamline::HandleType PickFrom2D(const InteractionPositionEvent *positionEvent); + + //! Pick a Streamline handle from a 3D event + //! (passing by the general surface mapper and the Streamline object) + Streamline::HandleType PickFrom3D(const InteractionPositionEvent *positionEvent); + + void UpdateHandleHighlight(); + + //! the Streamline used for visual feedback and picking + Streamline::Pointer m_Streamline; + + //! The manipulated object's geometry + BaseGeometry::Pointer m_ManipulatedObjectGeometry; + + //! For picking on the vtkPolyData representing the Streamline + std::map> m_Picker; + + //! Part of the Streamline that was picked on last check + Streamline::HandleType m_PickedHandle = Streamline::NoHandle; + + //! Part of the Streamline that is currently highlighted + Streamline::HandleType m_HighlightedHandle = Streamline::NoHandle; + + //! Color (RGBA) used for highlighting + double m_ColorForHighlight[4]; + + //! Color (RGBA) that has been replaced by m_ColorForHighlight + double m_ColorReplacedByHighlight[4]; + + Point2D m_InitialClickPosition2D; //< Initial screen click position + double m_InitialClickPosition2DZ; //< Z value of the initial screen click position + Point3D m_InitialClickPosition3D; //< Initial 3D click position + + Point2D m_InitialStreamlineCenter2D; //< Initial position of the Streamline's center in screen coordinates + Point3D m_InitialStreamlineCenter3D; //< Initial 3D position of the Streamline's center + + Vector3D m_AxisOfMovement; //< Axis along which we move when translating + Vector3D m_AxisOfRotation; //< Axis around which we turn when rotating + + std::unique_ptr m_FinalDoOperation; //< Operation for the undo-stack + std::unique_ptr m_FinalUndoOperation; //< Operation for the undo-stack + + //! A copy of the origin geometry, to avoid accumulation of tiny errors + BaseGeometry::Pointer m_InitialManipulatedObjectGeometry; + }; +} +#endif diff --git a/Modules/FiberDissection/Interactor/resources/Interactions/Streamline3DConfig.xml b/Modules/FiberDissection/Interactor/resources/Interactions/Streamline3DConfig.xml new file mode 100644 index 0000000..f442503 --- /dev/null +++ b/Modules/FiberDissection/Interactor/resources/Interactions/Streamline3DConfig.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Modules/FiberDissection/Interactor/resources/Interactions/Streamline3DStates.xml b/Modules/FiberDissection/Interactor/resources/Interactions/Streamline3DStates.xml new file mode 100644 index 0000000..3d3cf64 --- /dev/null +++ b/Modules/FiberDissection/Interactor/resources/Interactions/Streamline3DStates.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/Modules/FiberDissection/files.cmake b/Modules/FiberDissection/files.cmake new file mode 100644 index 0000000..47f77da --- /dev/null +++ b/Modules/FiberDissection/files.cmake @@ -0,0 +1,13 @@ +set(H_FILES + Interactor/mitkStreamlineInteractor.h +) + +set(CPP_FILES + Interactor/mitkStreamlineInteractor.cpp +) + +set(RESOURCE_FILES + # "Interactions" prefix forced by mitk::StateMachine + Interactions/Gizmo3DStates.xml + Interactions/Gizmo3DConfig.xml +) diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index ac97051..926de49 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,8 +1,9 @@ set(MITK_MODULES DiffusionCore FiberTracking Connectomics MriSimulation DiffusionIO DiffusionCmdApps + FiberDissection ) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkInteractiveFiberDissectionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkInteractiveFiberDissectionView.cpp index a1e80fc..e3dcff1 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkInteractiveFiberDissectionView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkInteractiveFiberDissectionView.cpp @@ -1,583 +1,532 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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 #include // Qmitk #include "QmitkInteractiveFiberDissectionView.h" #include //Pointset #include //Pointset #include #include #include #include #include #include #include #include #include "usModuleRegistry.h" //#include #include "mitkNodePredicateDataType.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkInteractiveFiberDissectionView::VIEW_ID = "org.mitk.views.interactivefiberdissection"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace mitk; QmitkInteractiveFiberDissectionView::QmitkInteractiveFiberDissectionView() : QmitkAbstractView() , m_Controls( 0 ) , m_IterationCounter(0) { } // Destructor QmitkInteractiveFiberDissectionView::~QmitkInteractiveFiberDissectionView() { } void QmitkInteractiveFiberDissectionView::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::QmitkInteractiveFiberDissectionViewControls; m_Controls->setupUi( parent ); m_Controls->m_selectedPointSetWidget->SetDataStorage(GetDataStorage());//pointset m_Controls->m_selectedPointSetWidget->SetNodePredicate(mitk::NodePredicateAnd::New(//pointset mitk::TNodePredicateDataType::New(),//pointset mitk::NodePredicateNot::New(mitk::NodePredicateOr::New(//pointset mitk::NodePredicateProperty::New("helper object"),//pointset mitk::NodePredicateProperty::New("hidden object")))));//pointset m_Controls->m_selectedPointSetWidget->SetSelectionIsOptional(true);//pointset m_Controls->m_selectedPointSetWidget->SetAutoSelectNewNodes(true);//pointset m_Controls->m_selectedPointSetWidget->SetEmptyInfo(QString("Please select a point set"));//pointset m_Controls->m_selectedPointSetWidget->SetPopUpTitel(QString("Select point set"));//pointset connect(m_Controls->m_ErazorButton, SIGNAL( clicked() ), this, SLOT( RemovefromBundle() ) ); //need connect(m_Controls->m_HighlighterButton, SIGNAL( clicked() ), this, SLOT( AddtoBundle() ) ); //need connect(m_Controls->m_StreamlineCreation, SIGNAL( clicked() ), this, SLOT( CreateStreamline())); connect(m_Controls->m_AddRandomFibers, SIGNAL( clicked() ), this, SLOT( ExtractRandomFibersFromTractogram() ) ); //need connect(m_Controls->m_addPointSetPushButton, &QPushButton::clicked,//pointset this, &QmitkInteractiveFiberDissectionView::OnAddPointSetClicked);//pointset connect(m_Controls->m_selectedPointSetWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged,//pointset this, &QmitkInteractiveFiberDissectionView::OnCurrentSelectionChanged);//pointset auto renderWindowPart = this->GetRenderWindowPart();//pointset if (nullptr != renderWindowPart)//pointset this->RenderWindowPartActivated(renderWindowPart);//pointset this->OnCurrentSelectionChanged(m_Controls->m_selectedPointSetWidget->GetSelectedNodes());//pointset } UpdateGui(); } void QmitkInteractiveFiberDissectionView::SetFocus() { m_Controls->toolBoxx->setFocus(); //m_Controls->m_addPointSetPushButton->setFocus();//pointset } void QmitkInteractiveFiberDissectionView::UpdateGui() { m_Controls->m_FibLabel->setText("mandatory"); m_Controls->m_InputData->setTitle("Please Select Input Data"); // disable alle frames m_Controls->m_ErazorButton->setEnabled(false); m_Controls->m_HighlighterButton->setEnabled(false); m_Controls->m_addPointSetPushButton->setEnabled(false); m_Controls->m_StreamlineCreation->setEnabled(false); m_Controls->m_StreamtoTractogram->setEnabled(false); m_Controls->m_TrainClassifier->setEnabled(false); m_Controls->m_CreatePrediction->setEnabled(false); m_Controls->m_CreateUncertantyMap->setEnabled(false); m_Controls->m_Numtolabel->setEnabled(false); m_Controls->m_addPointSetPushButton->setEnabled(false); m_Controls->m_AddRandomFibers->setEnabled(false); bool fibSelected = !m_SelectedFB.empty(); bool multipleFibsSelected = (m_SelectedFB.size()>1); bool sthSelected = m_SelectedImageNode.IsNotNull(); bool psSelected = m_SelectedPS.IsNotNull(); bool nfibSelected = !m_negativeSelectedBundles.empty(); // toggle visibility of elements according to selected method // are fiber bundles selected? if ( fibSelected ) { m_Controls->m_FibLabel->setText(QString(m_SelectedFB.at(0)->GetName().c_str())); m_Controls->m_addPointSetPushButton->setEnabled(true); m_Controls->m_AddRandomFibers->setEnabled(true); // more than two bundles needed to join/subtract if (multipleFibsSelected) { m_Controls->m_FibLabel->setText("multiple bundles selected"); } } // is image selected if (sthSelected) { m_Controls->m_addPointSetPushButton->setEnabled(true); } if (psSelected) { m_Controls->m_StreamlineCreation->setEnabled(true); } if (nfibSelected) { m_Controls->m_HighlighterButton->setEnabled(true); m_Controls->m_ErazorButton->setEnabled(true); } } void QmitkInteractiveFiberDissectionView::OnEndInteraction() { } void QmitkInteractiveFiberDissectionView::OnAddPointSetClicked()//pointset { // ask for the name of the point set bool ok = false; QString name = QInputDialog::getText(QApplication::activeWindow(), tr("Add point set..."), tr("Enter name for the new point set"), QLineEdit::Normal, tr("PointSet").arg(++m_IterationCounter), &ok); // QString name = "PointSet"; if (!ok || name.isEmpty()) { return; } mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); pointSetNode->SetData(pointSet); pointSetNode->SetProperty("name", mitk::StringProperty::New(name.toStdString())); pointSetNode->SetProperty("opacity", mitk::FloatProperty::New(1)); pointSetNode->SetColor(1.0, 1.0, 0.0); this->GetDataStorage()->Add(pointSetNode, m_SelectedImageNode); m_Controls->m_selectedPointSetWidget->SetCurrentSelectedNode(pointSetNode); } void QmitkInteractiveFiberDissectionView::OnCurrentSelectionChanged(QmitkSingleNodeSelectionWidget::NodeList /*nodes*/)//pointset { m_Controls->m_poinSetListWidget->SetPointSetNode(m_Controls->m_selectedPointSetWidget->GetSelectedNode()); m_SelectedPS = m_Controls->m_selectedPointSetWidget->GetSelectedNode(); UpdateGui(); } void QmitkInteractiveFiberDissectionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { m_SelectedFB.clear(); if (nodes.empty() || nodes.front().IsNull()) { m_SelectedImageNode = nullptr; } else { m_SelectedImageNode = nodes.front(); } for (auto node: nodes) { if (dynamic_cast(node->GetData())) m_SelectedImage = dynamic_cast(node->GetData()); else if ( dynamic_cast(node->GetData()) ) m_SelectedFB.push_back(node); } UpdateGui(); } void QmitkInteractiveFiberDissectionView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart)//pointset { if (nullptr != m_Controls) { m_Controls->m_poinSetListWidget->AddSliceNavigationController(renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); m_Controls->m_poinSetListWidget->AddSliceNavigationController(renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); m_Controls->m_poinSetListWidget->AddSliceNavigationController(renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); } } void QmitkInteractiveFiberDissectionView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart)//pointset { if (nullptr != m_Controls) { m_Controls->m_poinSetListWidget->RemoveSliceNavigationController(renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); m_Controls->m_poinSetListWidget->RemoveSliceNavigationController(renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); m_Controls->m_poinSetListWidget->RemoveSliceNavigationController(renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); } } void QmitkInteractiveFiberDissectionView::CreateStreamline() { if (m_positivSelectedBundles.empty()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); m_positiveFibersData = vtkSmartPointer::New(); m_positiveFibersData->SetPoints(vtkSmartPointer::New()); m_positiveFibersData->SetLines(vtkSmartPointer::New()); m_positiveBundle = mitk::FiberBundle:: New(m_positiveFibersData); node->SetData( m_positiveBundle ); m_positivSelectedBundles.push_back(node); MITK_INFO << m_positivSelectedBundles.size(); this->GetDataStorage()->Add(m_positivSelectedBundles.at(0)); MITK_INFO << "Create Bundle"; } if (!m_positivSelectedBundles.empty()) { this->GetDataStorage()->Remove(m_positivSelectedBundles.at(m_positivSelectedBundles.size()-1)); MITK_INFO << "Adding fibers"; } mitk::PointSet::Pointer pointSet = dynamic_cast(m_SelectedPS->GetData()); vnl_matrix streamline; streamline.set_size(3, pointSet->GetSize()); streamline.fill(0.0); mitk::PointSet::PointsIterator begin = pointSet->Begin(); mitk::PointSet::PointsIterator end = pointSet->End(); unsigned int i; mitk::PointSet::PointsContainer::Iterator it; for (it = begin, i = 0; it != end; ++it, ++i) { PointSet::PointType pt = pointSet->GetPoint(it->Index()); vnl_vector_fixed< float, 3 > candV; candV[0]=pt[0]; candV[1]=pt[1]; candV[2]=pt[2]; streamline.set_column(i, candV); } vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); unsigned int counter = 0; for (unsigned int i=0; iGetNumberOfCells(); ++i) { vtkCell* cell = m_positiveFibersData->GetCell(i); auto numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (unsigned int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); counter++; } // build Fiber vtkSmartPointer container = vtkSmartPointer::New(); for (unsigned int j=0; jInsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); m_positiveFibersData = vtkSmartPointer::New(); m_positiveFibersData->SetPoints(vtkSmartPointer::New()); m_positiveFibersData->SetLines(vtkSmartPointer::New()); m_positiveFibersData->SetPoints(vNewPoints); m_positiveFibersData->SetLines(vNewLines); m_positiveBundle = mitk::FiberBundle::New(vNewPolyData); m_positiveBundle->SetTrackVisHeader(dynamic_cast(m_SelectedImageNode->GetData())->GetGeometry()); m_positiveBundle->SetFiberColors(255, 255, 255); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(m_positiveBundle); node->SetName("+Bundle"); m_positivSelectedBundles.push_back(node); MITK_INFO << m_positivSelectedBundles.size(); this->GetDataStorage()->Add(m_positivSelectedBundles.at(m_positivSelectedBundles.size()-1)); UpdateGui(); } void QmitkInteractiveFiberDissectionView::ExtractRandomFibersFromTractogram() { MITK_INFO << "Number of Fibers to extract from Tractogram: "; MITK_INFO << m_Controls->m_NumRandomFibers->value(); if (m_negativeSelectedBundles.empty()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); m_negativeFibersData = vtkSmartPointer::New(); m_negativeFibersData->SetPoints(vtkSmartPointer::New()); m_negativeFibersData->SetLines(vtkSmartPointer::New()); m_negativeBundle = mitk::FiberBundle:: New(m_negativeFibersData); node->SetData( m_negativeBundle ); m_negativeSelectedBundles.push_back(node); MITK_INFO << m_negativeSelectedBundles.size(); // this->GetDataStorage()->Add(m_negativeSelectedBundles.at(0)); // UpdateGui(); MITK_INFO << "Create Bundle"; } mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedFB.at(0)->GetData()); // mitk::DataNode::Pointer node = mitk::DataNode::New(); // node ->SetData(pi); // this->GetDataStorage()->Add(cur_bundle); vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); unsigned int counter = 0; for ( int i=0; im_NumRandomFibers->value(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); auto numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (unsigned int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } // weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); m_negativeFibersData = vtkSmartPointer::New(); m_negativeFibersData->SetPoints(vtkSmartPointer::New()); m_negativeFibersData->SetLines(vtkSmartPointer::New()); m_negativeFibersData->SetPoints(vNewPoints); m_negativeFibersData->SetLines(vNewLines); m_negativeBundle = mitk::FiberBundle::New(vNewPolyData); m_negativeBundle->SetFiberColors(255, 0, 0); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(m_negativeBundle); node->SetName("-Bundle"); m_negativeSelectedBundles.push_back(node); MITK_INFO << m_negativeSelectedBundles.size(); this->GetDataStorage()->Add(m_negativeSelectedBundles.at(m_negativeSelectedBundles.size()-1)); UpdateGui(); } void QmitkInteractiveFiberDissectionView::RemovefromBundle() { -// BaseRenderer *renderer = positionEvent->GetSender(); - -// auto positionEvent = dynamic_cast(interactionEvent); -// MITK_INFO << positionEvent; - -// if (interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D) -// { -// MITK_INFO << "2d"; -// } -// else -// { -// MITK_INFO << "3d"; -// } - -// auto mapper = GetDataNode()->GetMapper(BaseRenderer::Standard2D); -// auto gizmo_mapper = dynamic_cast(mapper); -// auto &picker = m_Picker[renderer]; - -// if (picker == nullptr) -// { -// picker = vtkSmartPointer::New(); -// picker->SetTolerance(0.005); - -// if (gizmo_mapper) -// { // doing this each time is bizarre -// picker->AddPickList(gizmo_mapper->GetVtkProp(renderer)); -// picker->PickFromListOn(); -// } -// } - -// auto displayPosition = positionEvent->GetPointerPositionOnScreen(); -// picker->Pick(displayPosition[0], displayPosition[1], 0, positionEvent->GetSender()->GetVtkRenderer()); - -// vtkIdType pickedPointID = picker->GetPointId(); -// if (pickedPointID == -1) -// { -// return Gizmo::NoHandle; -// } - -// vtkPolyData *polydata = gizmo_mapper->GetVtkPolyData(renderer); - -// if (polydata && polydata->GetPointData() && polydata->GetPointData()->GetScalars()) -// { -// double dataValue = polydata->GetPointData()->GetScalars()->GetTuple1(pickedPointID); -// return m_Gizmo->GetHandleFromPointDataValue(dataValue); -// } - -// return Gizmo::NoHandle; - -// m_picker1 = vtkSmartPointer::New(); -// m_picker1->PickFromListOn(); -// m_picker1->SetTolerance(0.005); -// m_picker1->GetCellId(); -// m_picker1->GetPickedPositions(); - -//// selPt = m_picker1->GetSelectionPoint(); -//// x = *selPt; -//// y = *(selPt + 1); -//// pickPos = m_picker1->GetPickedPositions(); -//// xp = *(pickPos->GetPoint(0)); -//// yp = *(pickPos->GetPoint(0)+1); -//// zp = *(pickPos->GetPoint(0)+2); -//// double worldPos[3]; - - -// double* worldPosition = m_picker1->GetPickPosition(); -// MITK_INFO << m_picker1; -// MITK_INFO << m_picker1->GetCellId(); -// MITK_INFO << m_picker1->GetPickPosition(); -// MITK_INFO << m_picker1->GetSelectionPoint(); -// MITK_INFO << worldPosition[0] ; -// MITK_INFO << worldPosition[1] ; - -// vtkNew iren; + if (m_negativeSelectedBundles.IsNotNull()) + { + + m_DataInteractor = .at(m_negativeSelectedBundles.size()-1)->GetDataInteractor(); + // If no data Interactor is present create a new one + if (m_DataInteractor.IsNull()) + { + // Create PointSetData Interactor + m_DataInteractor = mitk::StreamlineInteractor::New(); + // Load the according state machine for regular point set interaction + m_DataInteractor->LoadStateMachine("Streamline3DStates.xml"); + // Set the configuration file that defines the triggers for the transitions + m_DataInteractor->SetEventConfig("Streamline3D.xml"); + // set the DataNode (which already is added to the DataStorage + m_DataInteractor->SetDataNode(m_PointSetNode); + } + } + else + { + m_PointSetNode->SetDataInteractor(nullptr); + m_DataInteractor = nullptr; + } + UpdateGui(); } void QmitkInteractiveFiberDissectionView::OnAddBundle() { UpdateGui(); }