Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkAffineImageCropperInteractor.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 
19 #include "mitkInteractionConst.h"
21 #include "mitkRotationOperation.h"
22 #include "mitkSurface.h"
23 #include "mitkVtkMapper.h"
24 
25 #include <mitkBoundingObject.h>
26 #include <mitkMouseWheelEvent.h>
27 #include <vtkCamera.h>
28 #include <vtkInteractorStyle.h>
29 #include <vtkMatrix4x4.h>
30 #include <vtkPointData.h>
31 #include <vtkPolyData.h>
32 #include <vtkRenderWindowInteractor.h>
33 
34 #include <mitkRotationOperation.h>
35 #include <mitkScaleOperation.h>
36 
38 {
39  m_OriginalGeometry = Geometry3D::New();
40 }
41 
43 {
44 }
45 
47 {
48  // **Conditions** that can be used in the state machine, to ensure that certain conditions are met, before actually
49  // executing an action
50  CONNECT_CONDITION("isOverObject", CheckOverObject);
51 
52  // **Function** in the statmachine patterns also referred to as **Actions**
53  CONNECT_FUNCTION("selectObject", SelectObject);
54  CONNECT_FUNCTION("deselectObject", DeselectObject);
55  CONNECT_FUNCTION("initTranslate", InitTranslate);
56  CONNECT_FUNCTION("initRotate", InitRotate);
57  CONNECT_FUNCTION("initDeformation", InitDeformation);
58  CONNECT_FUNCTION("translateObject", TranslateObject);
59  CONNECT_FUNCTION("rotateObject", RotateObject);
60  CONNECT_FUNCTION("deformObject", DeformObject);
61  CONNECT_FUNCTION("scaleRadius", ScaleRadius);
62 }
63 
65 {
66 }
67 
69 {
70  mitk::DataNode::Pointer dn = this->GetDataNode();
71  if (dn.IsNull())
72  return false;
73  const InteractionPositionEvent *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
74  Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
75  mitk::BoundingObject *object = dynamic_cast<mitk::BoundingObject *>(dn->GetData());
76  object->GetGeometry()->WorldToIndex(currentPickedPoint, currentPickedPoint);
77  return object && object->GetGeometry()->GetBoundingBox()->IsInside(currentPickedPoint);
78 }
79 
81 {
82  mitk::DataNode::Pointer dn = this->GetDataNode();
83 
84  if (dn.IsNull())
85  return;
86 
87  m_SelectedNode = dn;
88 
89  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
90 }
91 
92 void mitk::AffineImageCropperInteractor::Deselect()
93 {
94  mitk::DataNode::Pointer dn = this->GetDataNode();
95 
96  if (dn.IsNull())
97  return;
98 
99  m_SelectedNode = dn;
100 }
101 
103 {
104  Deselect();
105  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
106 }
107 
109 {
110  const MouseWheelEvent *wheelEvent = dynamic_cast<const MouseWheelEvent *>(interactionEvent);
111  if (wheelEvent == NULL)
112  return;
113 
114  if (m_SelectedNode.IsNull())
115  return;
116 
117  double scale = (double)(wheelEvent->GetWheelDelta()) / 64.0;
118  mitk::Point3D newScale;
119  newScale[0] = newScale[1] = newScale[2] = scale;
120 
121  mitk::Point3D anchorPoint = wheelEvent->GetPositionInWorld();
122  ScaleOperation *doOp = new mitk::ScaleOperation(OpSCALE, newScale, anchorPoint);
123  m_SelectedNode->GetData()->GetGeometry()->ExecuteOperation(doOp);
124 
125  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
126 }
127 
129 {
130  if (m_SelectedNode.IsNull())
131  return;
132  InteractionPositionEvent *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
133  if (positionEvent == NULL)
134  return;
135 
136  m_InitialPickedPoint = positionEvent->GetPositionInWorld();
137  m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
138 
139  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
140  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
141  m_InitialOrigin = surGeo->GetOrigin();
142 }
143 
145 {
146  InteractionPositionEvent *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
147  if (positionEvent == NULL)
148  return;
149 
150  m_InitialPickedPoint = positionEvent->GetPositionInWorld();
151  m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
152 
153  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
154  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
155  m_OriginalGeometry = dynamic_cast<mitk::Geometry3D *>(surGeo.GetPointer());
156 }
157 
159 {
160  InteractionPositionEvent *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
161  if (positionEvent == NULL)
162  return;
163 
164  m_InitialPickedPoint = positionEvent->GetPositionInWorld();
165  m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
166 
167  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
168  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
169  m_OriginalGeometry = dynamic_cast<mitk::Geometry3D *>(surGeo.GetPointer());
170 }
171 
173 {
174  InteractionPositionEvent *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
175  if (positionEvent == NULL)
176  return;
177 
178  Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
179 
180  Vector3D interactionMove;
181  interactionMove[0] = currentPickedPoint[0] - m_InitialPickedPoint[0];
182  interactionMove[1] = currentPickedPoint[1] - m_InitialPickedPoint[1];
183  interactionMove[2] = currentPickedPoint[2] - m_InitialPickedPoint[2];
184 
185  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
186  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
187  surGeo->SetOrigin(m_InitialOrigin);
188  surGeo->Translate(interactionMove);
189 
190  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
191 }
192 
194 {
195  InteractionPositionEvent *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
196  if (positionEvent == NULL)
197  return;
198 
199  Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
200  Vector3D interactionMove = currentPickedPoint - m_InitialPickedPoint;
201 
202  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
203  surface->SetGeometry(m_OriginalGeometry);
204  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
205 
206  surGeo->WorldToIndex(interactionMove, interactionMove);
207  Point3D scale;
208  for (int i = 0; i < 3; ++i)
209  {
210  scale[i] = (interactionMove[i] * surGeo->GetMatrixColumn(i).magnitude()) - 1;
211  }
212 
213  mitk::Point3D anchorPoint = surGeo->GetCenter();
214 
215  ScaleOperation *doOp = new mitk::ScaleOperation(OpSCALE, scale, anchorPoint);
216  surGeo->ExecuteOperation(doOp);
217 
219 }
220 
222 {
223  InteractionPositionEvent *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
224  if (positionEvent == NULL)
225  return;
226 
227  Point2D currentPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
228  if (currentPickedDisplayPoint.EuclideanDistanceTo(m_InitialPickedDisplayPoint) < 1)
229  return;
230 
231  vtkRenderer *currentVtkRenderer = interactionEvent->GetSender()->GetVtkRenderer();
232 
233  if (currentVtkRenderer && currentVtkRenderer->GetActiveCamera())
234  {
235  double vpn[3];
236  currentVtkRenderer->GetActiveCamera()->GetViewPlaneNormal(vpn);
237 
238  Vector3D rotationAxis;
239  rotationAxis[0] = vpn[0];
240  rotationAxis[1] = vpn[1];
241  rotationAxis[2] = vpn[2];
242  rotationAxis.Normalize();
243 
244  Vector2D move = currentPickedDisplayPoint - m_InitialPickedDisplayPoint;
245 
246  double rotationAngle = -57.3 * atan(move[0] / move[1]);
247  if (move[1] < 0)
248  rotationAngle += 180;
249 
250  // Use center of data bounding box as center of rotation
251  Point3D rotationCenter = m_OriginalGeometry->GetCenter();
252  if (positionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D)
253  rotationCenter = m_InitialPickedPoint;
254 
255  // Reset current Geometry3D to original state (pre-interaction) and
256  // apply rotation
257  RotationOperation op(OpROTATE, rotationCenter, rotationAxis, rotationAngle);
258  Geometry3D::Pointer newGeometry = static_cast<Geometry3D *>(m_OriginalGeometry->Clone().GetPointer());
259  newGeometry->ExecuteOperation(&op);
260  m_SelectedNode->GetData()->SetGeometry(newGeometry);
261 
262  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
263  }
264 }
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
Super class for all position events.
Standard implementation of BaseGeometry.
virtual bool CheckOverObject(const InteractionEvent *)
Checks if the mouse pointer is over the object.
BaseRenderer * GetSender() const
virtual void InitTranslate(StateMachineAction *, InteractionEvent *)
virtual void DeformObject(StateMachineAction *, InteractionEvent *)
virtual void InitRotate(StateMachineAction *, InteractionEvent *)
static Pointer New()
Constants for most interaction classes, due to the generic StateMachines.
virtual void ScaleRadius(StateMachineAction *, InteractionEvent *interactionEvent)
virtual void DeselectObject(StateMachineAction *, InteractionEvent *)
Called if the mouse pointer leaves the area of the object.
virtual void SelectObject(StateMachineAction *, InteractionEvent *)
Called if the mouse pointer is over the object indicated by a color change.
superclass of all bounding objects (cylinder, cuboid,...)
virtual mitk::RenderingManager * GetRenderingManager() const
Setter for the RenderingManager that handles this instance of BaseRenderer.
virtual void TranslateObject(StateMachineAction *, InteractionEvent *)
Performs a translation of the object relative to the mouse movement.
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual MapperSlotId GetMapperID()
Get the MapperSlotId to use.
virtual void DeselectObject(StateMachineAction *, InteractionEvent *)
virtual bool CheckOverObject(const InteractionEvent *interactionEvent)
virtual void RotateObject(StateMachineAction *, InteractionEvent *interactionEvent)
#define CONNECT_CONDITION(a, f)
virtual void InitDeformation(StateMachineAction *, InteractionEvent *)
The ScaleOperation is an operation to scale any mitk::BaseGeometry.
virtual void SelectObject(StateMachineAction *, InteractionEvent *)
#define CONNECT_FUNCTION(a, f)
vtkRenderer * GetVtkRenderer() const
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
virtual void TranslateObject(StateMachineAction *, InteractionEvent *interactionEvent)
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.