Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkSurfaceDeformationDataInteractor3D.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 "mitkMouseWheelEvent.h"
20 
21 #include <vtkInteractorObserver.h>
22 #include <vtkPointData.h>
23 #include <vtkPolyData.h>
24 
26 {
27  m_OriginalPolyData = vtkPolyData::New();
28 
29  // Initialize vector arithmetic
30  m_ObjectNormal[0] = 0.0;
31  m_ObjectNormal[1] = 0.0;
32  m_ObjectNormal[2] = 1.0;
33 }
34 
36 {
37  m_OriginalPolyData->Delete();
38 }
39 
41 {
42  // **Conditions** that can be used in the state machine, to ensure that certain conditions are met, before
43  // actually executing an action
44  CONNECT_CONDITION("isOverObject", CheckOverObject);
45 
46  // **Function** in the statmachine patterns also referred to as **Actions**
47  CONNECT_FUNCTION("selectObject", SelectObject);
48  CONNECT_FUNCTION("deselectObject", DeselectObject);
49  CONNECT_FUNCTION("initDeformation", InitDeformation);
50  CONNECT_FUNCTION("deformObject", DeformObject);
51  CONNECT_FUNCTION("scaleRadius", ScaleRadius);
52 }
53 
55 {
56  if (this->GetDataNode() != nullptr)
57  {
58  m_Surface = dynamic_cast<Surface *>(this->GetDataNode()->GetData());
59 
60  if (m_Surface == NULL)
61  MITK_ERROR << "SurfaceDeformationDataInteractor3D::DataNodeChanged(): DataNode has to contain a surface.";
62  }
63  else
64  m_Surface = NULL;
65 }
66 
68 {
69  const InteractionPositionEvent *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
70  if (positionEvent == NULL)
71  return false;
72 
73  Point2D currentPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
74  Point3D currentPickedPoint;
75 
76  if (interactionEvent->GetSender()->PickObject(currentPickedDisplayPoint, currentPickedPoint) == this->GetDataNode())
77  {
78  // Colorized surface at current picked position
79  m_SurfaceColorizationCenter = currentPickedPoint;
80  return true;
81  }
82  return false;
83 }
84 
86 {
87  const InteractionPositionEvent *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
88  if (positionEvent == NULL)
89  return;
90 
91  int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
92  vtkPolyData *polyData = m_Surface->GetVtkPolyData(timeStep);
93 
94  this->GetDataNode()->SetColor(1.0, 0.0, 0.0);
95 
96  // Colorize surface / wireframe dependend on distance from picked point
97  this->ColorizeSurface(polyData, timeStep, m_SurfaceColorizationCenter, COLORIZATION_GAUSS);
98 
99  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
100 }
101 
103 {
104  const InteractionPositionEvent *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
105  if (positionEvent == NULL)
106  return;
107 
108  int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
109  vtkPolyData *polyData = m_Surface->GetVtkPolyData(timeStep);
110 
111  this->GetDataNode()->SetColor(1.0, 1.0, 1.0);
112 
113  // Colorize surface / wireframe as inactive
114  this->ColorizeSurface(polyData, timeStep, m_SurfaceColorizationCenter, COLORIZATION_CONSTANT, -1.0);
115 
116  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
117 }
118 
120 {
121  const InteractionPositionEvent *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
122  if (positionEvent == NULL)
123  return;
124 
125  int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
126  vtkPolyData *polyData = m_Surface->GetVtkPolyData(timeStep);
127 
128  // Store current picked point
129  mitk::Point2D currentPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
130  interactionEvent->GetSender()->PickObject(currentPickedDisplayPoint, m_InitialPickedPoint);
131 
132  vtkInteractorObserver::ComputeDisplayToWorld(interactionEvent->GetSender()->GetVtkRenderer(),
133  currentPickedDisplayPoint[0],
134  currentPickedDisplayPoint[1],
135  0.0, // m_InitialInteractionPickedPoint[2],
136  m_InitialPickedWorldPoint);
137 
138  // Make deep copy of vtkPolyData interacted on
139  m_OriginalPolyData->DeepCopy(polyData);
140 }
141 
143 {
144  const InteractionPositionEvent *positionEvent = dynamic_cast<const InteractionPositionEvent *>(interactionEvent);
145  if (positionEvent == NULL)
146  return;
147 
148  int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
149  vtkPolyData *polyData = m_Surface->GetVtkPolyData(timeStep);
150  BaseGeometry::Pointer geometry = this->GetDataNode()->GetData()->GetGeometry(timeStep);
151 
152  double currentWorldPoint[4];
153  mitk::Point2D currentDisplayPoint = positionEvent->GetPointerPositionOnScreen();
154  vtkInteractorObserver::ComputeDisplayToWorld(interactionEvent->GetSender()->GetVtkRenderer(),
155  currentDisplayPoint[0],
156  currentDisplayPoint[1],
157  0.0, // m_InitialInteractionPickedPoint[2],
158  currentWorldPoint);
159 
160  // Calculate mouse move in 3D space
161  Vector3D interactionMove;
162  interactionMove[0] = currentWorldPoint[0] - m_InitialPickedWorldPoint[0];
163  interactionMove[1] = currentWorldPoint[1] - m_InitialPickedWorldPoint[1];
164  interactionMove[2] = currentWorldPoint[2] - m_InitialPickedWorldPoint[2];
165 
166  // Transform mouse move into geometry space
167  this->GetDataNode()->GetData()->UpdateOutputInformation(); // make sure that the Geometry is up-to-date
168  Vector3D interactionMoveIndex;
169  geometry->WorldToIndex(interactionMove, interactionMoveIndex);
170 
171  // Get picked point and transform into local coordinates
172  Point3D pickedPoint;
173  geometry->WorldToIndex(m_InitialPickedPoint, pickedPoint);
174 
175  Vector3D v1 = pickedPoint.GetVectorFromOrigin();
176 
177  vtkDataArray *normal = polyData->GetPointData()->GetVectors("planeNormal");
178  if (normal != NULL)
179  {
180  m_ObjectNormal[0] = normal->GetComponent(0, 0);
181  m_ObjectNormal[1] = normal->GetComponent(0, 1);
182  m_ObjectNormal[2] = normal->GetComponent(0, 2);
183  }
184 
185  Vector3D v2 = m_ObjectNormal * (interactionMoveIndex * m_ObjectNormal);
186 
187  vtkPoints *originalPoints = m_OriginalPolyData->GetPoints();
188  vtkPoints *deformedPoints = polyData->GetPoints();
189 
190  double denom = m_GaussSigma * m_GaussSigma * 2;
191  double point[3];
192  for (vtkIdType i = 0; i < deformedPoints->GetNumberOfPoints(); ++i)
193  {
194  // Get original point
195  double *originalPoint = originalPoints->GetPoint(i);
196 
197  Vector3D v0;
198  v0[0] = originalPoint[0];
199  v0[1] = originalPoint[1];
200  v0[2] = originalPoint[2];
201 
202  // Calculate distance of this point from line through picked point
203  double d = itk::CrossProduct(m_ObjectNormal, (v1 - v0)).GetNorm();
204 
205  Vector3D t = v2 * exp(-d * d / denom);
206 
207  point[0] = originalPoint[0] + t[0];
208  point[1] = originalPoint[1] + t[1];
209  point[2] = originalPoint[2] + t[2];
210  deformedPoints->SetPoint(i, point);
211  }
212 
213  // Make sure that surface is colorized at initial picked position as long as we are in deformation state
214  m_SurfaceColorizationCenter = m_InitialPickedPoint;
215 
216  polyData->Modified();
217  m_Surface->Modified();
218 
219  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
220 }
221 
223 {
224  const MouseWheelEvent *wheelEvent = dynamic_cast<const MouseWheelEvent *>(interactionEvent);
225  if (wheelEvent == NULL)
226  return;
227 
228  m_GaussSigma += (double)(wheelEvent->GetWheelDelta()) / 20;
229  if (m_GaussSigma < 10.0)
230  {
231  m_GaussSigma = 10.0;
232  }
233  else if (m_GaussSigma > 128.0)
234  {
235  m_GaussSigma = 128.0;
236  }
237 
238  int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
239  vtkPolyData *polyData = m_Surface->GetVtkPolyData(timeStep);
240 
241  // Colorize surface / wireframe dependend on sigma and distance from picked point
242  this->ColorizeSurface(polyData, timeStep, m_SurfaceColorizationCenter, COLORIZATION_GAUSS);
243 
244  interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
245 }
246 
247 void mitk::SurfaceDeformationDataInteractor3D::ColorizeSurface(
248  vtkPolyData *polyData, int timeStep, const Point3D &pickedPoint, int mode, double scalar)
249 {
250  if (polyData == NULL)
251  return;
252 
253  vtkPoints *points = polyData->GetPoints();
254  vtkPointData *pointData = polyData->GetPointData();
255  if (pointData == NULL)
256  return;
257 
258  vtkDataArray *scalars = pointData->GetScalars();
259  if (scalars == NULL)
260  return;
261 
262  if (mode == COLORIZATION_GAUSS)
263  {
264  // Get picked point and transform into local coordinates
265  Point3D localPickedPoint;
266  BaseGeometry::Pointer geometry = this->GetDataNode()->GetData()->GetGeometry(timeStep);
267  geometry->WorldToIndex(pickedPoint, localPickedPoint);
268 
269  Vector3D v1 = localPickedPoint.GetVectorFromOrigin();
270 
271  vtkDataArray *normal = polyData->GetPointData()->GetVectors("planeNormal");
272  if (normal != NULL)
273  {
274  m_ObjectNormal[0] = normal->GetComponent(0, 0);
275  m_ObjectNormal[1] = normal->GetComponent(0, 1);
276  m_ObjectNormal[2] = normal->GetComponent(0, 2);
277  }
278 
279  double denom = m_GaussSigma * m_GaussSigma * 2;
280  for (vtkIdType i = 0; i < points->GetNumberOfPoints(); ++i)
281  {
282  // Get original point
283  double *point = points->GetPoint(i);
284  Vector3D v0;
285  v0[0] = point[0];
286  v0[1] = point[1];
287  v0[2] = point[2];
288 
289  // Calculate distance of this point from line through picked point
290  double d = itk::CrossProduct(m_ObjectNormal, (v1 - v0)).GetNorm();
291  double t = exp(-d * d / denom);
292 
293  scalars->SetComponent(i, 0, t);
294  }
295  }
296  else if (mode == COLORIZATION_CONSTANT)
297  {
298  for (vtkIdType i = 0; i < pointData->GetNumberOfTuples(); ++i)
299  {
300  scalars->SetComponent(i, 0, scalar);
301  }
302  }
303  polyData->Modified();
304  pointData->Update();
305 }
virtual void ScaleRadius(StateMachineAction *, InteractionEvent *)
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
virtual void SelectObject(StateMachineAction *, InteractionEvent *)
Super class for all position events.
virtual void DeselectObject(StateMachineAction *, InteractionEvent *)
virtual bool CheckOverObject(const InteractionEvent *)
Checks if the mouse pointer is over the object.
BaseRenderer * GetSender() const
#define MITK_ERROR
Definition: mitkLogMacros.h:24
virtual DataNode * PickObject(const Point2D &, Point3D &) const
Determines the object (mitk::DataNode) closest to the current position by means of picking...
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.
T::Pointer GetData(const std::string &name)
virtual void DeformObject(StateMachineAction *, InteractionEvent *)
virtual mitk::RenderingManager * GetRenderingManager() const
Setter for the RenderingManager that handles this instance of BaseRenderer.
Vector< ScalarType, 3 > Vector3D
Definition: mitkVector.h:134
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual void InitDeformation(StateMachineAction *, InteractionEvent *)
virtual unsigned int GetTimeStep() const
#define CONNECT_CONDITION(a, f)
static Point3D originalPoint
#define CONNECT_FUNCTION(a, f)
vtkRenderer * GetVtkRenderer() const
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.