32 #include <rotate_cursor.xpm> 35 : m_AlwaysReact(false)
37 , m_IndexToSliceModifier(4)
38 , m_InvertScrollDirection(false)
39 , m_InvertZoomDirection(false)
41 , m_InvertMoveDirection(false)
42 , m_InvertLevelWindowDirection(false)
45 m_StartCoordinateInMM.Fill(0);
46 m_LastDisplayCoordinate.Fill(0);
47 m_LastCoordinateInMM.Fill(0);
48 m_CurrentDisplayCoordinate.Fill(0);
52 props[
"name"] = std::string(
"DisplayActionEventBroadcast");
58 m_ServiceRegistration.Unregister();
64 if (!isHandled || m_AlwaysReact)
102 std::string strAlwaysReact =
"";
103 m_AlwaysReact =
false;
104 if (properties->GetStringProperty(
"alwaysReact", strAlwaysReact))
106 if (strAlwaysReact ==
"true")
108 m_AlwaysReact =
true;
113 std::string strAutoRepeat =
"";
114 m_AutoRepeat =
false;
115 if (properties->GetStringProperty(
"autoRepeat", strAutoRepeat))
117 if (strAutoRepeat ==
"true")
124 std::string strPixelPerSlice =
"";
125 m_IndexToSliceModifier = 4;
126 if (properties->GetStringProperty(
"pixelPerSlice", strPixelPerSlice))
128 m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str());
132 if (!properties->GetStringProperty(
"scrollDirection", m_ScrollDirection))
134 m_ScrollDirection =
"updown";
137 m_InvertScrollDirection = GetBoolProperty(properties,
"invertScrollDirection",
false);
140 if (!properties->GetStringProperty(
"zoomDirection", m_ZoomDirection))
142 m_ZoomDirection =
"updown";
145 m_InvertZoomDirection = GetBoolProperty(properties,
"invertZoomDirection",
false);
146 m_InvertMoveDirection = GetBoolProperty(properties,
"invertMoveDirection",
false);
148 if (!properties->GetStringProperty(
"levelWindowDirection", m_LevelDirection))
150 m_LevelDirection =
"leftright";
153 m_InvertLevelWindowDirection = GetBoolProperty(properties,
"invertLevelWindowDirection",
false);
156 std::string strCoupled =
"";
157 m_LinkPlanes =
false;
158 if (properties->GetStringProperty(
"coupled", strCoupled))
160 if (strCoupled ==
"true")
167 std::string strZoomFactor =
"";
168 properties->GetStringProperty(
"zoomFactor", strZoomFactor);
170 if (atoi(strZoomFactor.c_str()) > 0)
172 m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0);
179 if (
nullptr == sendingRenderer)
195 if (
nullptr == positionEvent)
226 if (
nullptr == positionEvent)
232 if (
nullptr == renderer)
238 if (
nullptr == rendererWorldPlaneGeometry)
243 Point3D position = positionEvent->GetPositionInWorld();
244 const auto spacing = rendererWorldPlaneGeometry->
GetSpacing();
247 Line3D intersectionLineWithGeometryToBeRotated;
249 bool hitMultipleLines(
false);
250 m_SNCsToBeRotated.clear();
252 const ScalarType threshholdDistancePixels = 12.0;
255 for (
auto renderWindow : allRenderWindows)
266 if (
nullptr == rendererPlaneGeometry)
273 if (!rendererWorldPlaneGeometry->
IntersectionLine(rendererPlaneGeometry, intersectionLine))
279 const double distanceFromIntersectionLine = intersectionLine.
Distance(position) / spacing[snc->GetDefaultViewDirection()];
282 if (distanceFromIntersectionLine > threshholdDistancePixels)
286 anyOtherGeometry = rendererPlaneGeometry;
290 m_SNCsToBeRotated.push_back(snc);
295 if (
nullptr == geometryToBeRotated)
297 geometryToBeRotated = rendererPlaneGeometry;
298 intersectionLineWithGeometryToBeRotated = intersectionLine;
299 m_SNCsToBeRotated.push_back(snc);
306 if (intersectionLine.
IsParallel(intersectionLineWithGeometryToBeRotated)
309 m_SNCsToBeRotated.push_back(snc);
313 hitMultipleLines =
true;
319 bool moveSlices(
true);
321 if (geometryToBeRotated && anyOtherGeometry && rendererWorldPlaneGeometry && !hitMultipleLines)
335 m_LastCursorPosition = intersectionLineWithGeometryToBeRotated.
Project(position);
338 if (anyOtherGeometry->
IntersectionPoint(intersectionLineWithGeometryToBeRotated, m_CenterOfRotation))
356 if (
nullptr == positionEvent)
362 if (
nullptr == renderer)
367 const Point3D& position = positionEvent->GetPositionInWorld();
369 m_SNCsToBeRotated.clear();
375 const ScalarType threshholdDistancePixels = 6.0;
378 for (
auto renderWindow : allRenderWindows)
389 if (
nullptr == rendererPlaneGeometry)
396 clickedGeometry = rendererPlaneGeometry;
397 m_SNCsToBeRotated.push_back(snc);
401 if (
nullptr == otherGeometry1)
403 otherGeometry1 = rendererPlaneGeometry;
407 otherGeometry2 = rendererPlaneGeometry;
412 m_SNCsToBeRotated.push_back(snc);
419 if ((
nullptr != clickedGeometry) && (
nullptr != otherGeometry1) && (
nullptr != otherGeometry2)
422 m_CenterOfRotation = point;
423 if (m_CenterOfRotation.EuclideanDistanceTo(position) < threshholdDistancePixels)
429 m_ReferenceCursor = positionEvent->GetPointerPositionOnScreen();
432 m_RotationPlaneNormal = clickedGeometry->
GetNormal();
436 clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D(xVector), m_RotationPlaneXVector);
437 clickedGeometry->BaseGeometry::IndexToWorld(
Vector3D(yVector), m_RotationPlaneYVector);
439 m_RotationPlaneNormal.Normalize();
440 m_RotationPlaneXVector.Normalize();
441 m_RotationPlaneYVector.Normalize();
443 m_PreviousRotationAxis.Fill(0.0);
444 m_PreviousRotationAxis[2] = 1.0;
445 m_PreviousRotationAngle = 0.0;
460 if (
nullptr == positionEvent)
465 m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
466 m_CurrentDisplayCoordinate = m_LastDisplayCoordinate;
467 positionEvent->GetSender()->DisplayToPlane(m_LastDisplayCoordinate, m_StartCoordinateInMM);
468 m_LastCoordinateInMM = m_StartCoordinateInMM;
474 if (
nullptr == positionEvent)
480 Vector2D moveVector = m_LastDisplayCoordinate - positionEvent->GetPointerPositionOnScreen();
482 if (m_InvertMoveDirection)
490 m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
499 if (
nullptr == positionEvent)
504 Point3D position = positionEvent->GetPositionInWorld();
513 if (
nullptr == positionEvent)
521 if (m_ZoomDirection ==
"updown")
523 distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
527 distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
530 if (m_InvertZoomDirection)
538 factor = 1.0 / m_ZoomFactor;
540 else if (distance > 0.0)
542 factor = 1.0 * m_ZoomFactor;
546 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
547 m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
550 InvokeEvent(
DisplayZoomEvent(interactionEvent, factor, m_StartCoordinateInMM));
556 if (
nullptr == positionEvent)
564 if (m_ScrollDirection ==
"updown")
566 sliceDelta =
static_cast<int>(m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]);
570 sliceDelta =
static_cast<int>(m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]);
573 if (m_InvertScrollDirection)
580 if (sliceDelta > 0 && sliceDelta < m_IndexToSliceModifier)
582 sliceDelta = m_IndexToSliceModifier;
584 else if (sliceDelta < 0 && sliceDelta > -m_IndexToSliceModifier)
586 sliceDelta = -m_IndexToSliceModifier;
588 sliceDelta /= m_IndexToSliceModifier;
591 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
592 m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
601 if (m_InvertScrollDirection)
613 if (m_InvertScrollDirection)
625 if (
nullptr == positionEvent)
633 if (m_LevelDirection ==
"leftright")
635 level = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
636 window = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
640 level = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1];
641 window = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0];
644 if (m_InvertLevelWindowDirection)
654 m_LastDisplayCoordinate = m_CurrentDisplayCoordinate;
655 m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen();
674 if (
nullptr == positionEvent)
679 Point3D position = positionEvent->GetPositionInWorld();
681 Vector3D toProjected = m_LastCursorPosition - m_CenterOfRotation;
682 Vector3D toCursor = position - m_CenterOfRotation;
686 vnl_vector_fixed<ScalarType, 3> vnlDirection = vnl_cross_3d(toCursor.GetVnlVector(), toProjected.GetVnlVector());
687 axisOfRotation.SetVnlVector(vnlDirection);
691 ScalarType angle = -atan2((
double)(axisOfRotation.GetNorm()), (
double)(toCursor * toProjected));
692 angle *= 180.0 / vnl_math::pi;
693 m_LastCursorPosition = position;
699 for (
auto iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
701 TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
702 if (
nullptr == timeGeometry)
709 (*iter)->SendCreatedWorldGeometryUpdate();
718 if (
nullptr == positionEvent)
724 Point2D position = positionEvent->GetPointerPositionOnScreen();
726 Vector2D relativeCursor = position - m_ReferenceCursor;
727 Vector3D relativeCursorAxis = m_RotationPlaneXVector * relativeCursor[0] + m_RotationPlaneYVector * relativeCursor[1];
730 Vector3D rotationAxis = itk::CrossProduct(m_RotationPlaneNormal, relativeCursorAxis);
732 ScalarType rotationAngle = relativeCursor.GetNorm() / 2.0;
737 SNCVector::iterator iter;
738 for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
740 if (!(*iter)->GetSliceRotationLocked())
742 TimeGeometry* timeGeometry = (*iter)->GetCreatedWorldGeometry();
743 if (
nullptr == timeGeometry)
749 (*iter)->SendCreatedWorldGeometryUpdate();
756 for (iter = m_SNCsToBeRotated.begin(); iter != m_SNCsToBeRotated.end(); ++iter)
758 if (!(*iter)->GetSliceRotationLocked())
761 TimeGeometry *timeGeometry = (*iter)->GetCreatedWorldGeometry();
762 if (
nullptr == timeGeometry)
771 (*iter)->SendCreatedWorldGeometryUpdate();
775 m_PreviousRotationAxis = rotationAxis;
776 m_PreviousRotationAngle = rotationAngle;
785 auto stepper = sliceNaviController->
GetTime();
793 auto stepper = sliceNaviController->
GetTime();
801 if (
nullptr == positionEvent)
809 DataStorage::SetOfObjects::ConstPointer nodes = renderer->GetDataStorage()->GetSubset(isImageData).GetPointer();
816 renderer->DisplayToWorld(positionEvent->GetPointerPositionOnScreen(), worldposition);
817 auto globalCurrentTimePoint = renderer->GetTime();
831 bool isBinary(
false);
832 node->GetBoolProperty(
"binary", isBinary);
835 DataStorage::SetOfObjects::ConstPointer sourcenodes = renderer->GetDataStorage()->GetSources(node,
nullptr,
true);
836 if (!sourcenodes->empty())
840 if (topSourceNode.IsNotNull())
842 image3D =
dynamic_cast<Image*
>(topSourceNode->GetData());
843 topSourceNode->GetIntProperty(
"Image.Displayed Component", component);
847 image3D =
dynamic_cast<Image*
>(node->GetData());
848 node->GetIntProperty(
"Image.Displayed Component", component);
853 image3D =
dynamic_cast<Image *
>(node->GetData());
854 node->GetIntProperty(
"Image.Displayed Component", component);
859 if (image3D.IsNotNull() && statusBar !=
nullptr)
862 image3D->GetGeometry()->WorldToIndex(worldposition, p);
864 auto pixelType = image3D->GetChannelDescriptor().GetPixelType().GetPixelType();
865 if (pixelType == itk::ImageIOBase::RGB || pixelType == itk::ImageIOBase::RGBA)
867 std::string pixelValue =
"Pixel RGB(A) value: ";
869 statusBar->DisplayImageInfo(worldposition, p, renderer->GetTime(), pixelValue.c_str());
871 else if (pixelType == itk::ImageIOBase::DIFFUSIONTENSOR3D || pixelType == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR)
873 std::string pixelValue =
"See ODF Details view. ";
874 statusBar->DisplayImageInfo(worldposition, p, renderer->GetTime(), pixelValue.c_str());
881 image3D->GetChannelDescriptor().GetPixelType(),
883 image3D->GetVolumeData(renderer->GetTimeStep()),
887 statusBar->DisplayImageInfo(worldposition, p, renderer->GetTime(), pixelValue);
892 statusBar->DisplayImageInfoInvalid();
896 bool mitk::DisplayActionEventBroadcast::GetBoolProperty(
PropertyList::Pointer propertyList,
const char* propertyName,
bool defaultValue)
898 std::string valueAsString;
899 if (!propertyList->GetStringProperty(propertyName, valueAsString))
905 if (valueAsString ==
"true")
void Zoom(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
mitk::ScalarType FastSinglePixelAccess(mitk::PixelType, mitk::Image::Pointer im, ImageDataItem *item, itk::Index< 3 > idx, mitk::ScalarType &val, int component=0)
bool IsParallel(const Line< TCoordRep, NPointDimension > &line) const
Test if a lines is parallel to this line.
Super class for all position events.
void Move(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
Base class to implement InteractionEventObservers.
void StartRotation(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
static BaseRenderer * GetInstance(vtkRenderWindow *renWin)
ServiceRegistrationU RegisterService(const InterfaceMap &service, const ServiceProperties &properties=ServiceProperties())
void SetCrosshair(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
bool HandleEvent(InteractionEvent *event, DataNode *dataNode)
void Swivel(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
Organizes the rendering process.
double GetScaleFactorMMPerDisplayUnit() const
void Notify(InteractionEvent *interactionEvent, bool isHandled) override
bool FilterEvents(InteractionEvent *interactionEvent, DataNode *dataNode) override
Filters the event resp. the sender of the event.
bool IntersectionPoint(const Line3D &line, Point3D &intersectionPoint) const
Calculate intersection point between the plane and a line.
void EndRotation(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
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.
DisplayActionEventBroadcast()
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.
BaseRenderer * GetSender() const
void ConnectActionsAndFunctions() override
Connects the action names used in the state machine pattern with functions implemented within this In...
void Init(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
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
bool CheckRotationPossible(const InteractionEvent *interactionEvent)
static RenderingManager * GetInstance()
~DisplayActionEventBroadcast() override
virtual void SetAutoRepeat(bool _arg)
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual MapperSlotId GetMapperID()
Get the MapperSlotId to use.
Image class for storing images.
void Scroll(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
const mitk::PlaneGeometry * GetCurrentPlaneGeometry()
Returns the currently selected Plane in the current BaseGeometry (if existent).
void DecreaseTimeStep(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
void ScrollOneUp(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
void ResetMouseCursor()
Resets the mouse cursor (if modified by the SlicesCoordinator) to its original state.
void ScrollOneDown(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
bool CheckSwivelPossible(const InteractionEvent *interactionEvent)
void SetMouseCursor(const char *xpm[], int hotspotX, int hotspotY)
Sets the specified mouse cursor.
US_UNORDERED_MAP_TYPE< std::string, Any > ServiceProperties
void IncreaseTimeStep(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
void ConfigurationChanged() override
This function is executed when a config object is set / changed (via 'SetEventConfig' or 'AddEventCon...
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!
#define CONNECT_CONDITION(a, f)
Vector3D GetNormal() const
Normal of the plane.
void Rotate(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
MITKCORE_EXPORT const ScalarType eps
virtual SliceNavigationController * GetSliceNavigationController()
PropertyList::Pointer GetAttributes() const
mitk::Stepper * GetTime()
Get the Stepper through the time.
#define mitkPixelTypeMultiplex5(function, ptype, param1, param2, param3, param4, param5)
Describes a two-dimensional, rectangular plane.
#define CONNECT_FUNCTION(a, f)
void AdjustLevelWindow(StateMachineAction *stateMachineAction, InteractionEvent *interactionEvent)
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.
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
const RenderWindowVector & GetAllRegisteredRenderWindows()
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Class for nodes of the DataTree.
bool CheckPositionEvent(const InteractionEvent *interactionEvent)
Check if the given interaction event is actually an 'InteractionPositionEvent'.