Public Member Functions | Static Public Member Functions | Protected Member Functions | Protected Attributes

mitk::SlicesRotator Class Reference
[Navigation Control Classes]

Enables rotation of visible slices (for sliced geometries).This class takes care of several SliceNavigationControllers and handles slice selection / slice rotation. It is added as listener to GlobalInteraction by QmitkStdMultiWidget. More...

#include <mitkSlicesRotator.h>

Inheritance diagram for mitk::SlicesRotator:
Inheritance graph
[legend]
Collaboration diagram for mitk::SlicesRotator:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 mitkClassMacro (SlicesRotator, SlicesCoordinator)
 mitkNewMacro1Param (Self, const char *)
 New Macro with one parameter for creating this object with static New(..) method.
virtual void SetGeometry (const itk::EventObject &EventObject)
virtual void RotateToPoint (SliceNavigationController *rotationPlaneSNC, SliceNavigationController *rotatedPlaneSNC, const Point3D &point, bool linked=false)

Static Public Member Functions

static Pointer New ()

Protected Member Functions

 SlicesRotator (const char *machine)
virtual ~SlicesRotator ()
virtual void OnSliceControllerAdded (SliceNavigationController *snc)
virtual void OnSliceControllerRemoved (SliceNavigationController *snc)
virtual void UpdateRelevantSNCs ()
 Updates the list of SliceNavigationControllers that can handle rotation.
virtual bool ExecuteAction (Action *action, StateEvent const *stateEvent)

Protected Attributes

SNCVector m_RelevantSNCs
SNCVector m_SNCsToBeRotated
 all SNCs that currently have CreatedWorldGeometries, that can be rotated.
Point3D m_LastCursorPosition
 all SNCs that will be rotated
Point3D m_CenterOfRotation

Detailed Description

Enables rotation of visible slices (for sliced geometries).

This class takes care of several SliceNavigationControllers and handles slice selection / slice rotation. It is added as listener to GlobalInteraction by QmitkStdMultiWidget.

The SlicesRotator class adds the possibility of slice rotation to the "normal" behaviour of SliceNavigationControllers. This additional class is needed, because one has to be aware of several "visible slices" (selected Geometry2Ds of some SliceNavigationControllers) in order to choose between rotation and slice selection.

Rotation is achieved by modifying (rotating) the generated TimeSlicedGeometry of the corresponding SliceNavigationController.

With SlicesRotator, the rule to choose between slice rotation and selection is simple: For a mouse down event, count the number of visible planes, which are "near" the cursor. If this number equals 2 (one for the window, which currently holds the cursor, one for the intersection line of another visible slice), then initiate rotation, else select slices near the cursor. If "LinkPlanes" is set to true, the rotation is applied to the planes of all registered SNCs, not only of the one associated with the directly selected plane.

In contrast to the situation without the SlicesRotator, the SliceNavigationControllers are now not directly registered as listeners to GlobalInteraction. SlicesRotator is registered as a listener and decides whether something should be rotated or whether another slice should be selected. In the latter case, a PositionEvent is just forwarded to the SliceNavigationController.

See also:
SlicesSwiveller

Definition at line 63 of file mitkSlicesRotator.h.


Constructor & Destructor Documentation

mitk::SlicesRotator::SlicesRotator ( const char *  machine ) [protected]

Definition at line 51 of file mitkSlicesRotator.cpp.

