Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
itkFibersFromPlanarFiguresFilter.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 ===================================================================*/
17 
18 #define _USE_MATH_DEFINES
19 #include <math.h>
20 
21 // MITK
25 #include <mitkFiberBuilder.h>
29 #include <mitkRotationOperation.h>
30 #include <mitkInteractionConst.h>
31 
32 // ITK
33 #include <itkImageDuplicator.h>
34 #include <itkResampleImageFilter.h>
35 #include <itkTimeProbe.h>
36 #include <itkMersenneTwisterRandomVariateGenerator.h>
37 
38 // MISC
39 #include <math.h>
40 
41 namespace itk{
42 
44 {
45 
46 }
47 
49 {
50 
51 }
52 
53 
55 {
57  randGen->SetSeed((unsigned int)0);
58  m_2DPoints.clear();
59  int count = 0;
60 
61  while (count < m_Parameters.m_Density)
62  {
64  switch (m_Parameters.m_Distribution) {
65  case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN:
66  p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance);
67  p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance);
68  break;
69  default:
70  p[0] = randGen->GetUniformVariate(-1, 1);
71  p[1] = randGen->GetUniformVariate(-1, 1);
72  }
73 
74  if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1)
75  {
76  m_2DPoints.push_back(p);
77  count++;
78  }
79  }
80 }
81 
83 {
84  // check if enough fiducials are available
85  for (unsigned int i=0; i<m_Parameters.m_Fiducials.size(); i++)
86  if (m_Parameters.m_Fiducials.at(i).size()<2)
87  itkExceptionMacro("At least 2 fiducials needed per fiber bundle!");
88 
89  for (unsigned int i=0; i<m_Parameters.m_Fiducials.size(); i++)
90  {
91  vtkSmartPointer<vtkCellArray> m_VtkCellArray = vtkSmartPointer<vtkCellArray>::New();
92  vtkSmartPointer<vtkPoints> m_VtkPoints = vtkSmartPointer<vtkPoints>::New();
93 
94  vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i);
95 
96  vector< unsigned int > fliplist;
97  if (i<m_Parameters.m_FlipList.size())
98  fliplist = m_Parameters.m_FlipList.at(i);
99  else
100  fliplist.resize(bundle.size(), 0);
101  if (fliplist.size()<bundle.size())
102  fliplist.resize(bundle.size(), 0);
103 
104  GeneratePoints();
105  for (int j=0; j<m_Parameters.m_Density; j++)
106  {
107  vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
108 
109  mitk::PlanarEllipse::Pointer figure = bundle.at(0);
110  mitk::Point2D p0 = figure->GetControlPoint(0);
111  mitk::Point2D p1 = figure->GetControlPoint(1);
112  mitk::Point2D p2 = figure->GetControlPoint(2);
113  mitk::Point2D p3 = figure->GetControlPoint(3);
114  double r1 = p0.EuclideanDistanceTo(p1);
115  double r2 = p0.EuclideanDistanceTo(p2);
116  mitk::Vector2D eDir = p1-p0; eDir.Normalize();
117  mitk::Vector2D tDir = p3-p0; tDir.Normalize();
118 
119  // apply twist
120  vnl_matrix_fixed<double, 2, 2> tRot;
121  tRot[0][0] = tDir[0];
122  tRot[1][1] = tRot[0][0];
123  tRot[1][0] = sin(acos(tRot[0][0]));
124  tRot[0][1] = -tRot[1][0];
125  if (tDir[1]<0)
126  tRot.inplace_transpose();
127  m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector());
128 
129  // apply new ellipse shape
130  vnl_vector_fixed< double, 2 > newP;
131  newP[0] = m_2DPoints.at(j)[0];
132  newP[1] = m_2DPoints.at(j)[1];
133  double alpha = acos(eDir[0]);
134  if (eDir[1]>0)
135  alpha = 2*M_PI-alpha;
136  vnl_matrix_fixed<double, 2, 2> eRot;
137  eRot[0][0] = cos(alpha);
138  eRot[1][1] = eRot[0][0];
139  eRot[1][0] = sin(alpha);
140  eRot[0][1] = -eRot[1][0];
141  newP = eRot*newP;
142  newP[0] *= r1;
143  newP[1] *= r2;
144  newP = eRot.transpose()*newP;
145 
146  p0[0] += newP[0];
147  p0[1] += newP[1];
148 
149  const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry();
150 
151  mitk::Point3D w, wc;
152  planeGeo->Map(p0, w);
153 
154  wc = figure->GetWorldControlPoint(0);
155 
156  vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer());
157  container->GetPointIds()->InsertNextId(id);
158 
159  vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl();
160 
161  for (unsigned int k=1; k<bundle.size(); k++)
162  {
163  figure = bundle.at(k);
164  p0 = figure->GetControlPoint(0);
165  p1 = figure->GetControlPoint(1);
166  p2 = figure->GetControlPoint(2);
167  p3 = figure->GetControlPoint(3);
168  r1 = p0.EuclideanDistanceTo(p1);
169  r2 = p0.EuclideanDistanceTo(p2);
170 
171  eDir = p1-p0; eDir.Normalize();
172  mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize();
173  mitk::Vector2D temp; temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector());
174 
175  // apply twist
176  tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1];
177  tRot[1][1] = tRot[0][0];
178  tRot[1][0] = sin(acos(tRot[0][0]));
179  tRot[0][1] = -tRot[1][0];
180  if (temp[1]<0)
181  tRot.inplace_transpose();
182  m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector());
183  tDir = tDir2;
184 
185  // apply new ellipse shape
186  newP[0] = m_2DPoints.at(j)[0];
187  newP[1] = m_2DPoints.at(j)[1];
188 
189  // calculate normal
190  mitk::PlaneGeometry* planeGeo = const_cast<mitk::PlaneGeometry*>(figure->GetPlaneGeometry());
191  mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize();
192  vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl();
193  wc = figure->GetWorldControlPoint(0);
194 
195  // is flip needed?
196  if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001)
197  newP[0] *= -1;
198  if (fliplist.at(k)>0)
199  newP[0] *= -1;
200  n = n2;
201 
202  alpha = acos(eDir[0]);
203  if (eDir[1]>0)
204  alpha = 2*M_PI-alpha;
205  eRot[0][0] = cos(alpha);
206  eRot[1][1] = eRot[0][0];
207  eRot[1][0] = sin(alpha);
208  eRot[0][1] = -eRot[1][0];
209  newP = eRot*newP;
210  newP[0] *= r1;
211  newP[1] *= r2;
212  newP = eRot.transpose()*newP;
213 
214  p0[0] += newP[0];
215  p0[1] += newP[1];
216 
217  mitk::Point3D w;
218  planeGeo->Map(p0, w);
219 
220 
221  vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer());
222  container->GetPointIds()->InsertNextId(id);
223  }
224 
225  m_VtkCellArray->InsertNextCell(container);
226  }
227 
228  vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
229  fiberPolyData->SetPoints(m_VtkPoints);
230  fiberPolyData->SetLines(m_VtkCellArray);
231  mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData);
233  m_FiberBundles.push_back(mitkFiberBundle);
234  }
235 }
236 
237 }
238 
239 
240 
241 
itk::SmartPointer< Self > Pointer
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
vector< mitk::Vector2D > m_2DPoints
container for the 2D fiber waypoints
Constants for most interaction classes, due to the generic StateMachines.
VnlVector GetNormalVnl() const
Normal of the plane as VnlVector.
FlipListType m_FlipList
contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber...
Point3D ProjectPointOntoPlane(const Point3D &pt) const
Returns the lot from the point to the plane.
Describes a two-dimensional, rectangular plane.
FiducialListType m_Fiducials
container of the planar ellipses used as fiducials for the fiber generation process ...
FiberContainerType m_FiberBundles
container for the output fiber bundles
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.