Medical Imaging Interaction Toolkit  2018.4.99-a3d2e8fb
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include "mitkInteractionConst.h"
17 #include "mitkRotationOperation.h"
18 #include "mitkSurface.h"
19 #include "mitkVtkMapper.h"
20 
21 #include <mitkBoundingObject.h>
22 #include <mitkMouseWheelEvent.h>
23 #include <vtkCamera.h>
24 #include <vtkInteractorStyle.h>
25 #include <vtkMatrix4x4.h>
26 #include <vtkPointData.h>
27 #include <vtkPolyData.h>
28 #include <vtkRenderWindowInteractor.h>
29 
30 #include <mitkRotationOperation.h>
31 #include <mitkScaleOperation.h>
32 
34 {
35  m_OriginalGeometry = Geometry3D::New();
36 }
37 
39 {
40 }
41 
43 {
44  // **Conditions** that can be used in the state machine, to ensure that certain conditions are met, before actually
45  // executing an action
46  CONNECT_CONDITION("isOverObject", CheckOverObject);
47 
48  // **Function** in the statmachine patterns also referred to as **Actions**
49  CONNECT_FUNCTION("selectObject", SelectObject);
50  CONNECT_FUNCTION("deselectObject", DeselectObject);
51  CONNECT_FUNCTION("initTranslate", InitTranslate);
52  CONNECT_FUNCTION("initRotate", InitRotate);
53  CONNECT_FUNCTION("initDeformation", InitDeformation);
54  CONNECT_FUNCTION("translateObject", TranslateObject);
55  CONNECT_FUNCTION("rotateObject", RotateObject);
56  CONNECT_FUNCTION("deformObject", DeformObject);
57  CONNECT_FUNCTION("scaleRadius", ScaleRadius);
58 }
59 
61 {
62 }
63 
65 {
67  if (dn.IsNull())
68  return false;
69  const auto *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
70  Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
71  auto *object = dynamic_cast<mitk::BoundingObject *>(dn->GetData());
72  object->GetGeometry()->WorldToIndex(currentPickedPoint, currentPickedPoint);
73  return object && object->GetGeometry()->GetBoundingBox()->IsInside(currentPickedPoint);
74 }
75 
77 {
79 
80  if (dn.IsNull())
81  return;
82 
83  m_SelectedNode = dn;
84 
86 }
87 
88 void mitk::AffineImageCropperInteractor::Deselect()
89 {
91 
92  if (dn.IsNull())
93  return;
94 
95  m_SelectedNode = dn;
96 }
97 
99 {
100  Deselect();
102 }
103 
105 {
106  const auto *wheelEvent = dynamic_cast<const MouseWheelEvent *>(interactionEvent);
107  if (wheelEvent == nullptr)
108  return;
109 
110  if (m_SelectedNode.IsNull())
111  return;
112 
113  double scale = (double)(wheelEvent->GetWheelDelta()) / 64.0;
114  mitk::Point3D newScale;
115  newScale[0] = newScale[1] = newScale[2] = scale;
116 
117  mitk::Point3D anchorPoint = wheelEvent->GetPositionInWorld();
118  auto *doOp = new mitk::ScaleOperation(OpSCALE, newScale, anchorPoint);
119  m_SelectedNode->GetData()->GetGeometry()->ExecuteOperation(doOp);
120 
122 }
123 
125 {
126  if (m_SelectedNode.IsNull())
127  return;
128  auto *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
129  if (positionEvent == nullptr)
130  return;
131 
132  m_InitialPickedPoint = positionEvent->GetPositionInWorld();
133  m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
134 
135  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
136  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
137  m_InitialOrigin = surGeo->GetOrigin();
138 }
139 
141 {
142  auto *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
143  if (positionEvent == nullptr)
144  return;
145 
146  m_InitialPickedPoint = positionEvent->GetPositionInWorld();
147  m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
148 
149  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
150  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
151  m_OriginalGeometry = dynamic_cast<mitk::Geometry3D *>(surGeo.GetPointer());
152 }
153 
155 {
156  auto *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
157  if (positionEvent == nullptr)
158  return;
159 
160  m_InitialPickedPoint = positionEvent->GetPositionInWorld();
161  m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
162 
163  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
164  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
165  m_OriginalGeometry = dynamic_cast<mitk::Geometry3D *>(surGeo.GetPointer());
166 }
167 
169 {
170  auto *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
171  if (positionEvent == nullptr)
172  return;
173 
174  Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
175 
176  Vector3D interactionMove;
177  interactionMove[0] = currentPickedPoint[0] - m_InitialPickedPoint[0];
178  interactionMove[1] = currentPickedPoint[1] - m_InitialPickedPoint[1];
179  interactionMove[2] = currentPickedPoint[2] - m_InitialPickedPoint[2];
180 
181  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
182  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
183  surGeo->SetOrigin(m_InitialOrigin);
184  surGeo->Translate(interactionMove);
185 
187 }
188 
190 {
191  auto *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
192  if (positionEvent == nullptr)
193  return;
194 
195  Point3D currentPickedPoint = positionEvent->GetPositionInWorld();
196  Vector3D interactionMove = currentPickedPoint - m_InitialPickedPoint;
197 
198  mitk::Surface::Pointer surface = dynamic_cast<mitk::Surface *>(m_SelectedNode->GetData());
199  surface->SetGeometry(m_OriginalGeometry);
200  mitk::BaseGeometry::Pointer surGeo = surface->GetGeometry();
201 
202  surGeo->WorldToIndex(interactionMove, interactionMove);
203  Point3D scale;
204  for (int i = 0; i < 3; ++i)
205  {
206  scale[i] = (interactionMove[i] * surGeo->GetMatrixColumn(i).magnitude()) - 1;
207  }
208 
209  mitk::Point3D anchorPoint = surGeo->GetCenter();
210 
211  auto *doOp = new mitk::ScaleOperation(OpSCALE, scale, anchorPoint);
212  surGeo->ExecuteOperation(doOp);
213 
215 }
216 
218 {
219  auto *positionEvent = dynamic_cast<InteractionPositionEvent *>(interactionEvent);
220  if (positionEvent == nullptr)
221  return;
222 
223  Point2D currentPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
224  if (currentPickedDisplayPoint.EuclideanDistanceTo(m_InitialPickedDisplayPoint) < 1)
225  return;
226 
227  vtkRenderer *currentVtkRenderer = interactionEvent->GetSender()->GetVtkRenderer();
228 
229  if (currentVtkRenderer && currentVtkRenderer->GetActiveCamera())
230  {
231  double vpn[3];
232  currentVtkRenderer->GetActiveCamera()->GetViewPlaneNormal(vpn);
233 
234  Vector3D rotationAxis;
235  rotationAxis[0] = vpn[0];
236  rotationAxis[1] = vpn[1];
237  rotationAxis[2] = vpn[2];
238  rotationAxis.Normalize();
239 
240  Vector2D move = currentPickedDisplayPoint - m_InitialPickedDisplayPoint;
241 
242  double rotationAngle = -57.3 * atan(move[0] / move[1]);
243  if (move[1] < 0)
244  rotationAngle += 180;
245 
246  // Use center of data bounding box as center of rotation
247  Point3D rotationCenter = m_OriginalGeometry->GetCenter();
248  if (positionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D)
249  rotationCenter = m_InitialPickedPoint;
250 
251  // Reset current Geometry3D to original state (pre-interaction) and
252  // apply rotation
253  RotationOperation op(OpROTATE, rotationCenter, rotationAxis, rotationAngle);
254  Geometry3D::Pointer newGeometry = static_cast<Geometry3D *>(m_OriginalGeometry->Clone().GetPointer());
255  newGeometry->ExecuteOperation(&op);
256  m_SelectedNode->GetData()->SetGeometry(newGeometry);
257 
259  }
260 }
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:28
Super class for all position events.
Standard implementation of BaseGeometry.
virtual void InitTranslate(StateMachineAction *, InteractionEvent *)
virtual void DeformObject(StateMachineAction *, InteractionEvent *)
vtkRenderer * GetVtkRenderer() const
virtual void InitRotate(StateMachineAction *, InteractionEvent *)
static Pointer New()
Constants for most interaction classes, due to the generic StateMachines.
virtual void ScaleRadius(StateMachineAction *, InteractionEvent *interactionEvent)
DataNode * GetDataNode() const
BaseRenderer * GetSender() const
superclass of all bounding objects (cylinder, cuboid,...)
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual void DeselectObject(StateMachineAction *, 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.
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)
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:138
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
virtual void TranslateObject(StateMachineAction *, InteractionEvent *interactionEvent)