Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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.