CustusX  16.5.0-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxSliceComputer.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxSliceComputer.h"
34 #include "cxDefinitions.h"
35 #include <math.h>
36 
37 namespace cx
38 {
39 
40 SlicePlane::SlicePlane(const Vector3D& c_, const Vector3D& i_, const Vector3D& j_) :
41  c(c_), i(i_), j(j_)
42 {
43 }
44 
45 std::ostream& operator<<(std::ostream& s, const SlicePlane& val)
46 {
47  s << "center : " << val.c << std::endl;
48  s << "i_vector : " << val.i << std::endl;
49  s << "j_vector : " << val.j << std::endl;
50  return s;
51 }
52 
53 bool similar(const SlicePlane& a, const SlicePlane& b)
54 {
55  return similar(a.c, b.c) && similar(a.i, b.i) && similar(a.j, b.j);
56 }
57 
61  mClinicalApplication(mdNEUROLOGICAL),
62  mOrientType(otORTHOGONAL),
63  mPlaneType(ptAXIAL),
64  mFollowType(ftFIXED_CENTER),
65  mFixedCenter(Vector3D(0,0,0)),
66  m_rMt(Transform3D::Identity()),
67  mToolOffset(0.0),
68  mUseGravity(false),
69  mGravityDirection(Vector3D(0,0,-1)) ,
70  mUseViewOffset(false),
71  mViewportHeight(1),
72  mViewOffset(0.5),
73  mUseConstrainedViewOffset(false)
74 {
75 }
76 
78 {
79 }
80 
83 void SliceComputer::initializeFromPlane(PLANE_TYPE plane, bool useGravity, const Vector3D& gravityDir, bool useViewOffset, double viewportHeight, double toolViewOffset, CLINICAL_VIEW application, bool useConstrainedViewOffset)
84 {
85  setPlaneType(plane);
86  mClinicalApplication = application;
87 
88  if (plane == ptSAGITTAL || plane == ptCORONAL || plane == ptAXIAL )
89  {
92  }
93  else if (plane == ptANYPLANE || plane==ptRADIALPLANE || plane==ptSIDEPLANE)
94  {
97 
98  setGravity(useGravity, gravityDir);
99  setToolViewOffset(useViewOffset, viewportHeight, toolViewOffset, useConstrainedViewOffset); // TODO finish this one
100  }
101 }
102 
103 void SliceComputer::setClinicalApplication(CLINICAL_VIEW application)
104 {
105  mClinicalApplication = application;
106 }
107 
108 ORIENTATION_TYPE SliceComputer::getOrientationType() const
109 {
110  return mOrientType;
111 }
112 
113 PLANE_TYPE SliceComputer::getPlaneType() const
114 {
115  return mPlaneType;
116 }
117 
119 {
120  return m_rMt;
121 }
122 
127 {
128  m_rMt = rMt;
129 }
130 
134 void SliceComputer::setOrientationType(ORIENTATION_TYPE val)
135 {
136  mOrientType = val;
137 }
138 
141 void SliceComputer::setPlaneType(PLANE_TYPE val)
142 {
143  mPlaneType = val;
144 }
145 
150 {
151  mFixedCenter = center;
152 }
153 
158 void SliceComputer::setFollowType(FOLLOW_TYPE val)
159 {
160  mFollowType = val;
161 }
162 
166 void SliceComputer::setGravity(bool use, const Vector3D& dir)
167 {
168  mUseGravity = use;
169  mGravityDirection = dir;
170 }
171 
175 {
176  mToolOffset = val;
177 }
178 
183 void SliceComputer::setToolViewOffset(bool use, double viewportHeight, double viewOffset, bool useConstrainedViewOffset)
184 {
185  mUseViewOffset = use;
186  mViewportHeight = viewportHeight;
187  mViewOffset = viewOffset;
188  mUseConstrainedViewOffset = useConstrainedViewOffset;
189 }
190 
193 void SliceComputer::setToolViewportHeight(double viewportHeight)
194 {
195  mViewportHeight = viewportHeight;
196 }
197 
201 {
202  std::pair<Vector3D,Vector3D> basis = generateBasisVectors();
203  SlicePlane plane;
204  plane.i = basis.first;
205  plane.j = basis.second;
206  plane.c = Vector3D(0,0,mToolOffset);
207 
208  // transform position from tool to reference space
209  plane.c = m_rMt.coord(plane.c);
210  // transform orientation from tool to reference space for the oblique case only
211  if (mOrientType==otOBLIQUE)
212  {
213  plane.i = m_rMt.vector(plane.i);
214  plane.j = m_rMt.vector(plane.j);
215  }
216 
217  // orient planes so that gravity is down
218  plane = orientToGravity(plane);
219 
220  // try to to this also for oblique views, IF the ftFIXED_CENTER is set.
221  // use special acs centermod algo
222  plane.c = generateFixedIJCenter(mFixedCenter, plane.c, plane.i, plane.j);
223 
224  // set center so that it is a fixed distance from viewport top
225  plane = applyViewOffset(plane);
226 
227  return plane;
228 }
229 
241 SlicePlane SliceComputer::applyViewOffset(const SlicePlane& base) const
242 {
243  if (!mUseViewOffset)
244  {
245  return base;
246  }
247 
248  double centerOffset = this->getViewOffsetAbsoluteFromCenter();
249 
250  SlicePlane retval = base;
251  if (mUseConstrainedViewOffset)
252  {
253  Vector3D toolOffsetCenter = m_rMt.coord(Vector3D(0,0,mToolOffset));
254  Vector3D newCenter = toolOffsetCenter + centerOffset * base.j;
255  double toolOffsetDistance = dot(newCenter - base.c, base.j);
256 
257  Vector3D toolCenter = m_rMt.coord(Vector3D(0,0,0));
258  newCenter = toolCenter - centerOffset * base.j;
259  double toolDistance = dot(newCenter - base.c, base.j);
260  double usedDistance = std::min(toolOffsetDistance, toolDistance);
261  retval.c = base.c + usedDistance * base.j; // extract j-component of newCenter
262  }
263  else
264  {
265  Vector3D toolCenter = m_rMt.coord(Vector3D(0,0,mToolOffset));
266  Vector3D newCenter = toolCenter - centerOffset * base.j;
267  double distance = dot(newCenter - base.c, base.j);
268  retval.c = base.c + distance * base.j; // extract j-component of newCenter
269  }
270  return retval;
271 }
272 
273 double SliceComputer::getViewOffsetAbsoluteFromCenter() const
274 {
275  if (mPlaneType==ptRADIALPLANE)
276  return 0; // position in the center
277 
278  return mViewportHeight*(0.5-mViewOffset);
279 }
280 
287 std::pair<Vector3D,Vector3D> SliceComputer::generateBasisVectors() const
288 {
289  switch (mClinicalApplication)
290  {
291  case mdRADIOLOGICAL:
292  return this->generateBasisVectorsRadiology();
293  case mdNEUROLOGICAL:
294  default:
295  return this->generateBasisVectorsNeurology();
296  }
297 }
298 
302 std::pair<Vector3D,Vector3D> SliceComputer::generateBasisVectorsNeurology() const
303 {
304  switch (mPlaneType)
305  {
306  // use left-right ordering for axial/coronal
307  case ptAXIAL: return std::make_pair(Vector3D(-1, 0, 0), Vector3D( 0,-1, 0));
308  case ptCORONAL: return std::make_pair(Vector3D(-1, 0, 0), Vector3D( 0, 0, 1));
309  case ptSAGITTAL: return std::make_pair(Vector3D( 0, 1, 0), Vector3D( 0, 0, 1));
310 
311  // use planes corresponding to the cx Tool definitions
312  case ptANYPLANE: return std::make_pair(Vector3D( 0,-1, 0), Vector3D( 0, 0,-1));
313  case ptSIDEPLANE: return std::make_pair(Vector3D(-1, 0, 0), Vector3D( 0, 0,-1));
314  case ptRADIALPLANE: return std::make_pair(Vector3D( 0,-1, 0), Vector3D(-1, 0, 0));
315  default:
316  throw std::exception();
317  }
318 }
319 
323 std::pair<Vector3D,Vector3D> SliceComputer::generateBasisVectorsRadiology() const
324 {
325  switch (mPlaneType)
326  {
327  // use right-left ordering for axial/coronal
328  case ptAXIAL: return std::make_pair(Vector3D( 1, 0, 0), Vector3D( 0,-1, 0));
329  case ptCORONAL: return std::make_pair(Vector3D( 1, 0, 0), Vector3D( 0, 0, 1));
330  case ptSAGITTAL: return std::make_pair(Vector3D( 0, 1, 0), Vector3D( 0, 0, 1));
331 
332  // use planes corresponding to the cx Tool definitions
333  case ptANYPLANE: return std::make_pair(Vector3D( 0,-1, 0), Vector3D( 0, 0,-1));
334  case ptSIDEPLANE: return std::make_pair(Vector3D(-1, 0, 0), Vector3D( 0, 0,-1));
335  case ptRADIALPLANE: return std::make_pair(Vector3D( 0,-1, 0), Vector3D(-1, 0, 0));
336  default:
337  throw std::exception();
338  }
339 }
340 
341 
349 Vector3D SliceComputer::generateFixedIJCenter(const Vector3D& center_r, const Vector3D& cross_r, const Vector3D& i, const Vector3D& j) const
350 {
351  if (mFollowType==ftFIXED_CENTER)
352  {
353  // r is REF, s is SLICE
354  Transform3D M_rs = createTransformIJC(i, j, Vector3D(0,0,0)); // transform from data to slice, zero center.
355  Transform3D M_sr = M_rs.inv();
356  Vector3D center_s = M_sr.coord(center_r);
357  Vector3D cross_s = M_sr.coord(cross_r);
358  // in SLICE space, use {xy} values from center and {z} value from cross.
359  Vector3D q_s(center_s[0], center_s[1], cross_s[2]);
360  Vector3D q_r = M_rs.coord(q_s);
361  return q_r;
362  }
363  return cross_r;
364 }
365 
377 SlicePlane SliceComputer::orientToGravity(const SlicePlane& base) const
378 {
379  if (!mUseGravity)
380  {
381  return base;
382  }
383 
384  SlicePlane retval = base;
385  const Vector3D k = cross(base.i, base.j); // plane normal. Constant
386  Vector3D up;
387  up = -mGravityDirection; // normal case
388 
389  // weight of nongravity, 0=<w=<1, 1 means dont use gravity
390  double w_n = dot(up, k);
391  w_n = w_n*w_n; // square to keep stability near normal use.
392 
393  Vector3D i_g = cross(up, k); // |i_g| varies from 0 to 1 depending on 1-w_n
394  Vector3D i_n = base.i; // |i_n|==1
395 
396 
397  // set i vector to a weighted mean of the two definitions
398  // can also experiment with a tanh function or simply a linear interpolation
399  //
400  // Note: i_g is already small here if w_n is small, this will increase
401  // the effect of i_n. Investigate.
402  //
403  retval.i = i_g*(1.0-w_n) + i_n*w_n;
404  retval.i = retval.i.normal(); // |i|==1
405  retval.j = cross(k, retval.i);
406 
407  return retval;
408 }
409 
410 
411 } // namespace cx
Vector3D j
defines the second axis of the plane. unit vector
void setToolViewportHeight(double viewportHeight)
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:56
A 2D slice plane in 3D. i,j are perpendicular unit vectors.
ftFOLLOW_TOOL
center follows tool
Definition: cxDefinitions.h:67
otOBLIQUE
orient planes relative to the tool space
Definition: cxDefinitions.h:50
mdRADIOLOGICAL
Definition: cxDefinitions.h:75
ftFIXED_CENTER
center is set.
Definition: cxDefinitions.h:67
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
void setToolViewOffset(bool use, double viewportHeight, double viewOffset, bool useConstrainedViewOffset=false)
void setClinicalApplication(CLINICAL_VIEW application)
ptAXIAL
a slice seen from the top of the patient
Definition: cxDefinitions.h:56
PLANE_TYPE getPlaneType() const
void setOrientationType(ORIENTATION_TYPE val)
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
Definition: cxVector3D.cpp:62
void setToolOffset(double val)
ptSAGITTAL
a slice seen from the side of the patient
Definition: cxDefinitions.h:56
Transform3D createTransformIJC(const Vector3D &ivec, const Vector3D &jvec, const Vector3D &center)
Vector3D c
defines the center of the plane
void initializeFromPlane(PLANE_TYPE plane, bool useGravity, const Vector3D &gravityDir, bool useViewOffset, double viewportHeight, double toolViewOffset, CLINICAL_VIEW application, bool useConstrainedViewOffset=false)
void setPlaneType(PLANE_TYPE val)
otORTHOGONAL
orient planes relative to the image/reference space.
Definition: cxDefinitions.h:50
void setFixedCenter(const Vector3D &center)
void setToolPosition(const Transform3D &rMt)
double dot(const Vector3D &a, const Vector3D &b)
compute inner product (or dot product) of a and b.
Definition: cxVector3D.cpp:67
std::ostream & operator<<(std::ostream &s, const IntBoundingBox3D &data)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
ptRADIALPLANE
y-rotated 90* relative to anyplane (bird's view)
Definition: cxDefinitions.h:56
Vector3D i
defines the first axis of the plane. unit vector
Transform3D getToolPosition() const
mdNEUROLOGICAL
Definition: cxDefinitions.h:75
ptANYPLANE
a plane aligned with the tool base plane
Definition: cxDefinitions.h:56
void setFollowType(FOLLOW_TYPE val)
void setGravity(bool use, const Vector3D &dir)
ORIENTATION_TYPE getOrientationType() const
SlicePlane getPlane() const
ptSIDEPLANE
z-rotated 90* relative to anyplane (dual anyplane)
Definition: cxDefinitions.h:56