Medical Imaging Interaction Toolkit  2018.4.99-36d69b77
Medical Imaging Interaction Toolkit
mitkPointSet.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 
13 #include "mitkPointSet.h"
14 #include "mitkInteractionConst.h"
15 #include "mitkPointOperation.h"
16 
17 #include <iomanip>
18 #include <mitkNumericTypes.h>
19 
20 mitk::PointSet::PointSet() : m_CalculateBoundingBox(true)
21 {
22  this->InitializeEmpty();
23 }
24 
27 {
28  // Copy points
29  for (std::size_t t = 0; t < m_PointSetSeries.size(); ++t)
30  {
31  m_PointSetSeries[t] = DataType::New();
32 
33  DataType::Pointer otherPts = other.GetPointSet(t);
34  for (PointsConstIterator i = other.Begin(t); i != other.End(t); ++i)
35  {
36  m_PointSetSeries[t]->SetPoint(i.Index(), i.Value());
37  PointDataType pointData;
38  if (otherPts->GetPointData(i.Index(), &pointData))
39  {
40  m_PointSetSeries[t]->SetPointData(i.Index(), pointData);
41  }
42  }
43  }
44 }
45 
47 {
48  this->ClearData();
49 }
50 
52 {
53  m_PointSetSeries.clear();
55 }
56 
58 {
59  m_PointSetSeries.resize(1);
60 
61  m_PointSetSeries[0] = DataType::New();
62  PointDataContainer::Pointer pointData = PointDataContainer::New();
63  m_PointSetSeries[0]->SetPointData(pointData);
64  m_CalculateBoundingBox = false;
65 
67  m_Initialized = true;
68 
69  m_EmptyPointsContainer = DataType::PointsContainer::New();
70 }
71 
72 bool mitk::PointSet::IsEmptyTimeStep(unsigned int t) const
73 {
74  return IsInitialized() && (GetSize(t) == 0);
75 }
76 
77 void mitk::PointSet::Expand(unsigned int timeSteps)
78 {
79  // Check if the vector is long enough to contain the new element
80  // at the given position. If not, expand it with sufficient pre-initialized
81  // elements.
82  //
83  // NOTE: This method will never REDUCE the vector size; it should only
84  // be used to make sure that the vector has enough elements to include the
85  // specified time step.
86 
87  unsigned int oldSize = m_PointSetSeries.size();
88 
89  if (timeSteps > oldSize)
90  {
91  Superclass::Expand(timeSteps);
92 
93  m_PointSetSeries.resize(timeSteps);
94  for (unsigned int i = oldSize; i < timeSteps; ++i)
95  {
96  m_PointSetSeries[i] = DataType::New();
97  PointDataContainer::Pointer pointData = PointDataContainer::New();
98  m_PointSetSeries[i]->SetPointData(pointData);
99  }
100 
101  // if the size changes, then compute the bounding box
102  m_CalculateBoundingBox = true;
103 
104  this->InvokeEvent(PointSetExtendTimeRangeEvent());
105  }
106 }
107 
109 {
110  return m_PointSetSeries.size();
111 }
112 
113 int mitk::PointSet::GetSize(unsigned int t) const
114 {
115  if (t < m_PointSetSeries.size())
116  {
117  return m_PointSetSeries[t]->GetNumberOfPoints();
118  }
119  else
120  {
121  return 0;
122  }
123 }
124 
125 mitk::PointSet::DataType::Pointer mitk::PointSet::GetPointSet(int t) const
126 {
127  if (t < (int)m_PointSetSeries.size())
128  {
129  return m_PointSetSeries[t];
130  }
131  else
132  {
133  return nullptr;
134  }
135 }
136 
138 {
139  if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
140  {
141  return m_PointSetSeries[t]->GetPoints()->Begin();
142  }
143  return m_EmptyPointsContainer->End();
144 }
145 
147 {
148  if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
149  {
150  return m_PointSetSeries[t]->GetPoints()->Begin();
151  }
152  return m_EmptyPointsContainer->End();
153 }
154 
156 {
157  if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
158  {
159  return m_PointSetSeries[t]->GetPoints()->End();
160  }
161  return m_EmptyPointsContainer->End();
162 }
163 
165 {
166  if (t >= 0 && t < static_cast<int>(m_PointSetSeries.size()))
167  {
168  return m_PointSetSeries[t]->GetPoints()->End();
169  }
170  return m_EmptyPointsContainer->End();
171 }
172 
174 {
175  if ((unsigned int)t >= m_PointSetSeries.size())
176  {
177  return m_EmptyPointsContainer->End();
178  }
179 
180  return this->Begin(t) == this->End(t) ? this->End(t) : --End(t);
181 }
182 
183 int mitk::PointSet::SearchPoint(Point3D point, ScalarType distance, int t) const
184 {
185  if (t >= (int)m_PointSetSeries.size())
186  {
187  return -1;
188  }
189 
190  // Out is the point which is checked to be the searched point
191  PointType out;
192  out.Fill(0);
193  PointType indexPoint;
194 
195  this->GetGeometry(t)->WorldToIndex(point, indexPoint);
196 
197  // Searching the first point in the Set, that is +- distance far away fro
198  // the given point
199  unsigned int i;
200  PointsContainer::Iterator it, end;
201  end = m_PointSetSeries[t]->GetPoints()->End();
202  int bestIndex = -1;
203  distance = distance * distance;
204 
205  // To correct errors from converting index to world and world to index
206  if (distance == 0.0)
207  {
208  distance = 0.000001;
209  }
210 
211  ScalarType bestDist = distance;
212  ScalarType dist, tmp;
213 
214  for (it = m_PointSetSeries[t]->GetPoints()->Begin(), i = 0; it != end; ++it, ++i)
215  {
216  bool ok = m_PointSetSeries[t]->GetPoints()->GetElementIfIndexExists(it->Index(), &out);
217 
218  if (!ok)
219  {
220  return -1;
221  }
222  else if (indexPoint == out) // if totally equal
223  {
224  return it->Index();
225  }
226 
227  // distance calculation
228  tmp = out[0] - indexPoint[0];
229  dist = tmp * tmp;
230  tmp = out[1] - indexPoint[1];
231  dist += tmp * tmp;
232  tmp = out[2] - indexPoint[2];
233  dist += tmp * tmp;
234 
235  if (dist < bestDist)
236  {
237  bestIndex = it->Index();
238  bestDist = dist;
239  }
240  }
241  return bestIndex;
242 }
243 
245 {
246  PointType out;
247  out.Fill(0);
248 
249  if ((unsigned int)t >= m_PointSetSeries.size())
250  {
251  return out;
252  }
253 
254  if (m_PointSetSeries[t]->GetPoints()->IndexExists(id))
255  {
256  m_PointSetSeries[t]->GetPoint(id, &out);
257  this->GetGeometry(t)->IndexToWorld(out, out);
258  return out;
259  }
260  else
261  {
262  return out;
263  }
264 }
265 
267 {
268  if ((unsigned int)t >= m_PointSetSeries.size())
269  {
270  return false;
271  }
272 
273  if (m_PointSetSeries[t]->GetPoints()->GetElementIfIndexExists(id, point))
274  {
275  this->GetGeometry(t)->IndexToWorld(*point, *point);
276  return true;
277  }
278  else
279  {
280  return false;
281  }
282 }
283 
285 {
286  // Adapt the size of the data vector if necessary
287  this->Expand(t + 1);
288 
289  mitk::Point3D indexPoint;
290  this->GetGeometry(t)->WorldToIndex(point, indexPoint);
291  m_PointSetSeries[t]->SetPoint(id, indexPoint);
292  PointDataType defaultPointData;
293  defaultPointData.id = id;
294  defaultPointData.selected = false;
295  defaultPointData.pointSpec = mitk::PTUNDEFINED;
296 
297  m_PointSetSeries[t]->SetPointData(id, defaultPointData);
298  // boundingbox has to be computed anyway
299  m_CalculateBoundingBox = true;
300  this->Modified();
301 }
302 
304 {
305  // Adapt the size of the data vector if necessary
306  this->Expand(t + 1);
307 
308  mitk::Point3D indexPoint;
309  this->GetGeometry(t)->WorldToIndex(point, indexPoint);
310  m_PointSetSeries[t]->SetPoint(id, indexPoint);
311  PointDataType defaultPointData;
312  defaultPointData.id = id;
313  defaultPointData.selected = false;
314  defaultPointData.pointSpec = spec;
315  m_PointSetSeries[t]->SetPointData(id, defaultPointData);
316  // boundingbox has to be computed anyway
317  m_CalculateBoundingBox = true;
318  this->Modified();
319 }
320 
322 {
323  this->InsertPoint(id, point, mitk::PTUNDEFINED, t);
324 }
325 
327 {
328  if ((unsigned int)t < m_PointSetSeries.size())
329  {
330  mitk::Point3D indexPoint;
331  mitk::BaseGeometry *tempGeometry = this->GetGeometry(t);
332  if (tempGeometry == nullptr)
333  {
334  MITK_INFO << __FILE__ << ", l." << __LINE__ << ": GetGeometry of " << t << " returned nullptr!" << std::endl;
335  return;
336  }
337  tempGeometry->WorldToIndex(point, indexPoint);
338  m_PointSetSeries[t]->GetPoints()->InsertElement(id, indexPoint);
339  PointDataType defaultPointData;
340  defaultPointData.id = id;
341  defaultPointData.selected = false;
342  defaultPointData.pointSpec = spec;
343  m_PointSetSeries[t]->GetPointData()->InsertElement(id, defaultPointData);
344 
345  // boundingbox has to be computed anyway
346  m_CalculateBoundingBox = true;
347  this->Modified();
348  }
349 }
350 
352 {
353  // Adapt the size of the data vector if necessary
354  this->Expand(t + 1);
355 
356  PointIdentifier id = 0;
357  if (m_PointSetSeries[t]->GetNumberOfPoints() > 0)
358  {
359  PointsIterator it = --End(t);
360  id = it.Index();
361  ++id;
362  }
363 
364  mitk::Point3D indexPoint;
365  this->GetGeometry(t)->WorldToIndex(point, indexPoint);
366  m_PointSetSeries[t]->SetPoint(id, indexPoint);
367  PointDataType defaultPointData;
368  defaultPointData.id = id;
369  defaultPointData.selected = false;
370  defaultPointData.pointSpec = mitk::PTUNDEFINED;
371 
372  m_PointSetSeries[t]->SetPointData(id, defaultPointData);
373  // boundingbox has to be computed anyway
374  m_CalculateBoundingBox = true;
375  this->Modified();
376 
377  return id;
378 }
379 
381 {
382  if ((unsigned int)t < m_PointSetSeries.size())
383  {
384  DataType *pointSet = m_PointSetSeries[t];
385 
386  PointsContainer *points = pointSet->GetPoints();
387  PointDataContainer *pdata = pointSet->GetPointData();
388 
389  bool exists = points->IndexExists(id);
390  if (exists)
391  {
392  points->DeleteIndex(id);
393  pdata->DeleteIndex(id);
394  return true;
395  }
396  }
397  return false;
398 }
399 
401 {
402  if ((unsigned int)t < m_PointSetSeries.size())
403  {
404  DataType *pointSet = m_PointSetSeries[t];
405 
406  PointsContainer *points = pointSet->GetPoints();
407  PointDataContainer *pdata = pointSet->GetPointData();
408 
409  PointsIterator bit = points->Begin();
410  PointsIterator eit = points->End();
411 
412  if (eit != bit)
413  {
414  PointsContainer::ElementIdentifier id = (--eit).Index();
415  points->DeleteIndex(id);
416  pdata->DeleteIndex(id);
417  PointsIterator eit2 = points->End();
418  return --eit2;
419  }
420  else
421  {
422  return eit;
423  }
424  }
425  return m_EmptyPointsContainer->End();
426 }
427 
428 bool mitk::PointSet::SwapPointPosition(PointIdentifier id, bool moveUpwards, int t)
429 {
430  if (IndexExists(id, t))
431  {
432  PointType point = GetPoint(id, t);
433 
434  if (moveUpwards)
435  { // up
436  if (IndexExists(id - 1, t))
437  {
438  InsertPoint(id, GetPoint(id - 1, t), t);
439  InsertPoint(id - 1, point, t);
440  this->Modified();
441  return true;
442  }
443  }
444  else
445  { // down
446  if (IndexExists(id + 1, t))
447  {
448  InsertPoint(id, GetPoint(id + 1, t), t);
449  InsertPoint(id + 1, point, t);
450  this->Modified();
451  return true;
452  }
453  }
454  }
455  return false;
456 }
457 
458 bool mitk::PointSet::IndexExists(int position, int t) const
459 {
460  if ((unsigned int)t < m_PointSetSeries.size())
461  {
462  return m_PointSetSeries[t]->GetPoints()->IndexExists(position);
463  }
464  else
465  {
466  return false;
467  }
468 }
469 
470 bool mitk::PointSet::GetSelectInfo(int position, int t) const
471 {
472  if (this->IndexExists(position, t))
473  {
474  PointDataType pointData = {0, false, PTUNDEFINED};
475  m_PointSetSeries[t]->GetPointData(position, &pointData);
476  return pointData.selected;
477  }
478  else
479  {
480  return false;
481  }
482 }
483 
484 void mitk::PointSet::SetSelectInfo(int position, bool selected, int t)
485 {
486  if (this->IndexExists(position, t))
487  {
488  // timeStep to ms
489  TimePointType timeInMS = this->GetTimeGeometry()->TimeStepToTimePoint(t);
490 
491  // point
492  Point3D point = this->GetPoint(position, t);
493 
494  std::unique_ptr<PointOperation> op;
495  if (selected)
496  {
497  op.reset(new mitk::PointOperation(OpSELECTPOINT, timeInMS, point, position));
498  }
499  else
500  {
501  op.reset(new mitk::PointOperation(OpDESELECTPOINT, timeInMS, point, position));
502  }
503 
504  this->ExecuteOperation(op.get());
505  }
506 }
507 
509 {
510  if (this->IndexExists(position, t))
511  {
512  PointDataType pointData = {0, false, PTUNDEFINED};
513  m_PointSetSeries[t]->GetPointData(position, &pointData);
514  return pointData.pointSpec;
515  }
516  else
517  {
518  return PTUNDEFINED;
519  }
520 }
521 
523 {
524  if ((unsigned int)t >= m_PointSetSeries.size())
525  {
526  return 0;
527  }
528 
529  int numberOfSelected = 0;
531  for (it = m_PointSetSeries[t]->GetPointData()->Begin(); it != m_PointSetSeries[t]->GetPointData()->End(); it++)
532  {
533  if (it->Value().selected == true)
534  {
535  ++numberOfSelected;
536  }
537  }
538 
539  return numberOfSelected;
540 }
541 
543 {
544  if ((unsigned int)t >= m_PointSetSeries.size())
545  {
546  return -1;
547  }
548 
550  for (it = m_PointSetSeries[t]->GetPointData()->Begin(); it != m_PointSetSeries[t]->GetPointData()->End(); it++)
551  {
552  if (it->Value().selected == true)
553  {
554  return it->Index();
555  }
556  }
557  return -1;
558 }
559 
561 {
562  int timeStep = -1;
563 
564  mitkCheckOperationTypeMacro(PointOperation, operation, pointOp);
565 
566  if (pointOp)
567  {
568  timeStep = this->GetTimeGeometry()->TimePointToTimeStep(pointOp->GetTimeInMS());
569  }
570 
571  if (timeStep < 0)
572  {
573  MITK_ERROR << "Time step (" << timeStep << ") outside of PointSet time bounds" << std::endl;
574  return;
575  }
576 
577  switch (operation->GetOperationType())
578  {
579  case OpNOTHING:
580  break;
581 
582  case OpINSERT: // inserts the point at the given position and selects it.
583  {
584  int position = pointOp->GetIndex();
585 
586  PointType pt;
587  pt.CastFrom(pointOp->GetPoint());
588 
589  if (timeStep >= (int)this->GetTimeSteps())
590  this->Expand(timeStep + 1);
591 
592  // transfer from world to index coordinates
593  mitk::BaseGeometry *geometry = this->GetGeometry(timeStep);
594  if (geometry == nullptr)
595  {
596  MITK_INFO << "GetGeometry returned nullptr!\n";
597  return;
598  }
599  geometry->WorldToIndex(pt, pt);
600 
601  m_PointSetSeries[timeStep]->GetPoints()->InsertElement(position, pt);
602 
603  PointDataType pointData = {
604  static_cast<unsigned int>(pointOp->GetIndex()), pointOp->GetSelected(), pointOp->GetPointType()};
605 
606  m_PointSetSeries[timeStep]->GetPointData()->InsertElement(position, pointData);
607 
608  this->Modified();
609 
610  // boundingbox has to be computed
611  m_CalculateBoundingBox = true;
612 
613  this->InvokeEvent(PointSetAddEvent());
614  this->OnPointSetChange();
615  }
616  break;
617 
618  case OpMOVE: // moves the point given by index
619  {
620  PointType pt;
621  pt.CastFrom(pointOp->GetPoint());
622 
623  // transfer from world to index coordinates
624  this->GetGeometry(timeStep)->WorldToIndex(pt, pt);
625 
626  // Copy new point into container
627  m_PointSetSeries[timeStep]->SetPoint(pointOp->GetIndex(), pt);
628 
629  // Insert a default point data object to keep the containers in sync
630  // (if no point data object exists yet)
631  PointDataType pointData;
632  if (!m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData))
633  {
634  m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
635  }
636 
637  this->OnPointSetChange();
638 
639  this->Modified();
640 
641  // boundingbox has to be computed anyway
642  m_CalculateBoundingBox = true;
643 
644  this->InvokeEvent(PointSetMoveEvent());
645  }
646  break;
647 
648  case OpREMOVE: // removes the point at given by position
649  {
650  m_PointSetSeries[timeStep]->GetPoints()->DeleteIndex((unsigned)pointOp->GetIndex());
651  m_PointSetSeries[timeStep]->GetPointData()->DeleteIndex((unsigned)pointOp->GetIndex());
652 
653  this->OnPointSetChange();
654 
655  this->Modified();
656  // boundingbox has to be computed anyway
657  m_CalculateBoundingBox = true;
658 
659  this->InvokeEvent(PointSetRemoveEvent());
660  }
661  break;
662 
663  case OpSELECTPOINT: // select the given point
664  {
665  PointDataType pointData = {0, false, PTUNDEFINED};
666  m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData);
667  pointData.selected = true;
668  m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
669  this->Modified();
670  }
671  break;
672 
673  case OpDESELECTPOINT: // unselect the given point
674  {
675  PointDataType pointData = {0, false, PTUNDEFINED};
676  m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData);
677  pointData.selected = false;
678  m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
679  this->Modified();
680  }
681  break;
682 
683  case OpSETPOINTTYPE:
684  {
685  PointDataType pointData = {0, false, PTUNDEFINED};
686  m_PointSetSeries[timeStep]->GetPointData(pointOp->GetIndex(), &pointData);
687  pointData.pointSpec = pointOp->GetPointType();
688  m_PointSetSeries[timeStep]->SetPointData(pointOp->GetIndex(), pointData);
689  this->Modified();
690  }
691  break;
692 
693  case OpMOVEPOINTUP: // swap content of point with ID pointOp->GetIndex() with the point preceding it in the
694  // container // move point position within the pointset
695  {
696  PointIdentifier currentID = pointOp->GetIndex();
697  /* search for point with this id and point that precedes this one in the data container */
698  PointsContainer::STLContainerType points = m_PointSetSeries[timeStep]->GetPoints()->CastToSTLContainer();
699  auto it = points.find(currentID);
700  if (it == points.end()) // ID not found
701  break;
702  if (it == points.begin()) // we are at the first element, there is no previous element
703  break;
704 
705  /* get and cache current point & pointdata and previous point & pointdata */
706  --it;
707  PointIdentifier prevID = it->first;
708  if (this->SwapPointContents(prevID, currentID, timeStep) == true)
709  this->Modified();
710  }
711  break;
712  case OpMOVEPOINTDOWN: // move point position within the pointset
713  {
714  PointIdentifier currentID = pointOp->GetIndex();
715  /* search for point with this id and point that succeeds this one in the data container */
716  PointsContainer::STLContainerType points = m_PointSetSeries[timeStep]->GetPoints()->CastToSTLContainer();
717  auto it = points.find(currentID);
718  if (it == points.end()) // ID not found
719  break;
720  ++it;
721  if (it == points.end()) // ID is already the last element, there is no succeeding element
722  break;
723 
724  /* get and cache current point & pointdata and previous point & pointdata */
725  PointIdentifier nextID = it->first;
726  if (this->SwapPointContents(nextID, currentID, timeStep) == true)
727  this->Modified();
728  }
729  break;
730 
731  default:
732  itkWarningMacro("mitkPointSet could not understrand the operation. Please check!");
733  break;
734  }
735 
736  // to tell the mappers, that the data is modified and has to be updated
737  // only call modified if anything is done, so call in cases
738  // this->Modified();
739 
740  mitk::OperationEndEvent endevent(operation);
741  ((const itk::Object *)this)->InvokeEvent(endevent);
742 
743  //*todo has to be done here, cause of update-pipeline not working yet
744  // As discussed lately, don't mess with the rendering from inside data structures
745  // mitk::RenderingManager::GetInstance()->RequestUpdateAll();
746 }
747 
749 {
750  if (this->GetSource())
751  {
752  this->GetSource()->UpdateOutputInformation();
753  }
754 
755  //
756  // first make sure, that the associated time sliced geometry has
757  // the same number of geometry 3d's as PointSets are present
758  //
759  TimeGeometry *timeGeometry = GetTimeGeometry();
760  if (timeGeometry->CountTimeSteps() != m_PointSetSeries.size())
761  {
762  itkExceptionMacro(<< "timeGeometry->CountTimeSteps() != m_PointSetSeries.size() -- use Initialize(timeSteps) with "
763  "correct number of timeSteps!");
764  }
765 
766  // This is needed to detect zero objects
767  mitk::ScalarType nullpoint[] = {0, 0, 0, 0, 0, 0};
768  BoundingBox::BoundsArrayType itkBoundsNull(nullpoint);
769 
770  //
771  // Iterate over the PointSets and update the Geometry
772  // information of each of the items.
773  //
775  {
776  for (unsigned int i = 0; i < m_PointSetSeries.size(); ++i)
777  {
778  const DataType::BoundingBoxType *bb = m_PointSetSeries[i]->GetBoundingBox();
779  BoundingBox::BoundsArrayType itkBounds = bb->GetBounds();
780 
781  if (m_PointSetSeries[i].IsNull() || (m_PointSetSeries[i]->GetNumberOfPoints() == 0) ||
782  (itkBounds == itkBoundsNull))
783  {
784  itkBounds = itkBoundsNull;
785  continue;
786  }
787 
788  // Ensure minimal bounds of 1.0 in each dimension
789  for (unsigned int j = 0; j < 3; ++j)
790  {
791  if (itkBounds[j * 2 + 1] - itkBounds[j * 2] < 1.0)
792  {
793  BoundingBox::CoordRepType center = (itkBounds[j * 2] + itkBounds[j * 2 + 1]) / 2.0;
794  itkBounds[j * 2] = center - 0.5;
795  itkBounds[j * 2 + 1] = center + 0.5;
796  }
797  }
798  this->GetGeometry(i)->SetBounds(itkBounds);
799  }
800  m_CalculateBoundingBox = false;
801  }
802  this->GetTimeGeometry()->Update();
803 }
804 
806 {
807 }
808 
810 {
811  return false;
812 }
813 
815 {
816  return true;
817 }
818 
819 void mitk::PointSet::SetRequestedRegion(const DataObject *)
820 {
821 }
822 
823 void mitk::PointSet::PrintSelf(std::ostream &os, itk::Indent indent) const
824 {
825  Superclass::PrintSelf(os, indent);
826 
827  os << indent << "Number timesteps: " << m_PointSetSeries.size() << "\n";
828  unsigned int i = 0;
829  for (auto it = m_PointSetSeries.begin(); it != m_PointSetSeries.end(); ++it)
830  {
831  os << indent << "Timestep " << i++ << ": \n";
832  MeshType::Pointer ps = *it;
833  itk::Indent nextIndent = indent.GetNextIndent();
834  ps->Print(os, nextIndent);
835  MeshType::PointsContainer *points = ps->GetPoints();
836  MeshType::PointDataContainer *datas = ps->GetPointData();
837  MeshType::PointDataContainer::Iterator dataIterator = datas->Begin();
838  for (MeshType::PointsContainer::Iterator pointIterator = points->Begin(); pointIterator != points->End();
839  ++pointIterator, ++dataIterator)
840  {
841  os << nextIndent << "Point " << pointIterator->Index() << ": [";
842  os << pointIterator->Value().GetElement(0);
843  for (unsigned int i = 1; i < PointType::GetPointDimension(); ++i)
844  {
845  os << ", " << pointIterator->Value().GetElement(i);
846  }
847  os << "]";
848  os << ", selected: " << dataIterator->Value().selected << ", point spec: " << dataIterator->Value().pointSpec
849  << "\n";
850  }
851  }
852 }
853 
855 {
856  /* search and cache contents */
857  PointType p1;
858  if (m_PointSetSeries[timeStep]->GetPoint(id1, &p1) == false)
859  return false;
860  PointDataType data1;
861  if (m_PointSetSeries[timeStep]->GetPointData(id1, &data1) == false)
862  return false;
863  PointType p2;
864  if (m_PointSetSeries[timeStep]->GetPoint(id2, &p2) == false)
865  return false;
866  PointDataType data2;
867  if (m_PointSetSeries[timeStep]->GetPointData(id2, &data2) == false)
868  return false;
869  /* now swap contents */
870  m_PointSetSeries[timeStep]->SetPoint(id1, p2);
871  m_PointSetSeries[timeStep]->SetPointData(id1, data2);
872  m_PointSetSeries[timeStep]->SetPoint(id2, p1);
873  m_PointSetSeries[timeStep]->SetPointData(id2, data1);
874  return true;
875 }
876 
878 {
879  return id == other.id && selected == other.selected && pointSpec == other.pointSpec;
880 }
881 
882 bool mitk::Equal(const mitk::PointSet *leftHandSide,
883  const mitk::PointSet *rightHandSide,
885  bool verbose,
886  bool checkGeometry)
887 {
888  if ((leftHandSide == nullptr) || (rightHandSide == nullptr))
889  {
890  MITK_ERROR << "mitk::Equal( const mitk::PointSet* leftHandSide, const mitk::PointSet* rightHandSide, "
891  "mitk::ScalarType eps, bool verbose ) does not work with nullptr pointer input.";
892  return false;
893  }
894  return Equal(*leftHandSide, *rightHandSide, eps, verbose, checkGeometry);
895 }
896 
897 bool mitk::Equal(const mitk::PointSet &leftHandSide,
898  const mitk::PointSet &rightHandSide,
900  bool verbose,
901  bool checkGeometry)
902 {
903  bool result = true;
904 
905  // If comparing point sets from file, you must not compare the geometries, as they are not saved. In other cases, you
906  // do need to check them.
907  if (checkGeometry)
908  {
909  if (!mitk::Equal(*leftHandSide.GetGeometry(), *rightHandSide.GetGeometry(), eps, verbose))
910  {
911  if (verbose)
912  MITK_INFO << "[( PointSet )] Geometries differ.";
913  result = false;
914  }
915  }
916 
917  if (leftHandSide.GetSize() != rightHandSide.GetSize())
918  {
919  if (verbose)
920  MITK_INFO << "[( PointSet )] Number of points differ.";
921  result = false;
922  }
923  else
924  {
925  // if the size is equal, we compare the point values
926  mitk::Point3D pointLeftHandSide;
927  mitk::Point3D pointRightHandSide;
928 
929  int numberOfIncorrectPoints = 0;
930 
931  // Iterate over both pointsets in order to compare all points pair-wise
932  mitk::PointSet::PointsConstIterator end = leftHandSide.End();
933  for (mitk::PointSet::PointsConstIterator pointSetIteratorLeft = leftHandSide.Begin(),
934  pointSetIteratorRight = rightHandSide.Begin();
935  pointSetIteratorLeft != end;
936  ++pointSetIteratorLeft, ++pointSetIteratorRight) // iterate simultaneously over both sets
937  {
938  pointLeftHandSide = pointSetIteratorLeft.Value();
939  pointRightHandSide = pointSetIteratorRight.Value();
940  if (!mitk::Equal(pointLeftHandSide, pointRightHandSide, eps, verbose))
941  {
942  if (verbose)
943  MITK_INFO << "[( PointSet )] Point values are different.";
944  result = false;
945  numberOfIncorrectPoints++;
946  }
947  }
948 
949  if ((numberOfIncorrectPoints > 0) && verbose)
950  {
951  MITK_INFO << numberOfIncorrectPoints << " of a total of " << leftHandSide.GetSize() << " points are different.";
952  }
953  }
954  return result;
955 }
MeshType DataType
Definition: mitkPointSet.h:131
DataType::PointsContainerIterator PointsIterator
Definition: mitkPointSet.h:135
PointsIterator GetMaxId(int t=0)
Get an iterator to the max ID element if existent. Return End() otherwise.
itk::SmartPointer< mitk::BaseDataSource > GetSource() const
Get the process object that generated this data object.
virtual void ClearData()
reset to non-initialized state, release memory
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
void PrintSelf(std::ostream &os, itk::Indent indent) const override
virtual TimeStepType CountTimeSteps() const =0
Returns the number of time steps.
void PrintSelf(std::ostream &os, itk::Indent indent) const override
print content of the object to os
void Expand(unsigned int timeSteps) override
Expands the TimeGeometry to a number of TimeSteps.
DataType::PointDataContainer PointDataContainer
Definition: mitkPointSet.h:137
int SearchPoint(Point3D point, ScalarType distance, int t=0) const
searches a point in the list == point +/- distance
#define MITK_INFO
Definition: mitkLogMacros.h:18
Base of all data objects.
Definition: mitkBaseData.h:42
virtual PointSpecificationType GetSpecificationTypeInfo(int position, int t) const
to get the type of the point at the position and the moment
Base class of all Operation-classes.
Definition: mitkOperation.h:29
#define MITK_ERROR
Definition: mitkLogMacros.h:20
virtual unsigned int GetPointSetSeriesSize() const
double ScalarType
void SetRequestedRegionToLargestPossibleRegion() override
Set the RequestedRegion to the LargestPossibleRegion.
void ExecuteOperation(Operation *operation) override
executes the given Operation
bool m_CalculateBoundingBox
flag to indicate the right time to call SetBounds
Definition: mitkPointSet.h:293
bool SwapPointContents(PointIdentifier id1, PointIdentifier id2, int t=0)
swaps point coordinates and point data of the points with identifiers id1 and id2 ...
#define mitkCheckOperationTypeMacro(OperationType, operation, newOperationName)
struct for data of a point
Definition: mitkPointSet.h:93
virtual void OnPointSetChange()
Definition: mitkPointSet.h:266
virtual int SearchSelectedPoint(int t=0) const
searches a selected point and returns the id of that point. If no point is found, then -1 is returned...
mitk::PointSpecificationType pointSpec
Definition: mitkPointSet.h:97
Constants for most interaction classes, due to the generic StateMachines.
void ClearData() override
reset to non-initialized state, release memory
DataType::PointsContainer::ConstIterator PointsConstIterator
Definition: mitkPointSet.h:136
virtual bool IndexExists(int position, int t=0) const
returns true if a point exists at this position
bool GetPointIfExists(PointIdentifier id, PointType *point, int t=0) const
Get the point with ID id in world coordinates.
void InitializeEmpty() override
Pure virtual; Must be used in subclasses to get a data object to a valid state. Should at least creat...
bool SwapPointPosition(PointIdentifier id, bool moveUpwards, int t=0)
Swap a point at the given position (id) with the upper point (moveUpwards=true) or with the lower poi...
PointSetSeries m_PointSetSeries
Definition: mitkPointSet.h:286
virtual void SetSelectInfo(int position, bool selected, int t=0)
bool RequestedRegionIsOutsideOfTheBufferedRegion() override
Determine whether the RequestedRegion is outside of the BufferedRegion.
DataType::PointIdentifier PointIdentifier
Definition: mitkPointSet.h:133
bool RemovePointIfExists(PointIdentifier id, int t=0)
Remove point with given id at timestep t, if existent.
virtual int GetSize(unsigned int t=0) const
returns the current size of the point-list
~PointSet() override
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:66
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:75
virtual int GetNumberOfSelected(int t=0) const
returns the number of selected points
virtual TimeStepType TimePointToTimeStep(TimePointType timePoint) const =0
Converts a time point to the corresponding time step.
bool verbose(false)
itk::BoundingBox< unsigned long, 3, mitk::ScalarType > BoundingBoxType
virtual bool GetSelectInfo(int position, int t=0) const
to get the state selected/unselected of the point on the position
virtual DataType::Pointer GetPointSet(int t=0) const
returns the pointset
virtual TimePointType TimeStepToTimePoint(TimeStepType timeStep) const =0
Converts a time step to a time point.
Operation that handles all actions on one Point.
void InsertPoint(PointIdentifier id, PointType point, int t=0)
Set the given point in world coordinate system into the itkPointSet.
mitk::ScalarType TimePointType
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
PointsIterator RemovePointAtEnd(int t=0)
Remove max id point at timestep t and return iterator to precedent point.
DataType::PointsContainer PointsContainer
Definition: mitkPointSet.h:134
void SetPoint(PointIdentifier id, PointType point, int t=0)
Set the given point in world coordinate system into the itkPointSet.
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
void SetBounds(const BoundsArrayType &bounds)
Set the bounding box (in index/unit coordinates)
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
DataType::PointsContainer::Pointer m_EmptyPointsContainer
Definition: mitkPointSet.h:288
bool VerifyRequestedRegion() override
Verify that the RequestedRegion is within the LargestPossibleRegion.
MITKCORE_EXPORT const ScalarType eps
unsigned int GetTimeSteps() const
Get the number of time steps from the TimeGeometry As the base data has not a data vector given by it...
Definition: mitkBaseData.h:360
PointsIterator Begin(int t=0)
bool IsEmptyTimeStep(unsigned int t) const override
Check whether object contains data (at a specified time), e.g., a set of points may be empty...
PointType GetPoint(PointIdentifier id, int t=0) const
Get the point with ID id in world coordinates.
DataType::PointDataContainerIterator PointDataIterator
Definition: mitkPointSet.h:138
OperationType GetOperationType()
void UpdateOutputInformation() override
void Update()
Updates the geometry.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:143
virtual void Expand(unsigned int timeSteps)
Expands the TimeGeometry to a number of TimeSteps.
PointSpecificationType
enumeration of the type a point can be
Definition: mitkPoint.h:26
PointsIterator End(int t=0)
virtual void InitializeTimeGeometry(unsigned int timeSteps=1)
Initialize the TimeGeometry for a number of time steps. The TimeGeometry is initialized empty and eve...
BaseGeometry Describes the geometry of a data object.
bool operator==(const PointDataType &other) const
BoundingBoxType::BoundsArrayType BoundsArrayType
void SetRequestedRegion(const itk::DataObject *data) override
Set the requested region from this data object to match the requested region of the data object passe...