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