Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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.