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
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.