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