: SlicesCoordinator(machine)
{

mitk::SlicesRotator::~SlicesRotator (  ) [protected, virtual]

Definition at line 57 of file mitkSlicesRotator.cpp.

{


Member Function Documentation

bool mitk::SlicesRotator::ExecuteAction ( Action action,
StateEvent const *  stateEvent 
) [protected, virtual]

for implementation in subclasses

Reimplemented from mitk::SlicesCoordinator.

Definition at line 282 of file mitkSlicesRotator.cpp.

References mitk::AcCHECKPOINT, mitk::AcMOVE, mitk::AcROTATE, mitk::AcROTATEEND, mitk::AcROTATESTART, mitk::Geometry2D::Distance(), mitk::EIDNO, mitk::EIDYES, mitk::StateMachine::ExecuteOperation(), mitk::Action::GetActionId(), mitk::BaseRenderer::GetDisplayGeometry(), mitk::StateEvent::GetEvent(), mitk::SlicedGeometry3D::GetGeometry2D(), mitk::TimeSlicedGeometry::GetGeometry3D(), mitk::RenderingManager::GetInstance(), mitk::DisplayGeometry::GetOriginInMM(), mitk::DisplayGeometry::GetScaleFactorMMPerDisplayUnit(), mitk::Event::GetSender(), mitk::BaseRenderer::GetSliceNavigationController(), mitk::DisplayPositionEvent::GetWorldPosition(), mitk::StateMachine::HandleEvent(), mitk::PlaneGeometry::IntersectionLine(), mitk::PlaneGeometry::IntersectionPoint(), m_CenterOfRotation, m_LastCursorPosition, mitk::SlicesCoordinator::m_LinkPlanes, m_RelevantSNCs, m_SNCsToBeRotated, mitk::DisplayGeometry::Map(), MITK_ERROR, mitk::DisplayGeometry::MoveBy(), mitk::OpROTATE, mitk::Line< TCoordRep, NPointDimension >::Project(), mitk::RenderingManager::RequestUpdateAll(), mitk::SlicesCoordinator::ResetMouseCursor(), mitk::SlicesCoordinator::SetMouseCursor(), and mitk::DisplayGeometry::WorldToDisplay().

{
  const ScalarType ThreshHoldDistancePixels = 12.0;
  
  bool ok = false;
  
  switch ( action->GetActionId() )
  {
    case AcMOVE:
    {
      // just reach through
      for (SNCVector::iterator iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter)
      {
        if ( !(*iter)->GetSliceLocked()  )
        {
          (*iter)->ExecuteAction(action, stateEvent);
        }
      }
      
      ok = true;
      break;
    }
    case AcROTATE:
    {
      const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
      if (!posEvent) break;
      
      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 op(OpROTATE, m_CenterOfRotation, axisOfRotation, angle);

      // TEST
      int i = 0;

      for (SNCVector::iterator iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
      {
        BaseRenderer *renderer = (*iter)->GetRenderer();
        if ( renderer == NULL )
        {
          continue;
        }

        DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();

        // MITK_INFO << i << ":" << std::endl;

        Point2D point2DWorld, point2DDisplayPre, point2DDisplayPost;
        displayGeometry->Map( m_CenterOfRotation, point2DWorld );
        displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPre );

        // MITK_INFO << "  WorldPre: " << point2DWorld << " / DisplayPre: " << point2DDisplayPre << std::endl;

        const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
        const TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>(geometry3D);
        if (!timeSlicedGeometry) continue;
        
        const_cast<TimeSlicedGeometry*>(timeSlicedGeometry)->ExecuteOperation(&op);

        //vtkLinearTransform *inverseTransformVtk = 
        //  displayGeometry->GetVtkTransform()->GetLinearInverse();

        //ScalarType pvtkCenterOfRotation[3];
        //pvtkCenterOfRotation[0] = m_CenterOfRotation[0];
        //pvtkCenterOfRotation[1] = m_CenterOfRotation[1];
        //pvtkCenterOfRotation[2] = m_CenterOfRotation[2];

        //ScalarType scaleFactorMMPerUnitX = 
        //  displayGeometry->GetExtentInMM(0) / displayGeometry->GetExtent(0);
        //ScalarType scaleFactorMMPerUnitY = 
        //  displayGeometry->GetExtentInMM(1) / displayGeometry->GetExtent(1);  

        //ScalarType scaleFactorMMPerDisplayUnit = displayGeometry->GetScaleFactorMMPerDisplayUnit();
        //Vector2D &originInMM = displayGeometry->GetOriginInMM();


        //ScalarType pvtkDisplayPost[3];
        //inverseTransformVtk->TransformPoint( pvtkCenterOfRotation, pvtkDisplayPost );

        //pvtkDisplayPost[0] *= scaleFactorMMPerUnitX;
        //pvtkDisplayPost[1] *= scaleFactorMMPerUnitY;

        //pvtkDisplayPost[0] -= originInMM[0];
        //pvtkDisplayPost[1] -= originInMM[1];

        //pvtkDisplayPost[0] /= scaleFactorMMPerDisplayUnit;
        //pvtkDisplayPost[1] /= scaleFactorMMPerDisplayUnit;

        //point2DDisplayPost[0] = pvtkDisplayPost[0];
        //point2DDisplayPost[1] = pvtkDisplayPost[1];


        displayGeometry->Map( m_CenterOfRotation, point2DWorld );
        displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
        Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;

        Vector2D origin = displayGeometry->GetOriginInMM();
        // MITK_INFO << "  WorldPost: " << point2DWorld << " / DisplayPost: " << point2DDisplayPost << std::endl;
        // MITK_INFO << "  Diff   - " << vector2DDisplayDiff << std::endl;
        // MITK_INFO << "  Origin - " << origin << std::endl;
        ++i;

        displayGeometry->MoveBy( vector2DDisplayDiff );

        (*iter)->SendCreatedWorldGeometryUpdate();
      } 
      // MITK_INFO << "--------------------------------" << std::endl;

      
      
      // TEST
      //BaseRenderer* renderer = stateEvent->GetEvent()->GetSender(); // TODO this is NOT SNC-specific! Should be!
      //
      //DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry();
      //if (!displayGeometry) break;

      //Point2D point2DWorld, point2DDisplay;
      //displayGeometry->Map( m_CenterOfRotation, point2DWorld );
      //displayGeometry->WorldToDisplay( point2DWorld, point2DDisplay );

      //MITK_INFO << "RotationCenter: " << m_CenterOfRotation << std::endl;
      //MITK_INFO << "PointWorld:     " << point2DWorld << std::endl;
      //MITK_INFO << "PointDisplay:   " << point2DDisplay << std::endl;
      //MITK_INFO << "--------------------------------------------" << std::endl;



      RenderingManager::GetInstance()->RequestUpdateAll();
      
      this->InvokeEvent( SliceRotationEvent() ); // notify listeners
      
      ok = true;
      break;
    }
    case AcCHECKPOINT:
    {
      // decide between moving and rotation 

      // Alle SNCs (Anzahl N) nach dem Abstand von posEvent->GetWorldPosition() zur aktuellen Ebene fragen.
      // Anzahl der Ebenen zaehlen, die naeher als ein gewisser Schwellwertwert sind -> nNah.
      // Wenn nNah == N
      //   Generiere ein PointEvent und schicke das an alle SNCs -> bewege den kreuz-mittelpunkt
      // Wenn nNah == 2
      //   Streiche stateEvent->Sender aus der Liste der nahen Ebenen
      //   fuer die uebrigen generiere eine RotationOperation und fuehre die aus
      // sonst
      //   
      const DisplayPositionEvent* posEvent = dynamic_cast<const DisplayPositionEvent*>(stateEvent->GetEvent());
      if (!posEvent) break;

      Point3D cursor = posEvent->GetWorldPosition();
      //m_LastCursorPosition = cursor;
      
      unsigned int numNearPlanes = 0;
      m_SNCsToBeRotated.clear();
      Geometry2D* geometryToBeRotated = NULL;  // this one is grabbed
      Geometry2D* otherGeometry = NULL;        // this is also visible (for calculation of intersection)
      Geometry2D* clickedGeometry = NULL;      // the event originates from this one
      SlicedGeometry3D* clickedSlicedGeometry;

      for (SNCVector::iterator iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.end(); ++iter)
      {
        unsigned int slice = (*iter)->GetSlice()->GetPos();
        unsigned int time  = (*iter)->GetTime()->GetPos();
        
        const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
        const TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
        if (!timeSlicedGeometry) continue;
    
        const SlicedGeometry3D* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>( timeSlicedGeometry->GetGeometry3D(time) );
        if (!slicedGeometry) continue;

        Geometry2D* geometry2D = slicedGeometry->GetGeometry2D(slice);
        if (!geometry2D) continue; // this is not necessary?

        ScalarType distanceMM = geometry2D->Distance( cursor );

        BaseRenderer* renderer = stateEvent->GetEvent()->GetSender(); // TODO this is NOT SNC-specific! Should be!
        
        DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry();
        if (!displayGeometry) continue;
        
        ScalarType distancePixels = distanceMM / displayGeometry->GetScaleFactorMMPerDisplayUnit();
        if ( distancePixels <= ThreshHoldDistancePixels )
        {
          ++numNearPlanes; // count this one as a plane near to the cursor
        }
       
        if ( *iter == renderer->GetSliceNavigationController() ) // don't rotate the one where the user clicked
        {
          clickedGeometry = geometry2D;
          clickedSlicedGeometry = const_cast<SlicedGeometry3D*>(slicedGeometry);
        }
        else
        {
          // @TODO here waits some bug to be found - maybe fixed by the || m_LinkPlanes in next line
          if ( (distancePixels <= ThreshHoldDistancePixels)
            && !(*iter)->GetSliceRotationLocked()
            && (m_SNCsToBeRotated.empty() || m_LinkPlanes) )
          {
            // this one is behind the clicked "line"
            m_SNCsToBeRotated.push_back(*iter);
            geometryToBeRotated = geometry2D;
          }
          else
          {
            otherGeometry = geometry2D;

            if ( m_LinkPlanes )
            {
              // All slices are rotated, i.e. the relative angles between
              // slices remain fixed
              m_SNCsToBeRotated.push_back(*iter);
            }
          }
        }
      }

      bool move (true);

      if ( geometryToBeRotated && otherGeometry && clickedGeometry
        && ( numNearPlanes == 2 ) )
      {
        // assure all three are valid, so calculation of center of rotation can be done
        move = false;
      }
      
      StateEvent *newStateEvent(NULL);

      // question in state machine is: "rotate?"
      if (move)
      {
        // move all planes to posEvent->GetWorldPosition()
        newStateEvent = new StateEvent(EIDNO, stateEvent->GetEvent());
      }
      else
      {
        // determine center of rotation TODO requires two plane geometries...
        PlaneGeometry* planeGeometry  = dynamic_cast<PlaneGeometry*>(clickedGeometry);
        PlaneGeometry* planeGeometry1 = dynamic_cast<PlaneGeometry*>(geometryToBeRotated);
        PlaneGeometry* planeGeometry2 = dynamic_cast<PlaneGeometry*>(otherGeometry);

        if (!planeGeometry || !planeGeometry1 || !planeGeometry2) break; 
        
        Line3D intersection;
        if (!planeGeometry->IntersectionLine( planeGeometry1, intersection ))   break;
        m_LastCursorPosition = intersection.Project(cursor);
        if (!planeGeometry2->IntersectionPoint(intersection, m_CenterOfRotation)) break;
        // everything's fine
        newStateEvent = new StateEvent(EIDYES, stateEvent->GetEvent());

      }

      if (!newStateEvent) MITK_ERROR << "rotation would be nice but is impossible... " << std::endl;
      
      this->HandleEvent( newStateEvent );
      delete newStateEvent;

      ok = true;
      break;
    }
    case AcROTATESTART:
    {
      this->SetMouseCursor( rotate_cursor_xpm, 0, 0 );
      this->InvokeEvent( SliceRotationEvent() ); // notify listeners
      break;
    }
    case AcROTATEEND:
    {
      this->ResetMouseCursor();
      this->InvokeEvent( SliceRotationEvent() ); // notify listeners
      break;
    }
    default:
    {
      break;
    }
  }

  return ok;
mitk::SlicesRotator::mitkClassMacro ( SlicesRotator  ,
SlicesCoordinator   
)
mitk::SlicesRotator::mitkNewMacro1Param ( Self  ,
const char *   
)

New Macro with one parameter for creating this object with static New(..) method.

Reimplemented from mitk::SlicesCoordinator.

SlicesRotator::Pointer mitk::SlicesRotator::New (  ) [static]

Definition at line 46 of file mitkSlicesRotator.cpp.

Referenced by QmitkStdMultiWidget::InitializeWidget().

{
  return SlicesRotator::New("slices-rotator");
void mitk::SlicesRotator::OnSliceControllerAdded ( SliceNavigationController snc ) [protected, virtual]

for implementation in subclasses

Reimplemented from mitk::SlicesCoordinator.

Definition at line 64 of file mitkSlicesRotator.cpp.

References mitk::SliceNavigationController::ConnectGeometrySendEvent().

{
  if (!snc) return;

  snc->ConnectGeometrySendEvent(this); // connects creation of new world geometry to Self::SetGeometry
void mitk::SlicesRotator::OnSliceControllerRemoved ( SliceNavigationController snc ) [protected, virtual]

for implementation in subclasses

Reimplemented from mitk::SlicesCoordinator.

Definition at line 72 of file mitkSlicesRotator.cpp.

{
  if (!snc) return;
  // nothing to do
void mitk::SlicesRotator::RotateToPoint ( SliceNavigationController rotationPlaneSNC,
SliceNavigationController rotatedPlaneSNC,
const Point3D &  point,
bool  linked = false 
) [virtual]

Definition at line 88 of file mitkSlicesRotator.cpp.

References mitk::PlaneGeometry::DistanceFromPlane(), mitk::StateMachine::ExecuteOperation(), mitk::SliceNavigationController::GetCreatedWorldGeometry(), mitk::SliceNavigationController::GetCurrentPlaneGeometry(), mitk::BaseRenderer::GetDisplayGeometry(), mitk::DisplayGeometry::GetOriginInMM(), mitk::SliceNavigationController::GetRenderer(), mitk::PlaneGeometry::IntersectionLine(), mitk::PlaneGeometry::IntersectionPoint(), m_RelevantSNCs, mitk::DisplayGeometry::Map(), mitk::DisplayGeometry::MoveBy(), mitk::OpROTATE, mitk::Line< TCoordRep, NPointDimension >::Project(), mitk::Geometry2D::Project(), mitk::SliceNavigationController::SendCreatedWorldGeometryUpdate(), and mitk::DisplayGeometry::WorldToDisplay().

{
  SliceNavigationController *thirdSNC = NULL;

  SNCVector::iterator iter;
  for ( iter = m_RelevantSNCs.begin(); iter != m_RelevantSNCs.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 );

    const Geometry3D *geometry3D = rotatedPlaneSNC->GetCreatedWorldGeometry();
    const TimeSlicedGeometry *timeSlicedGeometry = 
      dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
    if ( !timeSlicedGeometry )
    {
      return;
    }
    
    const_cast< TimeSlicedGeometry * >( timeSlicedGeometry )->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_RelevantSNCs.begin(); iter != m_RelevantSNCs.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 );

      const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
      const TimeSlicedGeometry *timeSlicedGeometry = 
        dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
      if ( !timeSlicedGeometry )
      {
        continue;
      }
      
      const_cast< TimeSlicedGeometry * >( timeSlicedGeometry )->ExecuteOperation( &op );

      displayGeometry->Map( rotationCenter, point2DWorld );
      displayGeometry->WorldToDisplay( point2DWorld, point2DDisplayPost );
      Vector2D vector2DDisplayDiff = point2DDisplayPost - point2DDisplayPre;

      Vector2D origin = displayGeometry->GetOriginInMM();

      displayGeometry->MoveBy( vector2DDisplayDiff );

      (*iter)->SendCreatedWorldGeometryUpdate();
    } 
  }
void mitk::SlicesRotator::SetGeometry ( const itk::EventObject &  EventObject ) [virtual]

Is called whenever a SliceNavigationController invokes an event. Will update the list of SliceNavigationControllers that can handle rotation

Definition at line 80 of file mitkSlicesRotator.cpp.

{
  // there is no way to determine the sender?
  // ==> update whole list of SNCs
  UpdateRelevantSNCs();
void mitk::SlicesRotator::UpdateRelevantSNCs (  ) [protected, virtual]

Updates the list of SliceNavigationControllers that can handle rotation.

Definition at line 238 of file mitkSlicesRotator.cpp.

{
  m_RelevantSNCs.clear();

  for (SNCVector::iterator iter = m_SliceNavigationControllers.begin(); iter != m_SliceNavigationControllers.end(); ++iter)
  {
    const Geometry3D* geometry3D = (*iter)->GetCreatedWorldGeometry();
    const TimeSlicedGeometry* timeSlicedGeometry = dynamic_cast<const TimeSlicedGeometry*>( geometry3D );
    if (!timeSlicedGeometry) continue;

    const SlicedGeometry3D* slicedGeometry = dynamic_cast<const SlicedGeometry3D*>( timeSlicedGeometry->GetGeometry3D(0) );
    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 );
    }
  }

Member Data Documentation

Definition at line 101 of file mitkSlicesRotator.h.

Referenced by ExecuteAction().

all SNCs that will be rotated

Definition at line 100 of file mitkSlicesRotator.h.

Referenced by ExecuteAction().

Definition at line 97 of file mitkSlicesRotator.h.

Referenced by ExecuteAction(), and RotateToPoint().

all SNCs that currently have CreatedWorldGeometries, that can be rotated.

Definition at line 98 of file mitkSlicesRotator.h.

Referenced by ExecuteAction().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines