diff --git a/Modules/Segmentation/Interactions/mitkContourModelInteractor.cpp b/Modules/Segmentation/Interactions/mitkContourModelInteractor.cpp index b31ca0c1d4..e95b9bdf25 100644 --- a/Modules/Segmentation/Interactions/mitkContourModelInteractor.cpp +++ b/Modules/Segmentation/Interactions/mitkContourModelInteractor.cpp @@ -1,283 +1,283 @@ /*=================================================================== 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 "mitkContourModelInteractor.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include #include #include mitk::ContourModelInteractor::ContourModelInteractor(DataNode* dataNode) :Interactor("ContourModelInteractor2", dataNode) { CONNECT_ACTION( AcCHECKPOINT, OnCheckPointClick ); CONNECT_ACTION( AcCHECKOBJECT, OnCheckContourClick ); CONNECT_ACTION( AcDELETEPOINT, OnDeletePoint ); CONNECT_ACTION( AcMOVEPOINT, OnMovePoint ); // CONNECT_ACTION( AcMOVE, OnMoveContour ); CONNECT_ACTION( AcMOVE, OnMove ); CONNECT_ACTION( AcFINISH, OnFinishEditing ); } mitk::ContourModelInteractor::~ContourModelInteractor() { } float mitk::ContourModelInteractor::CanHandleEvent(StateEvent const* stateEvent) const { float returnValue = 0.0; //if it is a key event that can be handled in the current state, then return 0.5 mitk::PositionEvent const *positionEvent = dynamic_cast (stateEvent->GetEvent()); //Key event handling: if (positionEvent == NULL) { //check for delete and escape event if(stateEvent->GetId() == 12 || stateEvent->GetId() == 14) { return 1.0; } //check, if the current state has a transition waiting for that key event. else if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { return 0.5; } else { return 0; } } int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); if ( contour != NULL ) { mitk::Point3D worldPoint3D = positionEvent->GetWorldPosition(); mitk::Geometry3D *contourGeometry = dynamic_cast< Geometry3D * >( contour->GetGeometry( timestep ) ); if ( contourGeometry ) { //if click is inside bounds the interactor can handle the event best if( contourGeometry->IsInside(worldPoint3D) ) { return 1.0; } return 0.9; } } return returnValue; } void mitk::ContourModelInteractor::DataChanged() { //go to initial state const mitk::Event* nullEvent = new mitk::Event(NULL, Type_User, BS_NoButton, BS_NoButton, Key_none); mitk::StateEvent* newStateEvent = new mitk::StateEvent(AcFINISH, nullEvent); this->HandleEvent( newStateEvent ); delete newStateEvent; delete nullEvent; return; } bool mitk::ContourModelInteractor::OnCheckPointClick( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; mitk::StateEvent* newStateEvent = NULL; int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); contour->Deselect(); /* * Check distance to any vertex. * Transition YES if click close to a vertex */ mitk::Point3D click = positionEvent->GetWorldPosition(); if (contour->SelectVertexAt(click, 1.5, timestep) ) { contour->SetSelectedVertexAsControlPoint(); assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent()); m_lastMousePosition = click; } else { newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } this->HandleEvent( newStateEvent ); return true; } bool mitk::ContourModelInteractor::OnCheckContourClick( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::Point3D click = positionEvent->GetWorldPosition(); mitk::StateEvent* newStateEvent = NULL; mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); mitk::Geometry3D *contourGeometry = dynamic_cast< Geometry3D * >( contour->GetGeometry( timestep ) ); if ( contourGeometry->IsInside(click) ) { m_lastMousePosition = click; newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent()); } else { newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } this->HandleEvent( newStateEvent ); return true; } bool mitk::ContourModelInteractor::OnDeletePoint( Action* action, const StateEvent* stateEvent) { int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); contour->RemoveVertex(contour->GetSelectedVertex()); return true; } bool mitk::ContourModelInteractor::OnMove( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; int timestep = positionEvent->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); mitk::Point3D currentPosition = positionEvent->GetWorldPosition(); m_DataNode->SetBoolProperty("contour.hovering", contour->IsNearContour(currentPosition, 1.5, timestep) ); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::ContourModelInteractor::OnMovePoint( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); mitk::Vector3D translation; mitk::Point3D currentPosition = positionEvent->GetWorldPosition(); translation[0] = currentPosition[0] - this->m_lastMousePosition[0]; translation[1] = currentPosition[1] - this->m_lastMousePosition[1]; translation[2] = currentPosition[2] - this->m_lastMousePosition[2]; contour->ShiftSelectedVertex(translation); this->m_lastMousePosition = positionEvent->GetWorldPosition(); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::ContourModelInteractor::OnMoveContour( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; int timestep = positionEvent->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); mitk::Vector3D translation; mitk::Point3D currentPosition = positionEvent->GetWorldPosition(); translation[0] = currentPosition[0] - this->m_lastMousePosition[0]; translation[1] = currentPosition[1] - this->m_lastMousePosition[1]; translation[2] = currentPosition[2] - this->m_lastMousePosition[2]; contour->ShiftContour(translation, timestep); this->m_lastMousePosition = positionEvent->GetWorldPosition(); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::ContourModelInteractor::OnFinishEditing( Action* action, const StateEvent* stateEvent) { m_DataNode->SetBoolProperty( "contour.editing", false ); - mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); - contour->Deselect(); + // mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); + // contour->Deselect(); assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); return true; } diff --git a/Modules/Segmentation/Interactions/mitkContourModelLiveWireInteractor.cpp b/Modules/Segmentation/Interactions/mitkContourModelLiveWireInteractor.cpp index 9d7ed9384a..ec86f43d9e 100644 --- a/Modules/Segmentation/Interactions/mitkContourModelLiveWireInteractor.cpp +++ b/Modules/Segmentation/Interactions/mitkContourModelLiveWireInteractor.cpp @@ -1,351 +1,354 @@ /*=================================================================== 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 "mitkContourModelLiveWireInteractor.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include #include #include mitk::ContourModelLiveWireInteractor::ContourModelLiveWireInteractor(DataNode* dataNode) :ContourModelInteractor(dataNode) { m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New(); mitk::ContourModel::Pointer m_ContourLeft = mitk::ContourModel::New(); mitk::ContourModel::Pointer m_ContourRight = mitk::ContourModel::New(); m_NextActiveVertexDown.Fill(0); m_NextActiveVertexUp.Fill(0); } mitk::ContourModelLiveWireInteractor::~ContourModelLiveWireInteractor() { } bool mitk::ContourModelLiveWireInteractor::OnCheckPointClick( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) { this->HandleEvent( new mitk::StateEvent(EIDNO, stateEvent->GetEvent()) ); return false; } mitk::StateEvent* newStateEvent = NULL; int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); contour->Deselect(); /* * Check distance to any vertex. * Transition YES if click close to a vertex */ mitk::Point3D click = positionEvent->GetWorldPosition(); if (contour->SelectVertexAt(click, 1.5, timestep) ) { contour->SetSelectedVertexAsControlPoint(); m_DataNode->SetBoolProperty( "contour.editing", true ); assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent()); m_lastMousePosition = click; mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); // m_ContourLeft = mitk::ContourModel::New(); //get coordinates of next active vertex downwards from selected vertex int downIndex = this->SplitContourFromSelectedVertex( contour, m_ContourLeft, false, timestep); mitk::ContourModel::VertexIterator itDown = contour->IteratorBegin() + downIndex; m_NextActiveVertexDown = (*itDown)->Coordinates; // m_ContourRight = mitk::ContourModel::New(); //get coordinates of next active vertex upwards from selected vertex int upIndex = this->SplitContourFromSelectedVertex( contour, m_ContourRight, true, timestep); mitk::ContourModel::VertexIterator itUp = contour->IteratorBegin() + upIndex; m_NextActiveVertexUp = (*itUp)->Coordinates; } else { m_DataNode->SetBoolProperty( "contour.editing", false ); newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } this->HandleEvent( newStateEvent ); + assert( positionEvent->GetSender()->GetRenderWindow() ); + mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); + return true; } bool mitk::ContourModelLiveWireInteractor::OnDeletePoint( Action* action, const StateEvent* stateEvent) { int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); if(contour->GetSelectedVertex()) { mitk::ContourModel::Pointer newContour = mitk::ContourModel::New(); newContour->Expand(contour->GetTimeSteps()); newContour->Concatenate( m_ContourLeft, timestep ); //recompute contour between neighbored two active control points this->m_LiveWireFilter->SetStartPoint( m_NextActiveVertexDown ); this->m_LiveWireFilter->SetEndPoint( m_NextActiveVertexUp ); this->m_LiveWireFilter->Update(); mitk::ContourModel::Pointer liveWireContour = mitk::ContourModel::New(); liveWireContour = this->m_LiveWireFilter->GetOutput(); //insert new liveWire computed points newContour->Concatenate( liveWireContour, timestep ); newContour->Concatenate( m_ContourRight, timestep ); newContour->SetIsClosed(contour->IsClosed(timestep), timestep); m_DataNode->SetData(newContour); assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); } return true; } bool mitk::ContourModelLiveWireInteractor::OnMovePoint( Action* action, const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); mitk::ContourModel *contour = dynamic_cast( m_DataNode->GetData() ); mitk::ContourModel::Pointer newContour = mitk::ContourModel::New(); newContour->Expand(contour->GetTimeSteps()); /*++++++++++++++ concatenate LEFT ++++++++++++++++++++++++++++++*/ newContour->Concatenate( m_ContourLeft, timestep ); mitk::Point3D currentPosition = positionEvent->GetWorldPosition(); /*+++++++++++++++ start computation ++++++++++++++++++++*/ //recompute contour between previous active vertex and selected vertex this->m_LiveWireFilter->SetStartPoint( m_NextActiveVertexDown ); this->m_LiveWireFilter->SetEndPoint( currentPosition ); this->m_LiveWireFilter->Update(); mitk::ContourModel::Pointer liveWireContour = mitk::ContourModel::New(); liveWireContour = this->m_LiveWireFilter->GetOutput(); //remove point at current position because it is included in next livewire segment too. liveWireContour->RemoveVertexAt( liveWireContour->GetNumberOfVertices(timestep) - 1, timestep); /*++++++++++++++ concatenate LIVEWIRE ++++++++++++++++++++++++++++++*/ //insert new liveWire computed points newContour->Concatenate( liveWireContour, timestep ); //recompute contour between selected vertex and next active vertex this->m_LiveWireFilter->SetStartPoint( currentPosition ); this->m_LiveWireFilter->SetEndPoint( m_NextActiveVertexUp ); this->m_LiveWireFilter->Update(); liveWireContour = this->m_LiveWireFilter->GetOutput(); //make point at mouse position active again, so it is drawn const_cast( liveWireContour->GetVertexAt(0, timestep) )->IsControlPoint = true; /*++++++++++++++ concatenate RIGHT ++++++++++++++++++++++++++++++*/ //insert new liveWire computed points newContour->Concatenate( liveWireContour, timestep ); /*------------------------------------------------*/ newContour->Concatenate( m_ContourRight, timestep ); newContour->SetIsClosed(contour->IsClosed(timestep), timestep); newContour->SelectVertexAt(currentPosition,1.5,timestep); //newContour->Deselect();//just to make sure m_DataNode->SetData(newContour); this->m_lastMousePosition = positionEvent->GetWorldPosition(); assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } int mitk::ContourModelLiveWireInteractor::SplitContourFromSelectedVertex(mitk::ContourModel* sourceContour, mitk::ContourModel* destinationContour, bool fromSelectedUpwards, int timestep) { mitk::ContourModel::VertexIterator end =sourceContour->IteratorEnd(); mitk::ContourModel::VertexIterator begin =sourceContour->IteratorBegin(); //search next active control point to left and rigth and set as start and end point for filter mitk::ContourModel::VertexIterator itSelected = sourceContour->IteratorBegin(); //move iterator to position while((*itSelected) != sourceContour->GetSelectedVertex()) { itSelected++; } //CASE search upwards for next control point if(fromSelectedUpwards) { mitk::ContourModel::VertexIterator itUp = itSelected; if(itUp != end) { itUp++;//step once up otherwise the the loop breaks immediately } while( itUp != end && !((*itUp)->IsControlPoint)){ itUp++; } mitk::ContourModel::VertexIterator it = itUp; if(itSelected != begin) { //copy the rest of the original contour while(it != end) { destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } } //else do not copy the contour //return the offset of iterator at one before next-vertex-upwards if(itUp != begin) { return std::distance( begin, itUp) - 1; } else { return std::distance( begin, itUp); } } else //CASE search downwards for next control point { mitk::ContourModel::VertexIterator itDown = itSelected; mitk::ContourModel::VertexIterator it = sourceContour->IteratorBegin(); if( itSelected != begin ) { if(itDown != begin) { itDown--;//step once down otherwise the the loop breaks immediately } while( itDown != begin && !((*itDown)->IsControlPoint)){ itDown--; } if(it != end)//if not empty { //always add the first vertex destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } //copy from begin to itDown while(it <= itDown) { destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } } else { //if selected vertex is the first element search from end of contour downwards itDown = end; itDown--; while(!((*itDown)->IsControlPoint)){itDown--;} //move one forward as we don't want the first control point it++; //move iterator to second control point while( (it!=end) && !((*it)->IsControlPoint) ){it++;} //copy from begin to itDown while(it <= itDown) { //copy the contour from second control point to itDown destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } } //add vertex at itDown - it's not considered during while loop if( it != begin && it != end) { //destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsControlPoint, timestep); } //return the offset of iterator at one after next-vertex-downwards if( itDown != end) { return std::distance( begin, itDown);// + 1;//index of next vertex } else { return std::distance( begin, itDown) - 1; } } }