GteContEllipsoid3.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 
15 
16 namespace gte
17 {
18 
19 // The input points are fit with a Gaussian distribution. The center C of the
20 // ellipsoid is chosen to be the mean of the distribution. The axes of the
21 // ellipsoid are chosen to be the eigenvectors of the covariance matrix M.
22 // The shape of the ellipsoid is determined by the absolute values of the
23 // eigenvalues. NOTE: The construction is ill-conditioned if the points are
24 // (nearly) collinear or (nearly) planar. In this case M has a (nearly) zero
25 // eigenvalue, so inverting M is problematic.
26 template <typename Real>
27 bool GetContainer(int numPoints, Vector3<Real> const* points,
28  Ellipsoid3<Real>& ellipsoid);
29 
30 // Test for containment of a point inside an ellipsoid.
31 template <typename Real>
32 bool InContainer(Vector3<Real> const& point,
33  Ellipsoid3<Real> const& ellipsoid);
34 
35 // Construct a bounding ellipsoid for the two input ellipsoids. The result is
36 // not necessarily the minimum-volume ellipsoid containing the two ellipsoids.
37 template <typename Real>
38 bool MergeContainers(Ellipsoid3<Real> const& ellipsoid0,
39  Ellipsoid3<Real> const& ellipsoid1, Ellipsoid3<Real>& merge);
40 
41 
42 template <typename Real>
43 bool GetContainer(int numPoints, Vector3<Real> const* points,
44  Ellipsoid3<Real>& ellipsoid)
45 {
46  // Fit the points with a Gaussian distribution. The covariance matrix
47  // is M = sum_j D[j]*U[j]*U[j]^T, where D[j] are the eigenvalues and U[j]
48  // are corresponding unit-length eigenvectors.
49  ApprGaussian3<Real> fitter;
50  if (fitter.Fit(numPoints, points))
51  {
52  OrientedBox3<Real> box = fitter.GetParameters();
53 
54  // If either eigenvalue is nonpositive, adjust the D[] values so that
55  // we actually build an ellipse.
56  for (int j = 0; j < 3; ++j)
57  {
58  if (box.extent[j] < (Real)0)
59  {
60  box.extent[j] = -box.extent[j];
61  }
62  }
63 
64  // Grow the ellipsoid, while retaining its shape determined by the
65  // covariance matrix, to enclose all the input points. The quadratic
66  // form that is used for the ellipsoid construction is
67  // Q(X) = (X-C)^T*M*(X-C)
68  // = (X-C)^T*(sum_j D[j]*U[j]*U[j]^T)*(X-C)
69  // = sum_j D[j]*Dot(U[j],X-C)^2
70  // If the maximum value of Q(X[i]) for all input points is V^2, then a
71  // bounding ellipsoid is Q(X) = V^2 since Q(X[i]) <= V^2 for all i.
72 
73  Real maxValue = (Real)0;
74  for (int i = 0; i < numPoints; ++i)
75  {
76  Vector3<Real> diff = points[i] - box.center;
77  Real dot[3] =
78  {
79  Dot(box.axis[0], diff),
80  Dot(box.axis[1], diff),
81  Dot(box.axis[2], diff)
82  };
83 
84  Real value =
85  box.extent[0] * dot[0] * dot[0] +
86  box.extent[1] * dot[1] * dot[1] +
87  box.extent[2] * dot[2] * dot[2];
88 
89  if (value > maxValue)
90  {
91  maxValue = value;
92  }
93  }
94 
95  // Arrange for the quadratic to satisfy Q(X) <= 1.
96  ellipsoid.center = box.center;
97  for (int j = 0; j < 3; ++j)
98  {
99  ellipsoid.axis[j] = box.axis[j];
100  ellipsoid.extent[j] = sqrt(maxValue / box.extent[j]);
101  }
102  return true;
103  }
104 
105  return false;
106 }
107 
108 template <typename Real>
109 bool InContainer(Vector3<Real> const& point,
110  Ellipsoid3<Real> const& ellipsoid)
111 {
112  Vector3<Real> diff = point - ellipsoid.center;
113  Vector3<Real> standardized{
114  Dot(diff, ellipsoid.axis[0]) / ellipsoid.extent[0],
115  Dot(diff, ellipsoid.axis[1]) / ellipsoid.extent[1],
116  Dot(diff, ellipsoid.axis[2]) / ellipsoid.extent[2] };
117  return Length(standardized) <= (Real)1;
118 }
119 
120 template <typename Real>
121 bool MergeContainers(Ellipsoid3<Real> const& ellipsoid0,
122  Ellipsoid3<Real> const& ellipsoid1, Ellipsoid3<Real>& merge)
123 {
124  // Compute the average of the input centers
125  merge.center = ((Real)0.5)*(ellipsoid0.center + ellipsoid1.center);
126 
127  // The bounding ellipsoid orientation is the average of the input
128  // orientations.
129  Matrix3x3<Real> rot0, rot1;
130  rot0.SetCol(0, ellipsoid0.axis[0]);
131  rot0.SetCol(1, ellipsoid0.axis[1]);
132  rot0.SetCol(2, ellipsoid0.axis[2]);
133  rot1.SetCol(0, ellipsoid1.axis[0]);
134  rot1.SetCol(1, ellipsoid1.axis[1]);
135  rot1.SetCol(2, ellipsoid1.axis[2]);
138  if (Dot(q0, q1) < (Real)0)
139  {
140  q1 = -q1;
141  }
142 
143  Quaternion<Real> q = q0 + q1;
144  Normalize(q);
146  for (int j = 0; j < 3; ++j)
147  {
148  merge.axis[j] = rot.GetCol(j);
149  }
150 
151  // Project the input ellipsoids onto the axes obtained by the average
152  // of the orientations and that go through the center obtained by the
153  // average of the centers.
154  for (int i = 0; i < 3; ++i)
155  {
156  // Projection axis.
157  Line3<Real> line(merge.center, merge.axis[i]);
158 
159  // Project ellipsoids onto the axis.
160  Real min0, max0, min1, max1;
161  Project(ellipsoid0, line, min0, max0);
162  Project(ellipsoid1, line, min1, max1);
163 
164  // Determine the smallest interval containing the projected
165  // intervals.
166  Real maxIntr = (max0 >= max1 ? max0 : max1);
167  Real minIntr = (min0 <= min1 ? min0 : min1);
168 
169  // Update the average center to be the center of the bounding box
170  // defined by the projected intervals.
171  merge.center += line.direction*(((Real)0.5)*(minIntr + maxIntr));
172 
173  // Compute the extents of the box based on the new center.
174  merge.extent[i] = ((Real)0.5)*(maxIntr - minIntr);
175  }
176 
177  return true;
178 }
179 
180 
181 }
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
GVector< Real > Project(GVector< Real > const &v, int reject)
Definition: GteGVector.h:625
bool GetContainer(int numPoints, Vector3< Real > const *points, Capsule3< Real > &capsule)
Vector< N, Real > extent
bool MergeContainers(Capsule3< Real > const &capsule0, Capsule3< Real > const &capsule1, Capsule3< Real > &merge)
bool InContainer(Vector3< Real > const &point, Capsule3< Real > const &capsule)
GLsizei const GLfloat * value
Definition: glcorearb.h:819
Vector< N, Real > direction
Definition: GteLine.h:29
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
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:255
Vector< N, Real > center
Vector< N, Real > center
std::array< Vector< N, Real >, N > axis


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