Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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