iMSTK
Interactive Medical Simulation Toolkit
imstkOrientedBox.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkOrientedBox.h"
8 #include "imstkLogger.h"
9 
10 namespace imstk
11 {
12 void
14 {
16  LOG(INFO) << "Extent0: " << m_extents[0];
17  LOG(INFO) << "Extent1: " << m_extents[1];
18  LOG(INFO) << "Extent2: " << m_extents[2];
19 }
20 
21 Vec3d
22 OrientedBox::getExtents(DataType type /* = DataType::PostTransform */)
23 {
24  if (type == DataType::PostTransform)
25  {
28  }
29  return m_extents;
30 }
31 
32 void
33 OrientedBox::setExtents(const Vec3d extents)
34 {
35  if (extents[0] <= 0.0 || extents[1] <= 0.0 || extents[2] <= 0.0)
36  {
37  LOG(WARNING) << "error: extents should be positive.";
38  return;
39  }
40  if (m_extents == extents)
41  {
42  return;
43  }
44  m_extents = extents;
45  m_transformApplied = false;
46  this->postModified();
47 }
48 
49 void
51 {
53  Vec3d s = Vec3d(
54  m.block<3, 1>(0, 0).norm(),
55  m.block<3, 1>(0, 1).norm(),
56  m.block<3, 1>(0, 2).norm());
57  this->setExtents(m_extents.cwiseProduct(s));
58  this->postModified();
59 }
60 
61 void
63 {
64  if (m_transformApplied)
65  {
66  return;
67  }
69  const Vec3d s = getScaling();
70  m_extentsPostTransform = m_extents.cwiseProduct(s);
71  m_transformApplied = true;
72 }
73 
74 double
75 OrientedBox::getFunctionValue(const Vec3d& pos) const
76 {
77  const Mat3d rot = m_orientationPostTransform.toRotationMatrix().transpose();
78  const Vec3d& extents = m_extentsPostTransform;
79 
80  const Vec3d diff = (pos - m_positionPostTransform);
81  const Vec3d proj = rot * diff; // dot product/project onto each axes
82 
83  bool inside[3] =
84  {
85  (std::abs(proj[0]) < extents[0]),
86  (std::abs(proj[1]) < extents[1]),
87  (std::abs(proj[2]) < extents[2])
88  };
89  bool isInsideCube = inside[0] && inside[1] && inside[2];
90 
91  double signedDist = 0.0;
92  if (isInsideCube)
93  {
94  // If inside, find closest face, that is the signed distance
95  signedDist = std::numeric_limits<double>::lowest();
96  for (int i = 0; i < 3; i++)
97  {
98  double dist = proj[i];
99  if (dist < extents[i] && dist >= 0.0)
100  {
101  const double unsignedDistToSide = (extents[i] - dist);
102  if (-unsignedDistToSide > signedDist)
103  {
104  signedDist = -unsignedDistToSide;
105  }
106  }
107  else if (dist > -extents[i] && dist < 0.0)
108  {
109  const double unsignedDistToSide = (extents[i] + dist);
110  if (-unsignedDistToSide > signedDist)
111  {
112  signedDist = -unsignedDistToSide;
113  }
114  }
115  }
116  }
117  else
118  {
119  // If outside we need to also consider diagonal distance to corners and edges
120  // Compute nearest point
121  Vec3d axialSignedDists = Vec3d::Zero();
122  for (int i = 0; i < 3; i++)
123  {
124  double dist = proj[i];
125 
126  // If distance farther than the box extents, clamp to the box
127  if (dist >= extents[i] || dist <= -extents[i])
128  {
129  axialSignedDists[i] = std::abs(dist) - extents[i];
130  }
131  }
132  signedDist = axialSignedDists.norm();
133  }
134  return signedDist;
135 }
136 
137 void
138 OrientedBox::computeBoundingBox(Vec3d& min, Vec3d& max, const double imstkNotUsed(paddingPercent))
139 {
141 
142  const Mat3d r = m_orientationPostTransform.toRotationMatrix();
143  const Vec3d a = r.col(0) * m_extentsPostTransform[0];
144  const Vec3d b = r.col(1) * m_extentsPostTransform[1];
145  const Vec3d c = r.col(2) * m_extentsPostTransform[2];
146 
147  Vec3d pts[8];
148  pts[0] = m_positionPostTransform + a + b + c;
149  pts[1] = m_positionPostTransform + a + b - c;
150  pts[2] = m_positionPostTransform + a - b + c;
151  pts[3] = m_positionPostTransform + a - b - c;
152  pts[4] = m_positionPostTransform - a + b + c;
153  pts[5] = m_positionPostTransform - a + b - c;
154  pts[6] = m_positionPostTransform - a - b + c;
155  pts[7] = m_positionPostTransform - a - b - c;
156 
157  min = pts[0];
158  max = pts[0];
159  for (int i = 1; i < 8; i++)
160  {
161  min = min.cwiseMin(pts[i]);
162  max = max.cwiseMax(pts[i]);
163  }
164 }
165 } // namespace imstk
void updatePostTransformData() const override
Update the Cube parameters applying the latest transform.
virtual void print() const
Print.
void updatePostTransformData() const override
Apply the global transform to the local parameters producing post transformed parameters.
Vec3d m_extentsPostTransform
Half dimensions of the oriented box once transform applied.
void setExtents(const Vec3d extents)
Sets the extents of the cube (half dimensions)
Compound Geometry.
Vec3d getScaling() const
Get/Set scaling.
Vec3d getExtents(DataType type=DataType::PostTransform)
Returns the extents of the cube.
void postModified()
Post modified event.
void computeBoundingBox(Vec3d &min, Vec3d &max, const double paddingPercent=0.0) override
Get the min, max of the AABB around the cube.
double getFunctionValue(const Vec3d &pos) const override
Returns signed distance to surface at pos.
void print() const override
Print the cube info.
Quatd m_orientationPostTransform
orientation once transform is applied
void applyTransform(const Mat4d &m) override
Apply a user transform directly to (pre-transformed) parameters producing new parameters.
Vec3d m_positionPostTransform
position once transform applied
void applyTransform(const Mat4d &m) override
Apply a user transform directly to (pre-transformed) parameters producing new parameters.
DataType
Enumeration for the data to retrieve PreTransform for data where transform matrix is not applied Po...
Definition: imstkGeometry.h:41