31 #include "vtkRenderWindowInteractor.h"
35 #include "rotate_cursor.xpm"
50 if (!isHandled || m_AlwaysReact)
81 : m_IndexToSliceModifier(4),
83 m_InvertScrollDirection(false),
84 m_InvertZoomDirection(false),
85 m_InvertMoveDirection(false),
86 m_InvertLevelWindowDirection(false),
91 m_StartCoordinateInMM.Fill(0);
92 m_LastDisplayCoordinate.Fill(0);
93 m_LastCoordinateInMM.Fill(0);
94 m_CurrentDisplayCoordinate.Fill(0);
104 if (positionEvent == NULL)
135 if (posEvent ==
nullptr)
141 if (!ourViewportGeometry)
147 Line3D intersectionLineWithGeometryToBeRotated;
149 bool hitMultipleLines(
false);
150 m_SNCsToBeRotated.clear();
152 const double threshholdDistancePixels = 12.0;
156 for (
auto renWin : renWindows)
165 if (otherRenderersRenderPlane == NULL)
170 if (!ourViewportGeometry->
IntersectionLine(otherRenderersRenderPlane, intersectionLine))
176 double distanceFromIntersectionLine = intersectionLine.
Distance(cursorPosition);
179 if (distanceFromIntersectionLine > threshholdDistancePixels)
181 anyOtherGeometry = otherRenderersRenderPlane;
186 m_SNCsToBeRotated.push_back(snc);
191 if (geometryToBeRotated == NULL)
193 geometryToBeRotated = otherRenderersRenderPlane;
194 intersectionLineWithGeometryToBeRotated = intersectionLine;
195 m_SNCsToBeRotated.push_back(snc);
202 if (intersectionLine.
IsParallel(intersectionLineWithGeometryToBeRotated) &&
205 m_SNCsToBeRotated.push_back(snc);
209 hitMultipleLines =
true;
215 bool moveSlices(
true);
217 if (geometryToBeRotated && anyOtherGeometry && ourViewportGeometry && !hitMultipleLines)
229 m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.
Project(
233 intersectionLineWithGeometryToBeRotated,
248 const ScalarType ThresholdDistancePixels = 6.0;
257 if (!posEvent || !renderer)
262 m_SNCsToBeRotated.clear();
270 for (
auto renWin : renWindows)
287 clickedGeometry = planeGeometry;
288 m_SNCsToBeRotated.push_back(snc);
292 if (otherGeometry1 == NULL)
294 otherGeometry1 = planeGeometry;
298 otherGeometry2 = planeGeometry;
303 m_SNCsToBeRotated.push_back(snc);
310 if ((clickedGeometry != NULL) && (otherGeometry1 != NULL) && (otherGeometry2 != NULL) &&
313 m_CenterOfRotation = point;
314 if (m_CenterOfRotation.EuclideanDistanceTo(cursor) < ThresholdDistancePixels)
323 m_RotationPlaneNormal = clickedGeometry->
GetNormal();
327 clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D(xVector), m_RotationPlaneXVector);
328 clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D(yVector), m_RotationPlaneYVector);
330 m_RotationPlaneNormal.Normalize();
331 m_RotationPlaneXVector.Normalize();
332 m_RotationPlaneYVector.Normalize();
334 m_PreviousRotationAxis.Fill(0.0);
335 m_PreviousRotationAxis[2] = 1.0;
336 m_PreviousRotationAngle = 0.0;
353 m_CurrentDisplayCoordinate = m_LastDisplayCoordinate;
355 m_LastCoordinateInMM = m_StartCoordinateInMM;
363 float invertModifier = -1.0;
364 if (m_InvertMoveDirection)
366 invertModifier = 1.0;
379 auto renWindows = sender->GetRenderingManager()->GetAllRegisteredRenderWindows();
383 for (
auto renWin : renWindows)
386 renWin != sender->GetRenderWindow())
399 if (m_ZoomDirection ==
"updown")
401 distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
405 distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
408 if (m_InvertZoomDirection)
416 factor = 1.0 / m_ZoomFactor;
418 else if (distance > 0.0)
420 factor = 1.0 * m_ZoomFactor;
425 sender->GetCameraController()->Zoom(factor, m_StartCoordinateInMM);
426 sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow());
429 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
439 if (sliceNaviController)
443 if (m_ScrollDirection ==
"updown")
452 if (m_InvertScrollDirection)
459 if (delta > 0 && delta < m_IndexToSliceModifier)
461 delta = m_IndexToSliceModifier;
463 else if (delta < 0 && delta > -m_IndexToSliceModifier)
465 delta = -m_IndexToSliceModifier;
467 delta /= m_IndexToSliceModifier;
469 int newPos = sliceNaviController->GetSlice()->GetPos() + delta;
472 int maxSlices = sliceNaviController->GetSlice()->GetSteps();
480 while (newPos >= maxSlices)
495 sliceNaviController->GetSlice()->SetPos(newPos);
496 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
505 if (!sliceNaviController->GetSliceLocked())
510 stepper = sliceNaviController->GetTime();
520 if (!sliceNaviController->GetSliceLocked())
525 stepper = sliceNaviController->GetTime();
536 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
543 for (
unsigned int i = 0; i < allImageNodes->size(); i++)
545 bool isActiveImage =
false;
546 bool propFound = allImageNodes->at(i)->GetBoolProperty(
"imageForLevelWindow", isActiveImage);
548 if (propFound && isActiveImage)
550 node = allImageNodes->at(i);
564 node->GetLevelWindow(lv);
571 if (m_LevelDirection !=
"leftright")
577 int directionModifier = 1;
578 if (m_InvertLevelWindowDirection)
580 directionModifier = -1;
584 level += (m_CurrentDisplayCoordinate[levelIndex] - m_LastDisplayCoordinate[levelIndex]) * static_cast<ScalarType>(2) *
586 window += (m_CurrentDisplayCoordinate[windowIndex] - m_LastDisplayCoordinate[windowIndex]) *
587 static_cast<ScalarType>(2) * directionModifier;
592 sender->GetRenderingManager()->RequestUpdateAll();
597 this->SetMouseCursor(rotate_cursor_xpm, 0, 0);
602 this->ResetMouseCursor();
608 if (posEvent ==
nullptr)
613 Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
614 Vector3D toCursor = cursor - m_CenterOfRotation;
618 vnl_vector_fixed<ScalarType, 3> vnlDirection = vnl_cross_3d(toCursor.GetVnlVector(), toProjected.GetVnlVector());
619 axisOfRotation.SetVnlVector(vnlDirection);
623 ScalarType angle = -atan2((
double)(axisOfRotation.GetNorm()), (
double)(toCursor * toProjected));
624 angle *= 180.0 / vnl_math::pi;
625 m_LastCursorPosition = cursor;
631 for (SNCVector::iterator iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
633 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
639 (*iter)->SendCreatedWorldGeometryUpdate();
654 Vector2D relativeCursor = cursor - m_ReferenceCursor;
655 Vector3D relativeCursorAxis = m_RotationPlaneXVector * relativeCursor[0] + m_RotationPlaneYVector * relativeCursor[1];
659 Vector3D rotationAxis = itk::CrossProduct(m_RotationPlaneNormal, relativeCursorAxis);
661 ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0;
667 SNCVector::iterator iter;
668 for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
670 if (!(*iter)->GetSliceRotationLocked())
672 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
677 (*iter)->SendCreatedWorldGeometryUpdate();
684 for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
686 if (!(*iter)->GetSliceRotationLocked())
689 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
697 (*iter)->SendCreatedWorldGeometryUpdate();
701 m_PreviousRotationAxis = rotationAxis;
702 m_PreviousRotationAngle = rotationAngle;
715 std::string statusText;
735 node = this->GetTopLayerNode(nodes, worldposition, posEvent->
GetSender());
736 if (node.IsNotNull())
738 bool isBinary(
false);
739 node->GetBoolProperty(
"binary", isBinary);
744 if (!sourcenodes->empty())
746 topSourceNode = this->GetTopLayerNode(sourcenodes, worldposition, posEvent->
GetSender());
748 if (topSourceNode.IsNotNull())
750 image3D =
dynamic_cast<mitk::Image *
>(topSourceNode->GetData());
751 topSourceNode->GetIntProperty(
"Image.Displayed Component", component);
755 image3D =
dynamic_cast<mitk::Image *
>(node->GetData());
756 node->GetIntProperty(
"Image.Displayed Component", component);
761 image3D =
dynamic_cast<mitk::Image *
>(node->GetData());
762 node->GetIntProperty(
"Image.Displayed Component", component);
769 if (image3D.IsNotNull() && statusBar !=
nullptr)
772 image3D->GetGeometry()->WorldToIndex(worldposition, p);
774 auto pixelType = image3D->GetChannelDescriptor().GetPixelType().GetPixelType();
776 if (pixelType == itk::ImageIOBase::RGB || pixelType == itk::ImageIOBase::RGBA)
778 std::string pixelValue =
"Pixel RGB(A) value: ";
780 statusBar->DisplayImageInfo(worldposition, p, posEvent->
GetSender()->
GetTime(), pixelValue.c_str());
786 image3D->GetChannelDescriptor().GetPixelType(),
792 statusBar->DisplayImageInfo(worldposition, p, posEvent->
GetSender()->
GetTime(), pixelValue);
797 statusBar->DisplayImageInfoInvalid();
805 std::string strAutoRepeat =
"";
806 if (properties->GetStringProperty(
"autoRepeat", strAutoRepeat))
808 if (strAutoRepeat ==
"true")
814 m_AutoRepeat =
false;
818 std::string strPixelPerSlice =
"";
819 if (properties->GetStringProperty(
"pixelPerSlice", strPixelPerSlice))
821 m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str());
825 m_IndexToSliceModifier = 4;
828 if (!properties->GetStringProperty(
"scrollDirection", m_ScrollDirection))
830 m_ScrollDirection =
"updown";
833 m_InvertScrollDirection = GetBoolProperty(properties,
"invertScrollDirection",
false);
836 if (!properties->GetStringProperty(
"zoomDirection", m_ZoomDirection))
838 m_ZoomDirection =
"updown";
841 m_InvertZoomDirection = GetBoolProperty(properties,
"invertZoomDirection",
false);
843 m_InvertMoveDirection = GetBoolProperty(properties,
"invertMoveDirection",
false);
845 if (!properties->GetStringProperty(
"levelWindowDirection", m_LevelDirection))
847 m_LevelDirection =
"leftright";
850 m_InvertLevelWindowDirection = GetBoolProperty(properties,
"invertLevelWindowDirection",
false);
853 std::string strCoupled =
"";
854 if (properties->GetStringProperty(
"coupled", strCoupled))
856 if (strCoupled ==
"true")
859 m_LinkPlanes =
false;
863 std::string strZoomFactor =
"";
864 properties->GetStringProperty(
"zoomFactor", strZoomFactor);
866 if (atoi(strZoomFactor.c_str()) > 0)
868 m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0);
871 std::string strAlwaysReact =
"";
872 if (properties->GetStringProperty(
"alwaysReact", strAlwaysReact))
874 if (strAlwaysReact ==
"true")
876 m_AlwaysReact =
true;
880 m_AlwaysReact =
false;
885 m_AlwaysReact =
false;
891 if (interactionEvent->
GetSender() ==
nullptr)
900 const char *propertyName,
903 std::string valueAsString;
904 if (!propertyList->GetStringProperty(propertyName, valueAsString))
910 if (valueAsString ==
"true")
927 if (nodes.IsNotNull())
929 int maxlayer = -32768;
930 bool isHelper(
false);
931 for (
unsigned int x = 0; x < nodes->size(); x++)
933 nodes->at(x)->GetBoolProperty(
"helper object", isHelper);
934 if (nodes->at(x)->GetData()->GetGeometry()->IsInside(worldposition) && isHelper ==
false)
937 if (!(nodes->at(x)->GetIntProperty(
"layer", layer)))
939 if (layer > maxlayer)
941 if (static_cast<mitk::DataNode::Pointer>(nodes->at(x))->IsVisible(ren))
mitk::ScalarType FastSinglePixelAccess(mitk::PixelType, mitk::Image::Pointer im, ImageDataItem *item, itk::Index< 3 > idx, mitk::ScalarType &val, int component=0)
virtual bool CheckRotationPossible(const InteractionEvent *interactionEvent)
const itk::Point< TCoordRep, NPointDimension > & GetPoint1() const
Get start point of the line.
Super class for all position events.
double Distance(const itk::Point< TCoordRep, NPointDimension > &point) const
Distance of a point from the line.
double GetScaleFactorMMPerDisplayUnit() const
void SelectSliceByPoint(const mitk::Point3D &point)
Positions the SNC according to the specified point.
The LevelWindowProperty class Property for the mitk::LevelWindow.
BaseRenderer * GetSender() const
bool IntersectionPoint(const Line3D &line, Point3D &intersectionPoint) const
Calculate intersection point between the plane and a line.
static BaseRenderer * GetInstance(vtkRenderWindow *renWin)
virtual void StartRotation(StateMachineAction *, InteractionEvent *)
Starts crosshair rotation.
virtual void EndRotation(StateMachineAction *, InteractionEvent *)
Ends crosshair rotation.
virtual void Rotate(StateMachineAction *, InteractionEvent *event)
Point3D GetPositionInWorld() const
bool HandleEvent(InteractionEvent *event, DataNode *dataNode)
virtual void Scroll(StateMachineAction *, InteractionEvent *)
Performs scrolling relative to mouse/pointer movement.
Organizes the rendering process.
virtual bool FilterEvents(InteractionEvent *interactionEvent, DataNode *dataNode) override
ScalarType GetTime() const
Get the time in ms of the currently displayed content.
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
virtual void Notify(InteractionEvent *interactionEvent, bool isHandled) override
bool IsParallel(const Line< TCoordRep, NPointDimension > &line) const
Test if a lines is parallel to this line.
void MoveBy(const Vector2D &moveVectorInMM)
Constants for most interaction classes, due to the generic StateMachines.
std::string MITKCORE_EXPORT ConvertCompositePixelValueToString(Image::Pointer image, itk::Index< 3 > index)
Converts composite pixel values to a displayable string.
Controls the selection of the slice the associated BaseRenderer will display.
Point2D GetPointerPositionOnScreen() const
Vector3D GetNormal() const
Normal of the plane.
itk::SmartPointer< const Self > ConstPointer
virtual DataStorage::Pointer GetDataStorage() const
bool GetBoolProperty(mitk::PropertyList::Pointer propertyList, const char *propertyName, bool defaultValue)
Method to retrieve bool-value for given property from string-property in given propertylist.
virtual void Move(StateMachineAction *, InteractionEvent *)
Performs panning of the data set in the render window.
virtual void ScrollOneUp(StateMachineAction *, InteractionEvent *)
Scrolls one layer down.
The LevelWindow class Class to store level/window values.
virtual unsigned int GetSteps() const
virtual void ExecuteOperation(Operation *op) override
Executes the given operation on all time steps.
virtual mitk::RenderingManager * GetRenderingManager() const
Setter for the RenderingManager that handles this instance of BaseRenderer.
Vector< ScalarType, 3 > Vector3D
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual CameraController * GetCameraController()
virtual MapperSlotId GetMapperID()
Get the MapperSlotId to use.
Image class for storing images.
virtual void Init(StateMachineAction *, InteractionEvent *)
Initializes an interaction, saves the pointers start position for further reference.
const mitk::PlaneGeometry * GetCurrentPlaneGeometry()
Returns the currently selected Plane in the current BaseGeometry (if existent).
virtual bool CheckPositionEvent(const InteractionEvent *interactionEvent)
virtual void Zoom(StateMachineAction *, InteractionEvent *)
Performs zooming relative to mouse/pointer movement.
virtual void ConfigurationChanged() override
virtual void UpdateStatusbar(StateMachineAction *, InteractionEvent *event)
Updates the Statusbar information with the information about the clicked position.
void DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const
This method converts a display point to the 2D world index, mapped onto the display plane using the g...
virtual void SetCrosshair(StateMachineAction *, InteractionEvent *)
Sets crosshair at clicked position*.
virtual unsigned int GetTimeStep() const
static StatusBar * GetInstance()
static method to get the GUI dependent StatusBar-instance so the methods DisplayText, etc. can be called No reference counting, cause of decentral static use!
static Pointer New(const char *_arg)
virtual void AdjustLevelWindow(StateMachineAction *, InteractionEvent *)
Adjusts the level windows relative to mouse/pointer movement.
void RequestUpdate(vtkRenderWindow *renderWindow)
#define CONNECT_CONDITION(a, f)
Helper class to step through a list.
itk::Point< TCoordRep, NPointDimension > Project(const itk::Point< TCoordRep, NPointDimension > &point) const
Project a point on the line.
bool IntersectionLine(const PlaneGeometry *plane, Line3D &crossline) const
Calculate the intersecting line of two planes.
virtual void ScrollOneDown(StateMachineAction *, InteractionEvent *)
Scrolls one layer up.
virtual ~DisplayInteractor()
MITKCORE_EXPORT const ScalarType eps
virtual bool CheckSwivelPossible(const InteractionEvent *interactionEvent)
virtual SliceNavigationController * GetSliceNavigationController()
void ConnectActionsAndFunctions() override
#define mitkPixelTypeMultiplex5(function, ptype, param1, param2, param3, param4, param5)
Describes a two-dimensional, rectangular plane.
#define CONNECT_FUNCTION(a, f)
void SetLevelWindow(ScalarType level, ScalarType window, bool expandRangesIfNecessary=true)
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
ScalarType GetWindow() const
returns the current window size, i.e the range size of the current grey value interval ...
const RenderWindowVector & GetAllRegisteredRenderWindows()
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
virtual void Swivel(StateMachineAction *, InteractionEvent *event)
Class for nodes of the DataTree.
ScalarType GetLevel() const
method that returns the level value, i.e. the center of the current grey value interval ...