GteApprEllipsoid3.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 
10 // The ellipsoid in general form is X^t A X + B^t X + C = 0 where
11 // A is a positive definite 3x3 matrix, B is a 3x1 vector, C is a
12 // scalar, and X is a 3x1 vector. Completing the square,
13 // (X-U)^t A (X-U) = U^t A U - C where U = -0.5 A^{-1} B. Define
14 // M = A/(U^t A U - C). The ellipsoid is (X-U)^t M (X-U) = 1. Factor
15 // M = R^t D R where R is orthonormal and D is diagonal with positive
16 // diagonal terms. The ellipsoid in factored form is
17 // (X-U)^t R^t D^t R (X-U) = 1
18 //
19 // Find the least squares fit of a set of N points P[0] through P[N-1].
20 // The error return value is the least-squares energy function at (U,R,D).
21 
28 
29 namespace gte
30 {
31 
32 template <typename Real>
34 {
35 public:
36  Real operator()(int numPoints, Vector3<Real> const* points,
37  Vector3<Real>& center, Matrix3x3<Real>& rotate, Real diagonal[3]);
38 
39 private:
40  static void MatrixToAngles(Matrix3x3<Real> const& rotate, Real angle[3]);
41  static void AnglesToMatrix(Real const angle[3], Matrix3x3<Real>& rotate);
42  static Real Energy(int numPoints, Vector3<Real> const* points,
43  Real const* input);
44 };
45 
46 
47 template <typename Real>
49  Vector3<Real> const* points, Vector3<Real>& center,
50  Matrix3x3<Real>& rotate, Real diagonal[3])
51 {
52  // Energy function is E : R^9 -> R where
53  // V = (V0,V1,V2,V3,V4,V5,V6,V7,V8)
54  // = (D[0],D[1],D[2],U[0],U,y,U[2],A0,A1,A2).
55  std::function<Real(Real const*)> energy =
56  [numPoints, points](Real const* input)
57  {
58  return Energy(numPoints, points, input);
59  };
60 
61  MinimizeN<Real> minimizer(9, energy, 8, 8, 32);
62 
63  // The initial guess for the minimizer is based on an oriented box that
64  // contains the points.
66  GetContainer(numPoints, points, box);
67  center = box.center;
68  for (int i = 0; i < 3; ++i)
69  {
70  rotate.SetRow(i, box.axis[i]);
71  diagonal[i] = box.extent[i];
72  }
73 
74  Real angle[3];
75  MatrixToAngles(rotate, angle);
76 
77  Real extent[3] =
78  {
79  diagonal[0] * std::abs(rotate(0, 0)) +
80  diagonal[1] * std::abs(rotate(0, 1)) +
81  diagonal[2] * std::abs(rotate(0, 2)),
82 
83  diagonal[0] * std::abs(rotate(1, 0)) +
84  diagonal[1] * std::abs(rotate(1, 1)) +
85  diagonal[2] * std::abs(rotate(1, 2)),
86 
87  diagonal[0] * std::abs(rotate(2, 0)) +
88  diagonal[1] * std::abs(rotate(2, 1)) +
89  diagonal[2] * std::abs(rotate(2, 2))
90  };
91 
92  Real v0[9] =
93  {
94  ((Real)0.5)*diagonal[0],
95  ((Real)0.5)*diagonal[1],
96  ((Real)0.5)*diagonal[2],
97  center[0] - extent[0],
98  center[1] - extent[1],
99  center[2] - extent[2],
100  -(Real)GTE_C_PI,
101  (Real)0,
102  (Real)0
103  };
104 
105  Real v1[9] =
106  {
107  ((Real)2)*diagonal[0],
108  ((Real)2)*diagonal[1],
109  ((Real)2)*diagonal[2],
110  center[0] + extent[0],
111  center[1] + extent[1],
112  center[2] + extent[2],
113  (Real)GTE_C_PI,
114  (Real)GTE_C_PI,
115  (Real)GTE_C_PI
116  };
117 
118  Real vInitial[9] =
119  {
120  diagonal[0],
121  diagonal[1],
122  diagonal[2],
123  center[0],
124  center[1],
125  center[2],
126  angle[0],
127  angle[1],
128  angle[2]
129  };
130 
131  Real vMin[9], error;
132  minimizer.GetMinimum(v0, v1, vInitial, vMin, error);
133 
134  diagonal[0] = vMin[0];
135  diagonal[1] = vMin[1];
136  diagonal[2] = vMin[2];
137  center[0] = vMin[3];
138  center[1] = vMin[4];
139  center[2] = vMin[5];
140  AnglesToMatrix(&vMin[6], rotate);
141 
142  return error;
143 }
144 
145 template <typename Real>
147  Real angle[3])
148 {
149  // rotation axis = (cos(a0)sin(a1),sin(a0)sin(a1),cos(a1))
150  // a0 in [-pi,pi], a1 in [0,pi], a2 in [0,pi]
151 
152  Real const zero = (Real)0;
153  Real const one = (Real)1;
155 
156  if (-one < aa.axis[2])
157  {
158  if (aa.axis[2] < one)
159  {
160  angle[0] = atan2(aa.axis[1], aa.axis[0]);
161  angle[1] = acos(aa.axis[2]);
162  }
163  else
164  {
165  angle[0] = zero;
166  angle[1] = zero;
167  }
168  }
169  else
170  {
171  angle[0] = zero;
172  angle[1] = (Real)GTE_C_PI;
173  }
174 }
175 
176 template <typename Real>
178  Matrix3x3<Real>& rotate)
179 {
180  // rotation axis = (cos(a0)sin(a1),sin(a0)sin(a1),cos(a1))
181  // a0 in [-pi,pi], a1 in [0,pi], a2 in [0,pi]
182 
183  Real cs0 = cos(angle[0]);
184  Real sn0 = sin(angle[0]);
185  Real cs1 = cos(angle[1]);
186  Real sn1 = sin(angle[1]);
188  aa.axis = { cs0*sn1, sn0*sn1, cs1 };
189  aa.angle = angle[2];
190  rotate = Rotation<3, Real>(aa);
191 }
192 
193 template <typename Real>
195  Real const* input)
196 {
197  // Build rotation matrix.
198  Matrix3x3<Real> rotate;
199  AnglesToMatrix(&input[6], rotate);
200 
201  // Uniformly scale the extents to keep reasonable floating point values
202  // in the distance calculations.
203  Real maxValue = std::max(std::max(input[0], input[1]), input[2]);
204  Real invMax = ((Real)1) / maxValue;
206  Vector3<Real>::Unit(1), Vector3<Real>::Unit(2) }, { invMax*input[0],
207  invMax*input[1], invMax*input[2] });
208 
209  // Transform the points to the coordinate system of center C and columns
210  // of rotation R.
212  Real energy = (Real)0;
213  for (int i = 0; i < numPoints; ++i)
214  {
215  Vector3<Real> diff = points[i] -
216  Vector3<Real>{ input[3], input[4], input[5] };
217 
218  Vector3<Real> prod = invMax * (diff * rotate);
219  Real dist = peQuery(prod, ellipsoid).distance;
220  energy += maxValue * dist;
221  }
222 
223  return energy;
224 }
225 
226 
227 }
std::array< Vector< N, Real >, N > axis
static void MatrixToAngles(Matrix3x3< Real > const &rotate, Real angle[3])
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
bool GetContainer(int numPoints, Vector3< Real > const *points, Capsule3< Real > &capsule)
GLfloat GLfloat v1
Definition: glcorearb.h:812
GLfloat angle
Definition: glext.h:6466
Vector< N, Real > extent
void GetMinimum(Real const *t0, Real const *t1, Real const *tInitial, Real *tMin, Real &fMin)
Definition: GteMinimizeN.h:93
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
#define GTE_C_PI
Definition: GteConstants.h:17
Real operator()(int numPoints, Vector3< Real > const *points, Vector3< Real > &center, Matrix3x3< Real > &rotate, Real diagonal[3])
static void AnglesToMatrix(Real const angle[3], Matrix3x3< Real > &rotate)
GLfloat v0
Definition: glcorearb.h:811
GLenum GLenum GLenum input
Definition: glext.h:9913
void SetRow(int r, Vector< NumCols, Real > const &vec)
Definition: GteMatrix.h:352
Vector< N, Real > axis
Definition: GteAxisAngle.h:26
static Real Energy(int numPoints, Vector3< Real > const *points, Real const *input)
Vector< N, Real > center
static Vector Unit(int d)
Definition: GteVector.h:303


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