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
mitkClippedSurfaceBoundsCalculator.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 ===================================================================*/
17 #include "mitkLine.h"
18 
19 #define ROUND_P(x) ((x) >= 0 ? (int)((x) + 0.5) : (int)((x)-0.5))
20 
23  : m_PlaneGeometry(nullptr), m_Geometry3D(nullptr), m_Image(nullptr)
24 {
25  this->InitializeOutput();
26 
27  this->SetInput(geometry, image);
28 }
29 
32  : m_PlaneGeometry(nullptr), m_Geometry3D(nullptr), m_Image(nullptr)
33 {
34  this->InitializeOutput();
35 
36  this->SetInput(geometry, image);
37 }
38 
41  : m_PlaneGeometry(nullptr), m_Geometry3D(nullptr), m_Image(image)
42 {
43  this->InitializeOutput();
44 
46 }
47 
49 {
50  // initialize with meaningless slice indices
51  m_MinMaxOutput.clear();
52  m_MinMaxOutput.reserve(3);
53  for (int i = 0; i < 3; i++)
54  {
56  }
57 }
58 
60 {
61 }
62 
64 {
65  if (geometry && image)
66  {
67  this->m_PlaneGeometry = geometry;
68  this->m_Image = image;
69  this->m_Geometry3D = nullptr; // Not possible to set both
70  m_ObjectPointsInWorldCoordinates.clear();
71  }
72 }
73 
75 {
76  if (geometry && image)
77  {
78  this->m_Geometry3D = geometry;
79  this->m_Image = image;
80  this->m_PlaneGeometry = nullptr; // Not possible to set both
81  m_ObjectPointsInWorldCoordinates.clear();
82  }
83 }
84 
85 void mitk::ClippedSurfaceBoundsCalculator::SetInput(const std::vector<mitk::Point3D> pointlist, mitk::Image *image)
86 {
87  if (!pointlist.empty() && image)
88  {
89  m_Geometry3D = nullptr;
90  m_PlaneGeometry = nullptr;
91  m_Image = image;
92  m_ObjectPointsInWorldCoordinates = pointlist;
93  }
94 }
95 
97 {
98  return this->m_MinMaxOutput[0];
99 }
100 
102 {
103  return this->m_MinMaxOutput[1];
104 }
105 
107 {
108  return this->m_MinMaxOutput[2];
109 }
110 
112 {
113  this->m_MinMaxOutput.clear();
114  m_MinMaxOutput.reserve(3);
115  for (int i = 0; i < 3; i++)
116  {
117  this->m_MinMaxOutput.push_back(OutputType(std::numeric_limits<int>::max(), std::numeric_limits<int>::min()));
118  }
119 
120  if (m_PlaneGeometry.IsNotNull())
121  {
122  this->CalculateIntersectionPoints(m_PlaneGeometry);
123  }
124  else if (m_Geometry3D.IsNotNull())
125  {
126  // go through all slices of the image, ...
127  const mitk::SlicedGeometry3D *slicedGeometry3D =
128  dynamic_cast<const mitk::SlicedGeometry3D *>(m_Geometry3D.GetPointer());
129  int allSlices = slicedGeometry3D->GetSlices();
130  this->CalculateIntersectionPoints(dynamic_cast<mitk::PlaneGeometry *>(slicedGeometry3D->GetPlaneGeometry(0)));
131  this->CalculateIntersectionPoints(
132  dynamic_cast<mitk::PlaneGeometry *>(slicedGeometry3D->GetPlaneGeometry(allSlices - 1)));
133  }
134  else if (!m_ObjectPointsInWorldCoordinates.empty())
135  {
136  this->CalculateIntersectionPoints(m_ObjectPointsInWorldCoordinates);
137  this->EnforceImageBounds();
138  }
139 }
140 
142 {
143  // SEE HEADER DOCUMENTATION for explanation
144 
145  const mitk::BaseGeometry::Pointer imageGeometry = m_Image->GetGeometry()->Clone();
146 
147  // the cornerpoint(0) is the corner based Origin, which is original center based
148  Point3D origin = imageGeometry->GetCornerPoint(0); // Left, bottom, front
149 
150  // Get axis vector for the spatial directions
151  const Vector3D xDirection = imageGeometry->GetAxisVector(0);
152  const Vector3D yDirection = imageGeometry->GetAxisVector(1);
153  const Vector3D zDirection = imageGeometry->GetAxisVector(2);
154 
155  const Point3D leftBottomFront = origin;
156  const Point3D leftTopFront = origin + yDirection;
157  const Point3D leftBottomBack = origin + zDirection;
158  const Point3D leftTopBack = origin + yDirection + zDirection;
159  const Point3D rightBottomFront = origin + xDirection;
160  const Point3D rightTopFront = origin + xDirection + yDirection;
161  const Point3D rightBottomBack = origin + xDirection + zDirection;
162  const Point3D rightTopBack = origin + xDirection + yDirection + zDirection;
163 
164  typedef std::vector<std::pair<mitk::Point3D, mitk::Point3D>> EdgesVector;
165  EdgesVector edgesOf3DBox;
166  edgesOf3DBox.reserve(12);
167 
168  edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // x = left=xfront, y=bottom=yfront, z=front=zfront
169  leftTopFront)); // left, top, front
170 
171  edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // left, bottom, front
172  leftBottomBack)); // left, bottom, back
173 
174  edgesOf3DBox.push_back(std::make_pair(leftBottomFront, // left, bottom, front
175  rightBottomFront)); // right, bottom, front
176 
177  edgesOf3DBox.push_back(std::make_pair(leftTopFront, // left, top, front
178  rightTopFront)); // right, top, front
179 
180  edgesOf3DBox.push_back(std::make_pair(leftTopFront, // left, top, front
181  leftTopBack)); // left, top, back
182 
183  edgesOf3DBox.push_back(std::make_pair(rightTopFront, // right, top, front
184  rightTopBack)); // right, top, back
185 
186  edgesOf3DBox.push_back(std::make_pair(rightTopFront, // right, top, front
187  rightBottomFront)); // right, bottom, front
188 
189  edgesOf3DBox.push_back(std::make_pair(rightBottomFront, // right, bottom, front
190  rightBottomBack)); // right, bottom, back
191 
192  edgesOf3DBox.push_back(std::make_pair(rightBottomBack, // right, bottom, back
193  leftBottomBack)); // left, bottom, back
194 
195  edgesOf3DBox.push_back(std::make_pair(rightBottomBack, // right, bottom, back
196  rightTopBack)); // right, top, back
197 
198  edgesOf3DBox.push_back(std::make_pair(rightTopBack, // right, top, back
199  leftTopBack)); // left, top, back
200 
201  edgesOf3DBox.push_back(std::make_pair(leftTopBack, // left, top, back
202  leftBottomBack)); // left, bottom, back
203 
204  for (auto iterator = edgesOf3DBox.cbegin(); iterator != edgesOf3DBox.cend(); ++iterator)
205  {
206  const Point3D startPoint = (*iterator).first; // start point of the line
207  const Point3D endPoint = (*iterator).second; // end point of the line
208  const Vector3D lineDirection = endPoint - startPoint;
209 
210  const mitk::Line3D line(startPoint, lineDirection);
211 
212  // Get intersection point of line and plane geometry
213  Point3D intersectionWorldPoint(std::numeric_limits<int>::min());
214 
215  double t = -1.0;
216  bool doesLineIntersectWithPlane(false);
217 
218  const double norm = line.GetDirection().GetNorm();
219  const double dist = geometry->Distance(line.GetPoint1());
220  if (norm < mitk::eps && dist < mitk::sqrteps)
221  {
222  t = 1.0;
223  doesLineIntersectWithPlane = true;
224  intersectionWorldPoint = line.GetPoint1();
225  }
226  else
227  {
228  geometry->IntersectionPoint(line, intersectionWorldPoint);
229  doesLineIntersectWithPlane = geometry->IntersectionPointParam(line, t);
230  }
231 
232  // Get index point
233  mitk::Point3D intersectionIndexPoint;
234  imageGeometry->WorldToIndex(intersectionWorldPoint, intersectionIndexPoint);
235 
236  const bool lowerBoundGood = (0 - mitk::sqrteps) <= t;
237  const bool upperBoundGood = t <= 1.0 + mitk::sqrteps;
238  if (doesLineIntersectWithPlane && lowerBoundGood && upperBoundGood)
239  {
240  for (int dim = 0; dim < 3; ++dim)
241  {
242  m_MinMaxOutput[dim].first = std::min(m_MinMaxOutput[dim].first, ROUND_P(intersectionIndexPoint[dim]));
243  m_MinMaxOutput[dim].second = std::max(m_MinMaxOutput[dim].second, ROUND_P(intersectionIndexPoint[dim]));
244  }
245  this->EnforceImageBounds();
246  }
247  }
248 }
249 
251 {
252  PointListType::const_iterator pointIterator;
253 
254  const mitk::SlicedGeometry3D::Pointer imageGeometry = m_Image->GetSlicedGeometry();
255  for (pointIterator = pointList.cbegin(); pointIterator != pointList.cend(); ++pointIterator)
256  {
257  mitk::Point3D pntInIndexCoordinates;
258  imageGeometry->WorldToIndex((*pointIterator), pntInIndexCoordinates);
259 
260  m_MinMaxOutput[0].first =
261  pntInIndexCoordinates[0] < m_MinMaxOutput[0].first ? ROUND_P(pntInIndexCoordinates[0]) : m_MinMaxOutput[0].first;
262  m_MinMaxOutput[0].second = pntInIndexCoordinates[0] > m_MinMaxOutput[0].second ? ROUND_P(pntInIndexCoordinates[0]) :
263  m_MinMaxOutput[0].second;
264 
265  m_MinMaxOutput[1].first =
266  pntInIndexCoordinates[1] < m_MinMaxOutput[1].first ? ROUND_P(pntInIndexCoordinates[1]) : m_MinMaxOutput[1].first;
267  m_MinMaxOutput[1].second = pntInIndexCoordinates[1] > m_MinMaxOutput[1].second ? ROUND_P(pntInIndexCoordinates[1]) :
268  m_MinMaxOutput[1].second;
269 
270  m_MinMaxOutput[2].first =
271  pntInIndexCoordinates[2] < m_MinMaxOutput[2].first ? ROUND_P(pntInIndexCoordinates[2]) : m_MinMaxOutput[2].first;
272  m_MinMaxOutput[2].second = pntInIndexCoordinates[2] > m_MinMaxOutput[2].second ? ROUND_P(pntInIndexCoordinates[2]) :
273  m_MinMaxOutput[2].second;
274  }
275 
276  // this->EnforceImageBounds();
277 }
278 
280 {
281  m_MinMaxOutput[0].first = std::max(m_MinMaxOutput[0].first, 0);
282  m_MinMaxOutput[1].first = std::max(m_MinMaxOutput[1].first, 0);
283  m_MinMaxOutput[2].first = std::max(m_MinMaxOutput[2].first, 0);
284 
285  m_MinMaxOutput[0].first = std::min(m_MinMaxOutput[0].first, (int)m_Image->GetDimension(0) - 1);
286  m_MinMaxOutput[1].first = std::min(m_MinMaxOutput[1].first, (int)m_Image->GetDimension(1) - 1);
287  m_MinMaxOutput[2].first = std::min(m_MinMaxOutput[2].first, (int)m_Image->GetDimension(2) - 1);
288 
289  m_MinMaxOutput[0].second = std::min(m_MinMaxOutput[0].second, (int)m_Image->GetDimension(0) - 1);
290  m_MinMaxOutput[1].second = std::min(m_MinMaxOutput[1].second, (int)m_Image->GetDimension(1) - 1);
291  m_MinMaxOutput[2].second = std::min(m_MinMaxOutput[2].second, (int)m_Image->GetDimension(2) - 1);
292 
293  m_MinMaxOutput[0].second = std::max(m_MinMaxOutput[0].second, 0);
294  m_MinMaxOutput[1].second = std::max(m_MinMaxOutput[1].second, 0);
295  m_MinMaxOutput[2].second = std::max(m_MinMaxOutput[2].second, 0);
296 }
OutputType GetMinMaxSpatialDirectionZ()
What Z coordinates (slice indices) are cut/visible in given plane.
bool IntersectionPointParam(const Line3D &line, double &t) const
Calculate line parameter of intersection point between the plane and a line.
void CalculateIntersectionPoints(const mitk::PlaneGeometry *geometry)
const itk::Point< TCoordRep, NPointDimension > & GetPoint1() const
Get start point of the line.
Definition: mitkLine.h:115
Descibes a line.
Definition: mitkLine.h:32
static char * line
Definition: svm.cpp:2884
bool IntersectionPoint(const Line3D &line, Point3D &intersectionPoint) const
Calculate intersection point between the plane and a line.
void SetInput(const mitk::PlaneGeometry *geometry, mitk::Image *image)
ScalarType Distance(const Point3D &pt3d_mm) const
Distance of the point from the geometry (bounding-box not considered)
const itk::Vector< TCoordRep, NPointDimension > & GetDirection() const
Get the direction vector of the line.
Definition: mitkLine.h:74
void EnforceImageBounds()
Clips the resulting index-coordinates to make sure they do not exceed the imagebounds.
Image class for storing images.
Definition: mitkImage.h:76
virtual mitk::PlaneGeometry * GetPlaneGeometry(int s) const
Returns the PlaneGeometry of the slice (s).
ClippedSurfaceBoundsCalculator(const mitk::PlaneGeometry *geometry=nullptr, mitk::Image::Pointer image=nullptr)
static T max(T x, T y)
Definition: svm.cpp:70
virtual unsigned int GetSlices() const
Get the number of slices.
Describes the geometry of a data object consisting of slices.
static T min(T x, T y)
Definition: svm.cpp:67
MITKCORE_EXPORT const ScalarType sqrteps
MITKCORE_EXPORT const ScalarType eps
OutputType GetMinMaxSpatialDirectionY()
What Y coordinates (slice indices) are cut/visible in given plane.
Describes a two-dimensional, rectangular plane.
OutputType GetMinMaxSpatialDirectionX()
What X coordinates (slice indices) are cut/visible in given plane.
std::pair< int, int > OutputType
Minimum (first) and maximum (second) slice index.
BaseGeometry Describes the geometry of a data object.