diff --git a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp index 7fa3017e35..a385926be8 100644 --- a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp +++ b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp @@ -1,685 +1,665 @@ /*=================================================================== 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 "mitkLiveWireTool2D.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkLiveWireTool2D.xpm" #include #include #include #include "mitkContourUtils.h" #include "mitkContour.h" #include namespace mitk { MITK_TOOL_MACRO(Segmentation_EXPORT, LiveWireTool2D, "LiveWire tool"); } - mitk::LiveWireTool2D::LiveWireTool2D() :SegTool2D("LiveWireTool") { - /* - m_Contour = mitk::ContourModel::New(); - m_ContourModelNode = mitk::DataNode::New(); - m_ContourModelNode->SetData( m_Contour ); - m_ContourModelNode->SetProperty("name", StringProperty::New("working contour node")); - m_ContourModelNode->SetProperty("visible", BoolProperty::New(true)); - m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), NULL, true ); - m_ContourModelNode->AddProperty( "selectedcolor", ColorProperty::New(1.0, 0.0, 0.1), NULL, true ); - - - m_LiveWireContour = mitk::ContourModel::New(); - m_LiveWireContourNode = mitk::DataNode::New(); - //m_LiveWireContourNode->SetData( m_LiveWireContour ); - m_LiveWireContourNode->SetProperty("name", StringProperty::New("active livewire node")); - m_LiveWireContourNode->SetProperty("visible", BoolProperty::New(true)); - m_LiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true ); - m_LiveWireContourNode->AddProperty( "selectedcolor", ColorProperty::New(0.5, 0.5, 0.1), NULL, true ); -*/ - m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New(); - // great magic numbers CONNECT_ACTION( AcINITNEWOBJECT, OnInitLiveWire ); CONNECT_ACTION( AcADDPOINT, OnAddPoint ); CONNECT_ACTION( AcMOVE, OnMouseMoveNoDynamicCosts ); CONNECT_ACTION( AcCHECKPOINT, OnCheckPoint ); CONNECT_ACTION( AcFINISH, OnFinish ); CONNECT_ACTION( AcDELETEPOINT, OnLastSegmentDelete ); CONNECT_ACTION( AcADDLINE, OnMouseMoved ); } - mitk::LiveWireTool2D::~LiveWireTool2D() { m_Contours.clear(); } float mitk::LiveWireTool2D::CanHandleEvent( StateEvent const *stateEvent) const { 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.0; } } else { if ( positionEvent->GetSender()->GetMapperID() != BaseRenderer::Standard2D ) return 0.0; // we don't want anything but 2D return 1.0; } } const char** mitk::LiveWireTool2D::GetXPM() const { return mitkLiveWireTool2D_xpm; } const char* mitk::LiveWireTool2D::GetName() const { return "LiveWire"; } void mitk::LiveWireTool2D::Activated() { Superclass::Activated(); } void mitk::LiveWireTool2D::Deactivated() { this->FinishTool(); DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); if ( !workingNode ) return; Image* workingImage = dynamic_cast(workingNode->GetData()); if ( !workingImage ) return; ContourUtils::Pointer contourUtils = mitk::ContourUtils::New(); /*+++++++++++++++++++++++ for all contours in list (currently created by tool) ++++++++++++++++++++++++++++++++++++*/ std::vector< std::pair >::iterator it = m_Contours.begin(); while(it != m_Contours.end() ) { //++++++++++if node contains data if( it->first->GetData() ) { //+++++++++++++++if this is a contourModel mitk::ContourModel* contourModel = dynamic_cast(it->first->GetData()); if( contourModel ) { //++++++++++++++++++++++ for each timestep of this contourModel for( int currentTimestep = 0; currentTimestep < contourModel->GetTimeSlicedGeometry()->GetTimeSteps(); currentTimestep++) { //get the segmentation image slice at current timestep mitk::Image::Pointer workingSlice = this->GetAffectedImageSliceAs2DImage(it->second, workingImage, currentTimestep); /*++++++++++++++++++++++ transfer to plain old contour to use contour util functionality +++++++++++++++++++++++*/ mitk::Contour::Pointer plainOldContour = mitk::Contour::New(); mitk::ContourModel::VertexIterator iter = contourModel->IteratorBegin(currentTimestep); while(iter != contourModel->IteratorEnd(currentTimestep) ) { plainOldContour->AddVertex( (*iter)->Coordinates ); iter++; } /*-------------------------------------------------------------------------------*/ mitk::Contour::Pointer projectedContour = contourUtils->ProjectContourTo2DSlice(workingSlice, plainOldContour, true, false); contourUtils->FillContourInSlice(projectedContour, workingSlice, 1.0); //write back to image volume this->WriteBackSegmentationResult(it->second, workingSlice, currentTimestep); } //remove contour node from datastorage m_ToolManager->GetDataStorage()->Remove( it->first ); } } ++it; } m_Contours.clear(); m_ToolManager->GetDataStorage()->Remove( m_LeftLiveWireContourNode ); m_ToolManager->GetDataStorage()->Remove( m_RightLiveWireContourNode ); m_LeftLiveWireContourNode = NULL; m_LeftLiveWireContour = NULL; m_RightLiveWireContourNode = NULL; m_RightLiveWireContour = NULL; Superclass::Deactivated(); } bool mitk::LiveWireTool2D::OnInitLiveWire (Action* action, const StateEvent* stateEvent) { MITK_INFO << "started"; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; int timestep = positionEvent->GetSender()->GetTimeStep(); m_Contour = mitk::ContourModel::New(); m_Contour->Expand(timestep+1); m_ContourModelNode = mitk::DataNode::New(); m_ContourModelNode->SetData( m_Contour ); m_ContourModelNode->SetName("working contour node"); m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), NULL, true ); m_ContourModelNode->AddProperty( "contour.points.color", ColorProperty::New(1.0, 0.0, 0.1), NULL, true ); m_ContourModelNode->AddProperty( "contour.points.show", BoolProperty::New(false), NULL, true ); m_ContourModelNode->AddProperty( "contour.controlpoints.show", BoolProperty::New(true), NULL, true ); m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContour->Expand(timestep+1); m_LiveWireContourNode = mitk::DataNode::New(); m_LiveWireContourNode->SetData( m_LiveWireContour ); m_LiveWireContourNode->SetName("active livewire node"); m_LiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true ); m_LiveWireContourNode->AddProperty( "contour.points.color", ColorProperty::New(0.5, 0.5, 0.1), NULL, true ); m_LeftLiveWireContour = mitk::ContourModel::New(); m_LeftLiveWireContour->Expand(timestep+1); m_LeftLiveWireContourNode = mitk::DataNode::New(); m_LeftLiveWireContourNode->SetData( m_LeftLiveWireContour ); m_LeftLiveWireContourNode->SetName("left node"); m_LeftLiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.0, 0.0, 1.0), NULL, true ); m_LeftLiveWireContourNode->AddProperty( "contour.points.color", ColorProperty::New(0.0, 0.0, 1.0), NULL, true ); m_LeftLiveWireContourNode->AddProperty( "contour.points.show", BoolProperty::New(true), NULL, true ); m_LeftLiveWireContourNode->AddProperty( "contour.controlpoints.show", BoolProperty::New(true), NULL, true ); + m_LeftLiveWireContourNode->AddProperty( "contour.numbers.show", BoolProperty::New(true), NULL, true ); m_RightLiveWireContour = mitk::ContourModel::New(); m_RightLiveWireContour->Expand(timestep+1); m_RightLiveWireContourNode = mitk::DataNode::New(); m_RightLiveWireContourNode->SetData( m_RightLiveWireContour ); m_RightLiveWireContourNode->SetName("right node"); m_RightLiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(1.0, 0.0, 0.0), NULL, true ); m_RightLiveWireContourNode->AddProperty( "contour.points.color", ColorProperty::New(1.0, 0.0, 0.0), NULL, true ); m_RightLiveWireContourNode->AddProperty( "contour.points.show", BoolProperty::New(true), NULL, true ); m_RightLiveWireContourNode->AddProperty( "contour.controlpoints.show", BoolProperty::New(true), NULL, true ); + m_RightLiveWireContourNode->AddProperty( "contour.numbers.show", BoolProperty::New(true), NULL, true ); m_ToolManager->GetDataStorage()->Add( m_ContourModelNode ); m_ToolManager->GetDataStorage()->Add( m_LiveWireContourNode ); m_ToolManager->GetDataStorage()->Add( m_RightLiveWireContourNode ); m_ToolManager->GetDataStorage()->Add( m_LeftLiveWireContourNode ); //set current slice as input for ImageToLiveWireContourFilter m_WorkingSlice = this->GetAffectedReferenceSlice(positionEvent); m_LiveWireFilter->SetInput(m_WorkingSlice); //map click to pixel coordinates mitk::Point3D click = const_cast(positionEvent->GetWorldPosition()); itk::Index<3> idx; m_WorkingSlice->GetGeometry()->WorldToIndex(click, idx); /*+++++++++++++++++++++++ get the pixel the gradient in region of 5x5 ++++++++++++++++++++++++++*/ itk::Index<3> indexWithHighestGradient; AccessFixedDimensionByItk_2(m_WorkingSlice, FindHighestGradientMagnitudeByITK, 2, idx, indexWithHighestGradient); /*----------------------------------------------------------------------------------------------------------------*/ //itk::Index to mitk::Point3D click[0] = indexWithHighestGradient[0]; click[1] = indexWithHighestGradient[1]; click[2] = indexWithHighestGradient[2]; m_WorkingSlice->GetGeometry()->IndexToWorld(click, click); //set initial start point m_Contour->AddVertex( click, true, timestep ); m_LiveWireFilter->SetStartPoint(click); m_CreateAndUseDynamicCosts = true; //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); MITK_INFO << "3"; return true; } bool mitk::LiveWireTool2D::OnAddPoint (Action* action, const StateEvent* stateEvent) { //complete LiveWire interaction for last segment //add current LiveWire contour to the finished contour and reset //to start new segment and computation /* check if event can be handled */ const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; /* END check if event can be handled */ int timestep = positionEvent->GetSender()->GetTimeStep(); //remove duplicate first vertex, it's already contained in m_Contour m_LiveWireContour->RemoveVertexAt(0, timestep); /* TODO fix this hack*/ //set last to active added point if( m_LiveWireContour->GetNumberOfVertices(timestep) > 0) { const_cast( m_LiveWireContour->GetVertexAt(m_LiveWireContour->GetNumberOfVertices(timestep)-1, timestep) )->IsControlPoint = true; } //merge contours m_Contour->Concatenate(m_LiveWireContour, timestep); //clear the livewire contour and reset the corresponding datanode m_LiveWireContour->Clear(timestep); //set new start point m_LiveWireFilter->SetStartPoint(const_cast(positionEvent->GetWorldPosition())); if( m_CreateAndUseDynamicCosts ) { //use dynamic cost map for next update m_LiveWireFilter->CreateDynamicCostMap(m_Contour); m_LiveWireFilter->SetUseDynamicCostMap(true); //m_CreateAndUseDynamicCosts = false; } //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnMouseMoved( Action* action, const StateEvent* stateEvent) { //compute LiveWire segment from last control point to current mouse position /* check if event can be handled */ if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; /* END check if event can be handled */ /* actual LiveWire computation */ int timestep = positionEvent->GetSender()->GetTimeStep(); m_LiveWireFilter->SetEndPoint(const_cast(positionEvent->GetWorldPosition())); m_LiveWireFilter->SetTimestep(timestep); m_LiveWireFilter->Update(); //ContourModel::VertexType* currentVertex = const_cast(m_LiveWireContour->GetVertexAt(0)); this->m_LiveWireContour = this->m_LiveWireFilter->GetOutput(); this->m_LiveWireContourNode->SetData(this->m_LiveWireFilter->GetOutput()); /* END actual LiveWire computation */ //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnMouseMoveNoDynamicCosts(Action* action, const StateEvent* stateEvent) { //do not use dynamic cost map m_LiveWireFilter->SetUseDynamicCostMap(false); OnMouseMoved(action, stateEvent); m_LiveWireFilter->SetUseDynamicCostMap(true); return true; } bool mitk::LiveWireTool2D::OnCheckPoint( Action* action, const StateEvent* stateEvent) { //check double click on first control point to finish the LiveWire tool // //Check distance to first point. //Transition YES if click close to first control point // mitk::StateEvent* newStateEvent = NULL; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) { //stay in current state newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } else { int timestep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D click = positionEvent->GetWorldPosition(); mitk::Point3D first = this->m_Contour->GetVertexAt(0, timestep)->Coordinates; if (first.EuclideanDistanceTo(click) < 4.5) { //finish newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent()); }else { //stay active newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent()); } } this->HandleEvent( newStateEvent ); return true; } bool mitk::LiveWireTool2D::OnFinish( Action* action, const StateEvent* stateEvent) { // finish livewire tool interaction /* check if event can be handled */ if ( Superclass::CanHandleEvent(stateEvent) < 1.0 ) return false; const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; /* END check if event can be handled */ //actual timestep int timestep = positionEvent->GetSender()->GetTimeStep(); //remove last control point being added by double click m_Contour->RemoveVertexAt(m_Contour->GetNumberOfVertices(timestep) - 1, timestep); //save contour and corresponding plane geometry to list std::pair contourPair(m_ContourModelNode.GetPointer(), dynamic_cast(positionEvent->GetSender()->GetCurrentWorldGeometry2D()->Clone().GetPointer()) ); m_Contours.push_back(contourPair); m_LiveWireFilter->SetUseDynamicCostMap(false); this->FinishTool(); return true; } void mitk::LiveWireTool2D::FinishTool() { unsigned int numberOfTimesteps = m_Contour->GetTimeSlicedGeometry()->GetTimeSteps(); //close contour in each timestep for( int i = 0; i <= numberOfTimesteps; i++) { m_Contour->Close(i); } m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode ); // clear live wire contour node m_LiveWireContourNode = NULL; m_LiveWireContour = NULL; //TODO visual feedback for completing livewire tool m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(1.0, 1.0, 0.1), NULL, true ); m_ContourModelNode->SetName("contour node"); //set the livewire interactor to edit control points mitk::ContourModelLiveWireInteractor::Pointer interactor = mitk::ContourModelLiveWireInteractor::New(m_ContourModelNode); interactor->SetWorkingImage(this->m_WorkingSlice); interactor->SetRightLiveWireContourModelNode(this->m_RightLiveWireContourNode); interactor->SetLeftLiveWireContourModelNode(this->m_LeftLiveWireContourNode); m_ContourModelNode->SetInteractor(interactor); //add interactor to globalInteraction instance mitk::GlobalInteraction::GetInstance()->AddInteractor(interactor); } bool mitk::LiveWireTool2D::OnLastSegmentDelete( Action* action, const StateEvent* stateEvent) { int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep(); //if last point of current contour will be removed go to start state and remove nodes if( m_Contour->GetNumberOfVertices(timestep) <= 1 ) { m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode ); m_ToolManager->GetDataStorage()->Remove( m_ContourModelNode ); m_LiveWireContour = mitk::ContourModel::New(); m_Contour = mitk::ContourModel::New(); m_ContourModelNode->SetData( m_Contour ); m_LiveWireContourNode->SetData( m_LiveWireContour ); Superclass::Deactivated(); //go to start state } else //remove last segment from contour and reset livewire contour { m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContourNode->SetData(m_LiveWireContour); mitk::ContourModel::Pointer newContour = mitk::ContourModel::New(); newContour->Expand(m_Contour->GetTimeSteps()); mitk::ContourModel::VertexIterator begin = m_Contour->IteratorBegin(); //iterate from last point to next active point mitk::ContourModel::VertexIterator newLast = m_Contour->IteratorBegin() + (m_Contour->GetNumberOfVertices() - 1); //go at least one down if(newLast != begin) { newLast--; } //search next active control point while(newLast != begin && !((*newLast)->IsControlPoint) ) { newLast--; } //set position of start point for livewire filter to coordinates of the new last point m_LiveWireFilter->SetStartPoint((*newLast)->Coordinates); mitk::ContourModel::VertexIterator it = m_Contour->IteratorBegin(); //fill new Contour while(it <= newLast) { newContour->AddVertex((*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } newContour->SetIsClosed(m_Contour->IsClosed()); //set new contour visible m_ContourModelNode->SetData(newContour); m_Contour = newContour; assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() ); } return true; } template void mitk::LiveWireTool2D::FindHighestGradientMagnitudeByITK(itk::Image* inputImage, itk::Index<3> &index, itk::Index<3> &returnIndex) { typedef itk::Image InputImageType; typedef typename InputImageType::IndexType IndexType; unsigned long xMAX = inputImage->GetLargestPossibleRegion().GetSize()[0]; unsigned long yMAX = inputImage->GetLargestPossibleRegion().GetSize()[1]; returnIndex[0] = index[0]; returnIndex[1] = index[1]; returnIndex[2] = 0.0; double gradientMagnitude = 0.0; double maxGradientMagnitude = 0.0; /* the size and thus the region of 7x7 is only used to calculate the gradient magnitude in that region not for searching the maximum value */ //maximum value in each direction for size typename InputImageType::SizeType size; size[0] = 7; size[1] = 7; //minimum value in each direction for startRegion IndexType startRegion; startRegion[0] = index[0] - 3; startRegion[1] = index[1] - 3; if(startRegion[0] < 0) startRegion[0] = 0; if(startRegion[1] < 0) startRegion[1] = 0; if(xMAX - index[0] < 7) startRegion[0] = xMAX - 7; if(yMAX - index[1] < 7) startRegion[1] = yMAX - 7; index[0] = startRegion[0] + 3; index[1] = startRegion[1] + 3; typename InputImageType::RegionType region; region.SetSize( size ); region.SetIndex( startRegion ); typedef typename itk::GradientMagnitudeImageFilter< InputImageType, InputImageType> GradientMagnitudeFilterType; typename GradientMagnitudeFilterType::Pointer gradientFilter = GradientMagnitudeFilterType::New(); gradientFilter->SetInput(inputImage); gradientFilter->GetOutput()->SetRequestedRegion(region); gradientFilter->Update(); typename InputImageType::Pointer gradientMagnImage; gradientMagnImage = gradientFilter->GetOutput(); IndexType currentIndex; currentIndex[0] = 0; currentIndex[1] = 0; // search max (approximate) gradient magnitude for( int x = -1; x <= 1; ++x) { currentIndex[0] = index[0] + x; for( int y = -1; y <= 1; ++y) { currentIndex[1] = index[1] + y; gradientMagnitude = gradientMagnImage->GetPixel(currentIndex); //check for new max if(maxGradientMagnitude < gradientMagnitude) { maxGradientMagnitude = gradientMagnitude; returnIndex[0] = currentIndex[0]; returnIndex[1] = currentIndex[1]; returnIndex[2] = 0.0; }//end if }//end for y currentIndex[1] = index[1]; }//end for x } diff --git a/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp b/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp index 5053820699..c37dc39ac7 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp @@ -1,359 +1,364 @@ /*=================================================================== 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 "mitkContourModelGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkContourModel.h" #include "mitkContourModelSubDivisionFilter.h" #include #include "mitkGL.h" mitk::ContourModelGLMapper2D::ContourModelGLMapper2D() { } mitk::ContourModelGLMapper2D::~ContourModelGLMapper2D() { } void mitk::ContourModelGLMapper2D::Paint(mitk::BaseRenderer * renderer) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); mitk::DataNode* dataNode = this->GetDataNode(); bool visible = true; dataNode->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; bool updateNeccesary=true; int timestep = renderer->GetTimeStep(); mitk::ContourModel::Pointer input = const_cast(this->GetInput()); mitk::ContourModel::Pointer renderingContour = input; bool subdivision = false; dataNode->GetBoolProperty( "subdivision curve", subdivision, renderer ); if (subdivision) { mitk::ContourModel::Pointer subdivContour = mitk::ContourModel::New(); mitk::ContourModelSubDivisionFilter::Pointer subdivFilter = mitk::ContourModelSubDivisionFilter::New(); subdivFilter->SetInput(input); subdivFilter->Update(); subdivContour = subdivFilter->GetOutput(); if(subdivContour->GetNumberOfVertices() == 0 ) { subdivContour = input; } renderingContour = subdivContour; } renderingContour->UpdateOutputInformation(); if( renderingContour->GetMTime() < ls->GetLastGenerateDataTime() ) updateNeccesary = false; if(renderingContour->GetNumberOfVertices(timestep) < 1) updateNeccesary = false; if (updateNeccesary) { // ok, das ist aus GenerateData kopiert mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //apply color and opacity read from the PropertyList ApplyProperties(renderer); bool isEditing = false; dataNode->GetBoolProperty("contour.editing", isEditing); mitk::ColorProperty::Pointer colorprop; if (isEditing) colorprop = dynamic_cast(dataNode->GetProperty("contour.editing.color", renderer)); else colorprop = dynamic_cast(dataNode->GetProperty("contour.color", renderer)); if(colorprop) { //set the color of the contour double red = colorprop->GetColor().GetRed(); double green = colorprop->GetColor().GetGreen(); double blue = colorprop->GetColor().GetBlue(); glColor4f(red,green,blue,0.5); } mitk::ColorProperty::Pointer selectedcolor = dynamic_cast(dataNode->GetProperty("contour.points.color", renderer)); if(!selectedcolor) { selectedcolor = mitk::ColorProperty::New(1.0,0.0,0.1); } vtkLinearTransform* transform = dataNode->GetVtkTransform(); // ContourModel::OutputType point; mitk::Point3D point; mitk::Point3D p, projected_p; float vtkp[3]; float lineWidth = 3.0; bool isHovering = false; dataNode->GetBoolProperty("contour.hovering", isHovering); if (isHovering) dataNode->GetFloatProperty("contour.hovering.width", lineWidth); else dataNode->GetFloatProperty("contour.width", lineWidth); bool drawit=false; mitk::ContourModel::VertexIterator pointsIt = renderingContour->IteratorBegin(timestep); Point2D pt2d; // projected_p in display coordinates Point2D lastPt2d; int index = 0; while ( pointsIt != renderingContour->IteratorEnd(timestep) ) { lastPt2d = pt2d; point = (*pointsIt)->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetNorm(); //draw lines bool projectmode=false; dataNode->GetVisibility(projectmode, renderer, "contour.project-onto-plane"); if(projectmode) { drawit=true; } else if(scalardiff<0.25) { drawit=true; } if(drawit) { //lastPt2d is not valid in first step if( !(pointsIt == renderingContour->IteratorBegin(timestep)) ) { glLineWidth(lineWidth); glBegin (GL_LINES); glVertex2f(pt2d[0], pt2d[1]); glVertex2f(lastPt2d[0], lastPt2d[1]); glEnd(); glLineWidth(1); } bool showControlPoints = false; dataNode->GetBoolProperty("contour.controlpoints.show", showControlPoints); if (showControlPoints) { //draw active points if ((*pointsIt)->IsControlPoint) { float pointsize = 4; Point2D tmp; Vector2D horz,vert; horz[1]=0; vert[0]=0; horz[0]=pointsize; vert[1]=pointsize; glColor3f(selectedcolor->GetColor().GetRed(), selectedcolor->GetColor().GetBlue(), selectedcolor->GetColor().GetGreen()); glLineWidth(1); //a rectangle around the point with the selected color glBegin (GL_LINE_LOOP); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); glEnd(); glLineWidth(1); //the actual point in the specified color to see the usual color of the point glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue()); glPointSize(1); glBegin (GL_POINTS); tmp=pt2d; glVertex2fv(&tmp[0]); glEnd (); } } bool showPoints = false; dataNode->GetBoolProperty("contour.points.show", showPoints); if (showPoints) { float pointsize = 3; Point2D tmp; Vector2D horz,vert; horz[1]=0; vert[0]=0; horz[0]=pointsize; vert[1]=pointsize; glColor3f(0.0, 0.0, 0.0); glLineWidth(1); //a rectangle around the point with the selected color glBegin (GL_LINE_LOOP); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); glEnd(); glLineWidth(1); //the actual point in the specified color to see the usual color of the point glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue()); glPointSize(1); glBegin (GL_POINTS); tmp=pt2d; glVertex2fv(&tmp[0]); glEnd (); } -/* - std::string l; - std::stringstream ss; - ss << index; - l.append(ss.str()); + bool showNumbers = false; + dataNode->GetBoolProperty("contour.numbers.show", showNumbers); - mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); - float rgb[3]; - rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0; - OpenGLrenderer->WriteSimpleText(l, pt2d[0] + 2, pt2d[1] + 2,rgb[0], rgb[1],rgb[2]); + if (showNumbers) + { + std::string l; + std::stringstream ss; + ss << index; + l.append(ss.str()); + + mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); + float rgb[3]; + rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0; + OpenGLrenderer->WriteSimpleText(l, pt2d[0] + 2, pt2d[1] + 2,rgb[0], rgb[1],rgb[2]); + } index++; -*/ } pointsIt++; }//end while iterate over controlpoints //close contour if necessary if(renderingContour->IsClosed(timestep) && drawit) { lastPt2d = pt2d; point = renderingContour->GetVertexAt(0,timestep)->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); glLineWidth(lineWidth); glBegin (GL_LINES); glVertex2f(lastPt2d[0], lastPt2d[1]); glVertex2f( pt2d[0], pt2d[1] ); glEnd(); glLineWidth(1); } //draw selected vertex if exists if(renderingContour->GetSelectedVertex()) { //transform selected vertex point = renderingContour->GetSelectedVertex()->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetNorm(); //---------------------------------- //draw point if close to plane if(scalardiff<0.25) { float pointsize = 5; Point2D tmp; glColor3f(0.0, 1.0, 0.0); glLineWidth(1); //a diamond around the point glBegin (GL_LINE_LOOP); //begin from upper left corner and paint clockwise tmp[0]=pt2d[0]-pointsize; tmp[1]=pt2d[1]+pointsize; glVertex2fv(&tmp[0]); tmp[0]=pt2d[0]+pointsize; tmp[1]=pt2d[1]+pointsize; glVertex2fv(&tmp[0]); tmp[0]=pt2d[0]+pointsize; tmp[1]=pt2d[1]-pointsize; glVertex2fv(&tmp[0]); tmp[0]=pt2d[0]-pointsize; tmp[1]=pt2d[1]-pointsize; glVertex2fv(&tmp[0]); glEnd (); } //------------------------------------ } } } const mitk::ContourModel* mitk::ContourModelGLMapper2D::GetInput(void) { return static_cast ( GetDataNode()->GetData() ); } void mitk::ContourModelGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite ); node->AddProperty( "contour.editing", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "contour.editing.color", ColorProperty::New(0.1, 0.9, 0.1), renderer, overwrite ); node->AddProperty( "contour.points.color", ColorProperty::New(1.0, 0.0, 0.1), renderer, overwrite ); node->AddProperty( "contour.points.show", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "contour.controlpoints.show", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "contour.width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "contour.hovering.width", mitk::FloatProperty::New( 3.0 ), renderer, overwrite ); node->AddProperty( "contour.hovering", mitk::BoolProperty::New( false ), renderer, overwrite ); + node->AddProperty( "contour.numbers.show", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "subdivision curve", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "contour.project-onto-plane", mitk::BoolProperty::New( false ), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); }