GteContOrientedBox3.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
13 
14 namespace gte
15 {
16 
17 // Compute an oriented bounding box of the points. The box center is the
18 // average of the points. The box axes are the eigenvectors of the covariance
19 // matrix.
20 template <typename Real>
21 bool GetContainer(int numPoints, Vector3<Real> const* points,
22  OrientedBox3<Real>& box);
23 
24 // Test for containment. Let X = C + y0*U0 + y1*U1 + y2*U2 where C is the
25 // box center and U0, U1, U2 are the orthonormal axes of the box. X is in
26 // the box if |y_i| <= E_i for all i where E_i are the extents of the box.
27 template <typename Real>
28 bool InContainer(Vector3<Real> const& point, OrientedBox3<Real> const& box);
29 
30 // Construct an oriented box that contains two other oriented boxes. The
31 // result is not guaranteed to be the minimum volume box containing the
32 // input boxes.
33 template <typename Real>
34 bool MergeContainers(OrientedBox3<Real> const& box0,
35  OrientedBox3<Real> const& box1, OrientedBox3<Real>& merge);
36 
37 
38 template <typename Real>
39 bool GetContainer(int numPoints, Vector3<Real> const* points,
40  OrientedBox3<Real>& box)
41 {
42  // Fit the points with a Gaussian distribution.
43  ApprGaussian3<Real> fitter;
44  if (fitter.Fit(numPoints, points))
45  {
46  box = fitter.GetParameters();
47 
48  // Let C be the box center and let U0, U1, and U2 be the box axes.
49  // Each input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.
50  // The following code computes min(y0), max(y0), min(y1), max(y1),
51  // min(y2), and max(y2). The box center is then adjusted to be
52  // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
53  // 0.5*(min(y2)+max(y2))*U2
54 
55  Vector3<Real> diff = points[0] - box.center;
56  Vector3<Real> pmin{ Dot(diff, box.axis[0]), Dot(diff, box.axis[1]),
57  Dot(diff, box.axis[2]) };
58  Vector3<Real> pmax = pmin;
59  for (int i = 1; i < numPoints; ++i)
60  {
61  diff = points[i] - box.center;
62  for (int j = 0; j < 3; ++j)
63  {
64  Real dot = Dot(diff, box.axis[j]);
65  if (dot < pmin[j])
66  {
67  pmin[j] = dot;
68  }
69  else if (dot > pmax[j])
70  {
71  pmax[j] = dot;
72  }
73  }
74  }
75 
76  for (int j = 0; j < 3; ++j)
77  {
78  box.center += (((Real)0.5)*(pmin[j] + pmax[j]))*box.axis[j];
79  box.extent[j] = ((Real)0.5)*(pmax[j] - pmin[j]);
80  }
81  return true;
82  }
83 
84  return false;
85 }
86 
87 template <typename Real>
88 bool InContainer(Vector3<Real> const& point, OrientedBox3<Real> const& box)
89 {
90  Vector3<Real> diff = point - box.center;
91  for (int i = 0; i < 3; ++i)
92  {
93  Real coeff = Dot(diff, box.axis[i]);
94  if (std::abs(coeff) > box.extent[i])
95  {
96  return false;
97  }
98  }
99  return true;
100 }
101 
102 template <typename Real>
104  OrientedBox3<Real> const& box1, OrientedBox3<Real>& merge)
105 {
106  // The first guess at the box center. This value will be updated later
107  // after the input box vertices are projected onto axes determined by an
108  // average of box axes.
109  merge.center = ((Real)0.5)*(box0.center + box1.center);
110 
111  // A box's axes, when viewed as the columns of a matrix, form a rotation
112  // matrix. The input box axes are converted to quaternions. The average
113  // quaternion is computed, then normalized to unit length. The result is
114  // the slerp of the two input quaternions with t-value of 1/2. The result
115  // is converted back to a rotation matrix and its columns are selected as
116  // the merged box axes.
117  Matrix3x3<Real> rot0, rot1;
118  rot0.SetCol(0, box0.axis[0]);
119  rot0.SetCol(1, box0.axis[1]);
120  rot0.SetCol(2, box0.axis[2]);
121  rot1.SetCol(0, box1.axis[0]);
122  rot1.SetCol(1, box1.axis[1]);
123  rot1.SetCol(2, box1.axis[2]);
126  if (Dot(q0, q1) < (Real)0)
127  {
128  q1 = -q1;
129  }
130 
131  Quaternion<Real> q = q0 + q1;
132  Normalize(q);
134  for (int j = 0; j < 3; ++j)
135  {
136  merge.axis[j] = rot.GetCol(j);
137  }
138 
139  // Project the input box vertices onto the merged-box axes. Each axis
140  // D[i] containing the current center C has a minimum projected value
141  // min[i] and a maximum projected value max[i]. The corresponding end
142  // points on the axes are C+min[i]*D[i] and C+max[i]*D[i]. The point C
143  // is not necessarily the midpoint for any of the intervals. The actual
144  // box center will be adjusted from C to a point C' that is the midpoint
145  // of each interval,
146  // C' = C + sum_{i=0}^2 0.5*(min[i]+max[i])*D[i]
147  // The box extents are
148  // e[i] = 0.5*(max[i]-min[i])
149 
150  std::array<Vector3<Real>, 8> vertex;
151  Vector3<Real> pmin{ (Real)0, (Real)0, (Real)0 };
152  Vector3<Real> pmax{ (Real)0, (Real)0, (Real)0 };
153 
154  box0.GetVertices(vertex);
155  for (int i = 0; i < 8; ++i)
156  {
157  Vector3<Real> diff = vertex[i] - merge.center;
158  for (int j = 0; j < 3; ++j)
159  {
160  Real dot = Dot(diff, merge.axis[j]);
161  if (dot > pmax[j])
162  {
163  pmax[j] = dot;
164  }
165  else if (dot < pmin[j])
166  {
167  pmin[j] = dot;
168  }
169  }
170  }
171 
172  box1.GetVertices(vertex);
173  for (int i = 0; i < 8; ++i)
174  {
175  Vector3<Real> diff = vertex[i] - merge.center;
176  for (int j = 0; j < 3; ++j)
177  {
178  Real dot = Dot(diff, merge.axis[j]);
179  if (dot > pmax[j])
180  {
181  pmax[j] = dot;
182  }
183  else if (dot < pmin[j])
184  {
185  pmin[j] = dot;
186  }
187  }
188  }
189 
190  // [min,max] is the axis-aligned box in the coordinate system of the
191  // merged box axes. Update the current box center to be the center of
192  // the new box. Compute the extents based on the new center.
193  Real const half = (Real)0.5;
194  for (int j = 0; j < 3; ++j)
195  {
196  merge.center += half*(pmax[j] + pmin[j])*merge.axis[j];
197  merge.extent[j] = half*(pmax[j] - pmin[j]);
198  }
199 
200  return true;
201 }
202 
203 
204 }
bool Fit(int numPoints, Vector3< Real > const *points)
std::array< Vector< N, Real >, N > axis
Vector< NumRows, Real > GetCol(int c) const
Definition: GteMatrix.h:383
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
bool GetContainer(int numPoints, Vector3< Real > const *points, Capsule3< Real > &capsule)
bool MergeContainers(Capsule3< Real > const &capsule0, Capsule3< Real > const &capsule1, Capsule3< Real > &merge)
bool InContainer(Vector3< Real > const &point, Capsule3< Real > const &capsule)
Vector< N, Real > extent
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
void SetCol(int c, Vector< NumRows, Real > const &vec)
Definition: GteMatrix.h:362
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
OrientedBox3< Real > const & GetParameters() const
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:255
Vector< N, Real > center
void GetVertices(std::array< Vector< N, Real >,(1<< N)> &vertex) const


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:59