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>
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 |
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.
Definition at line 63 of file mitkSlicesRotator.h.
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.
{
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 ); } }
Point3D mitk::SlicesRotator::m_CenterOfRotation [protected] |
Definition at line 101 of file mitkSlicesRotator.h.
Referenced by ExecuteAction().
Point3D mitk::SlicesRotator::m_LastCursorPosition [protected] |
all SNCs that will be rotated
Definition at line 100 of file mitkSlicesRotator.h.
Referenced by ExecuteAction().
SNCVector mitk::SlicesRotator::m_RelevantSNCs [protected] |
Definition at line 97 of file mitkSlicesRotator.h.
Referenced by ExecuteAction(), and RotateToPoint().
SNCVector mitk::SlicesRotator::m_SNCsToBeRotated [protected] |
all SNCs that currently have CreatedWorldGeometries, that can be rotated.
Definition at line 98 of file mitkSlicesRotator.h.
Referenced by ExecuteAction().