Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkRegVisHelper.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 
17 
18 //VTK
19 #include <vtkPolyLine.h>
20 #include <vtkIdList.h>
21 #include <vtkCellArray.h>
22 #include <vtkFloatArray.h>
23 #include <vtkPointData.h>
24 #include <vtkWarpVector.h>
25 #include <vtkCleanPolyData.h>
26 #include <vtkVectorNorm.h>
27 #include <vtkGlyph3D.h>
28 #include <vtkArrowSource.h>
29 
30 //MITK
31 #include <mitkProperties.h>
32 
33 //MITK
34 #include "mitkRegVisHelper.h"
35 #include "mitkRegVisPropertyTags.h"
38 
39 //MAP
40 #include "mapRegistration.h"
41 
42 namespace mitk
43 {
44 
45  void GetGridGeometryFromNode(const mitk::DataNode* regNode, mitk::Geometry3D::Pointer& gridDesc, unsigned int& gridFrequ)
46  {
47 
48  int internalFrequ = 1;
49 
50  if(!regNode->GetIntProperty(mitk::nodeProp_RegVisGridFrequence,internalFrequ))
51  {
52  mitkThrow() << "Cannot configure node correctly. Node property "<<mitk::nodeProp_RegVisGridFrequence<<" is not correctly defined.";
53  }
54 
55  mitk::Vector3DProperty* valueProp = NULL;
56  mitk::Vector3D size;
57  mitk::Vector3D spacing;
58 
59  if (regNode->GetProperty(valueProp, mitk::nodeProp_RegVisFOVSize))
60  {
61  size = valueProp->GetValue();
62  }
63  else
64  {
65  mitkThrow() << "Cannot configure node correctly. Node property "<<mitk::nodeProp_RegVisFOVSize<<" is not correctly defined.";
66  }
67 
68  if (regNode->GetProperty(valueProp, mitk::nodeProp_RegVisFOVSpacing))
69  {
70  spacing = valueProp->GetValue();
71  }
72  else
73  {
74  mitkThrow() << "Cannot configure node correctly. Node property "<<mitk::nodeProp_RegVisFOVSpacing<<" is not correctly defined.";
75  }
76 
77  mitk::Point3dProperty* originProp = NULL;
78  mitk::Point3D origin;
79  if (regNode->GetProperty(originProp, mitk::nodeProp_RegVisFOVOrigin))
80  {
81  origin = originProp->GetValue();
82  }
83  else
84  {
85  mitkThrow() << "Cannot configure node correctly. Node property "<<mitk::nodeProp_RegVisFOVOrigin<<" is not correctly defined.";
86  }
87 
88  gridDesc = mitk::Geometry3D::New();
89  mitk::Geometry3D::BoundsArrayType bounds = gridDesc->GetBounds();
90  bounds[0] = 0;
91  bounds[1] = size[0]/spacing[0];
92  bounds[2] = 0;
93  bounds[3] = size[1]/spacing[1];
94  bounds[4] = 0;
95  bounds[5] = size[2]/spacing[2];
96  gridDesc->SetBounds(bounds);
97  gridDesc->SetSpacing(spacing);
98  gridDesc->SetOrigin(origin);
99 
100  gridFrequ = internalFrequ;
101  }
102 
103 
104  vtkSmartPointer<vtkPolyData> Generate3DDeformationGlyph(const mitk::BaseGeometry* gridDesc, const map::core::RegistrationKernelBase<3,3>* regKernel)
105  {
106  assert(gridDesc);
107 
108  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
109  vtkSmartPointer<vtkFloatArray> vectors = vtkSmartPointer<vtkFloatArray>::New();
110  vectors->SetNumberOfComponents(3);
111  vectors->SetName("DeformationVectors");
112 
113  long xExtend = itk::Math::Ceil<long,mitk::ScalarType>(gridDesc->GetExtent(0));
114  long yExtend = itk::Math::Ceil<long,mitk::ScalarType>(gridDesc->GetExtent(1));
115  long zExtend = itk::Math::Ceil<long,mitk::ScalarType>(gridDesc->GetExtent(2));
116  long zOffset = xExtend*yExtend;
117 
118  mitk::Geometry3D::BoundsArrayType bounds = gridDesc->GetBounds();
119 
120  //Generate Points
121  mitk::Point3D pos;
122  for (pos[2] = bounds[4] ; pos[2]< bounds[4]+zExtend; ++(pos[2]))
123  {
124  for (pos[1] = bounds[2]; pos[1]< bounds[2]+yExtend; ++(pos[1]))
125  {
126  for (pos[0] = bounds[0]; pos[0]< bounds[0]+xExtend; ++(pos[0]))
127  {
128  mitk::Point3D worldPos;
129  gridDesc->IndexToWorld(pos,worldPos);
130  points->InsertNextPoint(worldPos[0],worldPos[1],worldPos[2]);
131 
132  if(regKernel)
133  {
134  map::core::RegistrationKernelBase<3,3>::InputPointType regInput(worldPos);
135  map::core::RegistrationKernelBase<3,3>::OutputPointType regOutput;
136 
137  bool mapped = regKernel->mapPoint(regInput,regOutput);
138  mitk::Vector3D vector(regOutput-regInput);
139  if (!mapped)
140  {
141  vector.Fill(0.0);
142  }
143 
144  vectors->InsertNextTuple(vector.GetDataPointer());
145  }
146  }
147  }
148  }
149 
150  vtkSmartPointer<vtkPolyData> input = vtkSmartPointer<vtkPolyData>::New();
151  vtkSmartPointer<vtkFloatArray> vectorMagnitude;
152 
153  input->SetPoints(points);
154 
155  if(regKernel)
156  {
157  input->GetPointData()->SetVectors(vectors);
158  input->GetPointData()->SetActiveVectors(vectors->GetName());
159 
160  vtkSmartPointer<vtkVectorNorm> norm = vtkSmartPointer<vtkVectorNorm>::New();
161  norm->SetInputData(input);
162  norm->SetAttributeModeToUsePointData();
163  norm->Update();
164 
165  vectorMagnitude = vtkFloatArray::SafeDownCast(norm->GetOutput()->GetPointData()->GetScalars());
166  vectorMagnitude->SetName("VectorMagnitude");
167  input->GetPointData()->SetScalars(vectorMagnitude);
168  input->GetPointData()->SetActiveScalars(vectorMagnitude->GetName());
169  }
170 
171  vtkSmartPointer<vtkGlyph3D> glyphFilter = vtkSmartPointer<vtkGlyph3D>::New();
172  glyphFilter->ScalingOn();
173  glyphFilter->OrientOn();
174  glyphFilter->SetVectorModeToUseVector();
175  glyphFilter->SetScaleModeToScaleByVector();
176  glyphFilter->SetInputData(input);
177 
178  vtkSmartPointer<vtkArrowSource> arrowSource = vtkSmartPointer<vtkArrowSource>::New();
179  arrowSource->SetTipLength(0.2);
180 
181  glyphFilter->SetSourceConnection(arrowSource->GetOutputPort());
182 
183  glyphFilter->Update();
184 
185  vtkSmartPointer<vtkPolyData> output = glyphFilter->GetOutput();
186 
187  return output;
188  }
189 
190  vtkSmartPointer<vtkPolyData> MITKMATCHPOINTREGISTRATION_EXPORT Generate3DDeformationGrid( const mitk::BaseGeometry* gridDesc, unsigned int gridFrequence, const map::core::RegistrationKernelBase<3,3>* regKernel /*= NULL*/ )
191  {
192  assert(gridDesc);
193 
194  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
195  vtkSmartPointer<vtkFloatArray> vectors = vtkSmartPointer<vtkFloatArray>::New();
196  vectors->SetNumberOfComponents(3);
197  vectors->SetName("DeformationVectors");
198 
199  long xExtend = itk::Math::Ceil<long,mitk::ScalarType>(gridDesc->GetExtent(0))+1;
200  long yExtend = itk::Math::Ceil<long,mitk::ScalarType>(gridDesc->GetExtent(1))+1;
201  long zExtend = itk::Math::Ceil<long,mitk::ScalarType>(gridDesc->GetExtent(2))+1;
202  long zOffset = xExtend*yExtend;
203 
204  mitk::Geometry3D::BoundsArrayType bounds = gridDesc->GetBounds();
205 
206  //Generate Points
207  mitk::Point3D pos;
208  for (pos[2] = bounds[4] ; pos[2]< bounds[4]+zExtend; ++(pos[2]))
209  {
210  for (pos[1] = bounds[2]; pos[1]< bounds[2]+yExtend; ++(pos[1]))
211  {
212  for (pos[0] = bounds[0]; pos[0]< bounds[0]+xExtend; ++(pos[0]))
213  {
214  mitk::Point3D worldPos;
215  gridDesc->IndexToWorld(pos,worldPos);
216  points->InsertNextPoint(worldPos[0],worldPos[1],worldPos[2]);
217 
218  if(regKernel)
219  {
220  map::core::RegistrationKernelBase<3,3>::InputPointType regInput(worldPos);
221  map::core::RegistrationKernelBase<3,3>::OutputPointType regOutput;
222 
223  bool mapped = regKernel->mapPoint(regInput,regOutput);
224  mitk::Vector3D vector(regOutput-regInput);
225  if (!mapped)
226  {
227  vector.Fill(0.0);
228  }
229 
230  vectors->InsertNextTuple(vector.GetDataPointer());
231  }
232  }
233  }
234  }
235 
236  vtkSmartPointer<vtkCellArray> gridLinesCell = vtkSmartPointer<vtkCellArray>::New();
237  vtkSmartPointer<vtkPolyLine> gridLine = vtkSmartPointer<vtkPolyLine>::New();
238  gridLine->GetPointIds()->SetNumberOfIds(2);
239 
240  //generate the gridlines between the points
241  for (long zPos = 0; zPos< zExtend-1; ++zPos)
242  {
243  for (long yPos = 0; yPos< yExtend-1; ++yPos)
244  {
245  for (long xPos = 0; xPos< xExtend-1; ++xPos)
246  {
247  gridLine->GetPointIds()->SetId(0, xPos+yPos*xExtend+zPos*zOffset);
248 
249  if ((yPos%gridFrequence == 0) && (zPos%gridFrequence == 0))
250  {
251  gridLine->GetPointIds()->SetId(1, (xPos+1)+yPos*xExtend+zPos*zOffset);
252  gridLinesCell->InsertNextCell(gridLine);
253  }
254 
255  if ((xPos%gridFrequence == 0) && (zPos%gridFrequence == 0))
256  {
257  gridLine->GetPointIds()->SetId(1, xPos+(yPos+1)*xExtend+zPos*zOffset);
258  gridLinesCell->InsertNextCell(gridLine);
259  }
260 
261  if ((xPos%gridFrequence == 0) && (yPos%gridFrequence == 0))
262  {
263  gridLine->GetPointIds()->SetId(1, xPos+yPos*xExtend+(zPos+1)*zOffset);
264  gridLinesCell->InsertNextCell(gridLine);
265  }
266  }
267  }
268  }
269 
270  vtkSmartPointer<vtkPolyData> grid = vtkSmartPointer<vtkPolyData>::New();
271  vtkSmartPointer<vtkFloatArray> vectorMagnitude;
272 
273  grid->SetPoints(points);
274  grid->SetLines(gridLinesCell);
275 
276  if(regKernel)
277  {
278  grid->GetPointData()->SetVectors(vectors);
279  grid->GetPointData()->SetActiveVectors(vectors->GetName());
280 
281  vtkSmartPointer<vtkVectorNorm> norm = vtkSmartPointer<vtkVectorNorm>::New();
282  norm->SetInputData(grid);
283  norm->SetAttributeModeToUsePointData();
284  norm->Update();
285 
286  vectorMagnitude = vtkFloatArray::SafeDownCast(norm->GetOutput()->GetPointData()->GetScalars());
287  vectorMagnitude->SetName("VectorMagnitude");
288  }
289 
290  vtkSmartPointer<vtkPolyData> input = grid;
291 
292  if(regKernel)
293  {
294  vtkSmartPointer<vtkWarpVector> warp = vtkSmartPointer<vtkWarpVector>::New();
295 
296  warp->SetInputData(input);
297  warp->SetScaleFactor(1);
298  warp->Update();
299 
300  input = warp->GetPolyDataOutput();
301 
302  input->GetPointData()->SetScalars(vectorMagnitude);
303  input->GetPointData()->SetActiveScalars(vectorMagnitude->GetName());
304  }
305 
306  return input;
307  }
308 
309 
310  bool GridIsOutdated(const mitk::DataNode* regNode, const itk::TimeStamp& reference)
311  {
312 
314  {
315  return true;
316  }
317 
318  if (PropertyIsOutdated(regNode,mitk::nodeProp_RegVisFOVSize,reference))
319  {
320  return true;
321  }
322 
324  {
325  return true;
326  }
327 
328  if (PropertyIsOutdated(regNode,mitk::nodeProp_RegVisFOVOrigin,reference))
329  {
330  return true;
331  }
332 
333  if (PropertyIsOutdated(regNode,mitk::nodeProp_RegVisDirection,reference))
334  {
335  return true;
336  }
337 
338  return false;
339  }
340 
341  bool PropertyIsOutdated(const mitk::DataNode* regNode, const std::string& propName, const itk::TimeStamp& reference)
342  {
343  if (!regNode)
344  {
345  mitkThrow() << "Cannot check for outdated property. Passed regNode is null.";
346  }
347 
348  bool result = false;
349 
350  mitk::BaseProperty* prop = regNode->GetProperty(propName.c_str());
351  if (prop)
352  {
353  result = reference < prop->GetMTime();
354  }
355  else
356  {
357  mitkThrow() << "Cannot check for outdated property. Property not defined in passed regNode. Property name: "<<propName;
358  }
359 
360  return result;
361  }
362 
363  const map::core::RegistrationKernelBase<3,3>* GetRelevantRegKernelOfNode(const mitk::DataNode* regNode)
364  {
365  const map::core::RegistrationKernelBase<3,3>* regKernel = NULL;
366 
367  if (!regNode) return regKernel;
368 
369  const mitk::MAPRegistrationWrapper* regWrapper = dynamic_cast<const mitk::MAPRegistrationWrapper*>(regNode->GetData());
370 
371  if (!regWrapper) return regKernel;
372 
373  const map::core::Registration<3,3>* reg = dynamic_cast<const map::core::Registration<3,3>*>(regWrapper->GetRegistration());
374 
375  if (reg)
376  {
377  mitk::RegVisDirectionProperty* directionProp = NULL;
378  if (regNode->GetProperty(directionProp, mitk::nodeProp_RegVisDirection))
379  {
380  if (directionProp->GetValueAsId()==0)
381  {
382  regKernel = &(reg->getDirectMapping());
383  }
384  else
385  {
386  regKernel = &(reg->getInverseMapping());
387  }
388  }
389  }
390  return regKernel;
391  }
392 
393 }
ScalarType GetExtent(unsigned int direction) const
Set the time bounds (in ms)
const char *const nodeProp_RegVisFOVOrigin
void GetGridGeometryFromNode(const mitk::DataNode *regNode, mitk::Geometry3D::Pointer &gridDesc, unsigned int &gridFrequ)
BoundingBoxType::BoundsArrayType BoundsArrayType
bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer=nullptr) const
Convenience access method for int properties (instances of IntProperty)
const char *const nodeProp_RegVisDirection
DataCollection - Class to facilitate loading/accessing structured data.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
MAPRegistrationWrapper Wrapper class to allow the handling of MatchPoint registration objects as mitk...
static Pointer New()
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
const BoundsArrayType GetBounds() const
const char *const nodeProp_RegVisFOVSpacing
map::core::RegistrationBase * GetRegistration()
Abstract base class for properties.
const char *const nodeProp_RegVisFOVSize
vtkSmartPointer< vtkPolyData > MITKMATCHPOINTREGISTRATION_EXPORT Generate3DDeformationGrid(const mitk::BaseGeometry *gridDesc, unsigned int gridFrequence, const map::core::RegistrationKernelBase< 3, 3 > *regKernel)
#define MITKMATCHPOINTREGISTRATION_EXPORT
#define mitkThrow()
bool PropertyIsOutdated(const mitk::DataNode *regNode, const std::string &propName, const itk::TimeStamp &reference)
bool GridIsOutdated(const mitk::DataNode *regNode, const itk::TimeStamp &reference)
vtkSmartPointer< vtkPolyData > Generate3DDeformationGlyph(const mitk::BaseGeometry *gridDesc, const map::core::RegistrationKernelBase< 3, 3 > *regKernel)
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
const char *const nodeProp_RegVisGridFrequence
BaseGeometry Describes the geometry of a data object.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
virtual IdType GetValueAsId() const
const map::core::RegistrationKernelBase< 3, 3 > * GetRelevantRegKernelOfNode(const mitk::DataNode *regNode)
virtual T GetValue() const
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.