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