diff --git a/Core/Code/Controllers/mitkSliceNavigationController.cpp b/Core/Code/Controllers/mitkSliceNavigationController.cpp index dea1cb8a25..fca6a8d591 100644 --- a/Core/Code/Controllers/mitkSliceNavigationController.cpp +++ b/Core/Code/Controllers/mitkSliceNavigationController.cpp @@ -1,803 +1,803 @@ /*=================================================================== 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 "mitkSliceNavigationController.h" #include "mitkBaseRenderer.h" #include "mitkSlicedGeometry3D.h" #include "mitkPlaneGeometry.h" #include "mitkOperation.h" #include "mitkOperationActor.h" #include "mitkStateEvent.h" #include "mitkCrosshairPositionEvent.h" #include "mitkPositionEvent.h" #include "mitkProportionalTimeGeometry.h" #include "mitkInteractionConst.h" #include "mitkAction.h" #include "mitkGlobalInteraction.h" #include "mitkEventMapper.h" #include "mitkFocusManager.h" #include "mitkVtkPropRenderer.h" #include "mitkRenderingManager.h" #include "mitkInteractionConst.h" #include "mitkPointOperation.h" #include "mitkPlaneOperation.h" #include "mitkUndoController.h" #include "mitkOperationEvent.h" #include "mitkNodePredicateDataType.h" #include "mitkStatusBar.h" #include "mitkMemoryUtilities.h" #include namespace mitk { SliceNavigationController::SliceNavigationController( const char *type ) : BaseController( type ), m_InputWorldGeometry3D( NULL ), m_InputWorldTimeGeometry( NULL ), m_CreatedWorldGeometry( NULL ), m_ViewDirection( Axial ), m_DefaultViewDirection( Axial ), m_RenderingManager( NULL ), m_Renderer( NULL ), m_Top( false ), m_FrontSide( false ), m_Rotated( false ), m_BlockUpdate( false ), m_SliceLocked( false ), m_SliceRotationLocked( false ), m_OldPos(0) { typedef itk::SimpleMemberCommand< SliceNavigationController > SNCCommandType; SNCCommandType::Pointer sliceStepperChangedCommand, timeStepperChangedCommand; sliceStepperChangedCommand = SNCCommandType::New(); timeStepperChangedCommand = SNCCommandType::New(); sliceStepperChangedCommand->SetCallbackFunction( this, &SliceNavigationController::SendSlice ); timeStepperChangedCommand->SetCallbackFunction( this, &SliceNavigationController::SendTime ); m_Slice->AddObserver( itk::ModifiedEvent(), sliceStepperChangedCommand ); m_Time->AddObserver( itk::ModifiedEvent(), timeStepperChangedCommand ); m_Slice->SetUnitName( "mm" ); m_Time->SetUnitName( "ms" ); m_Top = false; m_FrontSide = false; m_Rotated = false; } SliceNavigationController::~SliceNavigationController() { } void SliceNavigationController::SetInputWorldGeometry3D( const Geometry3D *geometry ) { if ( geometry != NULL ) { if ( const_cast< BoundingBox * >( geometry->GetBoundingBox()) ->GetDiagonalLength2() < eps ) { itkWarningMacro( "setting an empty bounding-box" ); geometry = NULL; } } if ( m_InputWorldGeometry3D != geometry ) { m_InputWorldGeometry3D = geometry; m_InputWorldTimeGeometry = NULL; this->Modified(); } } void SliceNavigationController::SetInputWorldTimeGeometry( const TimeGeometry *geometry ) { if ( geometry != NULL ) { if ( const_cast< BoundingBox * >( geometry->GetBoundingBoxInWorld()) ->GetDiagonalLength2() < eps ) { itkWarningMacro( "setting an empty bounding-box" ); geometry = NULL; } } if ( m_InputWorldTimeGeometry != geometry ) { m_InputWorldTimeGeometry = geometry; m_InputWorldGeometry3D = NULL; this->Modified(); } } RenderingManager * SliceNavigationController::GetRenderingManager() const { mitk::RenderingManager* renderingManager = m_RenderingManager.GetPointer(); if (renderingManager != NULL) return renderingManager; if ( m_Renderer != NULL ) { renderingManager = m_Renderer->GetRenderingManager(); if (renderingManager != NULL) return renderingManager; } return mitk::RenderingManager::GetInstance(); } void SliceNavigationController::SetViewDirectionToDefault() { m_ViewDirection = m_DefaultViewDirection; } void SliceNavigationController::Update() { if ( !m_BlockUpdate ) { if ( m_ViewDirection == Axial ) { this->Update( Axial, false, false, true ); } else { this->Update( m_ViewDirection ); } } } void SliceNavigationController::Update( SliceNavigationController::ViewDirection viewDirection, bool top, bool frontside, bool rotated ) { TimeGeometry::ConstPointer worldTimeGeometry = m_InputWorldTimeGeometry; if( m_BlockUpdate || ( m_InputWorldTimeGeometry.IsNull() && m_InputWorldGeometry3D.IsNull() ) || ( (worldTimeGeometry.IsNotNull()) && (worldTimeGeometry->GetNumberOfTimeSteps() == 0) ) ) { return; } m_BlockUpdate = true; if ( m_InputWorldTimeGeometry.IsNotNull() && m_LastUpdateTime < m_InputWorldTimeGeometry->GetMTime() ) { Modified(); } if ( m_InputWorldGeometry3D.IsNotNull() && m_LastUpdateTime < m_InputWorldGeometry3D->GetMTime() ) { Modified(); } this->SetViewDirection( viewDirection ); this->SetTop( top ); this->SetFrontSide( frontside ); this->SetRotated( rotated ); if ( m_LastUpdateTime < GetMTime() ) { m_LastUpdateTime = GetMTime(); // initialize the viewplane SlicedGeometry3D::Pointer slicedWorldGeometry = NULL; Geometry3D::ConstPointer currentGeometry = NULL; if (m_InputWorldTimeGeometry.IsNotNull()) if (m_InputWorldTimeGeometry->IsValidTimeStep(GetTime()->GetPos())) currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(GetTime()->GetPos()); else currentGeometry = m_InputWorldTimeGeometry->GetGeometryForTimeStep(0); else currentGeometry = m_InputWorldGeometry3D; m_CreatedWorldGeometry = NULL; switch ( viewDirection ) { case Original: if ( worldTimeGeometry.IsNotNull()) { itk::LightObject::Pointer cloned = worldTimeGeometry->Clone(); m_CreatedWorldGeometry = dynamic_cast (cloned.GetPointer()); worldTimeGeometry = m_CreatedWorldGeometry.GetPointer(); slicedWorldGeometry = dynamic_cast< SlicedGeometry3D * >( - m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ) ); + m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ).GetPointer() ); if ( slicedWorldGeometry.IsNotNull() ) { break; } } else { const SlicedGeometry3D *worldSlicedGeometry = dynamic_cast< const SlicedGeometry3D * >( currentGeometry.GetPointer()); if ( worldSlicedGeometry != NULL ) { slicedWorldGeometry = static_cast< SlicedGeometry3D * >( currentGeometry->Clone().GetPointer()); break; } } //else: use Axial: no "break" here!! case Axial: slicedWorldGeometry = SlicedGeometry3D::New(); slicedWorldGeometry->InitializePlanes( currentGeometry, PlaneGeometry::Axial, top, frontside, rotated ); slicedWorldGeometry->SetSliceNavigationController( this ); break; case Frontal: slicedWorldGeometry = SlicedGeometry3D::New(); slicedWorldGeometry->InitializePlanes( currentGeometry, PlaneGeometry::Frontal, top, frontside, rotated ); slicedWorldGeometry->SetSliceNavigationController( this ); break; case Sagittal: slicedWorldGeometry = SlicedGeometry3D::New(); slicedWorldGeometry->InitializePlanes( currentGeometry, PlaneGeometry::Sagittal, top, frontside, rotated ); slicedWorldGeometry->SetSliceNavigationController( this ); break; default: itkExceptionMacro("unknown ViewDirection"); } m_Slice->SetPos( 0 ); m_Slice->SetSteps( (int)slicedWorldGeometry->GetSlices() ); if ( m_CreatedWorldGeometry.IsNull() ) { // initialize TimeGeometry m_CreatedWorldGeometry = ProportionalTimeGeometry::New(); } if ( worldTimeGeometry.IsNull()) { m_CreatedWorldGeometry = ProportionalTimeGeometry::New(); dynamic_cast(m_CreatedWorldGeometry.GetPointer())->Initialize(slicedWorldGeometry, 1); m_Time->SetSteps( 0 ); m_Time->SetPos( 0 ); m_Time->InvalidateRange(); } else { m_BlockUpdate = true; m_Time->SetSteps( worldTimeGeometry->GetNumberOfTimeSteps() ); m_Time->SetPos( 0 ); const TimeBounds &timeBounds = worldTimeGeometry->GetTimeBounds(); m_Time->SetRange( timeBounds[0], timeBounds[1] ); m_BlockUpdate = false; - assert( worldTimeGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ) != NULL ); + assert( worldTimeGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ).IsNotNull() ); slicedWorldGeometry->SetTimeBounds( worldTimeGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() )->GetTimeBounds() ); //@todo implement for non-evenly-timed geometry! m_CreatedWorldGeometry = ProportionalTimeGeometry::New(); dynamic_cast(m_CreatedWorldGeometry.GetPointer())->Initialize(slicedWorldGeometry, worldTimeGeometry->GetNumberOfTimeSteps()); } } // unblock update; we may do this now, because if m_BlockUpdate was already // true before this method was entered, then we will never come here. m_BlockUpdate = false; // Send the geometry. Do this even if nothing was changed, because maybe // Update() was only called to re-send the old geometry and time/slice data. this->SendCreatedWorldGeometry(); this->SendSlice(); this->SendTime(); // Adjust the stepper range of slice stepper according to geometry this->AdjustSliceStepperRange(); } void SliceNavigationController::SendCreatedWorldGeometry() { // Send the geometry. Do this even if nothing was changed, because maybe // Update() was only called to re-send the old geometry. if ( !m_BlockUpdate ) { this->InvokeEvent( GeometrySendEvent(m_CreatedWorldGeometry, 0) ); } } void SliceNavigationController::SendCreatedWorldGeometryUpdate() { if ( !m_BlockUpdate ) { this->InvokeEvent( GeometryUpdateEvent(m_CreatedWorldGeometry, m_Slice->GetPos()) ); } } void SliceNavigationController::SendSlice() { if ( !m_BlockUpdate ) { if ( m_CreatedWorldGeometry.IsNotNull() ) { this->InvokeEvent( GeometrySliceEvent(m_CreatedWorldGeometry, m_Slice->GetPos()) ); // send crosshair event crosshairPositionEvent.Send(); // Request rendering update for all views this->GetRenderingManager()->RequestUpdateAll(); } } } void SliceNavigationController::SendTime() { if ( !m_BlockUpdate ) { if ( m_CreatedWorldGeometry.IsNotNull() ) { this->InvokeEvent( GeometryTimeEvent(m_CreatedWorldGeometry, m_Time->GetPos()) ); // Request rendering update for all views this->GetRenderingManager()->RequestUpdateAll(); } } } void SliceNavigationController::SetGeometry( const itk::EventObject & ) { } void SliceNavigationController ::SetGeometryTime( const itk::EventObject &geometryTimeEvent ) { const SliceNavigationController::GeometryTimeEvent *timeEvent = dynamic_cast< const SliceNavigationController::GeometryTimeEvent * >( &geometryTimeEvent); assert( timeEvent != NULL ); TimeGeometry *timeGeometry = timeEvent->GetTimeGeometry(); assert( timeGeometry != NULL ); if ( m_CreatedWorldGeometry.IsNotNull() ) { int timeStep = (int) timeEvent->GetPos(); ScalarType timeInMS; timeInMS = timeGeometry->TimeStepToTimePoint( timeStep ); timeStep = m_CreatedWorldGeometry->TimePointToTimeStep( timeInMS ); this->GetTime()->SetPos( timeStep ); } } void SliceNavigationController ::SetGeometrySlice(const itk::EventObject & geometrySliceEvent) { const SliceNavigationController::GeometrySliceEvent* sliceEvent = dynamic_cast( &geometrySliceEvent); assert(sliceEvent!=NULL); this->GetSlice()->SetPos(sliceEvent->GetPos()); } void SliceNavigationController::SelectSliceByPoint( const Point3D &point ) { //@todo add time to PositionEvent and use here!! SlicedGeometry3D* slicedWorldGeometry = dynamic_cast< SlicedGeometry3D * >( - m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ) ); + m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ).GetPointer() ); if ( slicedWorldGeometry ) { int bestSlice = -1; double bestDistance = itk::NumericTraits::max(); int s, slices; slices = slicedWorldGeometry->GetSlices(); if ( slicedWorldGeometry->GetEvenlySpaced() ) { mitk::Geometry2D *plane = slicedWorldGeometry->GetGeometry2D( 0 ); const Vector3D &direction = slicedWorldGeometry->GetDirectionVector(); Point3D projectedPoint; plane->Project( point, projectedPoint ); // Check whether the point is somewhere within the slice stack volume; // otherwise, the defualt slice (0) will be selected if ( direction[0] * (point[0] - projectedPoint[0]) + direction[1] * (point[1] - projectedPoint[1]) + direction[2] * (point[2] - projectedPoint[2]) >= 0 ) { bestSlice = (int)(plane->Distance( point ) / slicedWorldGeometry->GetSpacing()[2] + 0.5); } } else { Point3D projectedPoint; for ( s = 0; s < slices; ++s ) { slicedWorldGeometry->GetGeometry2D( s )->Project( point, projectedPoint ); Vector3D distance = projectedPoint - point; ScalarType currentDistance = distance.GetSquaredNorm(); if ( currentDistance < bestDistance ) { bestDistance = currentDistance; bestSlice = s; } } } if ( bestSlice >= 0 ) { this->GetSlice()->SetPos( bestSlice ); } else { this->GetSlice()->SetPos( 0 ); } this->SendCreatedWorldGeometryUpdate(); } } void SliceNavigationController::ReorientSlices( const Point3D &point, const Vector3D &normal ) { PlaneOperation op( OpORIENT, point, normal ); m_CreatedWorldGeometry->ExecuteOperation( &op ); this->SendCreatedWorldGeometryUpdate(); } void SliceNavigationController::ReorientSlices(const mitk::Point3D &point, const mitk::Vector3D &axisVec0, const mitk::Vector3D &axisVec1 ) { PlaneOperation op( OpORIENT, point, axisVec0, axisVec1 ); m_CreatedWorldGeometry->ExecuteOperation( &op ); this->SendCreatedWorldGeometryUpdate(); } mitk::TimeGeometry * SliceNavigationController::GetCreatedWorldGeometry() { return m_CreatedWorldGeometry; } const mitk::Geometry3D * SliceNavigationController::GetCurrentGeometry3D() { if ( m_CreatedWorldGeometry.IsNotNull() ) { return m_CreatedWorldGeometry->GetGeometryForTimeStep( this->GetTime()->GetPos() ); } else { return NULL; } } const mitk::PlaneGeometry * SliceNavigationController::GetCurrentPlaneGeometry() { const mitk::SlicedGeometry3D *slicedGeometry = dynamic_cast< const mitk::SlicedGeometry3D * > ( this->GetCurrentGeometry3D() ); if ( slicedGeometry ) { const mitk::PlaneGeometry *planeGeometry = dynamic_cast< mitk::PlaneGeometry * > ( slicedGeometry->GetGeometry2D(this->GetSlice()->GetPos()) ); return planeGeometry; } else { return NULL; } } void SliceNavigationController::SetRenderer( BaseRenderer *renderer ) { m_Renderer = renderer; } BaseRenderer * SliceNavigationController::GetRenderer() const { return m_Renderer; } void SliceNavigationController::AdjustSliceStepperRange() { const mitk::SlicedGeometry3D *slicedGeometry = dynamic_cast< const mitk::SlicedGeometry3D * > ( this->GetCurrentGeometry3D() ); const Vector3D &direction = slicedGeometry->GetDirectionVector(); int c = 0; int i, k = 0; for ( i = 0; i < 3; ++i ) { if ( fabs( (float) direction[i] ) < 0.000000001 ) { ++c; } else { k = i; } } if ( c == 2 ) { ScalarType min = slicedGeometry->GetOrigin()[k]; ScalarType max = min + slicedGeometry->GetExtentInMM( k ); m_Slice->SetRange( min, max ); } else { m_Slice->InvalidateRange(); } } void SliceNavigationController::ExecuteOperation( Operation *operation ) { // switch on type // - select best slice for a given point // - rotate created world geometry according to Operation->SomeInfo() if ( !operation ) { return; } switch ( operation->GetOperationType() ) { case OpMOVE: // should be a point operation { if ( !m_SliceLocked ) //do not move the cross position { // select a slice PointOperation *po = dynamic_cast< PointOperation * >( operation ); if ( po && po->GetIndex() == -1 ) { this->SelectSliceByPoint( po->GetPoint() ); } else if ( po && po->GetIndex() != -1 ) // undo case because index != -1, index holds the old position of this slice { this->GetSlice()->SetPos( po->GetIndex() ); } } break; } case OpRESTOREPLANEPOSITION: { m_CreatedWorldGeometry->ExecuteOperation( operation ); this->SendCreatedWorldGeometryUpdate(); break; } default: { // do nothing break; } } } mitk::DataNode::Pointer SliceNavigationController::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes,mitk::Point3D worldposition) { mitk::DataNode::Pointer node; int maxlayer = -32768; bool isHelper (false); if(nodes.IsNotNull()) { for (unsigned int x = 0; x < nodes->size(); x++) { nodes->at(x)->GetBoolProperty("helper object", isHelper); if(nodes->at(x)->GetData()->GetGeometry()->IsInside(worldposition) && isHelper == false) { int layer = 0; if(!(nodes->at(x)->GetIntProperty("layer", layer))) continue; if(layer > maxlayer) { if(static_cast(nodes->at(x))->IsVisible(m_Renderer)) { node = nodes->at(x); maxlayer = layer; } } } } } return node; } // Relict from the old times, when automous decisions were accepted // behavior. Remains in here, because some RenderWindows do exist outside // of StdMultiWidgets. bool SliceNavigationController ::ExecuteAction( Action* action, StateEvent const* stateEvent ) { bool ok = false; const PositionEvent* posEvent = dynamic_cast< const PositionEvent * >( stateEvent->GetEvent() ); if ( posEvent != NULL ) { if ( m_CreatedWorldGeometry.IsNull() ) { return true; } switch (action->GetActionId()) { case AcMOVE: { BaseRenderer *baseRenderer = posEvent->GetSender(); if ( !baseRenderer ) { baseRenderer = const_cast( GlobalInteraction::GetInstance()->GetFocus() ); } if ( baseRenderer ) if ( baseRenderer->GetMapperID() == 1 ) { PointOperation doOp(OpMOVE, posEvent->GetWorldPosition()); this->ExecuteOperation( &doOp ); // If click was performed in this render window than we have to update the status bar information about position and pixel value. if(baseRenderer == m_Renderer) { { std::string statusText; TNodePredicateDataType::Pointer isImageData = TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer nodes = baseRenderer->GetDataStorage()->GetSubset(isImageData).GetPointer(); mitk::Point3D worldposition = posEvent->GetWorldPosition(); //int maxlayer = -32768; mitk::Image::Pointer image3D; mitk::DataNode::Pointer node; mitk::DataNode::Pointer topSourceNode; bool isBinary (false); node = this->GetTopLayerNode(nodes,worldposition); if(node.IsNotNull()) { node->GetBoolProperty("binary", isBinary); if(isBinary) { mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = baseRenderer->GetDataStorage()->GetSources(node, NULL, true); if(!sourcenodes->empty()) { topSourceNode = this->GetTopLayerNode(sourcenodes,worldposition); } if(topSourceNode.IsNotNull()) { image3D = dynamic_cast(topSourceNode->GetData()); } else { image3D = dynamic_cast(node->GetData()); } } else { image3D = dynamic_cast(node->GetData()); } } std::stringstream stream; stream.imbue(std::locale::classic()); // get the position and gray value from the image and build up status bar text if(image3D.IsNotNull()) { Index3D p; image3D->GetGeometry()->WorldToIndex(worldposition, p); stream.precision(2); stream<<"Position: <" << std::fixed < mm"; stream<<"; Index: <"< "; mitk::ScalarType pixelValue = image3D->GetPixelValueByIndex(p, baseRenderer->GetTimeStep()); if (fabs(pixelValue)>1000000 || fabs(pixelValue) < 0.01) { stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << std::scientific<< pixelValue <<" "; } else { stream<<"; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: "<< pixelValue <<" "; } } else { stream << "No image information at this position!"; } statusText = stream.str(); mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str()); } } ok = true; break; } } default: ok = true; break; } return ok; } const DisplayPositionEvent *displPosEvent = dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() ); if ( displPosEvent != NULL ) { return true; } return false; } } // namespace diff --git a/Core/Code/Controllers/mitkSlicesRotator.cpp b/Core/Code/Controllers/mitkSlicesRotator.cpp index 7c0d8d8abb..92d3480778 100644 --- a/Core/Code/Controllers/mitkSlicesRotator.cpp +++ b/Core/Code/Controllers/mitkSlicesRotator.cpp @@ -1,512 +1,512 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rotate_cursor.xpm" namespace mitk { SlicesRotator::Pointer SlicesRotator::New() { return SlicesRotator::New("slices-rotator"); } SlicesRotator::SlicesRotator(const char* machine) : SlicesCoordinator(machine) { // make sure that AcSWITCHON and AcSWITCHOFF are defined int constants somewhere (e.g. mitkInteractionConst.h) CONNECT_ACTION( AcMOVE, DoSelectSlice ); CONNECT_ACTION( AcCHECKPOINT, DoDecideBetweenRotationAndSliceSelection ); CONNECT_ACTION( AcROTATESTART, DoStartRotation ); CONNECT_ACTION( AcROTATE, DoRotationStep ); CONNECT_ACTION( AcROTATEEND, DoEndRotation ); } SlicesRotator::~SlicesRotator() { } void SlicesRotator::OnSliceControllerAdded(SliceNavigationController* snc) { if (!snc) return; snc->ConnectGeometrySendEvent(this); // connects creation of new world geometry to Self::SetGeometry } void SlicesRotator::OnSliceControllerRemoved(SliceNavigationController* snc) { if (!snc) return; // nothing to do, base class does the bookkeeping } /// Is called whenever a SliceNavigationController invokes an event. Will update the list /// of SliceNavigationControllers that can handle rotation void SlicesRotator::SetGeometry(const itk::EventObject& /*EventObject*/) { // there is no way to determine the sender? // ==> update whole list of SNCs UpdateRotatableSNCs(); } void SlicesRotator::RotateToPoint( SliceNavigationController *rotationPlaneSNC, SliceNavigationController *rotatedPlaneSNC, const Point3D &point, bool linked ) { MITK_WARN << "Deprecated function! Use SliceNavigationController::ReorientSlices() instead"; SliceNavigationController *thirdSNC = NULL; SNCVector::iterator iter; for ( iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter ) { if ( ((*iter) != rotationPlaneSNC) && ((*iter) != rotatedPlaneSNC) ) { thirdSNC = *iter; break; } } if ( thirdSNC == NULL ) { return; } const PlaneGeometry *rotationPlane = rotationPlaneSNC->GetCurrentPlaneGeometry(); const PlaneGeometry *rotatedPlane = rotatedPlaneSNC->GetCurrentPlaneGeometry(); const PlaneGeometry *thirdPlane = thirdSNC->GetCurrentPlaneGeometry(); if ( (rotationPlane == NULL) || (rotatedPlane == NULL) || (thirdPlane == NULL) ) { return; } if ( rotatedPlane->DistanceFromPlane( point ) < 0.001 ) { // Skip irrelevant rotations return; } Point3D projectedPoint; Line3D intersection; Point3D rotationCenter; if ( !rotationPlane->Project( point, projectedPoint ) || !rotationPlane->IntersectionLine( rotatedPlane, intersection ) || !thirdPlane->IntersectionPoint( intersection, rotationCenter ) ) { return; } // All pre-requirements are met; execute the rotation Point3D referencePoint = intersection.Project( projectedPoint ); Vector3D toProjected = referencePoint - rotationCenter; Vector3D toCursor = projectedPoint - rotationCenter; // cross product: | A x B | = |A| * |B| * sin(angle) Vector3D axisOfRotation; vnl_vector_fixed< ScalarType, 3 > vnlDirection = vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() ); axisOfRotation.SetVnlVector( vnlDirection ); // scalar product: A * B = |A| * |B| * cos(angle) // tan = sin / cos ScalarType angle = - atan2( (double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected) ); angle *= 180.0 / vnl_math::pi; // create RotationOperation and apply to all SNCs that should be rotated RotationOperation op(OpROTATE, rotationCenter, axisOfRotation, angle); if ( !linked ) { BaseRenderer *renderer = rotatedPlaneSNC->GetRenderer(); if ( renderer == NULL ) { return; } DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost; displayGeometry->Map( rotationCenter, point2DWorld ); displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre ); TimeGeometry *timeGeometry= rotatedPlaneSNC->GetCreatedWorldGeometry(); if ( !timeGeometry ) { return; } timeGeometry->ExecuteOperation( &op ); displayGeometry->Map( rotationCenter, point2DWorld ); displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost ); Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre; //Vector2D origin = displayGeometry->GetOriginInMM(); displayGeometry->MoveBy( vector2DDisplayDiff ); rotatedPlaneSNC->SendCreatedWorldGeometryUpdate(); } else { SNCVector::iterator iter; for ( iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter ) { BaseRenderer *renderer = (*iter)->GetRenderer(); if ( renderer == NULL ) { continue; } DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost; displayGeometry->Map( rotationCenter, point2DWorld ); displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre ); TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry(); if ( !timeGeometry ) { continue; } timeGeometry->ExecuteOperation( &op ); displayGeometry->Map( rotationCenter, point2DWorld ); displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost ); Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre; //Vector2D origin = displayGeometry->GetOriginInMM(); displayGeometry->MoveBy( vector2DDisplayDiff ); (*iter)->SendCreatedWorldGeometryUpdate(); } } } // end RotateToPoint /// Updates the list of SliceNavigationControllers that can handle rotation void SlicesRotator::UpdateRotatableSNCs() { m_RotatableSNCs.clear(); for (SNCVector::iterator iter = m_SliceNavigationControllers.begin(); iter != m_SliceNavigationControllers.end(); ++iter) { const TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; - const SlicedGeometry3D* slicedGeometry = dynamic_cast( timeGeometry->GetGeometryForTimeStep(0) ); + const SlicedGeometry3D* slicedGeometry = dynamic_cast( timeGeometry->GetGeometryForTimeStep(0).GetPointer() ); if (!slicedGeometry) continue; if (slicedGeometry->IsValidSlice(0)) { // there were some lines of additional checks here in previous versions, // all of which would always evaluate to true, so the check was irrelevant. // Since the original intent was not documented, I removed all checks, // i.e. m_RotatableSNCs ends up being a list of all the registered // SliceNavigationControllers which have a SlicedGeometry3D with at least one slice, // which covers most standard cases. m_RotatableSNCs.push_back( *iter ); } } } bool SlicesRotator::DoSelectSlice(Action* a, const StateEvent* e) { // just reach through for (SNCVector::iterator iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter) { if ( !(*iter)->GetSliceLocked() ) { (*iter)->ExecuteAction(a,e); } } return true; } bool SlicesRotator::DoDecideBetweenRotationAndSliceSelection(Action*, const StateEvent* e) { // Decide between moving and rotation slices. // For basic decision logic see class documentation. /* Detail logic: 1. Find the SliceNavigationController that has sent the event: this one defines our rendering plane and will NOT be rotated. Must not even be counted or checked.. 2. Inspect every other SliceNavigationController - calculate the line intersection of this SliceNavigationController's plane with our rendering plane - if there is no interesection, ignore and continue - IF there is an intersection - check the mouse cursor's distance from that line. 0. if the line is NOT near the cursor, remember the plane as "one of the other planes" (which can be rotated in "locked" mode) 1. on first line near the cursor, just remember this intersection line as THE other plane that we want to rotate 2. on every consecutive line near the cursor, check if the line is geometrically identical to the line that we want to rotate - if yes, we just push this line to the "other" lines and rotate it along - if no, then we have a situation where the mouse is near two other lines (e.g. crossing point) and don't want to rotate */ const DisplayPositionEvent* posEvent = dynamic_cast(e->GetEvent()); if (!posEvent) return false; BaseRenderer* clickedRenderer = e->GetEvent()->GetSender(); const PlaneGeometry* ourViewportGeometry = dynamic_cast( clickedRenderer->GetCurrentWorldGeometry2D() ); if (!ourViewportGeometry) return false; DisplayGeometry* clickedDisplayGeometry = clickedRenderer->GetDisplayGeometry(); if (!clickedDisplayGeometry) return false; MITK_DEBUG << "============================================="; MITK_DEBUG << "Renderer under cursor is " << clickedRenderer->GetName(); Point3D cursorPosition = posEvent->GetWorldPosition(); const PlaneGeometry* geometryToBeRotated = NULL; // this one is under the mouse cursor const PlaneGeometry* anyOtherGeometry = NULL; // this is also visible (for calculation of intersection ONLY) Line3D intersectionLineWithGeometryToBeRotated; bool hitMultipleLines(false); m_SNCsToBeRotated.clear(); const double threshholdDistancePixels = 12.0; for (SNCVector::iterator iter = m_RotatableSNCs.begin(); iter != m_RotatableSNCs.end(); ++iter) { // If the mouse cursor is in 3D Renderwindow, do not check for intersecting planes. if (clickedRenderer->GetMapperID() == BaseRenderer::Standard3D) break; const PlaneGeometry* otherRenderersRenderPlane = (*iter)->GetCurrentPlaneGeometry(); if (otherRenderersRenderPlane == NULL) continue; // ignore, we don't see a plane MITK_DEBUG << " Checking plane of renderer " << (*iter)->GetRenderer()->GetName(); // check if there is an intersection Line3D intersectionLine; // between rendered/clicked geometry and the one being analyzed if (!ourViewportGeometry->IntersectionLine( otherRenderersRenderPlane, intersectionLine )) { continue; // we ignore this plane, it's parallel to our plane } // check distance from intersection line double distanceFromIntersectionLine = intersectionLine.Distance( cursorPosition ); ScalarType distancePixels = distanceFromIntersectionLine / clickedDisplayGeometry->GetScaleFactorMMPerDisplayUnit(); MITK_DEBUG << " Distance of plane from cursor " << distanceFromIntersectionLine << " mm, which is around " << distancePixels << " px" ; // far away line, only remember for linked rotation if necessary if (distanceFromIntersectionLine > threshholdDistancePixels) { MITK_DEBUG << " Plane is too far away --> remember as otherRenderersRenderPlane"; anyOtherGeometry = otherRenderersRenderPlane; // we just take the last one, so overwrite each iteration (we just need some crossing point) // TODO what about multiple crossings? NOW we have undefined behavior / random crossing point is used if (m_LinkPlanes) { m_SNCsToBeRotated.push_back(*iter); } } else // close to cursor { MITK_DEBUG << " Plane is close enough to cursor..."; if ( geometryToBeRotated == NULL ) // first one close to the cursor { MITK_DEBUG << " It is the first close enough geometry, remember as geometryToBeRotated"; geometryToBeRotated = otherRenderersRenderPlane; intersectionLineWithGeometryToBeRotated = intersectionLine; m_SNCsToBeRotated.push_back(*iter); } else { MITK_DEBUG << " Second or later close enough geometry"; // compare to the line defined by geometryToBeRotated: if identical, just rotate this otherRenderersRenderPlane together with the primary one // if different, DON'T rotate if ( intersectionLine.IsParallel( intersectionLineWithGeometryToBeRotated ) && intersectionLine.Distance( intersectionLineWithGeometryToBeRotated.GetPoint1() ) < mitk::eps ) { MITK_DEBUG << " This line is the same as intersectionLineWithGeometryToBeRotated which we already know"; m_SNCsToBeRotated.push_back(*iter); } else { MITK_DEBUG << " This line is NOT the same as intersectionLineWithGeometryToBeRotated which we already know"; hitMultipleLines = true; } } } } bool moveSlices(true); if ( geometryToBeRotated && anyOtherGeometry && ourViewportGeometry && !hitMultipleLines ) { // assure all three are valid, so calculation of center of rotation can be done moveSlices = false; } MITK_DEBUG << "geometryToBeRotated: " << (void*)geometryToBeRotated; MITK_DEBUG << "anyOtherGeometry: " << (void*)anyOtherGeometry; MITK_DEBUG << "ourViewportGeometry: " << (void*)ourViewportGeometry; MITK_DEBUG << "hitMultipleLines? " << hitMultipleLines; MITK_DEBUG << "moveSlices? " << moveSlices; std::auto_ptr decidedEvent; // question in state machine is: "rotate?" if (moveSlices) // i.e. NOT rotate { // move all planes to posEvent->GetWorldPosition() decidedEvent.reset( new StateEvent(EIDNO, e->GetEvent()) ); MITK_DEBUG << "Rotation not possible, not enough information (other planes crossing rendering plane) "; } else { // we DO have enough information for rotation m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.Project(cursorPosition); // remember where the last cursor position ON THE LINE has been observed if (anyOtherGeometry->IntersectionPoint(intersectionLineWithGeometryToBeRotated, m_CenterOfRotation)) // find center of rotation by intersection with any of the OTHER lines { decidedEvent.reset( new StateEvent(EIDYES, e->GetEvent()) ); MITK_DEBUG << "Rotation possible"; } else { MITK_DEBUG << "Rotation not possible, cannot determine the center of rotation!?"; decidedEvent.reset( new StateEvent(EIDNO, e->GetEvent()) ); } } this->HandleEvent( decidedEvent.get() ); return true; } bool SlicesRotator::DoStartRotation(Action*, const StateEvent*) { this->SetMouseCursor( rotate_cursor_xpm, 0, 0 ); this->InvokeEvent( SliceRotationEvent() ); // notify listeners return true; } bool SlicesRotator::DoEndRotation(Action*, const StateEvent*) { this->ResetMouseCursor(); this->InvokeEvent( SliceRotationEvent() ); // notify listeners return true; } bool SlicesRotator::DoRotationStep(Action*, const StateEvent* e) { const DisplayPositionEvent* posEvent = dynamic_cast(e->GetEvent()); if (!posEvent) return false; Point3D cursor = posEvent->GetWorldPosition(); Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation; Vector3D toCursor = cursor - m_CenterOfRotation; // cross product: | A x B | = |A| * |B| * sin(angle) Vector3D axisOfRotation; vnl_vector_fixed< ScalarType, 3 > vnlDirection = vnl_cross_3d( toCursor.GetVnlVector(), toProjected.GetVnlVector() ); axisOfRotation.SetVnlVector(vnlDirection); // scalar product: A * B = |A| * |B| * cos(angle) // tan = sin / cos ScalarType angle = - atan2( (double)(axisOfRotation.GetNorm()), (double)(toCursor * toProjected) ); angle *= 180.0 / vnl_math::pi; m_LastCursorPosition = cursor; // create RotationOperation and apply to all SNCs that should be rotated RotationOperation rotationOperation(OpROTATE, m_CenterOfRotation, axisOfRotation, angle); // iterate the OTHER slice navigation controllers: these are filled in DoDecideBetweenRotationAndSliceSelection for (SNCVector::iterator iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter) { // - remember the center of rotation on the 2D display BEFORE rotation // - execute rotation // - calculate new center of rotation on 2D display // - move display IF the center of rotation has moved slightly before and after rotation // DM 2012-10: this must probably be due to rounding errors only, right? // We don't have documentation on if/why this code is needed BaseRenderer *renderer = (*iter)->GetRenderer(); if ( !renderer ) continue; DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); Point2D rotationCenter2DWorld, point2DDisplayPreRotation, point2DDisplayPostRotation; displayGeometry->Map( m_CenterOfRotation, rotationCenter2DWorld ); displayGeometry->WorldToDisplay( rotationCenter2DWorld, point2DDisplayPreRotation ); TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; timeGeometry->ExecuteOperation(&rotationOperation); displayGeometry->Map( m_CenterOfRotation, rotationCenter2DWorld ); displayGeometry->WorldToDisplay( rotationCenter2DWorld, point2DDisplayPostRotation ); Vector2D vector2DDisplayDiff = point2DDisplayPostRotation - point2DDisplayPreRotation; displayGeometry->MoveBy( vector2DDisplayDiff ); (*iter)->SendCreatedWorldGeometryUpdate(); } RenderingManager::GetInstance()->RequestUpdateAll(); this->InvokeEvent( SliceRotationEvent() ); // notify listeners return true; } } // namespace diff --git a/Core/Code/Controllers/mitkSlicesSwiveller.cpp b/Core/Code/Controllers/mitkSlicesSwiveller.cpp index a8eb2f57d1..35b415ca1d 100644 --- a/Core/Code/Controllers/mitkSlicesSwiveller.cpp +++ b/Core/Code/Controllers/mitkSlicesSwiveller.cpp @@ -1,395 +1,395 @@ /*=================================================================== 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 "mitkSlicesSwiveller.h" #include "mitkSliceNavigationController.h" #include "mitkStateEvent.h" #include "mitkAction.h" #include "mitkInteractionConst.h" #include "mitkDisplayPositionEvent.h" #include "mitkRotationOperation.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkLine.h" #include "mitkGeometry3D.h" #include "mitkGeometry2D.h" #include "mitkPlaneGeometry.h" #include "mitkDisplayGeometry.h" #include "mitkSlicedGeometry3D.h" #include namespace mitk { SlicesSwiveller::Pointer SlicesSwiveller::New() { return SlicesSwiveller::New("slices-rotator"); } SlicesSwiveller::SlicesSwiveller(const char* machine) : SlicesCoordinator(machine), m_PreviousRotationAngle( 0.0 ) { } SlicesSwiveller::~SlicesSwiveller() { } // check if the slices of this SliceNavigationController can be rotated (???) Possible void SlicesSwiveller::OnSliceControllerAdded(SliceNavigationController* snc) { if (!snc) return; // connects creation of new world geometry to Self::SetGeometry snc->ConnectGeometrySendEvent(this); } void SlicesSwiveller::OnSliceControllerRemoved(SliceNavigationController* snc) { if (!snc) return; // nothing to do } /// Is called whenever a SliceNavigationController invokes an event. Will // update the list of SliceNavigationControllers that can handle rotation void SlicesSwiveller::SetGeometry(const itk::EventObject& /*EventObject*/) { // there is no way to determine the sender? // ==> update whole list of SNCs UpdateRelevantSNCs(); } /// Updates the list of SliceNavigationControllers that can handle rotation void SlicesSwiveller::UpdateRelevantSNCs() { m_RelevantSNCs.clear(); SNCVector::iterator iter; for ( iter = m_SliceNavigationControllers.begin(); iter != m_SliceNavigationControllers.end(); ++iter) { const TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; const SlicedGeometry3D* slicedGeometry = dynamic_cast( - timeGeometry->GetGeometryForTimeStep(0) ); + timeGeometry->GetGeometryForTimeStep(0).GetPointer() ); if (!slicedGeometry) continue; Geometry2D *firstSlice( NULL ); //Geometry2D *secondSlice( NULL ); if (slicedGeometry->IsValidSlice(0)) { firstSlice = slicedGeometry->GetGeometry2D(0); } // if (slicedGeometry->IsValidSlice(1)) // { // secondSlice = slicedGeometry->GetGeometry2D(1); // } // If the direction vector of these two slices is the same, then accept // this slice stack as rotatable Vector3D right1 = firstSlice->GetAxisVector(0); Vector3D up1 = firstSlice->GetAxisVector(1); vnl_vector_fixed< ScalarType, 3 > vnlDirection1 = vnl_cross_3d(right1.GetVnlVector(), up1.GetVnlVector()); Vector3D direction1; direction1.SetVnlVector(vnlDirection1); Vector3D right2 = firstSlice->GetAxisVector(0); Vector3D up2 = firstSlice->GetAxisVector(1); vnl_vector_fixed< ScalarType, 3 > vnlDirection2 = vnl_cross_3d(right2.GetVnlVector(), up2.GetVnlVector()); Vector3D direction2; direction2.SetVnlVector(vnlDirection2); bool equal = true; const ScalarType eps = 0.0001; for (int i = 0; i < 3; ++i) { if ( fabs(direction1[i] - direction2[i]) > eps ) { equal = false; } } if (equal) // equal direction vectors { m_RelevantSNCs.push_back( *iter ); } } } bool SlicesSwiveller ::ExecuteAction(Action* action, StateEvent const* stateEvent) { const ScalarType ThresholdDistancePixels = 6.0; bool ok = false; switch ( action->GetActionId() ) { case AcMOVE: { // just reach through SNCVector::iterator iter; for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter ) { if ( !(*iter)->GetSliceRotationLocked() ) { (*iter)->ExecuteAction(action, stateEvent); } } ok = true; break; } case AcROTATE: { const DisplayPositionEvent *posEvent = dynamic_cast(stateEvent->GetEvent()); if (!posEvent) break; // Determine relative mouse movement projected onto world space Point2D cursor = posEvent->GetDisplayPosition(); Vector2D relativeCursor = cursor - m_ReferenceCursor; Vector3D relativeCursorAxis = m_RotationPlaneXVector * relativeCursor[0] + m_RotationPlaneYVector * relativeCursor[1]; // Determine rotation axis (perpendicular to rotation plane and cursor // movement) Vector3D rotationAxis = itk::CrossProduct( m_RotationPlaneNormal, relativeCursorAxis ); ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0; // Restore the initial plane pose by undoing the previous rotation // operation RotationOperation op( OpROTATE, m_CenterOfRotation, m_PreviousRotationAxis, -m_PreviousRotationAngle ); SNCVector::iterator iter; for ( iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter ) { if ( !(*iter)->GetSliceRotationLocked() ) { TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; timeGeometry->ExecuteOperation(&op); (*iter)->SendCreatedWorldGeometryUpdate(); } } // Apply new rotation operation to all relevant SNCs RotationOperation op2( OpROTATE, m_CenterOfRotation, rotationAxis, rotationAngle ); for ( iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter) { if ( !(*iter)->GetSliceRotationLocked() ) { //// Map rotation center onto display geometry (will be used as //// pre-rotation vector for compensating a visual shift of the //// rotation center) //BaseRenderer *renderer = (*iter)->GetRenderer(); //DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); //Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost; //displayGeometry->Map( m_CenterOfRotation, point2DWorld ); //displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre ); // Retrieve the TimeGeometry of this SliceNavigationController TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry(); if (!timeGeometry) continue; // Execute the new rotation timeGeometry->ExecuteOperation(&op2); //// After rotation: map rotation center onto new display geometry... //displayGeometry->Map( m_CenterOfRotation, point2DWorld ); //displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost ); //Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre; //// And use the difference between pre- and post-rotation vectors to //// compensate for display geometry shift: //Vector2D origin = displayGeometry->GetOriginInMM(); //displayGeometry->MoveBy( vector2DDisplayDiff ); // Notify listeners (*iter)->SendCreatedWorldGeometryUpdate(); } } m_PreviousRotationAxis = rotationAxis; m_PreviousRotationAngle = rotationAngle; RenderingManager::GetInstance()->RequestUpdateAll(); this->InvokeEvent( SliceRotationEvent() ); // notify listeners ok = true; break; } case AcCHECKPOINT: { // Decide between moving and rotation: if we're close to the crossing // point of the planes, moving mode is entered, otherwise // rotation/swivel mode const DisplayPositionEvent *posEvent = dynamic_cast(stateEvent->GetEvent()); BaseRenderer *renderer = stateEvent->GetEvent()->GetSender(); if ( !posEvent || !renderer ) { break; } const Point3D &cursor = posEvent->GetWorldPosition(); m_SNCsToBeRotated.clear(); const PlaneGeometry *clickedGeometry( NULL ); const PlaneGeometry *otherGeometry1( NULL ); const PlaneGeometry *otherGeometry2( NULL ); SNCVector::iterator iter; for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter ) { //unsigned int slice = (*iter)->GetSlice()->GetPos(); //unsigned int time = (*iter)->GetTime()->GetPos(); const PlaneGeometry *planeGeometry = (*iter)->GetCurrentPlaneGeometry(); if ( !planeGeometry ) continue; if ( *iter == renderer->GetSliceNavigationController() ) { clickedGeometry = planeGeometry; m_SNCsToBeRotated.push_back(*iter); } else { if ( otherGeometry1 == NULL ) { otherGeometry1 = planeGeometry; } else { otherGeometry2 = planeGeometry; } if ( m_LinkPlanes ) { // If planes are linked, apply rotation to all planes m_SNCsToBeRotated.push_back(*iter); } } } std::auto_ptr newStateEvent; mitk::Line3D line; mitk::Point3D point; if ( (clickedGeometry != NULL) && (otherGeometry1 != NULL) && (otherGeometry2 != NULL) && clickedGeometry->IntersectionLine( otherGeometry1, line ) && otherGeometry2->IntersectionPoint( line, point )) { m_CenterOfRotation = point; if ( m_CenterOfRotation.EuclideanDistanceTo( cursor ) < ThresholdDistancePixels ) { newStateEvent.reset(new StateEvent(EIDNO, stateEvent->GetEvent())); } else { m_ReferenceCursor = posEvent->GetDisplayPosition(); // Get main axes of rotation plane and store it for rotation step m_RotationPlaneNormal = clickedGeometry->GetNormal(); ScalarType xVector[] = { 1.0, 0.0, 0.0 }; ScalarType yVector[] = { 0.0, 1.0, 0.0 }; clickedGeometry->Geometry3D::IndexToWorld( Vector3D( xVector), m_RotationPlaneXVector ); clickedGeometry->Geometry3D::IndexToWorld( Vector3D( yVector), m_RotationPlaneYVector ); m_RotationPlaneNormal.Normalize(); m_RotationPlaneXVector.Normalize(); m_RotationPlaneYVector.Normalize(); m_PreviousRotationAxis.Fill( 0.0 ); m_PreviousRotationAxis[2] = 1.0; m_PreviousRotationAngle = 0.0; newStateEvent.reset(new StateEvent(EIDYES, stateEvent->GetEvent())); } } else { newStateEvent.reset(new StateEvent(EIDNO, stateEvent->GetEvent())); } this->HandleEvent( newStateEvent.get() ); ok = true; break; } case AcROTATESTART: { this->InvokeEvent( SliceRotationEvent() ); // notify listeners break; } case AcROTATEEND: { this->InvokeEvent( SliceRotationEvent() ); // notify listeners break; } default: { break; } } return ok; } } // namespace diff --git a/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp b/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp index cbce4c9e97..6c02142c99 100644 --- a/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp +++ b/Core/Code/DataManagement/mitkProportionalTimeGeometry.cpp @@ -1,221 +1,223 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include mitk::ProportionalTimeGeometry::ProportionalTimeGeometry() : m_FirstTimePoint(0.0), m_StepDuration(1.0) { } mitk::ProportionalTimeGeometry::~ProportionalTimeGeometry() { } void mitk::ProportionalTimeGeometry::Initialize() { m_FirstTimePoint = 0.0; m_StepDuration = 1.0; } mitk::TimeStepType mitk::ProportionalTimeGeometry::GetNumberOfTimeSteps () const { return static_cast(m_GeometryVector.size() ); } mitk::TimePointType mitk::ProportionalTimeGeometry::GetMinimumTimePoint () const { return m_FirstTimePoint; } mitk::TimePointType mitk::ProportionalTimeGeometry::GetMaximumTimePoint () const { TimePointType timePoint = m_FirstTimePoint + m_StepDuration * GetNumberOfTimeSteps(); if (timePoint >std::numeric_limits().max()) timePoint = std::numeric_limits().max(); return timePoint; } mitk::TimeBounds mitk::ProportionalTimeGeometry::GetTimeBounds () const { TimeBounds bounds; bounds[0] = this->GetMinimumTimePoint(); bounds[1] = this->GetMaximumTimePoint(); return bounds; } bool mitk::ProportionalTimeGeometry::IsValidTimePoint (TimePointType timePoint) const { return this->GetMinimumTimePoint() <= timePoint && timePoint < this->GetMaximumTimePoint(); } bool mitk::ProportionalTimeGeometry::IsValidTimeStep (TimeStepType timeStep) const { return 0 <= timeStep && timeStep < this->GetNumberOfTimeSteps(); } mitk::TimePointType mitk::ProportionalTimeGeometry::TimeStepToTimePoint( TimeStepType timeStep) const { if (m_FirstTimePoint <= std::numeric_limits::min() || m_FirstTimePoint >= std::numeric_limits::max() || m_StepDuration <= std::numeric_limits::min() || m_StepDuration >= std::numeric_limits::max()) { return static_cast(timeStep); } return m_FirstTimePoint + timeStep * m_StepDuration; } mitk::TimeStepType mitk::ProportionalTimeGeometry::TimePointToTimeStep( TimePointType timePoint) const { if (m_FirstTimePoint <= timePoint) return static_cast((timePoint -m_FirstTimePoint) / m_StepDuration); else return 0; } -mitk::Geometry3D* mitk::ProportionalTimeGeometry::GetGeometryForTimeStep( TimeStepType timeStep) const +mitk::Geometry3D::Pointer mitk::ProportionalTimeGeometry::GetGeometryForTimeStep( TimeStepType timeStep) const { if (IsValidTimeStep(timeStep)) { return dynamic_cast(m_GeometryVector[timeStep].GetPointer()); } else { - return NULL; + return 0; } } -mitk::Geometry3D* mitk::ProportionalTimeGeometry::GetGeometryForTimePoint(TimePointType timePoint) const +mitk::Geometry3D::Pointer mitk::ProportionalTimeGeometry::GetGeometryForTimePoint(TimePointType timePoint) const { if (this->IsValidTimePoint(timePoint)) { TimeStepType timeStep = this->TimePointToTimeStep(timePoint); return this->GetGeometryForTimeStep(timeStep); } else - return NULL; + { + return 0; + } } mitk::Geometry3D::Pointer mitk::ProportionalTimeGeometry::GetGeometryCloneForTimeStep( TimeStepType timeStep) const { if (timeStep > m_GeometryVector.size()) return 0; return m_GeometryVector[timeStep]->Clone(); } -bool mitk::ProportionalTimeGeometry::IsValid() +bool mitk::ProportionalTimeGeometry::IsValid() const { bool isValid = true; isValid &= m_GeometryVector.size() > 0; isValid &= m_StepDuration > 0; return isValid; } void mitk::ProportionalTimeGeometry::ClearAllGeometries() { m_GeometryVector.clear(); } void mitk::ProportionalTimeGeometry::ReserveSpaceForGeometries(TimeStepType numberOfGeometries) { m_GeometryVector.reserve(numberOfGeometries); } void mitk::ProportionalTimeGeometry::Expand(mitk::TimeStepType size) { m_GeometryVector.reserve(size); while (m_GeometryVector.size() < size) { m_GeometryVector.push_back(Geometry3D::New()); } } -void mitk::ProportionalTimeGeometry::SetTimeStepGeometry(Geometry3D *geometry, TimeStepType timeStep) +void mitk::ProportionalTimeGeometry::SetTimeStepGeometry(Geometry3D* geometry, TimeStepType timeStep) { assert(timeStep<=m_GeometryVector.size()); assert(timeStep >= 0); if (timeStep == m_GeometryVector.size()) m_GeometryVector.push_back(geometry); m_GeometryVector[timeStep] = geometry; } itk::LightObject::Pointer mitk::ProportionalTimeGeometry::InternalClone() const { ProportionalTimeGeometry::Pointer newTimeGeometry = ProportionalTimeGeometry::New(); newTimeGeometry->m_BoundingBox = m_BoundingBox->DeepCopy(); newTimeGeometry->m_FirstTimePoint = this->m_FirstTimePoint; newTimeGeometry->m_StepDuration = this->m_StepDuration; newTimeGeometry->m_GeometryVector.clear(); newTimeGeometry->Expand(this->GetNumberOfTimeSteps()); for (TimeStepType i =0; i < GetNumberOfTimeSteps(); ++i) { Geometry3D::Pointer tempGeometry = GetGeometryForTimeStep(i)->Clone(); newTimeGeometry->SetTimeStepGeometry(tempGeometry.GetPointer(),i); } itk::LightObject::Pointer finalPointer = dynamic_cast(newTimeGeometry.GetPointer()); return finalPointer; } -void mitk::ProportionalTimeGeometry::Initialize (Geometry3D * geometry, TimeStepType timeSteps) +void mitk::ProportionalTimeGeometry::Initialize (Geometry3D* geometry, TimeStepType timeSteps) { timeSteps = (timeSteps > 0) ? timeSteps : 1; m_FirstTimePoint = geometry->GetTimeBounds()[0]; m_StepDuration = geometry->GetTimeBounds()[1] - geometry->GetTimeBounds()[0]; this->ReserveSpaceForGeometries(timeSteps); try{ for (TimeStepType currentStep = 0; currentStep < timeSteps; ++currentStep) { mitk::TimeBounds timeBounds; if (timeSteps > 1) { timeBounds[0] = m_FirstTimePoint + currentStep * m_StepDuration; timeBounds[1] = m_FirstTimePoint + (currentStep+1) * m_StepDuration; } else { timeBounds = geometry->GetTimeBounds(); } Geometry3D::Pointer clonedGeometry = geometry->Clone(); this->SetTimeStepGeometry(clonedGeometry.GetPointer(), currentStep); GetGeometryForTimeStep(currentStep)->SetTimeBounds(timeBounds); } } catch (...) { MITK_INFO << "Cloning of geometry produced an error!"; } Update(); } void mitk::ProportionalTimeGeometry::Initialize (TimeStepType timeSteps) { mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->Initialize(); if ( timeSteps > 1 ) { mitk::ScalarType timeBounds[] = {0.0, 1.0}; geometry->SetTimeBounds( timeBounds ); } this->Initialize(geometry.GetPointer(), timeSteps); } diff --git a/Core/Code/DataManagement/mitkProportionalTimeGeometry.h b/Core/Code/DataManagement/mitkProportionalTimeGeometry.h index 116c93f6b6..b3618cfa89 100644 --- a/Core/Code/DataManagement/mitkProportionalTimeGeometry.h +++ b/Core/Code/DataManagement/mitkProportionalTimeGeometry.h @@ -1,216 +1,216 @@ /*=================================================================== 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 ProportialTimeGeometry_h -#define ProportialTimeGeometry_h +#ifndef ProportionalTimeGeometry_h +#define ProportionalTimeGeometry_h //ITK #include #include #include //MITK #include #include #include #include "mitkOperationActor.h" #include "mitkVector.h" // To be replaced #include // STL #include namespace mitk { /** * \brief Organizes geometries over proportional time steps * * For this TimeGeometry implementation it is assumed that * the durations of the time steps are equidistant, e.g. * the durations of the time steps in one ProportionalTimeGeometry * are the same. The geometries of the time steps are independent, * and not linked to each other. Since the timeBounds of the * geometries are different for each time step it is not possible * to set the same geometry to different time steps. Instead * copies should be used. * * \addtogroup geometry */ class MITK_CORE_EXPORT ProportionalTimeGeometry : public TimeGeometry { public: mitkClassMacro(ProportionalTimeGeometry, TimeGeometry); ProportionalTimeGeometry(); typedef ProportionalTimeGeometry self; itkNewMacro(self); /** * \brief Returns the number of time steps. * * Returns the number of time steps for which * geometries are saved. The number of time steps * is also the upper bound of the time steps. The * minimum time steps is always 0. */ virtual TimeStepType GetNumberOfTimeSteps() const; /** * \brief Returns the first time point for which the object is valid. * * Returns the first valid time point for this geometry. If only one * time steps available it usually goes from -max to +max. The time point * is given in ms. */ virtual TimePointType GetMinimumTimePoint () const; /** * \brief Returns the last time point for which the object is valid * * Gives the last time point for which a valid geometrie is saved in * this time geometry. The time point is given in ms. */ virtual TimePointType GetMaximumTimePoint () const; /** * \brief Get the time bounds (in ms) */ virtual TimeBounds GetTimeBounds( ) const; /** * \brief Tests if a given time point is covered by this object * * Returns true if a geometry can be returned for the given time * point and falls if not. The time point must be given in ms. */ virtual bool IsValidTimePoint (TimePointType timePoint) const; /** * \brief Test for the given time step if a geometry is availible * * Returns true if a geometry is defined for the given time step. * Otherwise false is returned. * The time step is defined as positiv number. */ virtual bool IsValidTimeStep (TimeStepType timeStep) const; /** * \brief Converts a time step to a time point * * Converts a time step to a time point in a way that * the new time point indicates the same geometry as the time step. * If the original time steps does not point to a valid geometry, * a time point is calculated that also does not point to a valid * geometry, but no exception is raised. */ virtual TimePointType TimeStepToTimePoint (TimeStepType timeStep) const; /** * \brief Converts a time point to the corresponding time step * * Converts a time point to a time step in a way that * the new time step indicates the same geometry as the time point. * If a negativ invalid time point is given always time step 0 is * returned. If an positiv invalid time step is given an invalid * time step will be returned. */ virtual TimeStepType TimePointToTimeStep (TimePointType timePoint) const; /** * \brief Returns the geometry which corresponds to the given time step * * Returns a clone of the geometry which defines the given time step. If * the given time step is invalid an null-pointer is returned. */ virtual Geometry3D::Pointer GetGeometryCloneForTimeStep( TimeStepType timeStep) const; /** * \brief Returns the geometry which corresponds to the given time point * * Returns the geometry which defines the given time point. If * the given time point is invalid an null-pointer is returned. * * If the returned geometry is changed this will affect the saved * geometry. */ - virtual Geometry3D* GetGeometryForTimePoint ( TimePointType timePoint) const; + virtual Geometry3D::Pointer GetGeometryForTimePoint ( TimePointType timePoint) const; /** * \brief Returns the geometry which corresponds to the given time step * * Returns the geometry which defines the given time step. If * the given time step is invalid an null-pointer is returned. * * If the returned geometry is changed this will affect the saved * geometry. */ - virtual Geometry3D* GetGeometryForTimeStep ( TimeStepType timeStep) const; + virtual Geometry3D::Pointer GetGeometryForTimeStep ( TimeStepType timeStep) const; /** * \brief Tests if all necessary informations are set and the object is valid */ - virtual bool IsValid (); + virtual bool IsValid () const; /** * \brief Initilizes a new object with one time steps which contains an empty geometry. */ virtual void Initialize(); /** * \brief Expands the time geometry to the given number of time steps. * * Initializes the new time steps with empty geometries. * Shrinking is not supported. */ virtual void Expand(TimeStepType size); /** * \brief Sets the geometry for the given time step * * This method does not afflict other time steps, since the geometry for * each time step is saved individually. */ virtual void SetTimeStepGeometry(Geometry3D* geometry, TimeStepType timeStep); /** * \brief Makes a deep copy of the current object */ virtual itk::LightObject::Pointer InternalClone () const; itkGetMacro(FirstTimePoint, TimePointType); itkSetMacro(FirstTimePoint, TimePointType); itkGetMacro(StepDuration, TimePointType); itkSetMacro(StepDuration, TimePointType); // void SetGeometryForTimeStep(TimeStepType timeStep, BaseGeometry& geometry); void ClearAllGeometries (); // void AddGeometry(BaseGeometry geometry); void ReserveSpaceForGeometries (TimeStepType numberOfGeometries); /** * \brief Initializes the TimeGeometry with equally time Step geometries * * Saves a copy for each time step. */ - void Initialize (Geometry3D * geometry, TimeStepType timeSteps); + void Initialize (Geometry3D* geometry, TimeStepType timeSteps); /** * \brief Initialize the TimeGeometry with empty Geometry3D */ void Initialize (TimeStepType timeSteps); protected: virtual ~ProportionalTimeGeometry(); std::vector m_GeometryVector; TimePointType m_FirstTimePoint; TimePointType m_StepDuration; }; // end class ProportialTimeGeometry } // end namespace MITK -#endif // ProportialTimeGeometry_h \ No newline at end of file +#endif // ProportionalTimeGeometry_h \ No newline at end of file diff --git a/Core/Code/DataManagement/mitkSlicedData.cpp b/Core/Code/DataManagement/mitkSlicedData.cpp index 99dc3d67bd..48d727bbfa 100644 --- a/Core/Code/DataManagement/mitkSlicedData.cpp +++ b/Core/Code/DataManagement/mitkSlicedData.cpp @@ -1,344 +1,344 @@ /*=================================================================== 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 "mitkSlicedData.h" #include "mitkBaseProcess.h" #include mitk::SlicedData::SlicedData() : m_UseLargestPossibleRegion(false) { unsigned int i; for(i=0;i<4;++i) { m_LargestPossibleRegion.SetIndex(i, 0); m_LargestPossibleRegion.SetSize (i, 1); } } mitk::SlicedData::SlicedData( const SlicedData &other ): BaseData(other), m_LargestPossibleRegion(other.m_LargestPossibleRegion), m_RequestedRegion(other.m_RequestedRegion), m_BufferedRegion(other.m_BufferedRegion), m_UseLargestPossibleRegion(other.m_UseLargestPossibleRegion) { } mitk::SlicedData::~SlicedData() { } void mitk::SlicedData::UpdateOutputInformation() { Superclass::UpdateOutputInformation(); if (this->GetSource().IsNull()) // If we don't have a source, then let's make our Image // span our buffer { m_UseLargestPossibleRegion = true; } // Now we should know what our largest possible region is. If our // requested region was not set yet, (or has been set to something // invalid - with no data in it ) then set it to the largest possible // region. if ( ! m_RequestedRegionInitialized) { this->SetRequestedRegionToLargestPossibleRegion(); m_RequestedRegionInitialized = true; } m_LastRequestedRegionWasOutsideOfTheBufferedRegion = 0; } void mitk::SlicedData::PrepareForNewData() { if ( GetUpdateMTime() < GetPipelineMTime() || GetDataReleased() ) { ReleaseData(); } } void mitk::SlicedData::SetRequestedRegionToLargestPossibleRegion() { m_UseLargestPossibleRegion = true; if(GetGeometry()==NULL) return; unsigned int i; const RegionType::IndexType & index = GetLargestPossibleRegion().GetIndex(); const RegionType::SizeType & size = GetLargestPossibleRegion().GetSize(); for(i=0;i(requestedRegionSize[4]); if(requestedRegionSize[3] == largestPossibleRegionSize[3]) { for (; c< cEnd; ++c) if(IsChannelSet(c)==false) return true; return false; } // are whole volumes requested? int t, tEnd; t=requestedRegionIndex[3]; tEnd=t+static_cast(requestedRegionSize[3]); if(requestedRegionSize[2] == largestPossibleRegionSize[2]) { for (; c< cEnd; ++c) for (; t< tEnd; ++t) if(IsVolumeSet(t, c)==false) return true; return false; } // ok, only slices are requested. Check if they are available. int s, sEnd; s=requestedRegionIndex[2]; sEnd=s+static_cast(requestedRegionSize[2]); for (; c< cEnd; ++c) for (; t< tEnd; ++t) for (; s< sEnd; ++s) if(IsSliceSet(s, t, c)==false) return true; return false; } bool mitk::SlicedData::VerifyRequestedRegion() { if(GetTimeGeometry() == NULL) return false; unsigned int i; // Is the requested region within the LargestPossibleRegion? // Note that the test is indeed against the largest possible region // rather than the buffered region; see DataObject::VerifyRequestedRegion. const IndexType &requestedRegionIndex = m_RequestedRegion.GetIndex(); const IndexType &largestPossibleRegionIndex = GetLargestPossibleRegion().GetIndex(); const SizeType& requestedRegionSize = m_RequestedRegion.GetSize(); const SizeType& largestPossibleRegionSize = GetLargestPossibleRegion().GetSize(); for (i=0; i< RegionDimension; ++i) { if ( (requestedRegionIndex[i] < largestPossibleRegionIndex[i]) || ((requestedRegionIndex[i] + static_cast(requestedRegionSize[i])) > (largestPossibleRegionIndex[i]+static_cast(largestPossibleRegionSize[i])))) { return false; } } return true; } void mitk::SlicedData::SetRequestedRegion( const itk::DataObject *data) { m_UseLargestPossibleRegion=false; const mitk::SlicedData *slicedData = dynamic_cast(data); if (slicedData) { m_RequestedRegion = slicedData->GetRequestedRegion(); m_RequestedRegionInitialized = true; } else { // pointer could not be cast back down itkExceptionMacro( << "mitk::SlicedData::SetRequestedRegion(DataObject*) cannot cast " << typeid(data).name() << " to " << typeid(SlicedData*).name() ); } } void mitk::SlicedData::SetRequestedRegion(SlicedData::RegionType *region) { m_UseLargestPossibleRegion=false; if(region!=NULL) { m_RequestedRegion = *region; m_RequestedRegionInitialized = true; } else { // pointer could not be cast back down itkExceptionMacro( << "mitk::SlicedData::SetRequestedRegion(SlicedData::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(SlicedData*).name() ); } } void mitk::SlicedData::CopyInformation(const itk::DataObject *data) { // Standard call to the superclass' method Superclass::CopyInformation(data); const mitk::SlicedData *slicedData; slicedData = dynamic_cast(data); if (slicedData) { m_LargestPossibleRegion = slicedData->GetLargestPossibleRegion(); } else { // pointer could not be cast back down itkExceptionMacro( << "mitk::SlicedData::CopyInformation(const DataObject *data) cannot cast " << typeid(data).name() << " to " << typeid(SlicedData*).name() ); } } //const mitk::Geometry2D* mitk::SlicedData::GetGeometry2D(int s, int t) const //{ // const_cast(this)->SetRequestedRegionToLargestPossibleRegion(); // // const_cast(this)->UpdateOutputInformation(); // // return GetSlicedGeometry(t)->GetGeometry2D(s); //} // mitk::SlicedGeometry3D* mitk::SlicedData::GetSlicedGeometry(unsigned int t) const { if (GetTimeGeometry() == NULL) return NULL; - return dynamic_cast(GetTimeGeometry()->GetGeometryForTimeStep(t)); + return dynamic_cast(GetTimeGeometry()->GetGeometryForTimeStep(t).GetPointer()); } const mitk::SlicedGeometry3D* mitk::SlicedData::GetUpdatedSlicedGeometry(unsigned int t) { SetRequestedRegionToLargestPossibleRegion(); UpdateOutputInformation(); return GetSlicedGeometry(t); } void mitk::SlicedData::SetGeometry(Geometry3D* aGeometry3D) { if(aGeometry3D!=NULL) { ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); SlicedGeometry3D::Pointer slicedGeometry = dynamic_cast(aGeometry3D); if(slicedGeometry.IsNull()) { Geometry2D* geometry2d = dynamic_cast(aGeometry3D); if(geometry2d!=NULL) { if((GetSlicedGeometry()->GetGeometry2D(0)==geometry2d) && (GetSlicedGeometry()->GetSlices()==1)) return; slicedGeometry = SlicedGeometry3D::New(); slicedGeometry->InitializeEvenlySpaced(geometry2d, 1); } else { slicedGeometry = SlicedGeometry3D::New(); PlaneGeometry::Pointer planeGeometry = PlaneGeometry::New(); planeGeometry->InitializeStandardPlane(aGeometry3D); slicedGeometry->InitializeEvenlySpaced(planeGeometry, (unsigned int)(aGeometry3D->GetExtent(2))); } } assert(slicedGeometry.IsNotNull()); timeGeometry->Initialize(slicedGeometry, 1); Superclass::SetTimeGeometry(timeGeometry); } else { if(GetGeometry()==NULL) return; Superclass::SetGeometry(NULL); } } void mitk::SlicedData::SetSpacing(const float aSpacing[3]) { this->SetSpacing((mitk::Vector3D)aSpacing); } void mitk::SlicedData::SetOrigin(const mitk::Point3D& origin) { TimeGeometry* timeGeometry = GetTimeGeometry(); assert(timeGeometry!=NULL); mitk::SlicedGeometry3D* slicedGeometry; unsigned int steps = timeGeometry->GetNumberOfTimeSteps(); for(unsigned int timestep = 0; timestep < steps; ++timestep) { slicedGeometry = GetSlicedGeometry(timestep); if(slicedGeometry != NULL) { slicedGeometry->SetOrigin(origin); if(slicedGeometry->GetEvenlySpaced()) { mitk::Geometry2D* geometry2D = slicedGeometry->GetGeometry2D(0); geometry2D->SetOrigin(origin); slicedGeometry->InitializeEvenlySpaced(geometry2D, slicedGeometry->GetSlices()); } } //ProportionalTimeGeometry* timeGeometry = dynamic_cast(GetTimeGeometry()); //if(timeGeometry != NULL) //{ // timeGeometry->Initialize(slicedGeometry, steps); // break; //} } } void mitk::SlicedData::SetSpacing(mitk::Vector3D aSpacing) { TimeGeometry* timeGeometry = GetTimeGeometry(); assert(timeGeometry!=NULL); mitk::SlicedGeometry3D* slicedGeometry; unsigned int steps = timeGeometry->GetNumberOfTimeSteps(); for(unsigned int timestep = 0; timestep < steps; ++timestep) { slicedGeometry = GetSlicedGeometry(timestep); if(slicedGeometry != NULL) { slicedGeometry->SetSpacing(aSpacing); } } timeGeometry->Update(); } diff --git a/Core/Code/DataManagement/mitkTimeGeometry.cpp b/Core/Code/DataManagement/mitkTimeGeometry.cpp index 6f97b31e30..69b3e96729 100644 --- a/Core/Code/DataManagement/mitkTimeGeometry.cpp +++ b/Core/Code/DataManagement/mitkTimeGeometry.cpp @@ -1,166 +1,166 @@ /*=================================================================== 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 mitk::TimeGeometry::TimeGeometry() : m_BoundingBox(BoundingBox::New()) { typedef BoundingBox::PointsContainer ContainerType; ContainerType::Pointer points = ContainerType::New(); m_BoundingBox->SetPoints(points.GetPointer()); } mitk::TimeGeometry::~TimeGeometry() { } void mitk::TimeGeometry::Initialize() { } /* \brief short description * parameters * */ mitk::Point3D mitk::TimeGeometry::GetCornerPointInWorld(int id) const { assert(id >= 0); assert(m_BoundingBox.IsNotNull()); BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds(); Point3D cornerpoint; switch(id) { case 0: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[4]); break; case 1: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[5]); break; case 2: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[4]); break; case 3: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[5]); break; case 4: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[4]); break; case 5: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[5]); break; case 6: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[4]); break; case 7: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[5]); break; default: { itkExceptionMacro(<<"A cube only has 8 corners. These are labeled 0-7."); return Point3D(); } } // TimeGeometry has no Transformation. Therefore the bounding box // contains all data in world coordinates return cornerpoint; } mitk::Point3D mitk::TimeGeometry::GetCornerPointInWorld(bool xFront, bool yFront, bool zFront) const { assert(m_BoundingBox.IsNotNull()); BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds(); Point3D cornerpoint; cornerpoint[0] = (xFront ? bounds[0] : bounds[1]); cornerpoint[1] = (yFront ? bounds[2] : bounds[3]); cornerpoint[2] = (zFront ? bounds[4] : bounds[5]); return cornerpoint; } mitk::Point3D mitk::TimeGeometry::GetCenterInWorld() const { assert(m_BoundingBox.IsNotNull()); return m_BoundingBox->GetCenter(); } double mitk::TimeGeometry::GetDiagonalLength2InWorld() const { Vector3D diagonalvector = GetCornerPointInWorld()-GetCornerPointInWorld(false, false, false); return diagonalvector.GetSquaredNorm(); } double mitk::TimeGeometry::GetDiagonalLengthInWorld() const { return sqrt(GetDiagonalLength2InWorld()); } bool mitk::TimeGeometry::IsWorldPointInside(const mitk::Point3D& p) const { return m_BoundingBox->IsInside(p); } void mitk::TimeGeometry::UpdateBoundingBox () { assert(m_BoundingBox.IsNotNull()); typedef BoundingBox::PointsContainer ContainerType; unsigned long lastModifiedTime = 0; unsigned long currentModifiedTime = 0; ContainerType::Pointer points = ContainerType::New(); points->reserve(2*GetNumberOfTimeSteps()); for (TimeStepType step = 0; step GetMTime(); if (currentModifiedTime > lastModifiedTime) lastModifiedTime = currentModifiedTime; Point3D minimum = GetGeometryForTimeStep(step)->GetCornerPoint(false,false,false); Point3D maximum = GetGeometryForTimeStep(step)->GetCornerPoint(true,true,true); points->push_back(minimum); points->push_back(maximum); } m_BoundingBox->SetPoints(points); m_BoundingBox->ComputeBoundingBox(); if (this->GetMTime() < lastModifiedTime) this->Modified(); } mitk::ScalarType mitk::TimeGeometry::GetExtentInWorld (unsigned int direction) const { assert(direction < 3); assert(m_BoundingBox.IsNotNull()); BoundingBox::BoundsArrayType bounds = m_BoundingBox->GetBounds(); return bounds[direction * 2 + 1] - bounds[direction * 2]; } void mitk::TimeGeometry::Update() { this->UpdateBoundingBox(); this->UpdateWithoutBoundingBox(); } void mitk::TimeGeometry::ExecuteOperation(mitk::Operation* op) { for (TimeStepType step = 0; step < GetNumberOfTimeSteps(); ++step) { GetGeometryForTimeStep(step)->ExecuteOperation(op); } } void mitk::TimeGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const { //Superclass::PrintSelf(os,indent); os << indent << " TimeSteps: " << this->GetNumberOfTimeSteps() << std::endl; os << std::endl; os << indent << " GetGeometryForTimeStep(0): "; - if(GetGeometryForTimeStep(0)==NULL) + if(GetGeometryForTimeStep(0).IsNull()) os << "NULL" << std::endl; else GetGeometryForTimeStep(0)->Print(os, indent); } diff --git a/Core/Code/DataManagement/mitkTimeGeometry.h b/Core/Code/DataManagement/mitkTimeGeometry.h index 4afadbaa72..9a80384646 100644 --- a/Core/Code/DataManagement/mitkTimeGeometry.h +++ b/Core/Code/DataManagement/mitkTimeGeometry.h @@ -1,291 +1,296 @@ /*=================================================================== 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 TimeGeometry_h #define TimeGeometry_h //ITK #include #include #include //MITK #include #include #include "mitkOperationActor.h" #include "mitkVector.h" // To be replaced #include // STL #include namespace mitk { + /** + * \deprecatedSince{2013_09} GlobalInteraction is deprecated. It is replaced by mitk::Dispatcher. + * Please use the new implementation described in \see DataInteractionPage . + */ + typedef float TimePointType; typedef std::size_t TimeStepType; /** * \brief Manages the geometries of a data object for each time step * * This class is an abstract class. The concrete implementation * depends on the way the different time steps are managed. * * The time is defined either by a time step or a time point. Time steps * are non-negativ integers starting from 0. A time point is is an float value * which gives the passed time since start in ms. Be aware that the starting * point is not fixed so it is possible that the same time point defines two * different time depending on the start time of the used time geometry. * * \addtogroup geometry */ class MITK_CORE_EXPORT TimeGeometry : public itk::Object, public OperationActor { protected: TimeGeometry(); virtual ~TimeGeometry(); /** * \brief Contains a bounding box which includes all time steps */ BoundingBox::Pointer m_BoundingBox; public: mitkClassMacro(TimeGeometry, itk::Object); itkCloneMacro(Self); /** * \brief Returns the number of time steps. * * Returns the number of time steps for which * geometries are saved. The number of time steps * is also the upper bound of the time steps. The * minimum time steps is always 0. */ virtual TimeStepType GetNumberOfTimeSteps() const = 0; /** * \brief Returns the first time point for which the object is valid. * * Returns the first valid time point for this geometry. If only one * time steps available it usually goes from -max to +max. The time point * is given in ms. */ virtual TimePointType GetMinimumTimePoint () const = 0; /** * \brief Returns the last time point for which the object is valid * * Gives the last time point for which a valid geometrie is saved in * this time geometry. The time point is given in ms. */ virtual TimePointType GetMaximumTimePoint () const = 0; /** * \brief Get the time bounds (in ms) */ virtual TimeBounds GetTimeBounds( ) const = 0; /** * \brief Tests if a given time point is covered by this object * * Returns true if a geometry can be returned for the given time * point and falls if not. The time point must be given in ms. */ virtual bool IsValidTimePoint (TimePointType timePoint) const = 0; /** * \brief Test for the given time step if a geometry is availible * * Returns true if a geometry is defined for the given time step. * Otherwise false is returned. * The time step is defined as positiv number. */ virtual bool IsValidTimeStep (TimeStepType timeStep) const = 0; /** * \brief Converts a time step to a time point * * Converts a time step to a time point in a way that * the new time point indicates the same geometry as the time step. * If the original time steps does not point to a valid geometry, * a time point is calculated that also does not point to a valid * geometry, but no exception is raised. */ virtual TimePointType TimeStepToTimePoint (TimeStepType timeStep) const = 0; /** * \brief Converts a time point to the corresponding time step * * Converts a time point to a time step in a way that * the new time step indicates the same geometry as the time point. * If a negativ invalid time point is given always time step 0 is * returned. If an positiv invalid time step is given an invalid * time step will be returned. */ virtual TimeStepType TimePointToTimeStep (TimePointType timePoint) const = 0; /** * \brief Returns the geometry of a specific time point * * Returns the geometry which defines the given time point. If * the given time point is invalid an null-pointer is returned. * * The pointer to the returned geometry may point to the saved * geometry but this is not necessarily the case. So a change to * the returned geometry may or may not afflict the geometry for the * time point or all time points depending on the used implementation * of TimeGeometry. */ - virtual Geometry3D* GetGeometryForTimePoint ( TimePointType timePoint) const = 0; + virtual Geometry3D::Pointer GetGeometryForTimePoint ( TimePointType timePoint) const = 0; /** * \brief Returns the geometry which corresponds to the given time step * * Returns the geometry which defines the given time step. If * the given time step is invalid an null-pointer is returned. * * The pointer to the returned geometry may point to the saved * geometry but this is not necessarily the case. So a change to * the returned geometry may or may not afflict the geometry for the * time step or all time steps depending on the used implementation * of TimeGeometry. */ - virtual Geometry3D* GetGeometryForTimeStep ( TimeStepType timeStep) const = 0; + virtual Geometry3D::Pointer GetGeometryForTimeStep ( TimeStepType timeStep) const = 0; /** * \brief Returns a clone of the geometry of a specific time point * * If an invalid time step is given (e.g. no geometry is defined for this time step) * a null-pointer will be returned. */ virtual Geometry3D::Pointer GetGeometryCloneForTimeStep( TimeStepType timeStep) const = 0; /** * \brief Sets the geometry for a given time step * * Sets the geometry for the given time steps. This may also afflects other * time steps, depending on the implementation of TimeGeometry. */ virtual void SetTimeStepGeometry(Geometry3D* geometry, TimeStepType timeStep) = 0; /** * \brief Expands to the given number of time steps * * Expands to the given number of time steps. Each new created time * step is filled with an empty geometry. * Shrinking is not supported! */ virtual void Expand(TimeStepType size) = 0; /** * \brief Tests if all necessary informations are set and the object is valid */ - virtual bool IsValid () = 0; + virtual bool IsValid () const = 0; /** * \brief Get the position of the corner number \a id (in world coordinates) * * See SetImageGeometry for how a corner is defined on images. */ Point3D GetCornerPointInWorld(int id) const; /** * \brief Get the position of a corner (in world coordinates) * * See SetImageGeometry for how a corner is defined on images. */ Point3D GetCornerPointInWorld(bool xFront=true, bool yFront=true, bool zFront=true) const; /** * \brief Get the center of the bounding-box in mm */ Point3D GetCenterInWorld() const; /** * \brief Get the squared length of the diagonal of the bounding-box in mm */ double GetDiagonalLength2InWorld() const; /** * \brief Get the length of the diagonal of the bounding-box in mm */ double GetDiagonalLengthInWorld() const; /** * \brief Test whether the point \a p (world coordinates in mm) is inside the bounding box */ bool IsWorldPointInside(const mitk::Point3D& p) const; /** * \brief Updates the bounding box to cover the area used in all time steps * * The bounding box is updated by this method. The new bounding box * covers an area which includes all bounding boxes during * all times steps. */ void UpdateBoundingBox(); /** * \brief Returns a bounding box that covers all time steps */ BoundingBox* GetBoundingBoxInWorld() const { return m_BoundingBox; } /** * \brief Returns the world bounds of the object that cover all time steps */ BoundingBox::BoundsArrayType GetBoundsInWorld() const { return m_BoundingBox->GetBounds(); } /** * \brief Returns the Extend of the bounding in the given direction */ ScalarType GetExtentInWorld (unsigned int direction) const; /** * \brief Makes a deep copy of the current object */ virtual itk::LightObject::Pointer InternalClone () const = 0 ; /** * \brief Initializes the TimeGeometry */ virtual void Initialize(); /** * \brief Updates the geometry */ void Update(); /** * \brief Updates everything except the Bounding box * * This class should be overwritten by child classes. * The method is called when Update() is required. */ virtual void UpdateWithoutBoundingBox() {}; /** * \brief Executes the given operation on all time steps */ virtual void ExecuteOperation(Operation *op); virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; }; // end class TimeGeometry } // end namespace MITK #endif // TimeGeometry_h \ No newline at end of file diff --git a/Core/Code/Rendering/mitkBaseRenderer.cpp b/Core/Code/Rendering/mitkBaseRenderer.cpp index bfee58e066..b68517c242 100644 --- a/Core/Code/Rendering/mitkBaseRenderer.cpp +++ b/Core/Code/Rendering/mitkBaseRenderer.cpp @@ -1,848 +1,848 @@ /*=================================================================== 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 "mitkBaseRenderer.h" #include "mitkMapper.h" #include "mitkResliceMethodProperty.h" #include "mitkKeyEvent.h" // Geometries #include "mitkPlaneGeometry.h" #include "mitkSlicedGeometry3D.h" // Controllers #include "mitkCameraController.h" #include "mitkSliceNavigationController.h" #include "mitkCameraRotationController.h" #include "mitkVtkInteractorCameraController.h" #ifdef MITK_USE_TD_MOUSE #include "mitkTDMouseVtkCameraController.h" #else #include "mitkCameraController.h" #endif #include "mitkVtkLayerController.h" // Events // TODO: INTERACTION_LEGACY #include "mitkEventMapper.h" #include "mitkGlobalInteraction.h" #include "mitkPositionEvent.h" #include "mitkDisplayPositionEvent.h" #include "mitkProperties.h" #include "mitkWeakPointerProperty.h" #include "mitkInteractionConst.h" // VTK #include #include #include #include #include #include #include mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap; mitk::BaseRenderer* mitk::BaseRenderer::GetInstance(vtkRenderWindow * renWin) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).first == renWin) return (*mapit).second; } return NULL; } void mitk::BaseRenderer::AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer) { if (renWin == NULL || baseRenderer == NULL) return; // ensure that no BaseRenderer is managed twice mitk::BaseRenderer::RemoveInstance(renWin); baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer)); } void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow* renWin) { BaseRendererMapType::iterator mapit = baseRendererMap.find(renWin); if (mapit != baseRendererMap.end()) baseRendererMap.erase(mapit); } mitk::BaseRenderer* mitk::BaseRenderer::GetByName(const std::string& name) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).second->m_Name == name) return (*mapit).second; } return NULL; } vtkRenderWindow* mitk::BaseRenderer::GetRenderWindowByName(const std::string& name) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).second->m_Name == name) return (*mapit).first; } return NULL; } mitk::BaseRenderer::BaseRenderer(const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm) : m_RenderWindow(NULL), m_VtkRenderer(NULL), m_MapperID(defaultMapper), m_DataStorage(NULL), m_RenderingManager(rm), m_LastUpdateTime(0), m_CameraController( NULL), m_SliceNavigationController(NULL), m_CameraRotationController(NULL), /*m_Size(),*/ m_Focused(false), m_WorldGeometry(NULL), m_TimeWorldGeometry(NULL), m_CurrentWorldGeometry(NULL), m_CurrentWorldGeometry2D(NULL), m_DisplayGeometry( NULL), m_Slice(0), m_TimeStep(), m_CurrentWorldGeometry2DUpdateTime(), m_DisplayGeometryUpdateTime(), m_TimeStepUpdateTime(), m_WorldGeometryData( NULL), m_DisplayGeometryData(NULL), m_CurrentWorldGeometry2DData(NULL), m_WorldGeometryNode(NULL), m_DisplayGeometryNode(NULL), m_CurrentWorldGeometry2DNode( NULL), m_DisplayGeometryTransformTime(0), m_CurrentWorldGeometry2DTransformTime(0), m_Name(name), /*m_Bounds(),*/m_EmptyWorldGeometry( true), m_DepthPeelingEnabled(true), m_MaxNumberOfPeels(100), m_NumberOfVisibleLODEnabledMappers(0) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; if (name != NULL) { m_Name = name; } else { m_Name = "unnamed renderer"; itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name."); } if (renWin != NULL) { m_RenderWindow = renWin; m_RenderWindow->Register(NULL); } else { itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present."); } m_Size[0] = 0; m_Size[1] = 0; //instances.insert( this ); //adding this BaseRenderer to the List of all BaseRenderer // TODO: INTERACTION_LEGACY m_RenderingManager->GetGlobalInteraction()->AddFocusElement(this); m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor(); WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object*) this); m_CurrentWorldGeometry2D = mitk::PlaneGeometry::New(); m_CurrentWorldGeometry2DData = mitk::Geometry2DData::New(); m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D); m_CurrentWorldGeometry2DNode = mitk::DataNode::New(); m_CurrentWorldGeometry2DNode->SetData(m_CurrentWorldGeometry2DData); m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000)); m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New()); m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1)); m_CurrentWorldGeometry2DTransformTime = m_CurrentWorldGeometry2DNode->GetVtkTransform()->GetMTime(); m_DisplayGeometry = mitk::DisplayGeometry::New(); m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D); m_DisplayGeometryData = mitk::Geometry2DData::New(); m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry); m_DisplayGeometryNode = mitk::DataNode::New(); m_DisplayGeometryNode->SetData(m_DisplayGeometryData); m_DisplayGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_DisplayGeometryTransformTime = m_DisplayGeometryNode->GetVtkTransform()->GetMTime(); mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::SliceNavigationController::New("navigation"); sliceNavigationController->SetRenderer(this); sliceNavigationController->ConnectGeometrySliceEvent(this); sliceNavigationController->ConnectGeometryUpdateEvent(this); sliceNavigationController->ConnectGeometryTimeEvent(this, false); m_SliceNavigationController = sliceNavigationController; m_CameraRotationController = mitk::CameraRotationController::New(); m_CameraRotationController->SetRenderWindow(m_RenderWindow); m_CameraRotationController->AcquireCamera(); //if TD Mouse Interaction is activated, then call TDMouseVtkCameraController instead of VtkInteractorCameraController #ifdef MITK_USE_TD_MOUSE m_CameraController = mitk::TDMouseVtkCameraController::New(); #else m_CameraController = mitk::CameraController::New(NULL); #endif m_VtkRenderer = vtkRenderer::New(); if (mitk::VtkLayerController::GetInstance(m_RenderWindow) == NULL) { mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer); mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } else mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } mitk::BaseRenderer::~BaseRenderer() { if (m_VtkRenderer != NULL) { m_VtkRenderer->Delete(); m_VtkRenderer = NULL; } if (m_CameraController.IsNotNull()) m_CameraController->SetRenderer(NULL); m_RenderingManager->GetGlobalInteraction()->RemoveFocusElement(this); mitk::VtkLayerController::RemoveInstance(m_RenderWindow); RemoveAllLocalStorages(); m_DataStorage = NULL; if (m_BindDispatcherInteractor != NULL) { delete m_BindDispatcherInteractor; } if (m_RenderWindow != NULL) { m_RenderWindow->Delete(); m_RenderWindow = NULL; } } void mitk::BaseRenderer::RemoveAllLocalStorages() { this->InvokeEvent(mitk::BaseRenderer::RendererResetEvent()); std::list::iterator it; for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); it++) (*it)->ClearLocalStorage(this, false); m_RegisteredLocalStorageHandlers.clear(); } void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.push_back(lsh); } mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const { return m_BindDispatcherInteractor->GetDispatcher(); } mitk::Point3D mitk::BaseRenderer::Map2DRendererPositionTo3DWorldPosition(Point2D* mousePosition) const { Point2D p_mm; Point3D position; if (m_MapperID == 1) { GetDisplayGeometry()->ULDisplayToDisplay(*mousePosition, *mousePosition); GetDisplayGeometry()->DisplayToWorld(*mousePosition, p_mm); GetDisplayGeometry()->Map(p_mm, position); } else if (m_MapperID == 2) { GetDisplayGeometry()->ULDisplayToDisplay(*mousePosition, *mousePosition); PickWorldPoint(*mousePosition, position); } return position; } void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.remove(lsh); } void mitk::BaseRenderer::SetDataStorage(DataStorage* storage) { if (storage != NULL) { m_DataStorage = storage; m_BindDispatcherInteractor->SetDataStorage(m_DataStorage); this->Modified(); } } const mitk::BaseRenderer::MapperSlotId mitk::BaseRenderer::defaultMapper = 1; void mitk::BaseRenderer::Paint() { } void mitk::BaseRenderer::Initialize() { } void mitk::BaseRenderer::Resize(int w, int h) { m_Size[0] = w; m_Size[1] = h; if (m_CameraController) m_CameraController->Resize(w, h); //(formerly problematic on windows: vtkSizeBug) GetDisplayGeometry()->SetSizeInDisplayUnits(w, h); } void mitk::BaseRenderer::InitRenderer(vtkRenderWindow* renderwindow) { if (m_RenderWindow != NULL) { m_RenderWindow->Delete(); } m_RenderWindow = renderwindow; if (m_RenderWindow != NULL) { m_RenderWindow->Register(NULL); } RemoveAllLocalStorages(); if (m_CameraController.IsNotNull()) { m_CameraController->SetRenderer(this); } //BUG (#1551) added settings for depth peeling m_RenderWindow->SetAlphaBitPlanes(1); m_VtkRenderer->SetUseDepthPeeling(m_DepthPeelingEnabled); m_VtkRenderer->SetMaximumNumberOfPeels(m_MaxNumberOfPeels); m_VtkRenderer->SetOcclusionRatio(0.1); } void mitk::BaseRenderer::InitSize(int w, int h) { m_Size[0] = w; m_Size[1] = h; GetDisplayGeometry()->SetSizeInDisplayUnits(w, h, false); GetDisplayGeometry()->Fit(); } void mitk::BaseRenderer::SetSlice(unsigned int slice) { if (m_Slice != slice) { m_Slice = slice; if (m_TimeWorldGeometry.IsNotNull()) { - SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeWorldGeometry->GetGeometryForTimeStep(m_TimeStep)); + SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeWorldGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); if (slicedWorldGeometry != NULL) { if (m_Slice >= slicedWorldGeometry->GetSlices()) m_Slice = slicedWorldGeometry->GetSlices() - 1; SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) { if (m_TimeStep != timeStep) { m_TimeStep = timeStep; m_TimeStepUpdateTime.Modified(); if (m_TimeWorldGeometry.IsNotNull()) { if (m_TimeStep >= m_TimeWorldGeometry->GetNumberOfTimeSteps()) m_TimeStep = m_TimeWorldGeometry->GetNumberOfTimeSteps() - 1; - SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeWorldGeometry->GetGeometryForTimeStep(m_TimeStep)); + SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeWorldGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); if (slicedWorldGeometry != NULL) { SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } int mitk::BaseRenderer::GetTimeStep(const mitk::BaseData* data) const { if ((data == NULL) || (data->IsInitialized() == false)) { return -1; } return data->GetTimeGeometry()->TimePointToTimeStep(GetTime()); } mitk::ScalarType mitk::BaseRenderer::GetTime() const { if (m_TimeWorldGeometry.IsNull()) { return 0; } else { ScalarType timeInMS = m_TimeWorldGeometry->TimeStepToTimePoint(GetTimeStep()); if (timeInMS == ScalarTypeNumericTraits::NonpositiveMin()) return 0; else return timeInMS; } } void mitk::BaseRenderer::SetWorldTimeGeometry(mitk::TimeGeometry* geometry) { assert(geometry != NULL); itkDebugMacro("setting WorldTimeGeometry to " << geometry); if (m_TimeWorldGeometry != geometry) { if (geometry->GetBoundingBoxInWorld()->GetDiagonalLength2() == 0) return; m_TimeWorldGeometry = geometry; itkDebugMacro("setting TimeWorldGeometry to " << m_TimeWorldGeometry); if (m_TimeStep >= m_TimeWorldGeometry->GetNumberOfTimeSteps()) m_TimeStep = m_TimeWorldGeometry->GetNumberOfTimeSteps() - 1; Geometry3D* geometry3d; geometry3d = m_TimeWorldGeometry->GetGeometryForTimeStep(m_TimeStep); SetWorldGeometry3D(geometry3d); } } void mitk::BaseRenderer::SetWorldGeometry3D(mitk::Geometry3D* geometry) { itkDebugMacro("setting WorldGeometry3D to " << geometry); if (m_WorldGeometry != geometry) { if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0) return; m_WorldGeometry = geometry; SlicedGeometry3D* slicedWorldGeometry; slicedWorldGeometry = dynamic_cast(geometry); Geometry2D::Pointer geometry2d; if (slicedWorldGeometry != NULL) { if (m_Slice >= slicedWorldGeometry->GetSlices() && (m_Slice != 0)) m_Slice = slicedWorldGeometry->GetSlices() - 1; geometry2d = slicedWorldGeometry->GetGeometry2D(m_Slice); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->InitializeStandardPlane(slicedWorldGeometry); geometry2d = plane; } SetCurrentWorldGeometry(slicedWorldGeometry); } else { geometry2d = dynamic_cast(geometry); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = PlaneGeometry::New(); plane->InitializeStandardPlane(geometry); geometry2d = plane; } SetCurrentWorldGeometry(geometry); } SetCurrentWorldGeometry2D(geometry2d); // calls Modified() } if (m_CurrentWorldGeometry2D.IsNull()) itkWarningMacro("m_CurrentWorldGeometry2D is NULL"); } void mitk::BaseRenderer::SetDisplayGeometry(mitk::DisplayGeometry* geometry2d) { itkDebugMacro("setting DisplayGeometry to " << geometry2d); if (m_DisplayGeometry != geometry2d) { m_DisplayGeometry = geometry2d; m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry); m_DisplayGeometryUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SetCurrentWorldGeometry2D(mitk::Geometry2D* geometry2d) { if (m_CurrentWorldGeometry2D != geometry2d) { m_CurrentWorldGeometry2D = geometry2d; m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D); m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D); m_CurrentWorldGeometry2DUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SendUpdateSlice() { m_DisplayGeometryUpdateTime.Modified(); m_CurrentWorldGeometry2DUpdateTime.Modified(); } void mitk::BaseRenderer::SetCurrentWorldGeometry(mitk::Geometry3D* geometry) { m_CurrentWorldGeometry = geometry; if (geometry == NULL) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; m_EmptyWorldGeometry = true; return; } BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(NULL); const BoundingBox::BoundsArrayType& worldBounds = boundingBox->GetBounds(); m_Bounds[0] = worldBounds[0]; m_Bounds[1] = worldBounds[1]; m_Bounds[2] = worldBounds[2]; m_Bounds[3] = worldBounds[3]; m_Bounds[4] = worldBounds[4]; m_Bounds[5] = worldBounds[5]; if (boundingBox->GetDiagonalLength2() <= mitk::eps) m_EmptyWorldGeometry = true; else m_EmptyWorldGeometry = false; } void mitk::BaseRenderer::SetGeometry(const itk::EventObject & geometrySendEvent) { const SliceNavigationController::GeometrySendEvent* sendEvent = dynamic_cast(&geometrySendEvent); assert(sendEvent!=NULL); SetWorldTimeGeometry(sendEvent->GetTimeGeometry()); } void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject & geometryUpdateEvent) { const SliceNavigationController::GeometryUpdateEvent* updateEvent = dynamic_cast(&geometryUpdateEvent); if (updateEvent == NULL) return; if (m_CurrentWorldGeometry.IsNotNull()) { SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); if (slicedWorldGeometry) { Geometry2D* geometry2D = slicedWorldGeometry->GetGeometry2D(m_Slice); SetCurrentWorldGeometry2D(geometry2D); // calls Modified() } } } void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject & geometrySliceEvent) { const SliceNavigationController::GeometrySliceEvent* sliceEvent = dynamic_cast(&geometrySliceEvent); assert(sliceEvent!=NULL); SetSlice(sliceEvent->GetPos()); } void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject & geometryTimeEvent) { const SliceNavigationController::GeometryTimeEvent * timeEvent = dynamic_cast(&geometryTimeEvent); assert(timeEvent!=NULL); SetTimeStep(timeEvent->GetPos()); } const double* mitk::BaseRenderer::GetBounds() const { return m_Bounds; } void mitk::BaseRenderer::MousePressEvent(mitk::MouseEvent *me) { //set the Focus on the renderer /*bool success =*/m_RenderingManager->GetGlobalInteraction()->SetFocus(this); /* if (! success) mitk::StatusBar::GetInstance()->DisplayText("Warning! from mitkBaseRenderer.cpp: Couldn't focus this BaseRenderer!"); */ //if (m_CameraController) //{ // if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MousePressEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID > 1) //==2 for 3D and ==5 for stencil { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::MouseReleaseEvent(mitk::MouseEvent *me) { //if (m_CameraController) //{ // if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MouseReleaseEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::MouseMoveEvent(mitk::MouseEvent *me) { //if (m_CameraController) //{ // if((me->GetButtonState()<=512) || (me->GetButtonState()>=516))// provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MouseMoveEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::PickWorldPoint(const mitk::Point2D& displayPoint, mitk::Point3D& worldPoint) const { mitk::Point2D worldPoint2D; GetDisplayGeometry()->DisplayToWorld(displayPoint, worldPoint2D); GetDisplayGeometry()->Map(worldPoint2D, worldPoint); } void mitk::BaseRenderer::WheelEvent(mitk::WheelEvent * we) { if (m_MapperID == 1) { Point2D p(we->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, we->GetType(), we->GetButton(), we->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction()); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(we->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); we->SetDisplayPosition(p); mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::KeyPressEvent(mitk::KeyEvent *ke) { if (m_MapperID == 1) { Point2D p(ke->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::KeyEvent event(this, ke->GetType(), ke->GetButton(), ke->GetButtonState(), ke->GetKey(), ke->GetText(), p); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(ke->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); ke->SetDisplayPosition(p); mitk::EventMapper::MapEvent(ke, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D& itkNotUsed(p2d)) { MITK_INFO<<"BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer."<RequestUpdate(this->m_RenderWindow); } void mitk::BaseRenderer::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow); } unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const { return m_NumberOfVisibleLODEnabledMappers; } mitk::RenderingManager* mitk::BaseRenderer::GetRenderingManager() const { return m_RenderingManager.GetPointer(); } /*! Sets the new Navigation controller */ void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController) { if (SlicenavigationController == NULL) return; //disconnect old from globalinteraction m_RenderingManager->GetGlobalInteraction()->RemoveListener(SlicenavigationController); //copy worldgeometry SlicenavigationController->SetInputWorldTimeGeometry(SlicenavigationController->GetCreatedWorldGeometry()); SlicenavigationController->Update(); //set new m_SliceNavigationController = SlicenavigationController; m_SliceNavigationController->SetRenderer(this); if (m_SliceNavigationController.IsNotNull()) { m_SliceNavigationController->ConnectGeometrySliceEvent(this); m_SliceNavigationController->ConnectGeometryUpdateEvent(this); m_SliceNavigationController->ConnectGeometryTimeEvent(this, false); } } /*! Sets the new camera controller and deletes the vtkRenderWindowInteractor in case of the VTKInteractorCameraController */ void mitk::BaseRenderer::SetCameraController(CameraController* cameraController) { mitk::VtkInteractorCameraController::Pointer vtkInteractorCameraController = dynamic_cast(cameraController); if (vtkInteractorCameraController.IsNotNull()) MITK_INFO<<"!!!WARNING!!!: RenderWindow interaction events are no longer handled via CameraController (See Bug #954)."<SetRenderer(NULL); m_CameraController = NULL; m_CameraController = cameraController; m_CameraController->SetRenderer(this); } void mitk::BaseRenderer::PrintSelf(std::ostream& os, itk::Indent indent) const { os << indent << " MapperID: " << m_MapperID << std::endl; os << indent << " Slice: " << m_Slice << std::endl; os << indent << " TimeStep: " << m_TimeStep << std::endl; os << indent << " WorldGeometry: "; if (m_WorldGeometry.IsNull()) os << "NULL" << std::endl; else m_WorldGeometry->Print(os, indent); os << indent << " CurrentWorldGeometry2D: "; if (m_CurrentWorldGeometry2D.IsNull()) os << "NULL" << std::endl; else m_CurrentWorldGeometry2D->Print(os, indent); os << indent << " CurrentWorldGeometry2DUpdateTime: " << m_CurrentWorldGeometry2DUpdateTime << std::endl; os << indent << " CurrentWorldGeometry2DTransformTime: " << m_CurrentWorldGeometry2DTransformTime << std::endl; os << indent << " DisplayGeometry: "; if (m_DisplayGeometry.IsNull()) os << "NULL" << std::endl; else m_DisplayGeometry->Print(os, indent); os << indent << " DisplayGeometryTransformTime: " << m_DisplayGeometryTransformTime << std::endl; Superclass::PrintSelf(os, indent); } void mitk::BaseRenderer::SetDepthPeelingEnabled(bool enabled) { m_DepthPeelingEnabled = enabled; m_VtkRenderer->SetUseDepthPeeling(enabled); } void mitk::BaseRenderer::SetMaxNumberOfPeels(int maxNumber) { m_MaxNumberOfPeels = maxNumber; m_VtkRenderer->SetMaximumNumberOfPeels(maxNumber); } diff --git a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp index abd24289dc..3274cb83d4 100644 --- a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp @@ -1,544 +1,544 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkSurfaceGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkSurface.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkVtkScalarModeProperty.h" #include "mitkAbstractTransformGeometry.h" #include "mitkLookupTableProperty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::SurfaceGLMapper2D::SurfaceGLMapper2D() : m_Plane( vtkPlane::New() ), m_Cutter( vtkCutter::New() ), m_LUT( vtkLookupTable::New() ), m_PointLocator( vtkPKdTree::New() ), m_Stripper( vtkStripper::New() ), m_DrawNormals(false), m_FrontNormalLengthInPixels(10.0), m_BackNormalLengthInPixels(10.0) { // default for normals on front side = green m_FrontSideColor[0] = 0.0; m_FrontSideColor[1] = 1.0; m_FrontSideColor[2] = 0.0; m_FrontSideColor[3] = 1.0; // default for normals on back side = red m_BackSideColor[0] = 1.0; m_BackSideColor[1] = 0.0; m_BackSideColor[2] = 0.0; m_BackSideColor[3] = 1.0; // default for line color = yellow m_LineColor[0] = 1.0; m_LineColor[1] = 1.0; m_LineColor[2] = 0.0; m_LineColor[3] = 1.0; m_Cutter->SetCutFunction(m_Plane); m_Cutter->GenerateValues(1,0,1); m_LUT->SetTableRange(0,255); m_LUT->SetNumberOfColors(255); m_LUT->SetRampToLinear(); m_LUT->Build(); } mitk::SurfaceGLMapper2D::~SurfaceGLMapper2D() { m_Plane->Delete(); m_Cutter->Delete(); m_LUT->Delete(); m_PointLocator->Delete(); m_Stripper->Delete(); } const mitk::Surface *mitk::SurfaceGLMapper2D::GetInput(void) { if(m_Surface.IsNotNull()) return m_Surface; return static_cast ( GetDataNode()->GetData() ); } void mitk::SurfaceGLMapper2D::SetDataNode( mitk::DataNode* node ) { Superclass::SetDataNode( node ); bool useCellData; if (dynamic_cast(node->GetProperty("deprecated useCellDataForColouring")) == NULL) useCellData = false; else useCellData = dynamic_cast(node->GetProperty("deprecated useCellDataForColouring"))->GetValue(); if (!useCellData) { // search min/max point scalars over all time steps vtkFloatingPointType dataRange[2] = {0,0}; vtkFloatingPointType range[2]; Surface::Pointer input = const_cast< Surface* >(dynamic_cast( this->GetDataNode()->GetData() )); if(input.IsNull()) return; const TimeGeometry::Pointer inputTimeGeometry = input->GetTimeGeometry(); if(( inputTimeGeometry.IsNull() ) || ( inputTimeGeometry->GetNumberOfTimeSteps() == 0 ) ) return; for (unsigned int timestep=0; timestepGetNumberOfTimeSteps(); timestep++) { vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep ); if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) continue; vtkDataArray *vpointscalars = vtkpolydata->GetPointData()->GetScalars(); if (vpointscalars) { vpointscalars->GetRange( range, 0 ); if (dataRange[0]==0 && dataRange[1]==0) { dataRange[0] = range[0]; dataRange[1] = range[1]; } else { if (range[0] < dataRange[0]) dataRange[0] = range[0]; if (range[1] > dataRange[1]) dataRange[1] = range[1]; } } } if (dataRange[1] - dataRange[0] > 0) { m_LUT->SetTableRange( dataRange ); m_LUT->Build(); } } } void mitk::SurfaceGLMapper2D::Paint(mitk::BaseRenderer * renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) return; Surface::Pointer input = const_cast(this->GetInput()); if(input.IsNull()) return; // // get the TimeGeometry of the input object // const TimeGeometry* inputTimeGeometry = input->GetTimeGeometry(); if(( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetNumberOfTimeSteps() == 0 ) ) return; if (dynamic_cast(this->GetDataNode()->GetProperty("line width")) == NULL) m_LineWidth = 1; else m_LineWidth = dynamic_cast(this->GetDataNode()->GetProperty("line width"))->GetValue(); // // get the world time // Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry.IsNotNull() ); ScalarType time = worldGeometry->GetTimeBounds()[ 0 ]; int timestep=0; if( time > ScalarTypeNumericTraits::NonpositiveMin() ) timestep = inputTimeGeometry->TimePointToTimeStep( time ); // int timestep = this->GetTimestep(); if( inputTimeGeometry->IsValidTimeStep( timestep ) == false ) return; vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep ); if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) return; PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast(worldGeometry.GetPointer()); //apply color and opacity read from the PropertyList this->ApplyAllProperties(renderer); if (m_DrawNormals) { m_PointLocator->SetDataSet( vtkpolydata ); m_PointLocator->BuildLocatorFromPoints( vtkpolydata->GetPoints() ); } if(vtkpolydata!=NULL) { Point3D point; Vector3D normal; //Check if Lookup-Table is already given, else use standard one. vtkFloatingPointType* scalarLimits = m_LUT->GetTableRange(); vtkFloatingPointType scalarsMin = scalarLimits[0], scalarsMax = scalarLimits[1]; vtkLookupTable *lut;// = vtkLookupTable::New(); LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull() ) { lut = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); // check if the scalar range has been changed, e.g. manually, for the data tree node, and rebuild the LUT if necessary. double* oldRange = lut->GetTableRange(); if( oldRange[0] != scalarsMin || oldRange[1] != scalarsMax ) { lut->SetTableRange(scalarsMin, scalarsMax); lut->Build(); } } else { lut = m_LUT; } vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(timestep); if(worldPlaneGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=worldPlaneGeometry->GetOrigin(); normal=worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform((vtkAbstractTransform*)NULL); } else { AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); if(worldAbstractGeometry.IsNotNull()) { - AbstractTransformGeometry::ConstPointer surfaceAbstractGeometry = dynamic_cast(input->GetTimeGeometry()->GetGeometryForTimeStep(0)); + AbstractTransformGeometry::ConstPointer surfaceAbstractGeometry = dynamic_cast(input->GetTimeGeometry()->GetGeometryForTimeStep(0).GetPointer()); if(surfaceAbstractGeometry.IsNotNull()) //@todo substitude by operator== after implementation, see bug id 28 { PaintCells(renderer, vtkpolydata, worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut); return; } else { //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "flat plane" into a "curved plane"? return; // set up vtkPlane according to worldGeometry point=const_cast(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum(); FillVector3D(normal, 0, 0, 1); m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse()); } } else return; } vtkFloatingPointType vp[3], vnormal[3]; vnl2vtk(point.GetVnlVector(), vp); vnl2vtk(normal.GetVnlVector(), vnormal); //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); inversetransform->TransformPoint(vp, vp); inversetransform->TransformNormalAtPoint(vp, vnormal, vnormal); m_Plane->SetOrigin(vp); m_Plane->SetNormal(vnormal); //set data into cutter m_Cutter->SetInput(vtkpolydata); m_Cutter->Update(); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); if (m_DrawNormals) { m_Stripper->SetInput( m_Cutter->GetOutput() ); // calculate the cut m_Stripper->Update(); PaintCells(renderer, m_Stripper->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata); } else { PaintCells(renderer, m_Cutter->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata); } } } void mitk::SurfaceGLMapper2D::PaintCells(mitk::BaseRenderer* renderer, vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform * vtktransform, vtkLookupTable *lut, vtkPolyData* original3DObject) { // deprecated settings bool usePointData = false; bool useCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", useCellData); bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); if(scalarVisibility) { VtkScalarModeProperty* scalarMode; if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) { if( (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA) || (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT) ) { usePointData = true; } if(scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA) { useCellData = true; } } else { usePointData = true; } } vtkPoints *vpoints = contour->GetPoints(); vtkDataArray *vpointscalars = contour->GetPointData()->GetScalars(); vtkCellArray *vlines = contour->GetLines(); vtkDataArray* vcellscalars = contour->GetCellData()->GetScalars(); Point3D p; Point2D p2d, last; int i, j; int numberOfLines = vlines->GetNumberOfCells(); glLineWidth( m_LineWidth ); glBegin (GL_LINES); glColor4fv(m_LineColor); double distanceSinceLastNormal(0.0); vlines->InitTraversal(); for(i=0;iGetNextCell(cellSize, cell); vpoints->GetPoint(cell[0], vp); //take transformation via vtktransform into account vtktransform->TransformPoint(vp, vp); vtk2itk(vp, p); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map(p, p2d); //convert point (until now mm and in world coordinates) to display coordinates (units ) displayGeometry->WorldToDisplay(p2d, p2d); last=p2d; for(j=1; jGetPoint(cell[j], vp); Point3D originalPoint; vtk2itk(vp, originalPoint); //take transformation via vtktransform into account vtktransform->TransformPoint(vp, vp); vtk2itk(vp, p); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map(p, p2d); //convert point (until now mm and in world coordinates) to display coordinates (units ) displayGeometry->WorldToDisplay(p2d, p2d); vtkFloatingPointType color[3]; if (useCellData && vcellscalars != NULL ) { // color each cell according to cell data lut->GetColor( vcellscalars->GetComponent(i,0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(last[0], last[1]); glVertex2f(p2d[0], p2d[1]); } else if (usePointData && vpointscalars != NULL ) { lut->GetColor( vpointscalars->GetComponent(cell[j-1],0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(last[0], last[1]); lut->GetColor( vpointscalars->GetComponent(cell[j],0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(p2d[0], p2d[1]); } else { glVertex2f(last[0], last[1]); glVertex2f(p2d[0], p2d[1]); // draw normals ? if (m_DrawNormals && original3DObject) { distanceSinceLastNormal += sqrt((p2d[0]-last[0])*(p2d[0]-last[0]) + (p2d[1]-last[1])*(p2d[1]-last[1])); if (distanceSinceLastNormal >= 5.0) { distanceSinceLastNormal = 0.0; vtkPointData* pointData = original3DObject->GetPointData(); if (!pointData) break; vtkDataArray* normalsArray = pointData->GetNormals(); if (!normalsArray) break; // find 3D point closest to the currently drawn point double distance(0.0); vtkIdType closestPointId = m_PointLocator->FindClosestPoint(originalPoint[0], originalPoint[1], originalPoint[2], distance); if (closestPointId >= 0) { // find normal of 3D object at this 3D point double* normal = normalsArray->GetTuple3(closestPointId); double transformedNormal[3]; vtktransform->TransformNormal(normal, transformedNormal); Vector3D normalITK; vtk2itk(transformedNormal, normalITK); normalITK.Normalize(); // calculate a point (point from the cut 3D object) + (normal vector of closest point) Point3D tip3D = p + normalITK; // map this point into our 2D coordinate system Point2D tip2D; worldGeometry->Map(tip3D, tip2D); displayGeometry->WorldToDisplay(tip2D, tip2D); // calculate 2D vector from point to point+normal, normalize it to standard length Vector2D tipVectorGLFront = tip2D - p2d; tipVectorGLFront.Normalize(); tipVectorGLFront *= m_FrontNormalLengthInPixels; Vector2D tipVectorGLBack = p2d - tip2D; tipVectorGLBack.Normalize(); tipVectorGLBack *= m_BackNormalLengthInPixels; Point2D tipPoint2D = p2d + tipVectorGLFront; Point2D backTipPoint2D = p2d + tipVectorGLBack; // draw normalized mapped normal vector glColor4f(m_BackSideColor[0], m_BackSideColor[1], m_BackSideColor[2], m_BackSideColor[3]); // red backside glVertex2f(p2d[0], p2d[1]); glVertex2f(tipPoint2D[0], tipPoint2D[1]); glColor4f(m_FrontSideColor[0], m_FrontSideColor[1], m_FrontSideColor[2], m_FrontSideColor[3]); // green backside glVertex2f(p2d[0], p2d[1]); glVertex2f(backTipPoint2D[0], backTipPoint2D[1]); glColor4fv(m_LineColor); // back to line color } } } } last=p2d; } } glEnd(); glLineWidth(1.0); } void mitk::SurfaceGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", IntProperty::New(2), renderer, overwrite ); node->AddProperty( "scalar mode", VtkScalarModeProperty::New(), renderer, overwrite ); node->AddProperty( "draw normals 2D", BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "invert normals", BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "front color", ColorProperty::New(0.0, 1.0, 0.0), renderer, overwrite ); node->AddProperty( "back color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite ); node->AddProperty( "front normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); node->AddProperty( "back normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); node->AddProperty( "layer", mitk::IntProperty::New(100), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::SurfaceGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) { ApplyColorAndOpacityProperties(renderer); DataNode * node = GetDataNode(); if(node == NULL) { return; } node->GetBoolProperty("draw normals 2D", m_DrawNormals, renderer); // check for color and opacity properties, use it for rendering if they exists node->GetColor(m_LineColor, renderer, "color"); node->GetOpacity(m_LineColor[3], renderer, "opacity"); bool invertNormals(false); node->GetBoolProperty("invert normals", invertNormals, renderer); if (!invertNormals) { node->GetColor(m_FrontSideColor, renderer, "front color"); node->GetOpacity(m_FrontSideColor[3], renderer, "opacity"); node->GetColor(m_BackSideColor, renderer, "back color"); node->GetOpacity(m_BackSideColor[3], renderer, "opacity"); node->GetFloatProperty( "front normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); node->GetFloatProperty( "back normal lenth (px)", m_BackNormalLengthInPixels, renderer ); } else { node->GetColor(m_FrontSideColor, renderer, "back color"); node->GetOpacity(m_FrontSideColor[3], renderer, "opacity"); node->GetColor(m_BackSideColor, renderer, "front color"); node->GetOpacity(m_BackSideColor[3], renderer, "opacity"); node->GetFloatProperty( "back normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); node->GetFloatProperty( "front normal lenth (px)", m_BackNormalLengthInPixels, renderer ); } } diff --git a/Core/Code/Testing/mitkTimeGeometryTest.cpp b/Core/Code/Testing/mitkTimeGeometryTest.cpp index c04cadc657..e32602f1ac 100644 --- a/Core/Code/Testing/mitkTimeGeometryTest.cpp +++ b/Core/Code/Testing/mitkTimeGeometryTest.cpp @@ -1,752 +1,774 @@ /*=================================================================== 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 "mitkTimeGeometry.h" #include "mitkGeometry3D.h" #include "mitkRotationOperation.h" #include "mitkInteractionConst.h" #include #include #include "mitkTestingMacros.h" #include #include #include #include "mitkImageGenerator.h" #include "mitkPointSet.h" #include class mitkTimeGeometryTestClass { public: void Translation_Image_MovedOrigin(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { // DimX, DimY, DimZ, mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::Geometry3D::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0); mitk::Point3D imageOrigin = geometry->GetOrigin(); mitk::Point3D expectedOrigin; expectedOrigin[0] = 0; expectedOrigin[1] = 0; expectedOrigin[2] = 0; MITK_TEST_CONDITION(mitk::Equal(imageOrigin, expectedOrigin), "Original origin match expected origin"); expectedOrigin[0] = 0.325; expectedOrigin[1] = 0.487; expectedOrigin[2] = 0.78; mitk::Vector3D translationVector; translationVector[0] = expectedOrigin[0]; translationVector[1] = expectedOrigin[1]; translationVector[2] = expectedOrigin[2]; for (mitk::TimeStepType timeStep = 0; timeStep < image->GetTimeGeometry()->GetNumberOfTimeSteps(); ++timeStep) { image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)->Translate(translationVector); } imageOrigin = image->GetGeometry(0)->GetOrigin(); MITK_TEST_CONDITION(mitk::Equal(imageOrigin, expectedOrigin), "Translated origin match expected origin"); expectedOrigin[0] = 2*translationVector[0]; expectedOrigin[1] = 2*translationVector[1]; expectedOrigin[2] = 2*translationVector[2]; for (mitk::TimeStepType timeStep = 0; timeStep < image->GetTimeGeometry()->GetNumberOfTimeSteps(); ++timeStep) { image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep)->Translate(translationVector); } imageOrigin = image->GetGeometry(0)->GetOrigin(); MITK_TEST_CONDITION(mitk::Equal(imageOrigin, expectedOrigin), "Translated origin match expected origin"); } void Rotate_Image_RotatedPoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); // DimX, DimY, DimZ, dataNode->SetData(baseData); ds->Add(dataNode); mitk::Geometry3D::Pointer geometry = baseData->GetTimeGeometry()->GetGeometryForTimeStep(0); mitk::Point3D expectedPoint; expectedPoint[0] = 3*0.5; expectedPoint[1] = 3*0.33; expectedPoint[2] = 3*0.78; mitk::Point3D originalPoint; originalPoint[0] = 3; originalPoint[1] = 3; originalPoint[2] = 3; mitk::Point3D worldPoint; geometry->IndexToWorld(originalPoint, worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Index-to-World without rotation as expected "); mitk::Point3D pointOfRotation; pointOfRotation[0] = 0; pointOfRotation[1] = 0; pointOfRotation[2] = 0; mitk::Vector3D vectorOfRotation; vectorOfRotation[0] = 1; vectorOfRotation[1] = 0.5; vectorOfRotation[2] = 0.2; float angleOfRotation = 73.0; mitk::RotationOperation* rotation = new mitk::RotationOperation(mitk::OpROTATE,pointOfRotation, vectorOfRotation, angleOfRotation); baseData->GetTimeGeometry()->ExecuteOperation(rotation); delete rotation; expectedPoint[0] = 2.6080379; expectedPoint[1] = -0.75265157; expectedPoint[2] = 1.1564401; baseData->GetGeometry(0)->IndexToWorld(originalPoint,worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Rotation returns expected values "); } void Scale_Image_ScaledPoint(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { // DimX, DimY, DimZ, mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::Geometry3D::Pointer geometry = image->GetTimeGeometry()->GetGeometryForTimeStep(0); mitk::Point3D expectedPoint; expectedPoint[0] = 3*0.5; expectedPoint[1] = 3*0.33; expectedPoint[2] = 3*0.78; mitk::Point3D originalPoint; originalPoint[0] = 3; originalPoint[1] = 3; originalPoint[2] = 3; mitk::Point3D worldPoint; geometry->IndexToWorld(originalPoint, worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Index-to-World with old Scaling as expected "); mitk::Vector3D newSpacing; newSpacing[0] = 2; newSpacing[1] = 1.254; newSpacing[2] = 0.224; image->SetSpacing(newSpacing); mitk::BaseData* base; expectedPoint[0] = 3*2; expectedPoint[1] = 3*1.254; expectedPoint[2] = 3*0.224; image->GetGeometry(0)->IndexToWorld(originalPoint,worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Index-toWorld with new Scaling returns expected values "); } void GetMinimumTimePoint_4DBaseData_Zero(mitk::BaseData* baseData, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimePointType expectedTimePoint = geometry->GetMinimumTimePoint(); MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, 0), "Returns correct minimum time point "); } void GetMaximumTimePoint_4DBaseData_DimT(mitk::BaseData* baseData, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimePointType expectedTimePoint = geometry->GetMaximumTimePoint(); MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, DimT), "Returns correct maximum time point "); } void GetNumberOfTimeSteps_Image_ReturnDimT(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimeStepType expectedTimeSteps = geometry->GetNumberOfTimeSteps(); MITK_TEST_CONDITION(mitk::Equal(expectedTimeSteps, DimT), "Returns correct number of time Steps "); } void GetMinimumTimePoint_3DImage_Min(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimePointType expectedTimePoint = geometry->GetMinimumTimePoint(); MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, -std::numeric_limits().max()), "Returns correct minimum time point "); } void GetMaximumTimePoint_3DImage_Max(mitk::BaseData* baseData,unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimePointType expectedTimePoint = geometry->GetMaximumTimePoint(); MITK_INFO << expectedTimePoint; MITK_INFO << std::numeric_limits().max(); MITK_TEST_CONDITION(mitk::Equal(expectedTimePoint, std::numeric_limits().max()), "Returns correct maximum time point "); } void GetTimeBounds_4DImage_ZeroAndDimT(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); mitk::TimeBounds expectedTimeBounds = geometry->GetTimeBounds(); MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[0], 0), "Returns correct minimum time point "); MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[1], DimT), "Returns correct maximum time point "); } void GetTimeBounds_3DImage_ZeroAndDimT(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimeBounds expectedTimeBounds = geometry->GetTimeBounds(); MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[0], -std::numeric_limits().max()), "Returns correct minimum time point "); MITK_TEST_CONDITION(mitk::Equal(expectedTimeBounds[1], std::numeric_limits().max()), "Returns correct maximum time point "); } void IsValidTimePoint_ImageValidTimePoint_True(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); bool isValid = geometry->IsValidTimePoint(DimT-1); MITK_TEST_CONDITION(mitk::Equal(isValid, true), "Is valid time Point correct minimum time point "); } void IsValidTimePoint_ImageNegativInvalidTimePoint_False(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); bool isValid = geometry->IsValidTimePoint(-DimT); MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point "); } void IsValidTimePoint_ImageInvalidTimePoint_False(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); bool isValid = geometry->IsValidTimePoint(DimT+1); MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point "); } void IsValidTimeStep_ImageValidTimeStep_True(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); bool isValid = geometry->IsValidTimeStep(DimT-1); MITK_TEST_CONDITION(mitk::Equal(isValid, true), "Is valid time Point correct minimum time point "); } void IsValidTimeStep_ImageNegativInvalidTimeStep_False(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); bool isValid = geometry->IsValidTimeStep(-DimT); MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point "); } void IsValidTimeStep_ImageInvalidTimeStep_False(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); bool isValid = geometry->IsValidTimeStep(DimT); MITK_TEST_CONDITION(mitk::Equal(isValid, false), "Is invalid time Point correct minimum time point "); } void TimeStepToTimePoint_ImageValidTimeStep_TimePoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimePointType timePoint= geometry->TimeStepToTimePoint(DimT-1); MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT-1), "Calculated right time Point for Time Step "); } void TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimePointType timePoint= geometry->TimeStepToTimePoint(DimT+1); MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT+1), "Calculated right time Point for invalid Time Step "); } void TimePointToTimeStep_ImageValidTimePoint_TimePoint(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::TimeStepType timePoint= geometry->TimePointToTimeStep(DimT-0.5); MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT-1), "Calculated right time step for valid time point"); } void TimePointToTimeStep_4DImageInvalidTimePoint_TimePoint(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); mitk::TimeStepType timePoint= geometry->TimePointToTimeStep(DimT+1.5); MITK_TEST_CONDITION(mitk::Equal(timePoint, DimT+1), "Calculated right time step for invalid time point"); } void TimePointToTimeStep_4DImageNegativInvalidTimePoint_TimePoint(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); mitk::TimePointType negativTimePoint = (-1.0*DimT) - 1.5; mitk::TimeStepType timePoint= geometry->TimePointToTimeStep(negativTimePoint); MITK_TEST_CONDITION(mitk::Equal(timePoint, 0), "Calculated right time step for negativ invalid time point"); } void GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(mitk::BaseData* baseData, float inputX, float inputY, float inputZ, float outputX, float outputY, float outputZ, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT-1); MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned"); mitk::Point3D expectedPoint; expectedPoint[0] = outputX; expectedPoint[1] = outputY; expectedPoint[2] = outputZ; mitk::Point3D originalPoint; originalPoint[0] = inputX; originalPoint[1] = inputY; originalPoint[2] = inputZ; mitk::Point3D worldPoint; geometry3D->IndexToWorld(originalPoint, worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Geometry transformation match expection. "); } void GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT+1); MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned"); } void GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(mitk::BaseData* baseData, float inputX, float inputY, float inputZ, float outputX, float outputY, float outputZ, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimePoint(DimT-0.5); MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned"); mitk::Point3D expectedPoint; expectedPoint[0] = outputX; expectedPoint[1] = outputY; expectedPoint[2] = outputZ; mitk::Point3D originalPoint; originalPoint[0] = inputX; originalPoint[1] = inputY; originalPoint[2] = inputZ; mitk::Point3D worldPoint; geometry3D->IndexToWorld(originalPoint, worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Geometry transformation match expection. "); } void GetGeometryForTimePoint_4DImageInvalidTimePoint_NullPointer(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimePoint(DimT+1); MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned with invalid time point"); } void GetGeometryForTimePoint_4DImageNEgativInvalidTimePoint_NullPointer(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); mitk::TimePointType timePoint = (-1.0*(DimT)) -1; mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimePoint(timePoint); MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned with invalid negativ time point"); } void GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(mitk::BaseData* baseData, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT-1); MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned"); mitk::Point3D expectedPoint; mitk::Point3D originalPoint; originalPoint[0] = 3; originalPoint[1] = 3; originalPoint[2] = 3; mitk::Point3D worldPoint; geometry3D->IndexToWorld(originalPoint, expectedPoint); mitk::Vector3D translationVector; translationVector[0] = 5; translationVector[1] = 8; translationVector[2] = 7; geometry3D->Translate(translationVector); geometry3D = geometry->GetGeometryForTimeStep(DimT-1); geometry3D->IndexToWorld(originalPoint, worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Geometry transformation not changed. "); } void GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(mitk::BaseData* baseData, unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT+1); MITK_TEST_CONDITION(geometry3D.IsNull(), "Null-Pointer geometry returned"); } void SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(mitk::BaseData* baseData, float scaleX, float scaleY, float scaleZ, unsigned int DimT) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryCloneForTimeStep(DimT-1); MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry returned"); mitk::Vector3D translationVector; translationVector[0] = 5; translationVector[1] = 8; translationVector[2] = 7; geometry3D->Translate(translationVector); geometry->SetTimeStepGeometry(geometry3D,DimT-1); mitk::Point3D expectedPoint; expectedPoint[0] = 3*scaleX+5; expectedPoint[1] = 3*scaleY+8; expectedPoint[2] = 3*scaleZ+7; mitk::Point3D originalPoint; originalPoint[0] = 3; originalPoint[1] = 3; originalPoint[2] = 3; mitk::Point3D worldPoint; geometry->GetGeometryForTimeStep(DimT-1)->IndexToWorld(originalPoint, worldPoint); MITK_TEST_CONDITION(mitk::Equal(worldPoint, expectedPoint), "Geometry transformation match expection. "); } void Expand_BaseDataDoubleSize_SizeChanged(mitk::BaseData* baseData, int DimT) { mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); MITK_TEST_CONDITION(geometry->GetNumberOfTimeSteps()==DimT, "Number of time Steps match expection. "); geometry->Expand(DimT * 2); MITK_TEST_CONDITION(geometry->GetNumberOfTimeSteps()==DimT*2, "Number of time Steps match expection. "); mitk::Geometry3D::Pointer geometry3D = geometry->GetGeometryForTimeStep(DimT*2 -1); MITK_TEST_CONDITION(geometry3D.IsNotNull(), "Non-zero geometry is generated. "); } void CheckBounds_BaseData_PointsAsExpected(mitk::BaseData* baseData, float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Point3D expectedPoint; expectedPoint[0] = minX; expectedPoint[1] = minY; expectedPoint[2] = minZ; mitk::Point3D point = geometry->GetCornerPointInWorld(0); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 0 as expected "); point = geometry->GetCornerPointInWorld(true,true,true); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 0 as expected "); point = geometry->GetCornerPointInWorld(1); expectedPoint[0] = minX; expectedPoint[1] = minY; expectedPoint[2] = maxZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "GBounding Point 1 as expected "); point = geometry->GetCornerPointInWorld(true,true,false); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 1 as expected "); point = geometry->GetCornerPointInWorld(2); expectedPoint[0] = minX; expectedPoint[1] = maxY; expectedPoint[2] = minZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 2 as expected "); point = geometry->GetCornerPointInWorld(true,false,true); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 2 as expected "); point = geometry->GetCornerPointInWorld(3); expectedPoint[0] = minX; expectedPoint[1] = maxY; expectedPoint[2] = maxZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 3 as expected "); point = geometry->GetCornerPointInWorld(true,false,false); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 3 as expected "); point = geometry->GetCornerPointInWorld(4); expectedPoint[0] = maxX; expectedPoint[1] = minY; expectedPoint[2] = minZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 4 as expected "); point = geometry->GetCornerPointInWorld(false,true,true); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 4 as expected "); point = geometry->GetCornerPointInWorld(5); expectedPoint[0] = maxX; expectedPoint[1] = minY; expectedPoint[2] = maxZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 5 as expected "); point = geometry->GetCornerPointInWorld(false,true,false); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 5 as expected "); point = geometry->GetCornerPointInWorld(6); expectedPoint[0] = maxX; expectedPoint[1] = maxY; expectedPoint[2] = minZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 6 as expected "); point = geometry->GetCornerPointInWorld(false,false,true); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 6 as expected "); point = geometry->GetCornerPointInWorld(7); expectedPoint[0] = maxX; expectedPoint[1] = maxY; expectedPoint[2] = maxZ; MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 7 as expected "); point = geometry->GetCornerPointInWorld(false,false,false); MITK_TEST_CONDITION(mitk::Equal(expectedPoint, point), "Bounding Point 7 as expected "); } void CheckLength_BaseData_AsExpected(mitk::BaseData* baseData, double length, double squareLength) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); double dimension = geometry->GetDiagonalLengthInWorld(); MITK_TEST_CONDITION(mitk::Equal(dimension,length ), "Length as expected "); dimension = geometry->GetDiagonalLength2InWorld(); MITK_TEST_CONDITION(mitk::Equal(dimension, squareLength ), "Square length as expected "); } void CheckPointInside_BaseDataPointInside_True(mitk::BaseData* baseData, float pointX, float pointY, float pointZ) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Point3D expectedPoint; expectedPoint[0] = pointX; expectedPoint[1] = pointY; expectedPoint[2] = pointZ; bool isInside = geometry->IsWorldPointInside(expectedPoint); MITK_TEST_CONDITION(isInside, "Point is inside Image..."); } void CheckPointInside_BaseDataPointOutside_False(mitk::BaseData* baseData, float pointX, float pointY, float pointZ) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::Point3D expectedPoint; expectedPoint[0] = pointX; expectedPoint[1] = pointY; expectedPoint[2] = pointZ; bool isInside = geometry->IsWorldPointInside(expectedPoint); MITK_TEST_CONDITION(!isInside, "Point is outside Image..."); } void CheckBounds_Image_AsSet(unsigned int DimX, unsigned int DimY, unsigned int DimZ, unsigned int DimT) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(DimX, DimY, DimZ, DimT,0.5,0.33,0.78,100); mitk::TimeGeometry::Pointer geometry = image->GetTimeGeometry(); mitk::BoundingBox::BoundsArrayType bound = geometry->GetBoundsInWorld(); bool isEqual = true; isEqual = isEqual && mitk::Equal(bound[0], -0.5*0.5); isEqual = isEqual && mitk::Equal(bound[1], 29.5*0.5); isEqual = isEqual && mitk::Equal(bound[2], -0.5*0.33); isEqual = isEqual && mitk::Equal(bound[3], 24.5*0.33); isEqual = isEqual && mitk::Equal(bound[4], -0.5*0.78); isEqual = isEqual && mitk::Equal(bound[5], 19.5*0.78); MITK_TEST_CONDITION(isEqual, "Bounds as precalculated..."); } void CheckBounds_BaseData_AsSet(mitk::BaseData* baseData, float minBoundX, float maxBoundX, float minBoundY, float maxBoundY, float minBoundZ, float maxBoundZ) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::BoundingBox::BoundsArrayType bound = geometry->GetBoundsInWorld(); bool isEqual = true; isEqual = isEqual && mitk::Equal(bound[0], minBoundX); isEqual = isEqual && mitk::Equal(bound[1], maxBoundX); isEqual = isEqual && mitk::Equal(bound[2], minBoundY); isEqual = isEqual && mitk::Equal(bound[3], maxBoundY); isEqual = isEqual && mitk::Equal(bound[4], minBoundZ); isEqual = isEqual && mitk::Equal(bound[5], maxBoundZ); MITK_TEST_CONDITION(isEqual, "Bounds as precalculated..."); } void CheckExtent_BaseData_AsSet(mitk::BaseData* baseData, double extentX, double extentY, double extentZ) { baseData->Update(); mitk::TimeGeometry::Pointer geometry = baseData->GetTimeGeometry(); mitk::BoundingBox::BoundsArrayType bound = geometry->GetBoundsInWorld(); bool isEqual = true; isEqual = isEqual && mitk::Equal(geometry->GetExtentInWorld(0), extentX);//30*0.5); isEqual = isEqual && mitk::Equal(geometry->GetExtentInWorld(1), extentY);//25*0.33); isEqual = isEqual && mitk::Equal(geometry->GetExtentInWorld(2), extentZ);//20*0.78); MITK_TEST_CONDITION(isEqual, "Extent as precalculated..."); } mitk::PointSet::Pointer makePointset() { mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); mitk::Point3D pointA, pointB, pointC; pointA.Fill(1); pointB.Fill(2); pointC.Fill(3); pointSet->SetPoint(1,pointA); pointSet->SetPoint(2,pointB); pointSet->SetPoint(3,pointC); pointSet->Update(); MITK_INFO<< pointSet->GetPoint(0); MITK_INFO<< pointSet->GetPoint(1); MITK_INFO<< pointSet->GetPoint(2); MITK_INFO<< pointSet->GetPoint(3); mitk::PointSet::Pointer pointSet2 = pointSet->Clone(); MITK_INFO<< pointSet2->GetPoint(0); MITK_INFO<< pointSet2->GetPoint(1); MITK_INFO<< pointSet2->GetPoint(2); MITK_INFO<< pointSet2->GetPoint(3); return pointSet; } }; int mitkTimeGeometryTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN(mitkTimeGeometryTest); mitkTimeGeometryTestClass testClass; MITK_TEST_OUTPUT(<< "Test for 3D image"); mitk::Image::Pointer image = mitk::ImageGenerator::GenerateRandomImage(30, 25, 20, 1,0.5,0.33,0.78,100); testClass.Translation_Image_MovedOrigin(30,25,20,1); testClass.Rotate_Image_RotatedPoint(image->Clone(),30,25,20,1); testClass.Scale_Image_ScaledPoint(30,25,20,1); testClass.GetNumberOfTimeSteps_Image_ReturnDimT(image->Clone(),30,25,20,1); testClass.GetMinimumTimePoint_3DImage_Min(image->Clone(),30,25,20,1); testClass.GetMaximumTimePoint_3DImage_Max(image->Clone(),30,25,20,1); testClass.GetTimeBounds_3DImage_ZeroAndDimT(image->Clone(),30,25,20,1); testClass.IsValidTimePoint_ImageValidTimePoint_True(image->Clone(),30,25,20,1); testClass.IsValidTimeStep_ImageValidTimeStep_True(image->Clone(), 30,25,20,1); testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(image->Clone(), 30,25,20,1); testClass.IsValidTimeStep_ImageInvalidTimeStep_False(image->Clone(), 30,25,20,1); testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(image->Clone(), 30,25,20,1); testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(image->Clone(), 30,25,20,1); testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(image->Clone(), 30,25,20,1); testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1); testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,1); testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1); testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),1); testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,1); testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),0.5,0.33,0.78,1); testClass.Expand_BaseDataDoubleSize_SizeChanged(image->Clone(),1); testClass.CheckBounds_BaseData_PointsAsExpected(image->Clone(),-0.5*0.5,-0.5*0.33,-0.5*0.78,29.5*0.5,24.5*0.33,19.5*0.78); testClass.CheckLength_BaseData_AsExpected(image->Clone(), 23.160796233014466, 536.42248214721712); testClass.CheckPointInside_BaseDataPointInside_True(image->Clone(),10,5,5); testClass.CheckPointInside_BaseDataPointOutside_False(image->Clone(),100,500,100); testClass.CheckBounds_Image_AsSet(30,25,20,1); testClass.CheckExtent_BaseData_AsSet(image->Clone(), 30*0.5,25*0.33,20*0.78); -/* - MITK_TEST_OUTPUT(<< "Test for 2D image"); - testClass.Translation_Image_MovedOrigin(30,25,1 ,1); // Test with 2D-Image - testClass.Rotate_Image_RotatedPoint(30,25,1 ,1); // Test with 2D-Image - testClass.Scale_Image_ScaledPoint(30,25,1 ,1); // Test with 2D-Image -*/ + MITK_TEST_OUTPUT(<< "Test for 2D image"); + image = mitk::ImageGenerator::GenerateRandomImage(30, 25, 1, 1,0.5,0.33,0.78,100); + testClass.Translation_Image_MovedOrigin(30,25,1,1); + testClass.Rotate_Image_RotatedPoint(image->Clone(),30,25,1,1); + testClass.Scale_Image_ScaledPoint(30,25,1,1); + testClass.GetNumberOfTimeSteps_Image_ReturnDimT(image->Clone(),30,25,1,1); + testClass.GetMinimumTimePoint_3DImage_Min(image->Clone(),30,25,1,1); + testClass.GetMaximumTimePoint_3DImage_Max(image->Clone(),30,25,1,1); + testClass.GetTimeBounds_3DImage_ZeroAndDimT(image->Clone(),30,25,1,1); + testClass.IsValidTimePoint_ImageValidTimePoint_True(image->Clone(),30,25,1,1); + testClass.IsValidTimeStep_ImageValidTimeStep_True(image->Clone(), 30,25,1,1); + testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(image->Clone(), 30,25,1,1); + testClass.IsValidTimeStep_ImageInvalidTimeStep_False(image->Clone(), 30,25,1,1); + testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(image->Clone(), 30,25,1,1); + testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(image->Clone(), 30,25,1,1); + testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(image->Clone(), 30,25,1,1); + testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1); + testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,1,1); + testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,1); + testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),1); + testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,1,1); + testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),0.5,0.33,0.78,1); + testClass.Expand_BaseDataDoubleSize_SizeChanged(image->Clone(),1); + testClass.CheckBounds_BaseData_PointsAsExpected(image->Clone(),-0.5*0.5,-0.5*0.33,-0.5*0.78,29.5*0.5,24.5*0.33,0.5*0.78); + testClass.CheckLength_BaseData_AsExpected(image->Clone(), 17.1368287615, 293.6709); + testClass.CheckPointInside_BaseDataPointInside_True(image->Clone(),10,5,0); + testClass.CheckPointInside_BaseDataPointOutside_False(image->Clone(),100,500,0.5); + testClass.CheckExtent_BaseData_AsSet(image->Clone(), 30*0.5,25*0.33,1*0.78); MITK_TEST_OUTPUT(<< "Test for 3D+time image"); image = mitk::ImageGenerator::GenerateRandomImage(30, 25, 20, 5,0.5,0.33,0.78,100); testClass.Translation_Image_MovedOrigin(30,25,20,5); // Test with 3D+t-Image testClass.Rotate_Image_RotatedPoint(image->Clone(),30,25,20,5); // Test with 3D+t-Image testClass.Scale_Image_ScaledPoint(30,25,20,5); // Test with 3D+t-Image testClass.GetNumberOfTimeSteps_Image_ReturnDimT(image->Clone(),30,25,20,5); testClass.GetMinimumTimePoint_4DBaseData_Zero(image->Clone(),5); testClass.GetMaximumTimePoint_4DBaseData_DimT(image->Clone(),5); testClass.GetTimeBounds_4DImage_ZeroAndDimT(30,25,20,5); testClass.IsValidTimePoint_ImageValidTimePoint_True(image->Clone(),30,25,20,5); testClass.IsValidTimePoint_ImageNegativInvalidTimePoint_False(30,25,20,5); testClass.IsValidTimePoint_ImageInvalidTimePoint_False(30,25,20,5); testClass.IsValidTimeStep_ImageValidTimeStep_True(image->Clone(), 30,25,20,5); testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(image->Clone(), 30,25,20,5); testClass.IsValidTimeStep_ImageInvalidTimeStep_False(image->Clone(), 30,25,20,5); testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(image->Clone(), 30,25,20,5); testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(image->Clone(), 30,25,20,5); testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(image->Clone(), 30,25,20,5); testClass.TimePointToTimeStep_4DImageInvalidTimePoint_TimePoint(30,25,20,5); testClass.TimePointToTimeStep_4DImageNegativInvalidTimePoint_TimePoint(30,25,20,5); testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,5); testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,5); testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(image->Clone(), 3,3,3,3*0.5,3*0.33,3*0.78,5); testClass.GetGeometryForTimePoint_4DImageInvalidTimePoint_NullPointer(30,25,20,5); testClass.GetGeometryForTimePoint_4DImageNEgativInvalidTimePoint_NullPointer(30,25,20,5); testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),5); testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(image->Clone(), 30,25,20,5); testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(image->Clone(),0.5,0.33,0.78,5); testClass.Expand_BaseDataDoubleSize_SizeChanged(image->Clone(),5); testClass.CheckBounds_BaseData_PointsAsExpected(image->Clone(),-0.5*0.5,-0.5*0.33,-0.5*0.78,29.5*0.5,24.5*0.33,19.5*0.78); testClass.CheckLength_BaseData_AsExpected(image->Clone(), 23.160796233014466, 536.42248214721712); testClass.CheckPointInside_BaseDataPointInside_True(image->Clone(),10,5,5); testClass.CheckPointInside_BaseDataPointOutside_False(image->Clone(), 100,100,500); testClass.CheckBounds_Image_AsSet(30,25,20,5); testClass.CheckExtent_BaseData_AsSet(image->Clone(), 30*0.5,25*0.33,20*0.78); /* MITK_TEST_OUTPUT(<< "Test for 2D+time image"); testClass.Translation_Image_MovedOrigin(30,25,1 ,5); // Test with 2D+t-Image testClass.Rotate_Image_RotatedPoint(30,25,1 ,5); // Test with 2D+t-Image testClass.Scale_Image_ScaledPoint(30,25,1 ,5); // Test with 2D+t-Image */ mitk::PointSet::Pointer pointSet = mitk::PointSet::New(); mitk::Point3D pointA, pointB, pointC; pointA.Fill(1); pointB.Fill(2); pointC.Fill(3); pointSet->SetPoint(0,pointA); pointSet->SetPoint(1,pointB); pointSet->SetPoint(2,pointC); testClass.GetNumberOfTimeSteps_Image_ReturnDimT(pointSet->Clone(),30,25,20,1); testClass.GetMinimumTimePoint_3DImage_Min(pointSet->Clone(),30,25,20,1); testClass.GetMaximumTimePoint_3DImage_Max(pointSet->Clone(),30,25,20,1); testClass.GetTimeBounds_3DImage_ZeroAndDimT(pointSet->Clone(),30,25,20,1); testClass.IsValidTimePoint_ImageValidTimePoint_True(pointSet->Clone(),30,25,20,1); testClass.IsValidTimeStep_ImageValidTimeStep_True(pointSet->Clone(),30,25,20,1); testClass.IsValidTimeStep_ImageNegativInvalidTimeStep_False(pointSet->Clone(),30,25,20,1); testClass.IsValidTimeStep_ImageInvalidTimeStep_False(pointSet->Clone(),30,25,20,1); testClass.TimeStepToTimePoint_ImageValidTimeStep_TimePoint(pointSet->Clone(),30,25,20,1); testClass.TimeStepToTimePoint_ImageInvalidTimeStep_TimePoint(pointSet->Clone(),30,25,20,1); testClass.TimePointToTimeStep_ImageValidTimePoint_TimePoint(pointSet->Clone(),30,25,20,1); testClass.GetGeometryForTimeStep_BaseDataValidTimeStep_CorrectGeometry(pointSet->Clone(), 3,3,3,3,3,3,1); testClass.GetGeometryForTimeStep_ImageInvalidTimeStep_NullPointer(pointSet->Clone(), 30,25,20,1); testClass.GetGeometryForTimePoint_BaseDataValidTimePoint_CorrectGeometry(pointSet->Clone(), 3,3,3,3,3,3,1); testClass.GetGeometryCloneForTimeStep_BaseDataValidTimeStep_CorrectGeometry(pointSet->Clone(),1); testClass.GetGeometryCloneForTimeStep_ImageInvalidTimeStep_NullPointer(pointSet->Clone(), 30,25,20,1); testClass.SetTimeStepGeometry_BaseDataValidTimeStep_CorrectGeometry(pointSet->Clone(), 1,1,1,1); testClass.Expand_BaseDataDoubleSize_SizeChanged(pointSet->Clone(),1); testClass.CheckBounds_BaseData_PointsAsExpected(pointSet->Clone(),1,1,1,3,3,3); testClass.CheckLength_BaseData_AsExpected(pointSet->Clone(),3.46410161,12); testClass.CheckPointInside_BaseDataPointInside_True(pointSet->Clone(),2,2,3); testClass.CheckPointInside_BaseDataPointOutside_False(pointSet->Clone(),4,5,1); testClass.CheckBounds_BaseData_AsSet(pointSet->Clone(),1,3,1,3,1,3); testClass.CheckExtent_BaseData_AsSet(pointSet->Clone(),2,2,2 ); MITK_TEST_END(); return EXIT_SUCCESS; } diff --git a/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp b/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp index e56e45b19c..01cda35ab7 100644 --- a/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp +++ b/Modules/IpPicSupport/Testing/mitkPicFileReaderTest.cpp @@ -1,189 +1,189 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include "mitkImage.h" #include "mitkPicFileReader.h" #include "mitkPicHelper.h" #include "mitkSlicedGeometry3D.h" #include #include #include #include int mitkPicFileReaderTest(int argc, char* argv[]) { MITK_TEST_BEGIN(mitkPicFileReaderTest) if(argc>=1) { if(itksys::SystemTools::FileLength(argv[1]) == 0) { mitk::PicFileReader::Pointer emptyFileReader = mitk::PicFileReader::New(); emptyFileReader->SetFileName(argv[1]); MITK_TEST_FOR_EXCEPTION(itk::ImageFileReaderException,emptyFileReader->Update()); } else { //independently read header of pic file mitkIpPicDescriptor *picheader=NULL; if(itksys::SystemTools::LowerCase(itksys::SystemTools::GetFilenameExtension(argv[1])).find(".pic")!=std::string::npos) { picheader = mitkIpPicGetHeader(argv[1], NULL); } if(picheader==NULL) { std::cout<<"file not found/not a pic-file - test not applied [PASSED]"<SetFileName(argv[1]); reader->Update(); std::cout << "Testing IsInitialized(): "; if(reader->GetOutput()->IsInitialized()==false) { std::cout<<"[FAILED]"<GetOutput()->IsSliceSet(0)==false) { std::cout<<"[FAILED]"<GetOutput()->GetGeometry()==NULL) { std::cout<<"[FAILED]"<GetOutput()->GetTimeGeometry(); if(timeGeometry==NULL) { std::cout<<"[FAILED]"<GetGeometryForTimeStep(0)==NULL) + if(timeGeometry->GetGeometryForTimeStep(0).IsNull()) { std::cout<<"[FAILED]"<(timeGeometry->GetGeometryForTimeStep(0)); + slicedgeometry = dynamic_cast(timeGeometry->GetGeometryForTimeStep(0).GetPointer()); if(slicedgeometry==NULL) { std::cout<<"[FAILED]"<GetGeometry2D(0); if(geometry2d==NULL) { std::cout<<"[FAILED]"<GetExtent(0)-picheader->n[0])>mitk::eps) || (fabs(geometry2d->GetExtent(1)-picheader->n[1])>mitk::eps)) { std::cout<<"[FAILED]"<GetExtent(0)-picheader->n[0])>mitk::eps) || (fabs(slicedgeometry->GetExtent(1)-picheader->n[1])>mitk::eps) || (picheader->dim>2 && (fabs(slicedgeometry->GetExtent(2)-picheader->n[2])>mitk::eps)) ) { std::cout<<"[FAILED]"<GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).two_norm(); spacing[1] = slicedgeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1).two_norm(); spacing[2] = slicedgeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).two_norm(); mitk::Vector3D readspacing=slicedgeometry->GetSpacing(); mitk::Vector3D dist = spacing-readspacing; if(dist.GetSquaredNorm()>mitk::eps) { std::cout<<"[FAILED]"<mitk::eps) { std::cout<<"[FAILED]"<dim==4) { std::cout << "4D dataset: Testing that timebounds are not infinite: "; if((slicedgeometry->GetTimeBounds()[0] == mitk::ScalarTypeNumericTraits::NonpositiveMin()) && (slicedgeometry->GetTimeBounds()[1] == mitk::ScalarTypeNumericTraits::max()) ) { std::cout<<"[FAILED]"< mitk::GeometryClipImageFilter::GeometryClipImageFilter() : m_ClippingGeometry(NULL), m_ClipPartAboveGeometry(true), m_OutsideValue(0), m_AutoOutsideValue(false), m_LabelBothSides(false), m_AutoOrientLabels(false), m_AboveGeometryLabel(1), m_BelowGeometryLabel(2) { this->SetNumberOfIndexedInputs(2); this->SetNumberOfRequiredInputs(2); m_InputTimeSelector = mitk::ImageTimeSelector::New(); m_OutputTimeSelector = mitk::ImageTimeSelector::New(); m_ClippingGeometryData = mitk::GeometryData::New(); } mitk::GeometryClipImageFilter::~GeometryClipImageFilter() { } void mitk::GeometryClipImageFilter::SetClippingGeometry(const mitk::TimeGeometry* timeClippingGeometry) { m_TimeClippingGeometry = timeClippingGeometry; SetClippingGeometry(timeClippingGeometry->GetGeometryForTimeStep(0)); } void mitk::GeometryClipImageFilter::SetClippingGeometry(const mitk::Geometry3D* aClippingGeometry) { if(aClippingGeometry != m_ClippingGeometry.GetPointer()) { m_ClippingGeometry = aClippingGeometry; m_ClippingGeometryData->SetGeometry(const_cast(aClippingGeometry)); SetNthInput(1, m_ClippingGeometryData); Modified(); } } const mitk::Geometry3D* mitk::GeometryClipImageFilter::GetClippingGeometry() const { return m_ClippingGeometry; } const mitk::TimeGeometry* mitk::GeometryClipImageFilter::GetClippingTimeGeometry() const { return m_TimeClippingGeometry; } void mitk::GeometryClipImageFilter::GenerateInputRequestedRegion() { Superclass::GenerateInputRequestedRegion(); mitk::Image* output = this->GetOutput(); mitk::Image* input = const_cast< mitk::Image * > ( this->GetInput() ); if((output->IsInitialized()==false) || (m_ClippingGeometry.IsNull())) return; input->SetRequestedRegionToLargestPossibleRegion(); GenerateTimeInInputRegion(output, input); } void mitk::GeometryClipImageFilter::GenerateOutputInformation() { mitk::Image::ConstPointer input = this->GetInput(); mitk::Image::Pointer output = this->GetOutput(); if ((output->IsInitialized()) && (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime())) return; itkDebugMacro(<<"GenerateOutputInformation()"); unsigned int i; unsigned int *tmpDimensions = new unsigned int[input->GetDimension()]; for(i=0;iGetDimension();++i) tmpDimensions[i]=input->GetDimension(i); output->Initialize(input->GetPixelType(), input->GetDimension(), tmpDimensions, input->GetNumberOfChannels()); delete [] tmpDimensions; output->SetGeometry(static_cast(input->GetGeometry()->Clone().GetPointer())); output->SetPropertyList(input->GetPropertyList()->Clone()); m_TimeOfHeaderInitialization.Modified(); } template < typename TPixel, unsigned int VImageDimension > void mitk::_InternalComputeClippedImage(itk::Image* inputItkImage, mitk::GeometryClipImageFilter* geometryClipper, const mitk::Geometry2D* clippingGeometry2D) { typedef itk::Image ItkInputImageType; typedef itk::Image ItkOutputImageType; typedef itk::ImageRegionConstIteratorWithIndex< ItkInputImageType > ItkInputImageIteratorType; typedef itk::ImageRegionIteratorWithIndex< ItkOutputImageType > ItkOutputImageIteratorType; typename mitk::ImageToItk::Pointer outputimagetoitk = mitk::ImageToItk::New(); outputimagetoitk->SetInput(geometryClipper->m_OutputTimeSelector->GetOutput()); outputimagetoitk->Update(); typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput(); // create the iterators typename ItkInputImageType::RegionType inputRegionOfInterest = inputItkImage->GetLargestPossibleRegion(); ItkInputImageIteratorType inputIt( inputItkImage, inputRegionOfInterest ); ItkOutputImageIteratorType outputIt( outputItkImage, inputRegionOfInterest ); typename ItkOutputImageType::PixelType outsideValue; if(geometryClipper->m_AutoOutsideValue) outsideValue = itk::NumericTraits::min(); else outsideValue = (typename ItkOutputImageType::PixelType) geometryClipper->m_OutsideValue; mitk::Geometry3D* inputGeometry = geometryClipper->m_InputTimeSelector->GetOutput()->GetGeometry(); typedef itk::Index IndexType; Point3D indexPt; indexPt.Fill(0); int i, dim=IndexType::GetIndexDimension(); Point3D pointInMM; bool above = geometryClipper->m_ClipPartAboveGeometry; bool labelBothSides = geometryClipper->GetLabelBothSides(); if (geometryClipper->GetAutoOrientLabels()) { Point3D leftMostPoint; leftMostPoint.Fill( std::numeric_limits::min() / 2.0 ); if(clippingGeometry2D->IsAbove(pointInMM) != above) { // invert meaning of above --> left is always the "above" side above = !above; MITK_INFO << leftMostPoint << " is BELOW geometry. Inverting meaning of above" << std::endl; } else MITK_INFO << leftMostPoint << " is above geometry" << std::endl; } typename ItkOutputImageType::PixelType aboveLabel = (typename ItkOutputImageType::PixelType)geometryClipper->GetAboveGeometryLabel(); typename ItkOutputImageType::PixelType belowLabel = (typename ItkOutputImageType::PixelType)geometryClipper->GetBelowGeometryLabel(); for ( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt) { if((typename ItkOutputImageType::PixelType)inputIt.Get() == outsideValue) { outputIt.Set(outsideValue); } else { for(i=0;iIndexToWorld(indexPt, pointInMM); if(clippingGeometry2D->IsAbove(pointInMM) == above) { if ( labelBothSides ) outputIt.Set( aboveLabel ); else outputIt.Set( outsideValue ); } else { if ( labelBothSides) outputIt.Set( belowLabel ); else outputIt.Set( inputIt.Get() ); } } } } #include "mitkImageAccessByItk.h" void mitk::GeometryClipImageFilter::GenerateData() { Image::ConstPointer input = this->GetInput(); Image::Pointer output = this->GetOutput(); if((output->IsInitialized()==false) || (m_ClippingGeometry.IsNull())) return; const Geometry2D * clippingGeometryOfCurrentTimeStep = NULL; if(m_TimeClippingGeometry.IsNull()) { clippingGeometryOfCurrentTimeStep = dynamic_cast(m_ClippingGeometry.GetPointer()); } else { - clippingGeometryOfCurrentTimeStep = dynamic_cast(m_TimeClippingGeometry->GetGeometryForTimeStep(0)); + clippingGeometryOfCurrentTimeStep = dynamic_cast(m_TimeClippingGeometry->GetGeometryForTimeStep(0).GetPointer()); } if(clippingGeometryOfCurrentTimeStep == NULL) return; m_InputTimeSelector->SetInput(input); m_OutputTimeSelector->SetInput(this->GetOutput()); mitk::Image::RegionType outputRegion = output->GetRequestedRegion(); const mitk::TimeGeometry *outputTimeGeometry = output->GetTimeGeometry(); const mitk::TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); ScalarType timeInMS; int timestep=0; int tstart=outputRegion.GetIndex(3); int tmax=tstart+outputRegion.GetSize(3); int t; for(t=tstart;tTimeStepToTimePoint( t ); timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS ); m_InputTimeSelector->SetTimeNr(timestep); m_InputTimeSelector->UpdateLargestPossibleRegion(); m_OutputTimeSelector->SetTimeNr(t); m_OutputTimeSelector->UpdateLargestPossibleRegion(); if(m_TimeClippingGeometry.IsNotNull()) { timestep = m_TimeClippingGeometry->TimePointToTimeStep( timeInMS ); if(m_TimeClippingGeometry->IsValidTimeStep(timestep) == false) continue; - clippingGeometryOfCurrentTimeStep = dynamic_cast(m_TimeClippingGeometry->GetGeometryForTimeStep(timestep)); + clippingGeometryOfCurrentTimeStep = dynamic_cast(m_TimeClippingGeometry->GetGeometryForTimeStep(timestep).GetPointer()); } AccessByItk_2(m_InputTimeSelector->GetOutput(),_InternalComputeClippedImage,this,clippingGeometryOfCurrentTimeStep); } m_TimeOfHeaderInitialization.Modified(); } diff --git a/Modules/MitkExt/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp b/Modules/MitkExt/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp index 6f00b3d7fb..ed60e81010 100644 --- a/Modules/MitkExt/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkPointSetToCurvedGeometryFilter.cpp @@ -1,165 +1,165 @@ /*=================================================================== 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 "mitkPointSetToCurvedGeometryFilter.h" #include "mitkThinPlateSplineCurvedGeometry.h" #include "mitkPlaneGeometry.h" #include "mitkImage.h" #include "mitkDataNode.h" #include "mitkGeometryData.h" #include "mitkGeometry2DData.h" #include "mitkProperties.h" #include "itkMesh.h" #include "itkPointSet.h" mitk::PointSetToCurvedGeometryFilter::PointSetToCurvedGeometryFilter() { m_ProjectionMode = YZPlane; m_PCAPlaneCalculator = mitk::PlaneFit::New(); m_ImageToBeMapped = NULL; m_Sigma = 1000; mitk::Geometry2DData::Pointer output = static_cast ( this->MakeOutput ( 0 ).GetPointer() ); output->Initialize(); Superclass::SetNumberOfRequiredOutputs ( 1 ); Superclass::SetNthOutput ( 0, output.GetPointer() ); } mitk::PointSetToCurvedGeometryFilter::~PointSetToCurvedGeometryFilter() {} void mitk::PointSetToCurvedGeometryFilter::GenerateOutputInformation() { mitk::PointSet::ConstPointer input = this->GetInput(); mitk::Geometry2DData::Pointer output = dynamic_cast ( this->GetOutput() ); if ( input.IsNull() ) itkGenericExceptionMacro ( "Input point set is NULL!" ); if ( input->GetTimeGeometry()->GetNumberOfTimeSteps() != 1 ) itkWarningMacro ( "More than one time step is not yet supported!" ); if ( output.IsNull() ) itkGenericExceptionMacro ( "Output is NULL!" ); if ( m_ImageToBeMapped.IsNull() ) itkGenericExceptionMacro ( "Image to be mapped is NULL!" ); bool update = false; if ( output->GetGeometry() == NULL || output->GetGeometry2D() == NULL || output->GetTimeGeometry() == NULL ) update = true; if ( ( ! update ) && ( output->GetTimeGeometry()->GetNumberOfTimeSteps() != input->GetTimeGeometry()->GetNumberOfTimeSteps() ) ) update = true; if ( update ) { mitk::ThinPlateSplineCurvedGeometry::Pointer curvedGeometry = mitk::ThinPlateSplineCurvedGeometry::New(); output->SetGeometry(curvedGeometry); } } void mitk::PointSetToCurvedGeometryFilter::GenerateData() { mitk::PointSet::ConstPointer input = this->GetInput(); mitk::GeometryData::Pointer output = this->GetOutput(); // // check preconditions // if ( input.IsNull() ) itkGenericExceptionMacro ( "Input point set is NULL!" ); if ( output.IsNull() ) itkGenericExceptionMacro ( "output geometry data is NULL!" ); if ( output->GetTimeGeometry() == NULL ) itkGenericExceptionMacro ( "Output time sliced geometry is NULL!" ); - if ( output->GetTimeGeometry()->GetGeometryForTimeStep ( 0 ) == NULL ) + if ( output->GetTimeGeometry()->GetGeometryForTimeStep ( 0 ).IsNull() ) itkGenericExceptionMacro ( "Output geometry3d is NULL!" ); - mitk::ThinPlateSplineCurvedGeometry::Pointer curvedGeometry = dynamic_cast ( output->GetTimeGeometry()->GetGeometryForTimeStep( 0 ) ); + mitk::ThinPlateSplineCurvedGeometry::Pointer curvedGeometry = dynamic_cast ( output->GetTimeGeometry()->GetGeometryForTimeStep( 0 ).GetPointer() ); if ( curvedGeometry.IsNull() ) itkGenericExceptionMacro ( "Output geometry3d is not an instance of mitk::ThinPlateSPlineCurvedGeometry!" ); if ( m_ImageToBeMapped.IsNull() ) itkGenericExceptionMacro ( "Image to be mapped is NULL!" ); // // initialize members if needed // if ( m_XYPlane.IsNull() || m_XZPlane.IsNull() || m_YZPlane.IsNull() ) { m_ImageToBeMapped->UpdateOutputInformation(); const mitk::Geometry3D* imageGeometry = m_ImageToBeMapped->GetUpdatedGeometry(); imageGeometry = m_ImageToBeMapped->GetUpdatedGeometry(); m_XYPlane = mitk::PlaneGeometry::New(); m_XZPlane = mitk::PlaneGeometry::New(); m_YZPlane = mitk::PlaneGeometry::New(); m_XYPlane->InitializeStandardPlane ( imageGeometry, mitk::PlaneGeometry::Axial ); m_YZPlane->InitializeStandardPlane ( imageGeometry, mitk::PlaneGeometry::Sagittal ); m_XZPlane->InitializeStandardPlane ( imageGeometry, mitk::PlaneGeometry::Frontal ); } if ( m_PlaneLandmarkProjector.IsNull() ) { m_PlaneLandmarkProjector = mitk::PlaneLandmarkProjector::New(); m_SphereLandmarkProjector = mitk::SphereLandmarkProjector::New(); } // // set up geometry according to the current settings // if ( m_ProjectionMode == Sphere ) { curvedGeometry->SetLandmarkProjector ( m_SphereLandmarkProjector ); } else { if ( m_ProjectionMode == XYPlane ) m_PlaneLandmarkProjector->SetProjectionPlane ( m_XYPlane ); else if ( m_ProjectionMode == XZPlane ) m_PlaneLandmarkProjector->SetProjectionPlane ( m_XZPlane ); else if ( m_ProjectionMode == YZPlane ) m_PlaneLandmarkProjector->SetProjectionPlane ( m_YZPlane ); else if ( m_ProjectionMode == PCAPlane ) { itkExceptionMacro ( "PCAPlane not yet implemented!" ); m_PCAPlaneCalculator->SetInput ( input ); m_PCAPlaneCalculator->Update(); m_PlaneLandmarkProjector->SetProjectionPlane ( dynamic_cast ( m_PCAPlaneCalculator->GetOutput() ) ); } else itkExceptionMacro ( "Unknown projection mode" ); curvedGeometry->SetLandmarkProjector ( m_PlaneLandmarkProjector ); } //curvedGeometry->SetReferenceGeometry( m_ImageToBeMapped->GetGeometry() ); curvedGeometry->SetTargetLandmarks ( input->GetPointSet ( 0 )->GetPoints() ); curvedGeometry->SetSigma ( m_Sigma ); curvedGeometry->ComputeGeometry(); curvedGeometry->SetOversampling ( 1.0 ); } void mitk::PointSetToCurvedGeometryFilter::SetDefaultCurvedGeometryProperties ( mitk::DataNode* node ) { if ( node == NULL ) { itkGenericOutputMacro ( "Warning: node is NULL!" ); return; } node->SetIntProperty ( "xresolution", 50 ); node->SetIntProperty ( "yresolution", 50 ); node->SetProperty ( "name", mitk::StringProperty::New ( "Curved Plane" ) ); // exclude extent of this plane when calculating DataStorage bounding box node->SetProperty ( "includeInBoundingBox", mitk::BoolProperty::New ( false ) ); } diff --git a/Modules/QmitkExt/QmitkSlicesInterpolator.cpp b/Modules/QmitkExt/QmitkSlicesInterpolator.cpp index 94f1057580..40d37199ce 100644 --- a/Modules/QmitkExt/QmitkSlicesInterpolator.cpp +++ b/Modules/QmitkExt/QmitkSlicesInterpolator.cpp @@ -1,1074 +1,1074 @@ /*=================================================================== 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 "QmitkSlicesInterpolator.h" #include "QmitkStdMultiWidget.h" #include "QmitkSelectableGLWidget.h" #include "mitkToolManager.h" #include "mitkDataNodeFactory.h" #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkProgressBar.h" #include "mitkGlobalInteraction.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkInteractionConst.h" #include "mitkApplyDiffImageOperation.h" #include "mitkDiffImageApplier.h" #include "mitkSegTool2D.h" #include "mitkCoreObjectFactory.h" #include "mitkSurfaceToImageFilter.h" #include #include #include #include #include #include #include #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) const std::map QmitkSlicesInterpolator::createActionToSliceDimension() { std::map actionToSliceDimension; actionToSliceDimension[new QAction("Axial (red window)", 0)] = 2; actionToSliceDimension[new QAction("Sagittal (green window)", 0)] = 0; actionToSliceDimension[new QAction("Coronal (blue window)", 0)] = 1; return actionToSliceDimension; } QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget* parent, const char* /*name*/) :QWidget(parent), ACTION_TO_SLICEDIMENSION( createActionToSliceDimension() ), m_Interpolator( mitk::SegmentationInterpolationController::New() ), m_MultiWidget(NULL), m_ToolManager(NULL), m_Initialized(false), m_LastSliceDimension(2), m_LastSliceIndex(0), m_2DInterpolationEnabled(false), m_3DInterpolationEnabled(false) { m_SurfaceInterpolator = mitk::SurfaceInterpolationController::GetInstance(); QHBoxLayout* layout = new QHBoxLayout(this); m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this); QGridLayout* grid = new QGridLayout(m_GroupBoxEnableExclusiveInterpolationMode); m_RBtnEnable3DInterpolation = new QRadioButton("3D",this); connect(m_RBtnEnable3DInterpolation, SIGNAL(toggled(bool)), this, SLOT(On3DInterpolationEnabled(bool))); m_RBtnEnable3DInterpolation->setChecked(true); m_RBtnEnable3DInterpolation->setToolTip("Interpolate a binary volume from a set of arbitrarily arranged contours."); grid->addWidget(m_RBtnEnable3DInterpolation,0,0); m_BtnAccept3DInterpolation = new QPushButton("Accept", this); m_BtnAccept3DInterpolation->setEnabled(false); connect(m_BtnAccept3DInterpolation, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked())); grid->addWidget(m_BtnAccept3DInterpolation, 0,1); m_CbShowMarkers = new QCheckBox("Show Position Nodes", this); m_CbShowMarkers->setChecked(false); connect(m_CbShowMarkers, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool))); connect(m_CbShowMarkers, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool))); grid->addWidget(m_CbShowMarkers,0,2); m_RBtnEnable2DInterpolation = new QRadioButton("2D",this); connect(m_RBtnEnable2DInterpolation, SIGNAL(toggled(bool)), this, SLOT(On2DInterpolationEnabled(bool))); m_RBtnEnable2DInterpolation ->setToolTip("Interpolate contours in left-out slices from a set of slice-by-slice arranged contours."); grid->addWidget(m_RBtnEnable2DInterpolation,1,0); m_BtnAcceptInterpolation = new QPushButton("Accept", this); m_BtnAcceptInterpolation->setEnabled( false ); connect( m_BtnAcceptInterpolation, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()) ); grid->addWidget(m_BtnAcceptInterpolation,1,1); m_BtnAcceptAllInterpolations = new QPushButton("... for all slices", this); m_BtnAcceptAllInterpolations->setEnabled( false ); connect( m_BtnAcceptAllInterpolations, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()) ); grid->addWidget(m_BtnAcceptAllInterpolations,1,2); m_RBtnDisableInterpolation = new QRadioButton("Disable", this); connect(m_RBtnDisableInterpolation, SIGNAL(toggled(bool)), this, SLOT(OnInterpolationDisabled(bool))); m_RBtnDisableInterpolation->setToolTip("Disable interpolation."); grid->addWidget(m_RBtnDisableInterpolation, 2,0); layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode); this->setLayout(layout); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged ); InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver( itk::ModifiedEvent(), command ); itk::ReceptorMemberCommand::Pointer command2 = itk::ReceptorMemberCommand::New(); command2->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged ); SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver( itk::ModifiedEvent(), command2 ); // feedback node and its visualization properties m_FeedbackNode = mitk::DataNode::New(); mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties( m_FeedbackNode ); m_FeedbackNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) ); m_FeedbackNode->SetProperty( "color", mitk::ColorProperty::New(255.0, 255.0, 0.0) ); m_FeedbackNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(false) ); m_FeedbackNode->SetProperty( "layer", mitk::IntProperty::New( 20 ) ); m_FeedbackNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_FeedbackNode->SetProperty( "name", mitk::StringProperty::New("Interpolation feedback") ); m_FeedbackNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) ); m_FeedbackNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode = mitk::DataNode::New(); m_InterpolatedSurfaceNode->SetProperty( "color", mitk::ColorProperty::New(255.0,255.0,0.0) ); m_InterpolatedSurfaceNode->SetProperty( "name", mitk::StringProperty::New("Surface Interpolation feedback") ); m_InterpolatedSurfaceNode->SetProperty( "opacity", mitk::FloatProperty::New(0.5) ); m_InterpolatedSurfaceNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_InterpolatedSurfaceNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_InterpolatedSurfaceNode->SetVisibility(false); m_3DContourNode = mitk::DataNode::New(); m_3DContourNode->SetProperty( "color", mitk::ColorProperty::New(0.0, 0.0, 0.0) ); m_3DContourNode->SetProperty("helper object", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "name", mitk::StringProperty::New("Drawn Contours") ); m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f)); m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true)); m_3DContourNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); m_3DContourNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); QWidget::setContentsMargins(0, 0, 0, 0); if ( QWidget::layout() != NULL ) { QWidget::layout()->setContentsMargins(0, 0, 0, 0); } //For running 3D Interpolation in background // create a QFuture and a QFutureWatcher connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished())); connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer())); m_Timer = new QTimer(this); connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor())); } void QmitkSlicesInterpolator::SetDataStorage( mitk::DataStorage& storage ) { m_DataStorage = &storage; m_SurfaceInterpolator->SetDataStorage(storage); } mitk::DataStorage* QmitkSlicesInterpolator::GetDataStorage() { if ( m_DataStorage.IsNotNull() ) { return m_DataStorage; } else { return NULL; } } void QmitkSlicesInterpolator::Initialize(mitk::ToolManager* toolManager, QmitkStdMultiWidget* multiWidget) { if (m_Initialized) { // remove old observers if (m_ToolManager) { m_ToolManager->WorkingDataChanged -= mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified ); m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified ); } if (m_MultiWidget) { disconnect( m_MultiWidget, SIGNAL(destroyed(QObject*)), this, SLOT(OnMultiWidgetDeleted(QObject*)) ); mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); slicer->RemoveObserver( TSliceObserverTag ); slicer->RemoveObserver( TTimeObserverTag ); slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); slicer->RemoveObserver( SSliceObserverTag ); slicer->RemoveObserver( STimeObserverTag ); slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); slicer->RemoveObserver( FSliceObserverTag ); slicer->RemoveObserver( FTimeObserverTag ); } //return; } m_MultiWidget = multiWidget; connect( m_MultiWidget, SIGNAL(destroyed(QObject*)), this, SLOT(OnMultiWidgetDeleted(QObject*)) ); m_ToolManager = toolManager; if (m_ToolManager) { // set enabled only if a segmentation is selected mitk::DataNode* node = m_ToolManager->GetWorkingData(0); QWidget::setEnabled( node != NULL ); // react whenever the set of selected segmentation changes m_ToolManager->WorkingDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified ); m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate( this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified ); // connect to the steppers of the three multi widget widgets. after each change, call the interpolator if (m_MultiWidget) { mitk::SliceNavigationController* slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); m_TimeStep.resize(3); m_TimeStep[2] = slicer->GetTime()->GetPos(); { itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnAxialTimeChanged ); TTimeObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), command ); } { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnAxialSliceChanged ); TSliceObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } // connect to the steppers of the three multi widget widgets. after each change, call the interpolator slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); m_TimeStep[0] = slicer->GetTime()->GetPos(); { itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSagittalTimeChanged ); STimeObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), command ); } { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnSagittalSliceChanged ); SSliceObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } // connect to the steppers of the three multi widget widgets. after each change, call the interpolator slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); m_TimeStep[1] = slicer->GetTime()->GetPos(); { itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnFrontalTimeChanged ); FTimeObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometryTimeEvent(NULL, 0), command ); } { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkSlicesInterpolator::OnFrontalSliceChanged ); FSliceObserverTag = slicer->AddObserver( mitk::SliceNavigationController::GeometrySliceEvent(NULL, 0), command ); } } } m_Initialized = true; } QmitkSlicesInterpolator::~QmitkSlicesInterpolator() { if (m_MultiWidget) { mitk::SliceNavigationController* slicer; if(m_MultiWidget->mitkWidget1 != NULL) { slicer = m_MultiWidget->mitkWidget1->GetSliceNavigationController(); slicer->RemoveObserver( TSliceObserverTag ); slicer->RemoveObserver( TTimeObserverTag ); } if(m_MultiWidget->mitkWidget2 != NULL) { slicer = m_MultiWidget->mitkWidget2->GetSliceNavigationController(); slicer->RemoveObserver( SSliceObserverTag ); slicer->RemoveObserver( STimeObserverTag ); } if(m_MultiWidget->mitkWidget3 != NULL) { slicer = m_MultiWidget->mitkWidget3->GetSliceNavigationController(); slicer->RemoveObserver( FSliceObserverTag ); slicer->RemoveObserver( FTimeObserverTag ); } } if(m_DataStorage->Exists(m_3DContourNode)) m_DataStorage->Remove(m_3DContourNode); if(m_DataStorage->Exists(m_InterpolatedSurfaceNode)) m_DataStorage->Remove(m_InterpolatedSurfaceNode); // remove observer m_Interpolator->RemoveObserver( InterpolationInfoChangedObserverTag ); m_SurfaceInterpolator->RemoveObserver( SurfaceInterpolationInfoChangedObserverTag ); delete m_Timer; } void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status) { OnInterpolationActivated(status); m_Interpolator->Activate2DInterpolation(status); } void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status) { On3DInterpolationActivated(status); } void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status) { if (status) { OnInterpolationActivated(!status); On3DInterpolationActivated(!status); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::OnShowMarkers(bool state) { mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker" , mitk::BoolProperty::New(true))); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state)); } } void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified() { //For the 3D interpolation SetCurrentContourListID(); if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } } void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified() { if (m_2DInterpolationEnabled) { OnInterpolationActivated( true ); // re-initialize if needed } if (m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::OnAxialTimeChanged(itk::Object* sender, const itk::EventObject& e) { const mitk::SliceNavigationController::GeometryTimeEvent& event = dynamic_cast(e); m_TimeStep[2] = event.GetPos(); if (m_LastSliceDimension == 2) { mitk::SliceNavigationController* snc = dynamic_cast( sender ); if (snc) snc->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnTransversalTimeChanged(itk::Object* sender, const itk::EventObject& e) { this->OnAxialTimeChanged(sender, e); } void QmitkSlicesInterpolator::OnSagittalTimeChanged(itk::Object* sender, const itk::EventObject& e) { const mitk::SliceNavigationController::GeometryTimeEvent& event = dynamic_cast(e); m_TimeStep[0] = event.GetPos(); if (m_LastSliceDimension == 0) { mitk::SliceNavigationController* snc = dynamic_cast( sender ); if (snc) snc->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnFrontalTimeChanged(itk::Object* sender, const itk::EventObject& e) { const mitk::SliceNavigationController::GeometryTimeEvent& event = dynamic_cast(e); m_TimeStep[1] = event.GetPos(); if (m_LastSliceDimension == 1) { mitk::SliceNavigationController* snc = dynamic_cast( sender ); if (snc) snc->SendSlice(); // will trigger a new interpolation } } void QmitkSlicesInterpolator::OnAxialSliceChanged(const itk::EventObject& e) { if ( TranslateAndInterpolateChangedSlice( e, 2 ) ) { if (m_MultiWidget) { mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget1->GetRenderWindow())->RequestUpdate(); } } } void QmitkSlicesInterpolator::OnTransversalSliceChanged(const itk::EventObject& e) { this->OnAxialSliceChanged(e); } void QmitkSlicesInterpolator::OnSagittalSliceChanged(const itk::EventObject& e) { if ( TranslateAndInterpolateChangedSlice( e, 0 ) ) { if (m_MultiWidget) { mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget2->GetRenderWindow())->RequestUpdate(); } } } void QmitkSlicesInterpolator::OnFrontalSliceChanged(const itk::EventObject& e) { if ( TranslateAndInterpolateChangedSlice( e, 1 ) ) { if (m_MultiWidget) { mitk::BaseRenderer::GetInstance(m_MultiWidget->mitkWidget3->GetRenderWindow())->RequestUpdate(); } } } bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e, unsigned int windowID) { if (!m_2DInterpolationEnabled) return false; try { const mitk::SliceNavigationController::GeometrySliceEvent& event = dynamic_cast(e); mitk::TimeGeometry* tsg = event.GetTimeGeometry(); if (tsg && m_TimeStep.size() > windowID) { - mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(tsg->GetGeometryForTimeStep(m_TimeStep[windowID])); + mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(tsg->GetGeometryForTimeStep(m_TimeStep[windowID]).GetPointer()); if (slicedGeometry) { mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetGeometry2D( event.GetPos() )); if (plane) Interpolate( plane, m_TimeStep[windowID] ); return true; } } } catch(std::bad_cast) { return false; // so what } return false; } void QmitkSlicesInterpolator::Interpolate( mitk::PlaneGeometry* plane, unsigned int timeStep ) { if (m_ToolManager) { mitk::DataNode* node = m_ToolManager->GetWorkingData(0); if (node) { m_Segmentation = dynamic_cast(node->GetData()); if (m_Segmentation) { int clickedSliceDimension(-1); int clickedSliceIndex(-1); // calculate real slice position, i.e. slice of the image and not slice of the TimeGeometry mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex ); mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( clickedSliceDimension, clickedSliceIndex, timeStep ); m_FeedbackNode->SetData( interpolation ); // Workaround for Bug 11318 if ((interpolation.IsNotNull()) && (interpolation->GetGeometry() != NULL)) { if(clickedSliceDimension == 1) { mitk::Point3D orig = interpolation->GetGeometry()->GetOrigin(); orig[0] = orig[0]; orig[1] = orig[1] + 0.5; orig[2] = orig[2]; interpolation->GetGeometry()->SetOrigin(orig); } } // Workaround for Bug 11318 END m_LastSliceDimension = clickedSliceDimension; m_LastSliceIndex = clickedSliceIndex; } } } } void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished() { mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult(); if(interpolatedSurface.IsNotNull()) { m_BtnAccept3DInterpolation->setEnabled(true); m_InterpolatedSurfaceNode->SetData(interpolatedSurface); m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface()); this->Show3DInterpolationResult(true); if( !m_DataStorage->Exists(m_InterpolatedSurfaceNode) && !m_DataStorage->Exists(m_3DContourNode)) { m_DataStorage->Add(m_3DContourNode); m_DataStorage->Add(m_InterpolatedSurfaceNode); } } else if (interpolatedSurface.IsNull()) { m_BtnAccept3DInterpolation->setEnabled(false); if (m_DataStorage->Exists(m_InterpolatedSurfaceNode)) { this->Show3DInterpolationResult(false); } } if (m_MultiWidget) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::OnAcceptInterpolationClicked() { if (m_Segmentation && m_FeedbackNode->GetData()) { //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); mitk::OverwriteSliceImageFilter::Pointer slicewriter = mitk::OverwriteSliceImageFilter::New(); slicewriter->SetInput( m_Segmentation ); slicewriter->SetCreateUndoInformation( true ); slicewriter->SetSliceImage( dynamic_cast(m_FeedbackNode->GetData()) ); slicewriter->SetSliceDimension( m_LastSliceDimension ); slicewriter->SetSliceIndex( m_LastSliceIndex ); slicewriter->SetTimeStep( m_TimeStep[m_LastSliceDimension] ); slicewriter->Update(); m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::AcceptAllInterpolations(unsigned int windowID) { // first creates a 3D diff image, then applies this diff to the segmentation if (m_Segmentation) { int sliceDimension(-1); int dummySliceIndex(-1); if (!GetSliceForWindowsID(windowID, sliceDimension, dummySliceIndex)) { return; // cannot determine slice orientation } //making interpolation separately undoable mitk::UndoStackItem::IncCurrObjectEventId(); mitk::UndoStackItem::IncCurrGroupEventId(); mitk::UndoStackItem::ExecuteIncrement(); // create a diff image for the undo operation mitk::Image::Pointer diffImage = mitk::Image::New(); diffImage->Initialize( m_Segmentation ); mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); diffImage->Initialize( pixelType, 3, m_Segmentation->GetDimensions() ); memset( diffImage->GetData(), 0, (pixelType.GetBpe() >> 3) * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2) ); // now the diff image is all 0 unsigned int timeStep( m_TimeStep[windowID] ); // a slicewriter to create the diff image mitk::OverwriteSliceImageFilter::Pointer diffslicewriter = mitk::OverwriteSliceImageFilter::New(); diffslicewriter->SetCreateUndoInformation( false ); diffslicewriter->SetInput( diffImage ); diffslicewriter->SetSliceDimension( sliceDimension ); diffslicewriter->SetTimeStep( timeStep ); unsigned int totalChangedSlices(0); unsigned int zslices = m_Segmentation->GetDimension( sliceDimension ); mitk::ProgressBar::GetInstance()->AddStepsToDo(zslices); for (unsigned int sliceIndex = 0; sliceIndex < zslices; ++sliceIndex) { mitk::Image::Pointer interpolation = m_Interpolator->Interpolate( sliceDimension, sliceIndex, timeStep ); if (interpolation.IsNotNull()) // we don't check if interpolation is necessary/sensible - but m_Interpolator does { diffslicewriter->SetSliceImage( interpolation ); diffslicewriter->SetSliceIndex( sliceIndex ); diffslicewriter->Update(); ++totalChangedSlices; } mitk::ProgressBar::GetInstance()->Progress(); } if (totalChangedSlices > 0) { // store undo stack items if ( true ) { // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image mitk::ApplyDiffImageOperation* doOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); mitk::ApplyDiffImageOperation* undoOp = new mitk::ApplyDiffImageOperation( mitk::OpTEST, m_Segmentation, diffImage, timeStep ); undoOp->SetFactor( -1.0 ); std::stringstream comment; comment << "Accept all interpolations (" << totalChangedSlices << ")"; mitk::OperationEvent* undoStackItem = new mitk::OperationEvent( mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment.str() ); mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); // acutally apply the changes here mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation( doOp ); } } m_FeedbackNode->SetData(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkSlicesInterpolator::FinishInterpolation(int windowID) { //this redirect is for calling from outside if (windowID < 0) OnAcceptAllInterpolationsClicked(); else AcceptAllInterpolations( (unsigned int)windowID ); } void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked() { QMenu orientationPopup(this); std::map::const_iterator it; for(it = ACTION_TO_SLICEDIMENSION.begin(); it != ACTION_TO_SLICEDIMENSION.end(); it++) orientationPopup.addAction(it->first); connect( &orientationPopup, SIGNAL(triggered(QAction*)), this, SLOT(OnAcceptAllPopupActivated(QAction*)) ); orientationPopup.exec( QCursor::pos() ); } void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked() { if (m_InterpolatedSurfaceNode.IsNotNull() && m_InterpolatedSurfaceNode->GetData()) { mitk::SurfaceToImageFilter::Pointer s2iFilter = mitk::SurfaceToImageFilter::New(); s2iFilter->MakeOutputBinaryOn(); s2iFilter->SetInput(dynamic_cast(m_InterpolatedSurfaceNode->GetData())); // check if ToolManager holds valid ReferenceData if (m_ToolManager->GetReferenceData(0) == NULL) { return; } s2iFilter->SetImage(dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData())); s2iFilter->Update(); mitk::DataNode* segmentationNode = m_ToolManager->GetWorkingData(0); segmentationNode->SetData(s2iFilter->GetOutput()); m_RBtnDisableInterpolation->setChecked(true); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); this->Show3DInterpolationResult(false); } } void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction* action) { try { std::map::const_iterator iter = ACTION_TO_SLICEDIMENSION.find( action ); if (iter != ACTION_TO_SLICEDIMENSION.end()) { int windowID = iter->second; AcceptAllInterpolations( windowID ); } } catch(...) { /* Showing message box with possible memory error */ QMessageBox errorInfo; errorInfo.setWindowTitle("Interpolation Process"); errorInfo.setIcon(QMessageBox::Critical); errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!"); errorInfo.exec(); //additional error message on std::cerr std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl; } } void QmitkSlicesInterpolator::OnInterpolationActivated(bool on) { m_2DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() ) { if (on && !m_DataStorage->Exists(m_FeedbackNode)) { m_DataStorage->Add( m_FeedbackNode ); } //else //{ // m_DataStorage->Remove( m_FeedbackNode ); //} } } catch(...) { // don't care (double add/remove) } if (m_ToolManager) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); QWidget::setEnabled( workingNode != NULL ); m_BtnAcceptAllInterpolations->setEnabled( on ); m_BtnAcceptInterpolation->setEnabled( on ); m_FeedbackNode->SetVisibility( on ); if (!on) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } if (workingNode) { mitk::Image* segmentation = dynamic_cast(workingNode->GetData()); if (segmentation) { m_Interpolator->SetSegmentationVolume( segmentation ); if (referenceNode) { mitk::Image* referenceImage = dynamic_cast(referenceNode->GetData()); m_Interpolator->SetReferenceVolume( referenceImage ); // may be NULL } } } } UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::Run3DInterpolation() { m_SurfaceInterpolator->Interpolate(); } void QmitkSlicesInterpolator::StartUpdateInterpolationTimer() { m_Timer->start(500); } void QmitkSlicesInterpolator::StopUpdateInterpolationTimer() { m_Timer->stop(); m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0,255.0,0.0)); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::ChangeSurfaceColor() { float currentColor[3]; m_InterpolatedSurfaceNode->GetColor(currentColor); float yellow[3] = {255.0,255.0,0.0}; if( currentColor[2] == yellow[2]) { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(255.0,255.0,255.0)); } else { m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(yellow)); } m_InterpolatedSurfaceNode->Update(); mitk::RenderingManager::GetInstance()->RequestUpdate(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetRenderWindow()); } void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on) { m_3DInterpolationEnabled = on; try { if ( m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); if ((workingNode->IsSelected() && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult && m_3DInterpolationEnabled) { int ret = QMessageBox::Yes; if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5) { QMessageBox msgBox; msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!"); msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?"); msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); ret = msgBox.exec(); } if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); if (ret == QMessageBox::Yes) { m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } else { m_RBtnDisableInterpolation->toggle(); } } else if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnAccept3DInterpolation->setEnabled(m_3DInterpolationEnabled); } } else { QWidget::setEnabled( false ); m_CbShowMarkers->setEnabled(m_3DInterpolationEnabled); } } if (!m_3DInterpolationEnabled) { this->Show3DInterpolationResult(false); m_BtnAccept3DInterpolation->setEnabled(m_3DInterpolationEnabled); } } catch(...) { MITK_ERROR<<"Error with 3D surface interpolation!"; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::EnableInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated OnInterpolationActivated(on); } void QmitkSlicesInterpolator::Enable3DInterpolation(bool on) { // only to be called from the outside world // just a redirection to OnInterpolationActivated On3DInterpolationActivated(on); } void QmitkSlicesInterpolator::UpdateVisibleSuggestion() { if (m_2DInterpolationEnabled) { // determine which one is the current view, try to do an initial interpolation mitk::BaseRenderer* renderer = mitk::GlobalInteraction::GetInstance()->GetFocus(); if (renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeGeometry* timeGeometry = dynamic_cast( renderer->GetWorldGeometry() ); if (timeGeometry) { mitk::SliceNavigationController::GeometrySliceEvent event( const_cast(timeGeometry), renderer->GetSlice() ); if ( renderer->GetCurrentWorldGeometry2DNode() ) { if ( renderer->GetCurrentWorldGeometry2DNode()==this->m_MultiWidget->GetWidgetPlane1() ) { TranslateAndInterpolateChangedSlice( event, 2 ); } else if ( renderer->GetCurrentWorldGeometry2DNode()==this->m_MultiWidget->GetWidgetPlane2() ) { TranslateAndInterpolateChangedSlice( event, 0 ); } else if ( renderer->GetCurrentWorldGeometry2DNode()==this->m_MultiWidget->GetWidgetPlane3() ) { TranslateAndInterpolateChangedSlice( event, 1 ); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject& /*e*/) { // something (e.g. undo) changed the interpolation info, we should refresh our display UpdateVisibleSuggestion(); } void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject& /*e*/) { if(m_3DInterpolationEnabled) { if (m_Watcher.isRunning()) m_Watcher.waitForFinished(); m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation); m_Watcher.setFuture(m_Future); } } bool QmitkSlicesInterpolator::GetSliceForWindowsID(unsigned windowID, int& sliceDimension, int& sliceIndex) { mitk::BaseRenderer* renderer(NULL); // find sliceDimension for windowID: // windowID 2: axial window = renderWindow1 // windowID 1: frontal window = renderWindow3 // windowID 0: sagittal window = renderWindow2 if ( m_MultiWidget ) { switch (windowID) { case 2: default: renderer = m_MultiWidget->mitkWidget1->GetRenderer(); break; case 1: renderer = m_MultiWidget->mitkWidget3->GetRenderer(); break; case 0: renderer = m_MultiWidget->mitkWidget2->GetRenderer(); break; } } if ( m_Segmentation && renderer && renderer->GetMapperID() == mitk::BaseRenderer::Standard2D) { const mitk::TimeGeometry* timeGeometry = renderer->GetTimeWorldGeometry(); if (timeGeometry) { - mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(timeGeometry->GetGeometryForTimeStep(m_TimeStep[windowID])); + mitk::SlicedGeometry3D* slicedGeometry = dynamic_cast(timeGeometry->GetGeometryForTimeStep(m_TimeStep[windowID]).GetPointer()); if (slicedGeometry) { mitk::PlaneGeometry* plane = dynamic_cast(slicedGeometry->GetGeometry2D( renderer->GetSlice() )); Interpolate( plane, m_TimeStep[windowID] ); return mitk::SegTool2D::DetermineAffectedImageSlice( m_Segmentation, plane, sliceDimension, sliceIndex ); } } } return false; } void QmitkSlicesInterpolator::OnMultiWidgetDeleted(QObject*) { if (m_MultiWidget) { m_MultiWidget = NULL; } } void QmitkSlicesInterpolator:: SetCurrentContourListID() { if ( m_DataStorage.IsNotNull() && m_ToolManager ) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (workingNode) { //int listID; bool isInterpolationResult(false); workingNode->GetBoolProperty("3DInterpolationResult",isInterpolationResult); if ((m_MultiWidget != NULL && workingNode->IsSelected() && workingNode->IsVisible(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")))) && !isInterpolationResult) { QWidget::setEnabled( true ); mitk::Vector3D spacing = workingNode->GetData()->GetGeometry( m_MultiWidget->GetRenderWindow3()->GetRenderer()->GetTimeStep() )->GetSpacing(); double minSpacing (100); double maxSpacing (0); for (int i =0; i < 3; i++) { if (spacing[i] < minSpacing) { minSpacing = spacing[i]; } else if (spacing[i] > maxSpacing) { maxSpacing = spacing[i]; } } m_SurfaceInterpolator->SetSegmentationImage(dynamic_cast(workingNode->GetData())); m_SurfaceInterpolator->SetMaxSpacing(maxSpacing); m_SurfaceInterpolator->SetMinSpacing(minSpacing); m_SurfaceInterpolator->SetDistanceImageVolume(50000); m_SurfaceInterpolator->SetCurrentSegmentationInterpolationList(dynamic_cast(workingNode->GetData())); } } } } void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status) { if (m_InterpolatedSurfaceNode.IsNotNull()) m_InterpolatedSurfaceNode->SetVisibility(status); if (m_3DContourNode.IsNotNull()) m_3DContourNode->SetVisibility(status, mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); }