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