Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkUnstructuredGridClusteringFilter.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 
14 
15 #include <vector>
16 
17 #include <vtkDataArray.h>
18 #include <vtkDelaunay3D.h>
19 #include <vtkDoubleArray.h>
20 #include <vtkPointData.h>
21 #include <vtkPointLocator.h>
22 #include <vtkPoints.h>
23 #include <vtkPolyVertex.h>
24 #include <vtkSmartPointer.h>
25 #include <vtkUnstructuredGrid.h>
26 #include <vtkVariant.h>
27 
29  : m_eps(5.0), m_MinPts(4), m_Meshing(false), m_DistCalc(false)
30 {
31  this->m_UnstructGrid = mitk::UnstructuredGrid::New();
32 }
33 
35 {
36 }
37 
38 std::map<int, bool> visited;
39 std::map<int, bool> isNoise;
40 std::map<int, bool> clusterMember;
41 vtkSmartPointer<vtkPointLocator> pLocator;
42 std::vector<vtkSmartPointer<vtkPoints>> clusterVector;
43 
44 std::vector<std::vector<int>> clustersPointsIDs;
45 
47 {
48  m_UnstructGrid = this->GetOutput();
49 }
50 
52 {
53  mitk::UnstructuredGrid::Pointer inputGrid = const_cast<mitk::UnstructuredGrid *>(this->GetInput());
54  if (inputGrid.IsNull())
55  return;
56 
57  vtkSmartPointer<vtkUnstructuredGrid> vtkInpGrid = inputGrid->GetVtkUnstructuredGrid();
58  vtkSmartPointer<vtkPoints> inpPoints = vtkInpGrid->GetPoints();
59  pLocator = vtkSmartPointer<vtkPointLocator>::New();
60 
61  vtkSmartPointer<vtkDoubleArray> distances = vtkSmartPointer<vtkDoubleArray>::New();
62  if (inputGrid->GetVtkUnstructuredGrid()->GetPointData()->GetNumberOfArrays() > 0)
63  {
64  m_DistCalc = true;
65  distances = dynamic_cast<vtkDoubleArray *>(vtkInpGrid->GetPointData()->GetArray(0));
66  }
67 
68  pLocator->SetDataSet(vtkInpGrid);
69  pLocator->AutomaticOn();
70  pLocator->SetNumberOfPointsPerBucket(2);
71  pLocator->BuildLocator();
72 
73  // fill the visited map with false for checking
74  for (int i = 0; i < inpPoints->GetNumberOfPoints(); i++)
75  {
76  visited[i] = false;
77  isNoise[i] = false;
78  clusterMember[i] = false;
79  }
80 
81  for (int i = 0; i < inpPoints->GetNumberOfPoints(); i++)
82  {
83  if (!visited[i])
84  {
85  visited[i] = true; // mark P as visited
86  vtkSmartPointer<vtkIdList> idList = vtkSmartPointer<vtkIdList>::New(); // represent N
87  pLocator->FindPointsWithinRadius(m_eps, inpPoints->GetPoint(i), idList); // N = D.regionQuery(P, eps)
88  if (idList->GetNumberOfIds() < m_MinPts) // if sizeof(N) < MinPts
89  {
90  isNoise[i] = true; // mark P as NOISE
91  }
92  else
93  {
94  vtkSmartPointer<vtkPoints> cluster = vtkSmartPointer<vtkPoints>::New(); // represent a cluster
95  clusterVector.push_back(cluster); // C = next cluster
96  this->ExpandCluster(
97  i, idList, cluster, inpPoints); // expandCluster(P, N, C, eps, MinPts) mod. the parameter list
98  }
99  }
100  }
101 
102  // OUTPUT LOGIC
103  m_Clusters = clusterVector;
104  int numberOfClusterPoints = 0;
105  int IdOfBiggestCluster = 0;
106 
107  for (unsigned int i = 0; i < m_Clusters.size(); i++)
108  {
109  vtkSmartPointer<vtkDoubleArray> array = vtkSmartPointer<vtkDoubleArray>::New();
110  vtkSmartPointer<vtkPoints> points = m_Clusters.at(i);
111  if (m_DistCalc)
112  {
113  array->SetNumberOfComponents(1);
114  array->SetNumberOfTuples(points->GetNumberOfPoints());
115  for (int j = 0; j < points->GetNumberOfPoints(); j++)
116  {
117  double point[3];
118  points->GetPoint(j, point);
119  if (clustersPointsIDs.at(i).at(j) < inpPoints->GetNumberOfPoints())
120  {
121  if (distances->GetValue(clustersPointsIDs.at(i).at(j)) > 0.001)
122  {
123  double dist[1] = {distances->GetValue(clustersPointsIDs.at(i).at(j))};
124  array->SetTuple(j, dist);
125  }
126  else
127  {
128  double dist[1] = {0.0};
129  array->SetTuple(j, dist);
130  }
131  }
132  }
133  m_DistanceArrays.push_back(array);
134  }
135  if (points->GetNumberOfPoints() > numberOfClusterPoints)
136  {
137  numberOfClusterPoints = points->GetNumberOfPoints();
138  IdOfBiggestCluster = i;
139  }
140  }
141 
142  vtkSmartPointer<vtkUnstructuredGrid> biggestCluster = vtkSmartPointer<vtkUnstructuredGrid>::New();
143 
144  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
145  points = m_Clusters.at(IdOfBiggestCluster);
146 
147  vtkSmartPointer<vtkPolyVertex> verts = vtkSmartPointer<vtkPolyVertex>::New();
148  verts->GetPointIds()->SetNumberOfIds(m_Clusters.at(IdOfBiggestCluster)->GetNumberOfPoints());
149  for (int i = 0; i < m_Clusters.at(IdOfBiggestCluster)->GetNumberOfPoints(); i++)
150  {
151  verts->GetPointIds()->SetId(i, i);
152  }
153 
154  biggestCluster->Allocate(1);
155  biggestCluster->InsertNextCell(verts->GetCellType(), verts->GetPointIds());
156  biggestCluster->SetPoints(m_Clusters.at(IdOfBiggestCluster));
157 
158  if (m_Meshing)
159  {
160  vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
161  mesher->SetInputData(biggestCluster);
162  mesher->SetAlpha(0.9);
163  mesher->Update();
164 
165  vtkSmartPointer<vtkUnstructuredGrid> output = mesher->GetOutput();
166  m_UnstructGrid->SetVtkUnstructuredGrid(output);
167  }
168  else
169  {
170  m_UnstructGrid->SetVtkUnstructuredGrid(biggestCluster);
171  }
172 
173  clusterVector.clear();
174  clustersPointsIDs.clear();
175 }
176 
177 void mitk::UnstructuredGridClusteringFilter::ExpandCluster(int id,
178  vtkIdList *pointIDs,
179  vtkPoints *cluster,
180  vtkPoints *inpPoints)
181 {
182  std::vector<int> x;
183  x.push_back(id);
184  cluster->InsertNextPoint(inpPoints->GetPoint(id)); // add P to cluster C
185  clusterMember[id] = true;
186 
187  vtkSmartPointer<vtkPoints> neighbours = vtkSmartPointer<vtkPoints>::New(); // same N as in other function
188  inpPoints->GetPoints(pointIDs, neighbours);
189 
190  for (int i = 0; i < pointIDs->GetNumberOfIds(); i++) // for each point P' in N
191  {
192  if (!visited[pointIDs->GetId(i)]) // if P' is not visited
193  {
194  visited[pointIDs->GetId(i)] = true; // mark P' as visited
195  vtkSmartPointer<vtkIdList> idList = vtkSmartPointer<vtkIdList>::New(); // represent N'
196  pLocator->FindPointsWithinRadius(
197  m_eps, inpPoints->GetPoint(pointIDs->GetId(i)), idList); // N' = D.regionQuery(P', eps)
198 
199  if (idList->GetNumberOfIds() >= m_MinPts) // if sizeof(N') >= MinPts
200  {
201  for (int j = 0; j < idList->GetNumberOfIds(); j++) // N = N joined with N'
202  {
203  if (idList->GetId(j) < inpPoints->GetNumberOfPoints()) // a litte bit hacked ?!
204  {
205  pointIDs->InsertNextId(idList->GetId(j));
206  }
207  }
208  }
209  }
210  if (!clusterMember[pointIDs->GetId(i)]) // if P' is not yet member of any cluster
211  {
212  if (pointIDs->GetId(i) < inpPoints->GetNumberOfPoints())
213  {
214  clusterMember[pointIDs->GetId(i)] = true;
215  x.push_back(pointIDs->GetId(i));
216  cluster->InsertNextPoint(inpPoints->GetPoint(pointIDs->GetId(i))); // add P' to cluster C
217  }
218  }
219  }
220 
221  clustersPointsIDs.push_back(x);
222 }
223 
224 std::vector<mitk::UnstructuredGrid::Pointer> mitk::UnstructuredGridClusteringFilter::GetAllClusters()
225 {
226  std::vector<mitk::UnstructuredGrid::Pointer> mitkUGridVector;
227 
228  for (unsigned int i = 0; i < m_Clusters.size(); i++)
229  {
230  vtkSmartPointer<vtkUnstructuredGrid> cluster = vtkSmartPointer<vtkUnstructuredGrid>::New();
231 
232  vtkSmartPointer<vtkPoints> points = m_Clusters.at(i);
233 
234  vtkSmartPointer<vtkPolyVertex> verts = vtkSmartPointer<vtkPolyVertex>::New();
235 
236  verts->GetPointIds()->SetNumberOfIds(points->GetNumberOfPoints());
237  for (int j = 0; j < points->GetNumberOfPoints(); j++)
238  {
239  verts->GetPointIds()->SetId(j, j);
240  }
241 
242  cluster->Allocate(1);
243  cluster->InsertNextCell(verts->GetCellType(), verts->GetPointIds());
244  cluster->SetPoints(points);
245  if (m_DistCalc)
246  {
247  cluster->GetPointData()->AddArray(m_DistanceArrays.at(i));
248  }
249 
251 
252  if (m_Meshing)
253  {
254  vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
255  mesher->SetInputData(cluster);
256  mesher->SetAlpha(0.9);
257  mesher->Update();
258 
259  vtkSmartPointer<vtkUnstructuredGrid> output = mesher->GetOutput();
260  mitkGrid->SetVtkUnstructuredGrid(output);
261  }
262  else
263  {
264  mitkGrid->SetVtkUnstructuredGrid(cluster);
265  }
266 
267  mitkUGridVector.push_back(mitkGrid);
268  }
269 
270  return mitkUGridVector;
271 }
272 
274 {
275  return m_Clusters.size();
276 }
std::vector< std::vector< int > > clustersPointsIDs
OutputType * GetOutput()
std::map< int, bool > isNoise
std::map< int, bool > visited
static Pointer New()
std::vector< vtkSmartPointer< vtkPoints > > clusterVector
virtual std::vector< mitk::UnstructuredGrid::Pointer > GetAllClusters()
std::map< int, bool > clusterMember
vtkSmartPointer< vtkPointLocator > pLocator
Class for storing unstructured grids (vtkUnstructuredGrid)