28 #include "vtkRenderWindowInteractor.h" 32 #include "rotate_cursor.xpm" 47 if (!isHandled || m_AlwaysReact)
54 : m_IndexToSliceModifier(4)
56 , m_InvertScrollDirection(false)
57 , m_InvertZoomDirection(false)
58 , m_InvertMoveDirection(false)
59 , m_InvertLevelWindowDirection(false)
60 , m_AlwaysReact(false)
64 m_StartCoordinateInMM.Fill(0);
65 m_LastDisplayCoordinate.Fill(0);
66 m_LastCoordinateInMM.Fill(0);
67 m_CurrentDisplayCoordinate.Fill(0);
105 if (positionEvent ==
nullptr)
136 if (posEvent ==
nullptr)
142 if (!ourViewportGeometry)
145 Point3D cursorPosition = posEvent->GetPositionInWorld();
146 const auto spacing = ourViewportGeometry->
GetSpacing();
149 Line3D intersectionLineWithGeometryToBeRotated;
151 bool hitMultipleLines(
false);
152 m_SNCsToBeRotated.clear();
154 const double threshholdDistancePixels = 12.0;
158 for (
auto renWin : renWindows)
167 if (otherRenderersRenderPlane ==
nullptr)
172 if (!ourViewportGeometry->
IntersectionLine(otherRenderersRenderPlane, intersectionLine))
178 const double distanceFromIntersectionLine =
179 intersectionLine.
Distance(cursorPosition) / spacing[snc->GetDefaultViewDirection()];
182 if (distanceFromIntersectionLine > threshholdDistancePixels)
184 anyOtherGeometry = otherRenderersRenderPlane;
189 m_SNCsToBeRotated.push_back(snc);
194 if (geometryToBeRotated ==
nullptr)
196 geometryToBeRotated = otherRenderersRenderPlane;
197 intersectionLineWithGeometryToBeRotated = intersectionLine;
198 m_SNCsToBeRotated.push_back(snc);
205 if (intersectionLine.
IsParallel(intersectionLineWithGeometryToBeRotated) &&
208 m_SNCsToBeRotated.push_back(snc);
212 hitMultipleLines =
true;
218 bool moveSlices(
true);
220 if (geometryToBeRotated && anyOtherGeometry && ourViewportGeometry && !hitMultipleLines)
232 m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.
Project(
236 intersectionLineWithGeometryToBeRotated,
251 const ScalarType ThresholdDistancePixels = 6.0;
260 if (!posEvent || !renderer)
263 const Point3D &cursor = posEvent->GetPositionInWorld();
265 m_SNCsToBeRotated.clear();
273 for (
auto renWin : renWindows)
290 clickedGeometry = planeGeometry;
291 m_SNCsToBeRotated.push_back(snc);
295 if (otherGeometry1 ==
nullptr)
297 otherGeometry1 = planeGeometry;
301 otherGeometry2 = planeGeometry;
306 m_SNCsToBeRotated.push_back(snc);
313 if ((clickedGeometry !=
nullptr) && (otherGeometry1 !=
nullptr) && (otherGeometry2 !=
nullptr) &&
316 m_CenterOfRotation = point;
317 if (m_CenterOfRotation.EuclideanDistanceTo(cursor) < ThresholdDistancePixels)
323 m_ReferenceCursor = posEvent->GetPointerPositionOnScreen();
326 m_RotationPlaneNormal = clickedGeometry->
GetNormal();
330 clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D(xVector), m_RotationPlaneXVector);
331 clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D(yVector), m_RotationPlaneYVector);
333 m_RotationPlaneNormal.Normalize();
334 m_RotationPlaneXVector.Normalize();
335 m_RotationPlaneYVector.Normalize();
337 m_PreviousRotationAxis.Fill(0.0);
338 m_PreviousRotationAxis[2] = 1.0;
339 m_PreviousRotationAngle = 0.0;
355 m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
356 m_CurrentDisplayCoordinate = m_LastDisplayCoordinate;
357 positionEvent->GetSender()->DisplayToPlane(m_LastDisplayCoordinate, m_StartCoordinateInMM);
358 m_LastCoordinateInMM = m_StartCoordinateInMM;
366 float invertModifier = -1.0;
367 if (m_InvertMoveDirection)
369 invertModifier = 1.0;
372 Vector2D moveVector = (positionEvent->GetPointerPositionOnScreen() - m_LastDisplayCoordinate) * invertModifier;
377 m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
383 Point3D pos = positionEvent->GetPositionInWorld();
387 for (
auto renWin : renWindows)
399 auto stepper = sliceNaviController->
GetTime();
407 auto stepper = sliceNaviController->
GetTime();
417 if (m_ZoomDirection ==
"updown")
419 distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
423 distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
426 if (m_InvertZoomDirection)
434 factor = 1.0 / m_ZoomFactor;
436 else if (distance > 0.0)
438 factor = 1.0 * m_ZoomFactor;
442 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
443 m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
448 sender->GetCameraController()->Zoom(factor, m_StartCoordinateInMM);
458 if (sliceNaviController)
462 if (m_ScrollDirection ==
"updown")
464 delta =
static_cast<int>(m_LastDisplayCoordinate[1] - positionEvent->GetPointerPositionOnScreen()[1]);
468 delta =
static_cast<int>(m_LastDisplayCoordinate[0] - positionEvent->GetPointerPositionOnScreen()[0]);
471 if (m_InvertScrollDirection)
478 if (delta > 0 && delta < m_IndexToSliceModifier)
480 delta = m_IndexToSliceModifier;
482 else if (delta < 0 && delta > -m_IndexToSliceModifier)
484 delta = -m_IndexToSliceModifier;
486 delta /= m_IndexToSliceModifier;
488 int newPos = sliceNaviController->GetSlice()->GetPos() + delta;
491 int maxSlices = sliceNaviController->GetSlice()->GetSteps();
499 while (newPos >= maxSlices)
514 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
515 m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
518 sliceNaviController->GetSlice()->SetPos(newPos);
526 if (!sliceNaviController->GetSliceLocked())
531 stepper = sliceNaviController->GetTime();
541 if (!sliceNaviController->GetSliceLocked())
546 stepper = sliceNaviController->GetTime();
557 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
558 m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
563 for (
unsigned int i = 0; i < allImageNodes->size(); ++i)
565 bool isActiveImage =
false;
566 bool propFound = allImageNodes->at(i)->GetBoolProperty(
"imageForLevelWindow", isActiveImage);
568 if (propFound && isActiveImage)
570 node = allImageNodes->at(i);
584 node->GetLevelWindow(lv);
591 if (m_LevelDirection !=
"leftright")
597 int directionModifier = 1;
598 if (m_InvertLevelWindowDirection)
600 directionModifier = -1;
604 level += (m_CurrentDisplayCoordinate[levelIndex] - m_LastDisplayCoordinate[levelIndex]) * static_cast<ScalarType>(2) *
606 window += (m_CurrentDisplayCoordinate[windowIndex] - m_LastDisplayCoordinate[windowIndex]) *
607 static_cast<ScalarType>(2) * directionModifier;
628 if (posEvent ==
nullptr)
631 Point3D cursor = posEvent->GetPositionInWorld();
633 Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
634 Vector3D toCursor = cursor - m_CenterOfRotation;
638 vnl_vector_fixed<ScalarType, 3> vnlDirection = vnl_cross_3d(toCursor.GetVnlVector(), toProjected.GetVnlVector());
639 axisOfRotation.SetVnlVector(vnlDirection);
643 ScalarType angle = -atan2((
double)(axisOfRotation.GetNorm()), (
double)(toCursor * toProjected));
644 angle *= 180.0 / vnl_math::pi;
645 m_LastCursorPosition = cursor;
651 for (
auto iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
653 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
659 (*iter)->SendCreatedWorldGeometryUpdate();
673 Point2D cursor = posEvent->GetPointerPositionOnScreen();
674 Vector2D relativeCursor = cursor - m_ReferenceCursor;
675 Vector3D relativeCursorAxis = m_RotationPlaneXVector * relativeCursor[0] + m_RotationPlaneYVector * relativeCursor[1];
679 Vector3D rotationAxis = itk::CrossProduct(m_RotationPlaneNormal, relativeCursorAxis);
681 ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0;
687 SNCVector::iterator iter;
688 for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
690 if (!(*iter)->GetSliceRotationLocked())
692 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
697 (*iter)->SendCreatedWorldGeometryUpdate();
704 for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
706 if (!(*iter)->GetSliceRotationLocked())
709 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
717 (*iter)->SendCreatedWorldGeometryUpdate();
721 m_PreviousRotationAxis = rotationAxis;
722 m_PreviousRotationAngle = rotationAngle;
731 if (
nullptr == posEvent)
738 auto globalCurrentTimePoint = baseRenderer->GetTime();
739 mitk::DataStorage::SetOfObjects::ConstPointer nodes = baseRenderer->GetDataStorage()->GetSubset(isImageData).GetPointer();
751 baseRenderer->DisplayToWorld(posEvent->GetPointerPositionOnScreen(), worldposition);
765 bool isBinary(
false);
766 node->GetBoolProperty(
"binary", isBinary);
769 mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = baseRenderer->GetDataStorage()->GetSources(node,
nullptr,
true);
770 if (!sourcenodes->empty())
774 if (topSourceNode.IsNotNull())
776 image3D =
dynamic_cast<mitk::Image *
>(topSourceNode->GetData());
777 topSourceNode->GetIntProperty(
"Image.Displayed Component", component);
781 image3D =
dynamic_cast<mitk::Image *
>(node->GetData());
782 node->GetIntProperty(
"Image.Displayed Component", component);
787 image3D =
dynamic_cast<mitk::Image *
>(node->GetData());
788 node->GetIntProperty(
"Image.Displayed Component", component);
793 if (image3D.IsNotNull() && statusBar !=
nullptr)
796 image3D->GetGeometry()->WorldToIndex(worldposition, p);
798 auto pixelType = image3D->GetChannelDescriptor().GetPixelType().GetPixelType();
799 if (pixelType == itk::ImageIOBase::RGB || pixelType == itk::ImageIOBase::RGBA)
801 std::string pixelValue =
"Pixel RGB(A) value: ";
803 statusBar->DisplayImageInfo(worldposition, p, globalCurrentTimePoint, pixelValue.c_str());
805 else if (pixelType == itk::ImageIOBase::DIFFUSIONTENSOR3D || pixelType == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR)
807 std::string pixelValue =
"See ODF Details view. ";
808 statusBar->DisplayImageInfo(worldposition, p, globalCurrentTimePoint, pixelValue.c_str());
814 image3D->GetChannelDescriptor().GetPixelType(),
816 image3D->GetVolumeData(image3D->GetTimeGeometry()->TimePointToTimeStep(globalCurrentTimePoint)),
820 statusBar->DisplayImageInfo(worldposition, p, globalCurrentTimePoint, pixelValue);
825 statusBar->DisplayImageInfoInvalid();
833 std::string strAutoRepeat =
"";
834 if (properties->GetStringProperty(
"autoRepeat", strAutoRepeat))
836 if (strAutoRepeat ==
"true")
842 m_AutoRepeat =
false;
846 std::string strPixelPerSlice =
"";
847 if (properties->GetStringProperty(
"pixelPerSlice", strPixelPerSlice))
849 m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str());
853 m_IndexToSliceModifier = 4;
856 if (!properties->GetStringProperty(
"scrollDirection", m_ScrollDirection))
858 m_ScrollDirection =
"updown";
861 m_InvertScrollDirection =
GetBoolProperty(properties,
"invertScrollDirection",
false);
864 if (!properties->GetStringProperty(
"zoomDirection", m_ZoomDirection))
866 m_ZoomDirection =
"updown";
869 m_InvertZoomDirection =
GetBoolProperty(properties,
"invertZoomDirection",
false);
871 m_InvertMoveDirection =
GetBoolProperty(properties,
"invertMoveDirection",
false);
873 if (!properties->GetStringProperty(
"levelWindowDirection", m_LevelDirection))
875 m_LevelDirection =
"leftright";
878 m_InvertLevelWindowDirection =
GetBoolProperty(properties,
"invertLevelWindowDirection",
false);
881 std::string strCoupled =
"";
882 if (properties->GetStringProperty(
"coupled", strCoupled))
884 if (strCoupled ==
"true")
887 m_LinkPlanes =
false;
891 std::string strZoomFactor =
"";
892 properties->GetStringProperty(
"zoomFactor", strZoomFactor);
894 if (atoi(strZoomFactor.c_str()) > 0)
896 m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0);
899 std::string strAlwaysReact =
"";
900 if (properties->GetStringProperty(
"alwaysReact", strAlwaysReact))
902 if (strAlwaysReact ==
"true")
904 m_AlwaysReact =
true;
908 m_AlwaysReact =
false;
913 m_AlwaysReact =
false;
919 if (interactionEvent->
GetSender() ==
nullptr)
928 const char *propertyName,
931 std::string valueAsString;
932 if (!propertyList->GetStringProperty(propertyName, valueAsString))
938 if (valueAsString ==
"true")
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)
ScalarType GetLevel() const
method that returns the level value, i.e. the center of the current grey value interval ...
bool IsParallel(const Line< TCoordRep, NPointDimension > &line) const
Test if a lines is parallel to this line.
Super class for all position events.
void SelectSliceByPoint(const mitk::Point3D &point)
Positions the SNC according to the specified point.
The LevelWindowProperty class Property for the mitk::LevelWindow.
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)
bool HandleEvent(InteractionEvent *event, DataNode *dataNode)
virtual void Scroll(StateMachineAction *, InteractionEvent *)
Performs scrolling relative to mouse/pointer movement.
Organizes the rendering process.
bool FilterEvents(InteractionEvent *interactionEvent, DataNode *dataNode) override
double GetScaleFactorMMPerDisplayUnit() const
bool IntersectionPoint(const Line3D &line, Point3D &intersectionPoint) const
Calculate intersection point between the plane and a line.
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
void Notify(InteractionEvent *interactionEvent, bool isHandled) override
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.
const SliceNavigationController * GetTimeNavigationController() const
Controls the selection of the slice the associated BaseRenderer will display.
itk::Point< TCoordRep, NPointDimension > Project(const itk::Point< TCoordRep, NPointDimension > &point) const
Project a point on the line.
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.
BaseRenderer * GetSender() const
virtual void ScrollOneUp(StateMachineAction *, InteractionEvent *)
Scrolls one layer down.
The LevelWindow class Class to store level/window values.
virtual void DecreaseTimeStep(StateMachineAction *, InteractionEvent *)
Decreases the time step in 3d+t data.
double Distance(const itk::Point< TCoordRep, NPointDimension > &point) const
Distance of a point from the line.
const itk::Point< TCoordRep, NPointDimension > & GetPoint1() const
Get start point of the line.
bool IntersectionLine(const PlaneGeometry *plane, Line3D &crossline) const
Calculate the intersecting line of two planes.
void ExecuteOperation(Operation *op) override
Executes the given operation on all time steps.
Vector< ScalarType, 3 > Vector3D
static RenderingManager * GetInstance()
virtual void IncreaseTimeStep(StateMachineAction *, InteractionEvent *)
Increases the time step in 3d+t data.
virtual void SetAutoRepeat(bool _arg)
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).
void ResetMouseCursor()
Resets the mouse cursor (if modified by the SlicesCoordinator) to its original state.
virtual bool CheckPositionEvent(const InteractionEvent *interactionEvent)
virtual void Zoom(StateMachineAction *, InteractionEvent *)
Performs zooming relative to mouse/pointer movement.
void ConfigurationChanged() override
virtual void UpdateStatusbar(StateMachineAction *, InteractionEvent *event)
Updates the Statusbar information with the information about the clicked position.
void SetMouseCursor(const char *xpm[], int hotspotX, int hotspotY)
Sets the specified mouse cursor.
virtual void SetCrosshair(StateMachineAction *, InteractionEvent *)
Sets crosshair at clicked position*.
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.
ScalarType GetWindow() const
returns the current window size, i.e the range size of the current grey value interval ...
void RequestUpdate(vtkRenderWindow *renderWindow)
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
#define CONNECT_CONDITION(a, f)
Vector3D GetNormal() const
Normal of the plane.
Helper class to step through a list.
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
~DisplayInteractor() override
virtual void ScrollOneDown(StateMachineAction *, InteractionEvent *)
Scrolls one layer up.
MITKCORE_EXPORT const ScalarType eps
virtual bool CheckSwivelPossible(const InteractionEvent *interactionEvent)
virtual unsigned int GetSteps() const
virtual SliceNavigationController * GetSliceNavigationController()
PropertyList::Pointer GetAttributes() const
mitk::Stepper * GetTime()
Get the Stepper through the time.
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)
MITKCORE_EXPORT DataNode::Pointer FindTopmostVisibleNode(const DataStorage::SetOfObjects::ConstPointer nodes, const Point3D worldPosition, const TimePointType timePoint, const BaseRenderer *baseRender)
returns the topmost visible node of a given list of nodes. The function returns a node that is visibl...
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
const RenderWindowVector & GetAllRegisteredRenderWindows()
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
virtual void Swivel(StateMachineAction *, InteractionEvent *event)
Class for nodes of the DataTree.