diff --git a/Modules/TubeGraph/include/mitkTubeGraphDataInteractor.h b/Modules/TubeGraph/include/mitkTubeGraphDataInteractor.h index 4ca2b93bbd..faaacb4202 100644 --- a/Modules/TubeGraph/include/mitkTubeGraphDataInteractor.h +++ b/Modules/TubeGraph/include/mitkTubeGraphDataInteractor.h @@ -1,123 +1,126 @@ /*=================================================================== 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. ===================================================================*/ #ifndef mitkTubeGraphDataInteractor3D_h_ #define mitkTubeGraphDataInteractor3D_h_ #include #include #include #include "mitkTubeGraph.h" #include "mitkTubeGraphProperty.h" namespace mitk { // Define events for TubeGraph interaction notifications itkEventMacro(SelectionChangedTubeGraphEvent, itk::AnyEvent); /** * \brief * * \ingroup Interaction */ // Inherit from DataInteratcor, this provides functionality of a state machine and configurable inputs. class MITKTUBEGRAPH_EXPORT TubeGraphDataInteractor : public DataInteractor { public: mitkClassMacro(TubeGraphDataInteractor, DataInteractor); itkNewMacro(Self); /** * Describes, which activation modes are available based on the * currently picked tube: * * \li None means "no tube is active" * \li Single means "only the picked tube is active" * \li ToRoot means "all tubes from the picked on down to the root of the tube graph are active" * \li ToPeriphery means "all tubes included in the subgraph of the currently picked vessel are active" * \li Points means "shortes path between two picked tubes are active" * \li Multiple means "all picked tubes are active" */ enum ActivationMode { None = 0, Single, ToRoot, ToPeriphery, Points, Multiple }; enum ActionMode { AttributationMode = 0, AnnotationMode, EditMode, RootMode, InformationMode }; void SetActivationMode(const ActivationMode &activationMode); ActivationMode GetActivationMode(); void SetActionMode(const ActionMode &actionMode); ActionMode GetActionMode(); void ResetPickedTubes(); + mitk::Point3D GetLastPickedPosition(); + protected: TubeGraphDataInteractor(); ~TubeGraphDataInteractor() override; /** * Here actions strings from the loaded state machine pattern are mapped to functions of * the DataInteractor. These functions are called when an action from the state machine pattern is executed. */ void ConnectActionsAndFunctions() override; /** * This function is called when a DataNode has been set/changed. */ void DataNodeChanged() override; /** * Initializes the movement, stores starting position. */ virtual bool CheckOverTube(const InteractionEvent *); virtual void SelectTube(StateMachineAction *, InteractionEvent *); virtual void DeselectTube(StateMachineAction *, InteractionEvent *); void SelectTubesByActivationModus(); void UpdateActivation(); private: std::vector GetTubesToRoot(); std::vector GetTubesBetweenPoints(); std::vector GetPathToPeriphery(); std::vector GetPathBetweenTubes(const TubeGraph::TubeDescriptorType &start, const TubeGraph::TubeDescriptorType &end); TubeGraph::Pointer m_TubeGraph; TubeGraphProperty::Pointer m_TubeGraphProperty; TubeGraph::TubeDescriptorType m_LastPickedTube; TubeGraph::TubeDescriptorType m_SecondLastPickedTube; ActivationMode m_ActivationMode; ActionMode m_ActionMode; + mitk::TubeElement* m_LastPickedElement; }; } #endif diff --git a/Modules/TubeGraph/src/Interactions/mitkTubeGraphDataInteractor.cpp b/Modules/TubeGraph/src/Interactions/mitkTubeGraphDataInteractor.cpp index a0081daf50..422a4d04e4 100644 --- a/Modules/TubeGraph/src/Interactions/mitkTubeGraphDataInteractor.cpp +++ b/Modules/TubeGraph/src/Interactions/mitkTubeGraphDataInteractor.cpp @@ -1,280 +1,286 @@ /*=================================================================== 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 "mitkTubeGraphDataInteractor.h" #include #include #include #include "mitkTubeGraphPicker.h" #include #include #include #include #include mitk::TubeGraphDataInteractor::TubeGraphDataInteractor() : m_LastPickedTube(TubeGraph::ErrorId), m_SecondLastPickedTube(TubeGraph::ErrorId), m_ActivationMode(None), m_ActionMode(AttributationMode) { } -mitk::TubeGraphDataInteractor::~TubeGraphDataInteractor() -{ -} +mitk::TubeGraphDataInteractor::~TubeGraphDataInteractor() {} void mitk::TubeGraphDataInteractor::ConnectActionsAndFunctions() { // **Conditions** that can be used in the state machine, to ensure that certain conditions are met, before actually // executing an action CONNECT_CONDITION("isOverTube", CheckOverTube); // **Function** in the statmachine patterns also referred to as **Actions** CONNECT_FUNCTION("selectTube", SelectTube); CONNECT_FUNCTION("deselectTube", DeselectTube); } void mitk::TubeGraphDataInteractor::DataNodeChanged() { if (GetDataNode() != nullptr) { if (GetDataNode()->GetData() != nullptr) { m_TubeGraph = dynamic_cast(GetDataNode()->GetData()); m_TubeGraphProperty = dynamic_cast( m_TubeGraph->GetProperty("Tube Graph.Visualization Information").GetPointer()); if (m_TubeGraphProperty.IsNull()) MITK_ERROR << "Something went wrong! No tube graph property!"; } else m_TubeGraph = nullptr; } else m_TubeGraph = nullptr; } bool mitk::TubeGraphDataInteractor::CheckOverTube(const InteractionEvent *interactionEvent) { const auto *positionEvent = dynamic_cast(interactionEvent); if (positionEvent == nullptr) return false; auto *picker = new mitk::TubeGraphPicker(); picker->SetTubeGraph(m_TubeGraph); - TubeGraph::TubeDescriptorType tubeDescriptor = picker->GetPickedTube(positionEvent->GetPositionInWorld()).first; + auto pickedTube = picker->GetPickedTube(positionEvent->GetPositionInWorld()); + + TubeGraph::TubeDescriptorType tubeDescriptor = pickedTube.first; if (tubeDescriptor != TubeGraph::ErrorId) { + m_LastPickedElement = pickedTube.second; m_SecondLastPickedTube = m_LastPickedTube; m_LastPickedTube = tubeDescriptor; return true; } else // nothing picked return false; } void mitk::TubeGraphDataInteractor::SelectTube(StateMachineAction *, InteractionEvent *interactionEvent) { if (m_TubeGraph.IsNull()) return; this->SelectTubesByActivationModus(); interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll(); if (m_ActivationMode != None) { // show tube id on status bar std::stringstream displayText; displayText << "Picked tube: ID [" << m_LastPickedTube.first << "," << m_LastPickedTube.second << "]"; StatusBar::GetInstance()->DisplayText(displayText.str().c_str()); // TODO!!! this->InvokeEvent(SelectionChangedTubeGraphEvent()); } } void mitk::TubeGraphDataInteractor::DeselectTube(StateMachineAction *, InteractionEvent *interactionEvent) { if (m_TubeGraph.IsNull()) return; if ((m_ActivationMode != Multiple) && (m_ActivationMode != Points)) { m_TubeGraphProperty->DeactivateAllTubes(); interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll(); // TODO!!!this->InvokeEvent(SelectionChangedTubeGraphEvent()); } // show info on status bar StatusBar::GetInstance()->DisplayText("No tube hit!"); } void mitk::TubeGraphDataInteractor::SetActivationMode(const ActivationMode &activationMode) { m_ActivationMode = activationMode; if (m_TubeGraph.IsNotNull()) if (m_LastPickedTube != mitk::TubeGraph::ErrorId) this->UpdateActivation(); } mitk::TubeGraphDataInteractor::ActivationMode mitk::TubeGraphDataInteractor::GetActivationMode() { return m_ActivationMode; } void mitk::TubeGraphDataInteractor::SetActionMode(const ActionMode &actionMode) { m_ActionMode = actionMode; } mitk::TubeGraphDataInteractor::ActionMode mitk::TubeGraphDataInteractor::GetActionMode() { return m_ActionMode; } void mitk::TubeGraphDataInteractor::SelectTubesByActivationModus() { if (m_LastPickedTube != mitk::TubeGraph::ErrorId) { this->UpdateActivation(); } } void mitk::TubeGraphDataInteractor::UpdateActivation() { if (m_ActionMode == RootMode) { m_TubeGraphProperty->DeactivateAllTubes(); m_TubeGraphProperty->SetTubeActive(m_LastPickedTube, true); // QmitkTubeGraphSelectRootDialog* dialog = new QmitkTubeGraphSelectRootDialog(m_Parent); // int dialogReturnValue = dialog->exec(); // delete dialog; // if ( dialogReturnValue != QDialog::Rejected ) // user doesn't clicked cancel or pressed Esc or something similar //{ m_TubeGraph->SetRootTube(m_LastPickedTube); //} m_TubeGraphProperty->DeactivateAllTubes(); RenderingManager::GetInstance()->RequestUpdateAll(); } else { switch (m_ActivationMode) { case None: { m_TubeGraphProperty->DeactivateAllTubes(); } break; case Single: { m_TubeGraphProperty->DeactivateAllTubes(); m_TubeGraphProperty->SetTubeActive(m_LastPickedTube, true); } break; case Multiple: { // special deactivation for multiple modus // if activated--> deactivate; if not activated--> activate if (m_TubeGraphProperty->IsTubeActive(m_LastPickedTube)) m_TubeGraphProperty->SetTubeActive(m_LastPickedTube, false); else m_TubeGraphProperty->SetTubeActive(m_LastPickedTube, true); } break; case ToRoot: { m_TubeGraphProperty->DeactivateAllTubes(); std::vector activeTubes = this->GetTubesToRoot(); m_TubeGraphProperty->SetTubesActive(activeTubes); } break; case ToPeriphery: { m_TubeGraphProperty->DeactivateAllTubes(); std::vector activeTubes = this->GetPathToPeriphery(); m_TubeGraphProperty->SetTubesActive(activeTubes); } break; case Points: { m_TubeGraphProperty->DeactivateAllTubes(); std::vector activeTubes = this->GetTubesBetweenPoints(); m_TubeGraphProperty->SetTubesActive(activeTubes); } break; default: MITK_WARN << "Unknown tube graph interaction mode!"; break; } } } std::vector mitk::TubeGraphDataInteractor::GetTubesToRoot() { TubeGraph::TubeDescriptorType root = m_TubeGraph->GetRootTube(); if (root == TubeGraph::ErrorId) { root = m_TubeGraph->GetThickestTube(); m_TubeGraph->SetRootTube(root); } return this->GetPathBetweenTubes(m_LastPickedTube, root); } std::vector mitk::TubeGraphDataInteractor::GetTubesBetweenPoints() { return this->GetPathBetweenTubes(m_LastPickedTube, m_SecondLastPickedTube); } std::vector mitk::TubeGraphDataInteractor::GetPathBetweenTubes( const mitk::TubeGraph::TubeDescriptorType &start, const mitk::TubeGraph::TubeDescriptorType &end) { std::vector solutionPath; if ((start != TubeGraph::ErrorId) && (end != TubeGraph::ErrorId)) { if (start != end) solutionPath = m_TubeGraph->SearchAllPathBetweenVertices(start, end); else solutionPath.push_back(start); } return solutionPath; } std::vector mitk::TubeGraphDataInteractor::GetPathToPeriphery() { std::vector solutionPath; if (m_LastPickedTube != TubeGraph::ErrorId) solutionPath = m_TubeGraph->SearchPathToPeriphery(m_LastPickedTube); return solutionPath; } void mitk::TubeGraphDataInteractor::ResetPickedTubes() { m_LastPickedTube = TubeGraph::ErrorId; m_SecondLastPickedTube = TubeGraph::ErrorId; } + +mitk::Point3D mitk::TubeGraphDataInteractor::GetLastPickedPosition() +{ + return m_LastPickedElement->GetCoordinates(); +} diff --git a/Modules/TubeGraph/src/Interactions/mitkTubeGraphPicker.cpp b/Modules/TubeGraph/src/Interactions/mitkTubeGraphPicker.cpp index 24ad32b660..2abae5c5a5 100644 --- a/Modules/TubeGraph/src/Interactions/mitkTubeGraphPicker.cpp +++ b/Modules/TubeGraph/src/Interactions/mitkTubeGraphPicker.cpp @@ -1,92 +1,97 @@ /*=================================================================== 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 "mitkTubeGraphPicker.h" mitk::TubeGraphPicker::TubeGraphPicker() { m_WorldPosition.Fill(0.0); } -mitk::TubeGraphPicker::~TubeGraphPicker() -{ -} +mitk::TubeGraphPicker::~TubeGraphPicker() {} void mitk::TubeGraphPicker::SetTubeGraph(const mitk::TubeGraph *tubeGraph) { m_TubeGraph = tubeGraph; m_TubeGraphProperty = dynamic_cast(m_TubeGraph->GetProperty("Tube Graph.Visualization Information").GetPointer()); } /** -* Implements the picking process -*/ + * Implements the picking process + */ std::pair mitk::TubeGraphPicker::GetPickedTube( const Point3D pickedPosition) { if (!m_TubeGraph) { MITK_ERROR << "mitk::TubeGraphPicker: No tube graph available. Please set an input!" << std::endl; mitk::TubeElement *nullPointer = nullptr; return std::pair(TubeGraph::ErrorId, nullPointer); } m_WorldPosition = pickedPosition; Point3D currentPosition; ScalarType closestDistance = itk::NumericTraits::max(); ScalarType currentDistance = itk::NumericTraits::max(); float currentRadius = 0; TubeGraph::TubeDescriptorType currentTubeId(TubeGraph::ErrorId); TubeGraph::TubeDescriptorType tubeId(TubeGraph::ErrorId); TubeElement *tubeElement; // iterate over all edges and find the edge, which element is near by the clicked point std::vector allEdges = m_TubeGraph->GetVectorOfAllEdges(); for (auto edge = allEdges.begin(); edge != allEdges.end(); ++edge) { std::pair soureTargetPair = m_TubeGraph->GetVerticesOfAnEdge(m_TubeGraph->GetEdgeDescriptor(*edge)); currentTubeId = TubeGraph::TubeDescriptorType(m_TubeGraph->GetVertexDescriptor(soureTargetPair.first), m_TubeGraph->GetVertexDescriptor(soureTargetPair.second)); // check if the tube is visible, if not pass this tube. User can not choose a tube, which he can't see if (m_TubeGraphProperty->IsTubeVisible(currentTubeId)) { std::vector allElements = edge->GetElementVector(); for (unsigned int index = 0; index < edge->GetNumberOfElements(); index++) { currentPosition = allElements[index]->GetCoordinates(); if (dynamic_cast(allElements[index])) currentRadius = ((dynamic_cast(allElements[index]))->GetDiameter()) / 2; else currentRadius = 0; // calculate point->point distance + itk::Index<3> worldIndex; + m_TubeGraph->GetGeometry()->WorldToIndex(pickedPosition, worldIndex); + + m_WorldPosition[0] = worldIndex[0]; + m_WorldPosition[1] = worldIndex[1]; + m_WorldPosition[2] = worldIndex[2]; + currentDistance = m_WorldPosition.EuclideanDistanceTo(currentPosition); if (currentDistance < closestDistance && (currentDistance - currentRadius) < 1.0) { closestDistance = currentDistance; tubeId = currentTubeId; tubeElement = allElements[index]; } } } } return std::make_pair(tubeId, tubeElement); }