Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkContourElement.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 #include <algorithm>
13 #include <mitkContourElement.h>
14 #include <vtkMath.h>
15 
17 {
18  this->m_Vertices = new VertexListType();
19  this->m_IsClosed = false;
20 }
21 
23  : itk::LightObject(), m_Vertices(other.m_Vertices), m_IsClosed(other.m_IsClosed)
24 {
25 }
26 
28 {
29  delete this->m_Vertices;
30 }
31 
32 void mitk::ContourElement::AddVertex(mitk::Point3D &vertex, bool isControlPoint)
33 {
34  this->m_Vertices->push_back(new VertexType(vertex, isControlPoint));
35 }
36 
38 {
39  this->m_Vertices->push_back(&vertex);
40 }
41 
42 void mitk::ContourElement::AddVertexAtFront(mitk::Point3D &vertex, bool isControlPoint)
43 {
44  this->m_Vertices->push_front(new VertexType(vertex, isControlPoint));
45 }
46 
48 {
49  this->m_Vertices->push_front(&vertex);
50 }
51 
52 void mitk::ContourElement::InsertVertexAtIndex(mitk::Point3D &vertex, bool isControlPoint, int index)
53 {
54  if (index >= 0 && this->GetSize() > index)
55  {
56  auto _where = this->m_Vertices->begin();
57  _where += index;
58  this->m_Vertices->insert(_where, new VertexType(vertex, isControlPoint));
59  }
60 }
61 
62 void mitk::ContourElement::SetVertexAt(int pointId, const Point3D &point)
63 {
64  if (pointId >= 0 && this->GetSize() > pointId)
65  {
66  this->m_Vertices->at(pointId)->Coordinates = point;
67  }
68 }
69 
70 void mitk::ContourElement::SetVertexAt(int pointId, const VertexType *vertex)
71 {
72  if (pointId >= 0 && this->GetSize() > pointId)
73  {
74  this->m_Vertices->at(pointId)->Coordinates = vertex->Coordinates;
75  this->m_Vertices->at(pointId)->IsControlPoint = vertex->IsControlPoint;
76  }
77 }
78 
80 {
81  return this->m_Vertices->at(index);
82 }
83 
85 {
86  return this->m_Vertices->empty();
87 }
88 
90 {
91  /* current version iterates over the whole deque - should some kind of an octree with spatial query*/
92 
93  if (eps > 0)
94  {
95  // currently no method with better performance is available
96  return BruteForceGetVertexAt(point, eps);
97  } // if eps < 0
98  return nullptr;
99 }
100 
102 {
103  if (eps > 0)
104  {
105  std::deque<std::pair<double, VertexType *>> nearestlist;
106 
107  ConstVertexIterator it = this->m_Vertices->begin();
108 
109  ConstVertexIterator end = this->m_Vertices->end();
110 
111  while (it != end)
112  {
113  mitk::Point3D currentPoint = (*it)->Coordinates;
114 
115  double distance = currentPoint.EuclideanDistanceTo(point);
116  if (distance < eps)
117  {
118  // if list is emtpy, add point to list
119  if (nearestlist.size() < 1)
120  {
121  nearestlist.push_front(std::pair<double, VertexType *>((*it)->Coordinates.EuclideanDistanceTo(point), (*it)));
122  }
123  // found an approximate point - check if current is closer then first in nearestlist
124  else if (distance < nearestlist.front().first)
125  {
126  // found even closer vertex
127  nearestlist.push_front(std::pair<double, VertexType *>((*it)->Coordinates.EuclideanDistanceTo(point), (*it)));
128  }
129  } // if distance > eps
130 
131  it++;
132  } // while
133  if (nearestlist.size() > 0)
134  {
135  /*++++++++++++++++++++ return the nearest active point if one was found++++++++++++++++++*/
136  auto it = nearestlist.begin();
137  auto end = nearestlist.end();
138  while (it != end)
139  {
140  if ((*it).second->IsControlPoint)
141  {
142  return (*it).second;
143  }
144  it++;
145  }
146  /*---------------------------------------------------------------------------------------*/
147 
148  // return closest point
149  return nearestlist.front().second;
150  }
151  }
152  return nullptr;
153 }
154 
155 /*mitk::ContourElement::VertexType* mitk::ContourElement::OptimizedGetVertexAt(const mitk::Point3D &point, float eps)
156 {
157  if( (eps > 0) && (this->m_Vertices->size()>0) )
158  {
159  int k = 1;
160  int dim = 3;
161  int nPoints = this->m_Vertices->size();
162  ANNpointArray pointsArray;
163  ANNpoint queryPoint;
164  ANNidxArray indexArray;
165  ANNdistArray distanceArray;
166  ANNkd_tree* kdTree;
167 
168  queryPoint = annAllocPt(dim);
169  pointsArray = annAllocPts(nPoints, dim);
170  indexArray = new ANNidx[k];
171  distanceArray = new ANNdist[k];
172 
173 
174  int i = 0;
175 
176  //fill points array with our control points
177  for(VertexIterator it = this->m_Vertices->begin(); it != this->m_Vertices->end(); it++, i++)
178  {
179  mitk::Point3D cur = (*it)->Coordinates;
180  pointsArray[i][0]= cur[0];
181  pointsArray[i][1]= cur[1];
182  pointsArray[i][2]= cur[2];
183  }
184 
185  //create the kd tree
186  kdTree = new ANNkd_tree(pointsArray,nPoints, dim);
187 
188  //fill mitk::Point3D into ANN query point
189  queryPoint[0] = point[0];
190  queryPoint[1] = point[1];
191  queryPoint[2] = point[2];
192 
193  //k nearest neighbour search
194  kdTree->annkSearch(queryPoint, k, indexArray, distanceArray, eps);
195 
196  VertexType* ret = nullptr;
197 
198  try
199  {
200  ret = this->m_Vertices->at(indexArray[0]);
201  }
202  catch(std::out_of_range ex)
203  {
204  //ret stays nullptr
205  return ret;
206  }
207 
208  //clean up ANN
209  delete [] indexArray;
210  delete [] distanceArray;
211  delete kdTree;
212  annClose();
213 
214  return ret;
215  }
216  return nullptr;
217 }
218 */
219 
221 {
222  return this->m_Vertices;
223 }
224 
226 {
227  return this->m_IsClosed;
228 }
229 
231 {
232  ConstVertexIterator it1 = this->m_Vertices->begin();
233  ConstVertexIterator it2 = this->m_Vertices->begin();
234  it2++; // it2 runs one position ahead
235 
236  ConstVertexIterator end = this->m_Vertices->end();
237 
238  int counter = 0;
239 
240  for (; it1 != end; it1++, it2++, counter++)
241  {
242  if (it2 == end)
243  it2 = this->m_Vertices->begin();
244 
245  mitk::Point3D v1 = (*it1)->Coordinates;
246  mitk::Point3D v2 = (*it2)->Coordinates;
247 
248  const float l2 = v1.SquaredEuclideanDistanceTo(v2);
249 
250  mitk::Vector3D p_v1 = point - v1;
251  mitk::Vector3D v2_v1 = v2 - v1;
252 
253  double tc = (p_v1 * v2_v1) / l2;
254 
255  // take into account we have line segments and not (infinite) lines
256  if (tc < 0.0)
257  tc = 0.0;
258  if (tc > 1.0)
259  tc = 1.0;
260 
261  mitk::Point3D crossPoint = v1 + v2_v1 * tc;
262 
263  double distance = point.SquaredEuclideanDistanceTo(crossPoint);
264 
265  if (distance < eps)
266  {
267  return true;
268  }
269  }
270 
271  return false;
272 }
273 
275 {
276  this->m_IsClosed = true;
277 }
278 
280 {
281  this->m_IsClosed = false;
282 }
283 
285 {
286  isClosed ? this->Close() : this->Open();
287 }
288 
290 {
291  auto newVertices = new VertexListType();
292 
293  auto it = this->m_Vertices->begin();
294  auto end = this->m_Vertices->end();
295 
296  while (it != end)
297  {
298  if ((*it)->IsControlPoint)
299  {
300  newVertices->push_back((*it));
301  }
302  it++;
303  }
304 
305  return newVertices;
306 }
307 
309 {
310  if (other->GetSize() > 0)
311  {
312  ConstVertexIterator otherIt = other->m_Vertices->begin();
313  ConstVertexIterator otherEnd = other->m_Vertices->end();
314  while (otherIt != otherEnd)
315  {
316  if (check)
317  {
318  ConstVertexIterator thisIt = this->m_Vertices->begin();
319  ConstVertexIterator thisEnd = this->m_Vertices->end();
320 
321  bool found = false;
322  while (thisIt != thisEnd)
323  {
324  if ((*thisIt)->Coordinates == (*otherIt)->Coordinates)
325  {
326  found = true;
327  break;
328  }
329 
330  thisIt++;
331  }
332  if (!found)
333  this->m_Vertices->push_back(*otherIt);
334  }
335  else
336  {
337  this->m_Vertices->push_back(*otherIt);
338  }
339  otherIt++;
340  }
341  }
342 }
343 
345 {
346  auto it = this->m_Vertices->begin();
347 
348  auto end = this->m_Vertices->end();
349 
350  // search for vertex and remove it if exists
351  while (it != end)
352  {
353  if ((*it) == vertex)
354  {
355  this->m_Vertices->erase(it);
356  return true;
357  }
358 
359  it++;
360  }
361 
362  return false;
363 }
364 
366 {
367  auto it = this->m_Vertices->begin();
368 
369  auto end = this->m_Vertices->end();
370 
371  int index = 0;
372 
373  // search for vertex
374  while (it != end)
375  {
376  if ((*it) == vertex)
377  {
378  return index;
379  }
380 
381  it++;
382  ++index;
383  }
384 
385  return -1; // not found
386 }
387 
389 {
390  if (index >= 0 && static_cast<VertexListType::size_type>(index) < this->m_Vertices->size())
391  {
392  this->m_Vertices->erase(this->m_Vertices->begin() + index);
393  return true;
394  }
395  else
396  {
397  return false;
398  }
399 }
400 
402 {
403  /* current version iterates over the whole deque - should be some kind of an octree with spatial query*/
404 
405  if (eps > 0)
406  {
407  auto it = this->m_Vertices->begin();
408 
409  auto end = this->m_Vertices->end();
410 
411  while (it != end)
412  {
413  mitk::Point3D currentPoint = (*it)->Coordinates;
414 
415  if (currentPoint.EuclideanDistanceTo(point) < eps)
416  {
417  // approximate point found
418  // now erase it
419  this->m_Vertices->erase(it);
420  return true;
421  }
422 
423  it++;
424  }
425  }
426  return false;
427 }
428 
430 {
431  this->m_Vertices->clear();
432 }
433 //----------------------------------------------------------------------
435 {
436  int counter = 0;
437  auto _where = this->m_Vertices->begin();
438 
439  if (selected != nullptr)
440  {
441  while (_where != this->m_Vertices->end())
442  {
443  if ((*_where) == selected)
444  {
445  break;
446  }
447  _where++;
448  }
449  }
450 
451  auto _iter = _where;
452  while (_iter != this->m_Vertices->end())
453  {
454  div_t divresult;
455  divresult = div(counter, period);
456  (*_iter)->IsControlPoint = (divresult.rem == 0);
457  counter++;
458  _iter++;
459  }
460 
461  _iter = _where;
462  counter = 0;
463  while (_iter != this->m_Vertices->begin())
464  {
465  div_t divresult;
466  divresult = div(counter, period);
467  (*_iter)->IsControlPoint = (divresult.rem == 0);
468  counter++;
469  _iter--;
470  }
471 }
VertexListType * GetControlVertices()
Returns the approximate nearest vertex a given posoition in 3D space.
VertexType * BruteForceGetVertexAt(const mitk::Point3D &point, float eps)
Returns the approximate nearest vertex a given posoition in 3D space.
bool IsEmpty()
Returns whether the contour element is empty.
std::deque< VertexType * > VertexListType
virtual void Clear()
Clear the storage container.
mitk::Point3D Coordinates
Coordinates in 3D space.
virtual void Open()
Open the contour. Disconnect first and last element.
ContourModelVertex VertexType
void RedistributeControlVertices(const VertexType *vertex, int period)
Uniformly redistribute control points with a given period (in number of vertices) ...
Represents a contour in 3D space. A ContourElement is consisting of linked vertices implicitely defin...
virtual void SetVertexAt(int pointId, const mitk::Point3D &point)
Set coordinates a given index.
virtual void AddVertex(mitk::Point3D &point, bool isControlPoint)
Add a vertex at the end of the contour.
virtual bool IsClosed()
Returns if the conour is closed or not.
virtual bool RemoveVertex(const VertexType *vertex)
Remove the given vertex from the container if exists.
virtual void Close()
Close the contour. Connect first with last element.
virtual VertexType * GetVertexAt(int index)
Returns the vertex a given index.
VertexListType::const_iterator ConstVertexIterator
VertexListType * GetVertexList()
Returns the container of the vertices.
virtual void InsertVertexAtIndex(mitk::Point3D &point, bool isControlPoint, int index)
Add a vertex at a given index of the contour.
virtual bool IsNearContour(const mitk::Point3D &point, float eps)
Returns whether a given point is near a contour, according to eps.
void Concatenate(mitk::ContourElement *other, bool check)
Concatenate the contuor with a another contour. All vertices of the other contour will be added after...
virtual int GetIndex(const VertexType *vertex)
Returns the index of the given vertex within the contour.
virtual void SetClosed(bool isClosed)
Set the contours IsClosed property.
virtual void AddVertexAtFront(mitk::Point3D &point, bool isControlPoint)
Add a vertex at the front of the contour.
MITKCORE_EXPORT const ScalarType eps
virtual bool RemoveVertexAt(int index)
Remove a vertex at given index within the container if exists.
Represents a single vertex of contour.
virtual int GetSize()
Returns the number of contained vertices.
VertexListType * m_Vertices