Medical Imaging Interaction Toolkit  2018.4.99-dfa0c14e
Medical Imaging Interaction Toolkit
mitkBoundingObjectGroup.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 
14 #include "mitkBaseProcess.h"
16 #include <vtkLinearTransform.h>
17 
19  : m_BoundingObjects(0), m_Counter(0), m_CSGMode(Union) // m_CSGMode(Difference) //m_CSGMode(Intersection)
20 {
22  timeGeometry->Initialize(1);
23  SetTimeGeometry(timeGeometry);
24 
25  SetVtkPolyData(nullptr);
26 }
27 
29 {
30 }
31 
33 {
34  if (this->GetSource())
35  {
36  this->GetSource()->UpdateOutputInformation();
37  }
38 
39  // calculate global bounding box
40  if (m_BoundingObjects.size() < 1) // if there is no BoundingObject, the bounding box is zero
41  {
43  boundsArray.Fill(0);
45  timeGeometry->Initialize(1);
46  SetTimeGeometry(timeGeometry);
47  GetGeometry()->SetBounds(boundsArray);
49  return;
50  }
51 
52  // initialize container
53  mitk::BoundingBox::PointsContainer::Pointer pointscontainer = mitk::BoundingBox::PointsContainer::New();
54 
55  mitk::BoundingBox::PointIdentifier pointid = 0;
56  mitk::Point3D point;
57 
59  mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
60  transform->GetInverse(inverse);
61 
62  // calculate a bounding box that includes all BoundingObjects
63  // \todo probably we should do this additionally for each time-step
64  // while (boundingObjectsIterator != boundingObjectsIteratorEnd)
65  for (unsigned int j = 0; j < m_BoundingObjects.size(); j++)
66  {
67  const TimeGeometry *geometry = m_BoundingObjects.at(j)->GetUpdatedTimeGeometry();
68  unsigned char i;
69  for (i = 0; i < 8; ++i)
70  {
71  point = inverse->TransformPoint(geometry->GetCornerPointInWorld(i));
72  if (point[0] * point[0] + point[1] * point[1] + point[2] * point[2] < mitk::large)
73  pointscontainer->InsertElement(pointid++, point);
74  else
75  {
76  itkGenericOutputMacro(<< "Unrealistically distant corner point encountered. Ignored. BoundingObject: "
77  << m_BoundingObjects.at(j));
78  }
79  }
80  }
81 
82  mitk::BoundingBox::Pointer boundingBox = mitk::BoundingBox::New();
83  boundingBox->SetPoints(pointscontainer);
84  boundingBox->ComputeBoundingBox();
85 
86  BaseGeometry *geometry3d = GetGeometry(0);
87  geometry3d->SetIndexToWorldTransform(transform);
88  geometry3d->SetBounds(boundingBox->GetBounds());
89  /* the objects position is the center of all sub bounding objects */
90  // geometry3d->SetOrigin(center);
91 
93  timeGeometry->Initialize(geometry3d, GetTimeGeometry()->CountTimeSteps());
94  SetTimeGeometry(timeGeometry);
95 }
96 
98 {
99  if (boundingObject->GetPositive())
100  m_BoundingObjects.push_front(boundingObject);
101  else
102  m_BoundingObjects.push_back(boundingObject);
103  ++m_Counter;
105 }
106 
108 {
109  auto it = m_BoundingObjects.begin();
110  for (unsigned int i = 0; i < m_BoundingObjects.size(); i++)
111  {
112  if (m_BoundingObjects.at(i) == boundingObject)
113  m_BoundingObjects.erase(it);
114  ++it;
115  }
116  --m_Counter;
118 }
119 
121 {
122  bool inside = false; // initialize with true for intersection, with false for union
123  bool posInside = false;
124  bool negInside = false;
125 
126  for (unsigned int i = 0; i < m_BoundingObjects.size(); i++)
127  {
128  switch (m_CSGMode)
129  {
130  case Intersection:
131  inside = true;
132  // calculate intersection: each point, that is inside each BoundingObject is considered inside the group
133  inside = m_BoundingObjects.at(i)->IsInside(p) && inside;
134  if (!inside) // shortcut, it is enough to find one object that does not contain the point
135  i = m_BoundingObjects.size();
136  break;
137 
138  case Union:
139  case Difference:
140  posInside = false;
141  negInside = false;
142  // calculate union: each point, that is inside least one BoundingObject is considered inside the group
143  if (m_BoundingObjects.at(i)->GetPositive())
144  posInside = m_BoundingObjects.at(i)->IsInside(p) || posInside;
145  else
146  negInside = m_BoundingObjects.at(i)->IsInside(p) || negInside;
147 
148  if (posInside && !negInside)
149  inside = true;
150  else
151  inside = false;
152  break;
153 
154  default:
155  inside = false;
156  // calculate union: each point, that is inside least one BoundingObject is considered inside the group
157  inside = m_BoundingObjects.at(i)->IsInside(p) || inside;
158  if (inside) // shortcut, it is enough to find one object that contains the point
159  i = m_BoundingObjects.size();
160  break;
161  }
162  }
163  return inside;
164 }
165 
167 {
168  return m_Counter;
169 }
170 
172 {
173  return m_Counter > 0;
174 }
175 
177 {
178  // if ( m_BoundingObjects == nullptr )
179  return Superclass::GetGeometry(t);
180 
181  // mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boI = m_BoundingObjects->Begin();
182  // const mitk::BoundingObjectGroup::BoundingObjectContainer::ConstIterator boIEnd = m_BoundingObjects->End();
183  // mitk::Geometry3D* currentGeometry = nullptr;
184 
185  // while ( boI != boIEnd )
186  //{
187  // currentGeometry = boI.Value()->GetGeometry( t );
188  // boI++;
189  //}
190 
191  // return currentGeometry;
192 }
193 
194 void mitk::BoundingObjectGroup::SetBoundingObjects(const std::deque<mitk::BoundingObject::Pointer> boundingObjects)
195 {
196  m_BoundingObjects = boundingObjects;
197 }
198 
199 std::deque<mitk::BoundingObject::Pointer> mitk::BoundingObjectGroup::GetBoundingObjects()
200 {
201  return m_BoundingObjects;
202 }
itk::SmartPointer< mitk::BaseDataSource > GetSource() const
Get the process object that generated this data object.
Point3D GetCornerPointInWorld(int id) const
Get the position of the corner number id (in world coordinates)
std::deque< mitk::BoundingObject::Pointer > m_BoundingObjects
void SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
virtual void SetTimeGeometry(TimeGeometry *geometry)
Set the TimeGeometry of the data, which will be referenced (not copied!).
void RemoveBoundingObject(mitk::BoundingObject::Pointer boundingObject)
void AddBoundingObject(mitk::BoundingObject::Pointer boundingObject)
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:66
bool IsInside(const mitk::Point3D &p) const override
std::deque< mitk::BoundingObject::Pointer > GetBoundingObjects()
itk::AffineGeometryFrame< ScalarType, 3 >::TransformType AffineTransform3D
virtual void SetVtkPolyData(vtkPolyData *polydata, unsigned int t=0)
MITKCORE_EXPORT const double large
void SetBounds(const BoundsArrayType &bounds)
Set the bounding box (in index/unit coordinates)
bool VerifyRequestedRegion() override
Verify that the RequestedRegion is within the LargestPossibleRegion.
void SetBoundingObjects(const std::deque< mitk::BoundingObject::Pointer > boundingObjects)
void Update()
Updates the geometry.
BaseGeometry Describes the geometry of a data object.
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
BoundingBoxType::BoundsArrayType BoundsArrayType
mitk::BaseGeometry * GetGeometry(int t=0) const