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
mitkComputeContourSetNormalsFilter.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 "mitkIOUtil.h"
21 
23  : m_SegmentationBinaryImage(NULL),
24  m_MaxSpacing(5),
25  m_NegativeNormalCounter(0),
26  m_PositiveNormalCounter(0),
27  m_UseProgressBar(false),
28  m_ProgressStepSize(1)
29 {
31  this->SetNthOutput(0, output.GetPointer());
32 }
33 
35 {
36 }
37 
39 {
40  unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
41 
42  // Iterating over each input
43  for (unsigned int i = 0; i < numberOfInputs; i++)
44  {
45  // Getting the inputs polydata and polygons
46  Surface *currentSurface = const_cast<Surface *>(this->GetInput(i));
47  vtkPolyData *polyData = currentSurface->GetVtkPolyData();
48 
49  vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();
50 
51  vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();
52 
53  existingPolys->InitTraversal();
54 
55  vtkIdType *cell(NULL);
56  vtkIdType cellSize(0);
57 
58  // The array that contains all the vertex normals of the current polygon
59  vtkSmartPointer<vtkDoubleArray> normals = vtkSmartPointer<vtkDoubleArray>::New();
60  normals->SetNumberOfComponents(3);
61  normals->SetNumberOfTuples(polyData->GetNumberOfPoints());
62 
63  // If the current contour is an inner contour then the direction is -1
64  // A contour lies inside another one if the pixel values in the direction of the normal is 1
65  m_NegativeNormalCounter = 0;
66  m_PositiveNormalCounter = 0;
67  vtkIdType offSet(0);
68 
69  // Iterating over each polygon
70  for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
71  {
72  if (cellSize < 3)
73  continue;
74 
75  // First we calculate the current polygon's normal
76  double polygonNormal[3] = {0.0};
77 
78  double p1[3];
79  double p2[3];
80 
81  double v1[3];
82  double v2[3];
83 
84  existingPoints->GetPoint(cell[0], p1);
85  unsigned int index = cellSize * 0.5;
86  existingPoints->GetPoint(cell[index], p2);
87 
88  v1[0] = p2[0] - p1[0];
89  v1[1] = p2[1] - p1[1];
90  v1[2] = p2[2] - p1[2];
91 
92  for (vtkIdType k = 2; k < cellSize; k++)
93  {
94  index = cellSize * 0.25;
95  existingPoints->GetPoint(cell[index], p1);
96  index = cellSize * 0.75;
97  existingPoints->GetPoint(cell[index], p2);
98 
99  v2[0] = p2[0] - p1[0];
100  v2[1] = p2[1] - p1[1];
101  v2[2] = p2[2] - p1[2];
102 
103  vtkMath::Cross(v1, v2, polygonNormal);
104  if (vtkMath::Norm(polygonNormal) != 0)
105  break;
106  }
107 
108  vtkMath::Normalize(polygonNormal);
109 
110  // Now we start computing the normal for each vertex
111 
112  double vertexNormalTemp[3];
113  existingPoints->GetPoint(cell[0], p1);
114  existingPoints->GetPoint(cell[1], p2);
115 
116  v1[0] = p2[0] - p1[0];
117  v1[1] = p2[1] - p1[1];
118  v1[2] = p2[2] - p1[2];
119 
120  vtkMath::Cross(v1, polygonNormal, vertexNormalTemp);
121 
122  vtkMath::Normalize(vertexNormalTemp);
123 
124  double vertexNormal[3];
125 
126  for (vtkIdType j = 0; j < cellSize - 2; j++)
127  {
128  existingPoints->GetPoint(cell[j + 1], p1);
129  existingPoints->GetPoint(cell[j + 2], p2);
130 
131  v1[0] = p2[0] - p1[0];
132  v1[1] = p2[1] - p1[1];
133  v1[2] = p2[2] - p1[2];
134 
135  vtkMath::Cross(v1, polygonNormal, vertexNormal);
136 
137  vtkMath::Normalize(vertexNormal);
138 
139  double finalNormal[3];
140 
141  finalNormal[0] = (vertexNormal[0] + vertexNormalTemp[0]) * 0.5;
142  finalNormal[1] = (vertexNormal[1] + vertexNormalTemp[1]) * 0.5;
143  finalNormal[2] = (vertexNormal[2] + vertexNormalTemp[2]) * 0.5;
144  vtkMath::Normalize(finalNormal);
145 
146  // Here we determine the direction of the normal
147  if (m_SegmentationBinaryImage)
148  {
149  Point3D worldCoord;
150  worldCoord[0] = p1[0] + finalNormal[0] * m_MaxSpacing;
151  worldCoord[1] = p1[1] + finalNormal[1] * m_MaxSpacing;
152  worldCoord[2] = p1[2] + finalNormal[2] * m_MaxSpacing;
153 
154  double val = 0.0;
155 
156  itk::Index<3> idx;
157  m_SegmentationBinaryImage->GetGeometry()->WorldToIndex(worldCoord, idx);
158  try
159  {
160  if (m_SegmentationBinaryImage->GetImageDescriptor()
161  ->GetChannelDescriptor()
162  .GetPixelType()
163  .GetComponentType() == itk::ImageIOBase::UCHAR)
164  {
165  mitk::ImagePixelReadAccessor<unsigned char> readAccess(m_SegmentationBinaryImage);
166  val = readAccess.GetPixelByIndexSafe(idx);
167  }
168  else if (m_SegmentationBinaryImage->GetImageDescriptor()
169  ->GetChannelDescriptor()
170  .GetPixelType()
171  .GetComponentType() == itk::ImageIOBase::USHORT)
172  {
173  mitk::ImagePixelReadAccessor<unsigned short> readAccess(m_SegmentationBinaryImage);
174  val = readAccess.GetPixelByIndexSafe(idx);
175  }
176  }
177  catch (mitk::Exception e)
178  {
179  // If value is outside the image's region ignore it
180  MITK_WARN << e.what();
181  }
182 
183  if (val == 0.0)
184  {
185  // MITK_INFO << "val equals zero.";
186  ++m_PositiveNormalCounter;
187  }
188  else
189  {
190  // MITK_INFO << "val does not equal zero.";
191  ++m_NegativeNormalCounter;
192  }
193  }
194 
195  vertexNormalTemp[0] = vertexNormal[0];
196  vertexNormalTemp[1] = vertexNormal[1];
197  vertexNormalTemp[2] = vertexNormal[2];
198 
199  vtkIdType id = cell[j + 1];
200  normals->SetTuple(id, finalNormal);
201  }
202 
203  existingPoints->GetPoint(cell[0], p1);
204  existingPoints->GetPoint(cell[1], p2);
205 
206  v1[0] = p2[0] - p1[0];
207  v1[1] = p2[1] - p1[1];
208  v1[2] = p2[2] - p1[2];
209 
210  vtkMath::Cross(v1, polygonNormal, vertexNormal);
211 
212  vtkMath::Normalize(vertexNormal);
213 
214  vertexNormal[0] = (vertexNormal[0] + vertexNormalTemp[0]) * 0.5;
215  vertexNormal[1] = (vertexNormal[1] + vertexNormalTemp[1]) * 0.5;
216  vertexNormal[2] = (vertexNormal[2] + vertexNormalTemp[2]) * 0.5;
217  vtkMath::Normalize(vertexNormal);
218 
219  vtkIdType id = cell[0];
220  normals->SetTuple(id, vertexNormal);
221  id = cell[cellSize - 1];
222  normals->SetTuple(id, vertexNormal);
223 
224  if (m_NegativeNormalCounter > m_PositiveNormalCounter)
225  {
226  for (vtkIdType n = 0; n < cellSize; n++)
227  {
228  double normal[3];
229  normals->GetTuple(offSet + n, normal);
230  normal[0] = (-1) * normal[0];
231  normal[1] = (-1) * normal[1];
232  normal[2] = (-1) * normal[2];
233  normals->SetTuple(offSet + n, normal);
234  }
235  }
236 
237  m_NegativeNormalCounter = 0;
238  m_PositiveNormalCounter = 0;
239  offSet += cellSize;
240 
241  } // end for all cells
242 
243  Surface::Pointer surface = this->GetOutput(i);
244  surface->GetVtkPolyData()->GetCellData()->SetNormals(normals);
245  } // end for all inputs
246 
247  // Setting progressbar
248  if (this->m_UseProgressBar)
249  mitk::ProgressBar::GetInstance()->Progress(this->m_ProgressStepSize);
250 }
251 
253 {
254  // Just for debugging:
255  vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
256  vtkSmartPointer<vtkCellArray> newLines = vtkSmartPointer<vtkCellArray>::New();
257  vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
258  unsigned int idCounter(0);
259  // Debug end
260 
261  for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); i++)
262  {
263  Surface *currentSurface = const_cast<Surface *>(this->GetOutput(i));
264  vtkPolyData *polyData = currentSurface->GetVtkPolyData();
265 
266  vtkSmartPointer<vtkDoubleArray> currentCellNormals =
267  vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());
268 
269  vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();
270 
271  vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();
272 
273  existingPolys->InitTraversal();
274 
275  vtkIdType *cell(NULL);
276  vtkIdType cellSize(0);
277 
278  for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
279  {
280  for (vtkIdType j = 0; j < cellSize; j++)
281  {
282  double currentNormal[3];
283  currentCellNormals->GetTuple(cell[j], currentNormal);
284  vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();
285  line->GetPointIds()->SetNumberOfIds(2);
286  double newPoint[3];
287  double p0[3];
288  existingPoints->GetPoint(cell[j], p0);
289  newPoint[0] = p0[0] + currentNormal[0];
290  newPoint[1] = p0[1] + currentNormal[1];
291  newPoint[2] = p0[2] + currentNormal[2];
292 
293  line->GetPointIds()->SetId(0, idCounter);
294  newPoints->InsertPoint(idCounter, p0);
295  idCounter++;
296 
297  line->GetPointIds()->SetId(1, idCounter);
298  newPoints->InsertPoint(idCounter, newPoint);
299  idCounter++;
300 
301  newLines->InsertNextCell(line);
302  } // end for all points
303  } // end for all cells
304  } // end for all outputs
305 
306  newPolyData->SetPoints(newPoints);
307  newPolyData->SetLines(newLines);
308  newPolyData->BuildCells();
309 
311  surface->SetVtkPolyData(newPolyData);
312 
313  return surface;
314 }
315 
317 {
318  m_MaxSpacing = maxSpacing;
319 }
320 
322 {
323  Superclass::GenerateOutputInformation();
324 }
325 
327 {
328  for (unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
329  {
330  this->PopBackInput();
331  }
332  this->SetNumberOfIndexedInputs(0);
333  this->SetNumberOfIndexedOutputs(0);
334 
336  this->SetNthOutput(0, output.GetPointer());
337 }
338 
340 {
341  this->m_UseProgressBar = status;
342 }
343 
345 {
346  this->m_ProgressStepSize = stepSize;
347 }
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
static char * line
Definition: svm.cpp:2884
const TPixel & GetPixelByIndexSafe(const itk::Index< VDimension > &idx) const
Gives locked and index-based read access for a particular image part. The class provides several set-...
virtual vtkPolyData * GetVtkPolyData(unsigned int t=0) const
void SetProgressStepSize(unsigned int stepSize)
Set the stepsize which the progress bar should proceed.
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
void SetUseProgressBar(bool)
Set whether the mitkProgressBar should be used.
#define MITK_WARN
Definition: mitkLogMacros.h:23
An object of this class represents an exception of MITK. Please don't instantiate exceptions manually...
Definition: mitkException.h:49
void Normalize(itk::Image< TPixel, VImageDimension > *itkImage, mitk::Image::Pointer im2, mitk::Image::Pointer mask1, std::string output)
Definition: CLBrainMask.cpp:40
static Pointer New()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.