GteHyperellipsoid.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 #include <Mathematics/GteMatrix.h>
12 
13 // A hyperellipsoid has center K; axis directions U[0] through U[N-1], all
14 // unit-length vectors; and extents e[0] through e[N-1], all positive numbers.
15 // A point X = K + sum_{d=0}^{N-1} y[d]*U[d] is on the hyperellipsoid whenever
16 // sum_{d=0}^{N-1} (y[d]/e[d])^2 = 1. An algebraic representation for the
17 // hyperellipsoid is (X-K)^T * M * (X-K) = 1, where M is the NxN symmetric
18 // matrix M = sum_{d=0}^{N-1} U[d]*U[d]^T/e[d]^2, where the superscript T
19 // denotes transpose. Observe that U[i]*U[i]^T is a matrix, not a scalar dot
20 // product. The hyperellipsoid is also represented by a quadratic equation
21 // 0 = C + B^T*X + X^T*A*X, where C is a scalar, B is an Nx1 vector, and A is
22 // an NxN symmetric matrix with positive eigenvalues. The coefficients can be
23 // stored from lowest degree to highest degree,
24 // C = k[0]
25 // B = k[1], ..., k[N]
26 // A = k[N+1], ..., k[(N+1)(N+2)/2 - 1]
27 // where the A-coefficients are the upper-triangular elements of A listed in
28 // row-major order. For N = 2, X = (x[0],x[1]) and
29 // 0 = k[0] +
30 // k[1]*x[0] + k[2]*x[1] +
31 // k[3]*x[0]*x[0] + k[4]*x[0]*x[1]
32 // + k[5]*x[1]*x[1]
33 // For N = 3, X = (x[0],x[1],x[2]) and
34 // 0 = k[0] +
35 // k[1]*x[0] + k[2]*x[1] + k[3]*x[2] +
36 // k[4]*x[0]*x[0] + k[5]*x[0]*x[1] + k[6]*x[0]*x[2] +
37 // + k[7]*x[1]*x[1] + k[8]*x[1]*x[2] +
38 // + k[9]*x[2]*x[2]
39 // This equation can be factored to the form (X-K)^T * M * (X-K) = 1, where
40 // K = -A^{-1}*B/2, M = A/(B^T*A^{-1}*B/4-C).
41 
42 namespace gte
43 {
44 
45 template <int N, typename Real>
47 {
48 public:
49 
50  // Construction and destruction. The default constructor sets the center
51  // to Vector<N,Real>::Zero(), the axes to Vector<N,Real>::Unit(d), and all
52  // extents to 1.
54  Hyperellipsoid(Vector<N, Real> const& inCenter,
55  std::array<Vector<N, Real>, N> const inAxis,
56  Vector<N, Real> const& inExtent);
57 
58  // Compute M = sum_{d=0}^{N-1} U[d]*U[d]^T/e[d]^2.
59  void GetM(Matrix<N, N, Real>& M) const;
60 
61  // Compute M^{-1} = sum_{d=0}^{N-1} U[d]*U[d]^T*e[d]^2.
62  void GetMInverse(Matrix<N, N, Real>& MInverse) const;
63 
64  // Construct the coefficients in the quadratic equation that represents
65  // the hyperellipsoid.
66  void ToCoefficients(std::array<Real, (N+1)*(N+2)/2>& coeff) const;
68  Real& C) const;
69 
70  // Construct C, U[i], and e[i] from the equation. The return value is
71  // 'true' if and only if the input coefficients represent a
72  // hyperellipsoid. If the function returns 'false', the hyperellipsoid
73  // data members are undefined.
74  bool FromCoefficients(std::array<Real, (N + 1)*(N + 2) / 2> const& coeff);
76  Vector<N, Real> const& B, Real C);
77 
78  // Public member access.
80  std::array<Vector<N, Real>, N> axis;
82 
83 private:
84  static void Convert(std::array<Real, (N + 1)*(N + 2) / 2> const& coeff,
85  Matrix<N, N, Real>& A, Vector<N, Real>& B, Real& C);
86 
87  static void Convert(Matrix<N, N, Real> const& A, Vector<N, Real> const& B,
88  Real C, std::array<Real, (N + 1)*(N + 2) / 2>& coeff);
89 
90 public:
91  // Comparisons to support sorted containers.
92  bool operator==(Hyperellipsoid const& hyperellipsoid) const;
93  bool operator!=(Hyperellipsoid const& hyperellipsoid) const;
94  bool operator< (Hyperellipsoid const& hyperellipsoid) const;
95  bool operator<=(Hyperellipsoid const& hyperellipsoid) const;
96  bool operator> (Hyperellipsoid const& hyperellipsoid) const;
97  bool operator>=(Hyperellipsoid const& hyperellipsoid) const;
98 };
99 
100 // Template aliases for convenience.
101 template <typename Real>
103 
104 template <typename Real>
106 
107 
108 template <int N, typename Real>
110 {
111  center.MakeZero();
112  for (int d = 0; d < N; ++d)
113  {
114  axis[d].MakeUnit(d);
115  extent[d] = (Real)1;
116  }
117 }
118 
119 template <int N, typename Real>
121  std::array<Vector<N, Real>, N> const inAxis,
122  Vector<N, Real> const& inExtent)
123  :
124  center(inCenter),
125  axis(inAxis),
126  extent(inExtent)
127 {
128 }
129 
130 template <int N, typename Real>
132 {
133  M.MakeZero();
134  for (int d = 0; d < N; ++d)
135  {
136  Vector<N, Real> ratio = axis[d] / extent[d];
137  M += OuterProduct<N, N, Real>(ratio, ratio);
138  }
139 }
140 
141 template <int N, typename Real>
143 {
144  MInverse.MakeZero();
145  for (int d = 0; d < N; ++d)
146  {
147  Vector<N, Real> product = axis[d] * extent[d];
148  MInverse += OuterProduct<N, N, Real>(product, product);
149  }
150 }
151 
152 template <int N, typename Real>
154  std::array<Real, (N + 1)*(N + 2) / 2>& coeff) const
155 {
156  int const numCoefficients = (N + 1)*(N + 2) / 2;
158  Vector<N, Real> B;
159  Real C;
160  ToCoefficients(A, B, C);
161  Convert(A, B, C, coeff);
162 
163  // Arrange for one of the coefficients of the quadratic terms to be 1.
164  int quadIndex = numCoefficients - 1;
165  int maxIndex = quadIndex;
166  Real maxValue = std::abs(coeff[quadIndex]);
167  for (int d = 2; d < N; ++d)
168  {
169  quadIndex -= d;
170  Real absValue = std::abs(coeff[quadIndex]);
171  if (absValue > maxValue)
172  {
173  maxIndex = quadIndex;
174  maxValue = absValue;
175  }
176  }
177 
178  Real invMaxValue = ((Real)1) / maxValue;
179  for (int i = 0; i < numCoefficients; ++i)
180  {
181  if (i != maxIndex)
182  {
183  coeff[i] *= invMaxValue;
184  }
185  else
186  {
187  coeff[i] = (Real)1;
188  }
189  }
190 }
191 
192 template <int N, typename Real>
194  Vector<N, Real>& B, Real& C) const
195 {
196  GetM(A);
197  Vector<N, Real> product = A * center;
198  B = ((Real)-2) * product;
199  C = Dot(center, product) - (Real)1;
200 }
201 
202 template <int N, typename Real>
204  std::array<Real, (N + 1)*(N + 2) / 2> const& coeff)
205 {
207  Vector<N, Real> B;
208  Real C;
209  Convert(coeff, A, B, C);
210  return FromCoefficients(A, B, C);
211 }
212 
213 template <int N, typename Real>
215  Vector<N, Real> const& B, Real C)
216 {
217  // Compute the center K = -A^{-1}*B/2.
218  bool invertible;
219  Matrix<N, N, Real> invA = Inverse(A, &invertible);
220  if (!invertible)
221  {
222  return false;
223  }
224 
225  center = ((Real)-0.5) * (invA * B);
226 
227  // Compute B^T*A^{-1}*B/4 - C = K^T*A*K - C = -K^T*B/2 - C.
228  Real rightSide = -((Real)0.5) * Dot(center, B) - C;
229  if (rightSide == (Real)0)
230  {
231  return false;
232  }
233 
234  // Compute M = A/(K^T*A*K - C).
235  Real invRightSide = ((Real)1) / rightSide;
236  Matrix<N, N, Real> M = invRightSide * A;
237 
238  // Factor into M = R*D*R^T. M is symmetric, so it does not matter whether
239  // the matrix is stored in row-major or column-major order; they are
240  // equivalent. The output R, however, is in row-major order.
241  SymmetricEigensolver<Real> es(N, 32);
242  Matrix<N, N, Real> rotation;
243  std::array<Real, N> diagonal;
244  es.Solve(&M[0], +1); // diagonal[i] are nondecreasing
245  es.GetEigenvalues(&diagonal[0]);
246  es.GetEigenvectors(&rotation[0]);
247  if (!es.IsRotation())
248  {
249  auto negLast = -rotation.GetCol(N - 1);
250  rotation.SetCol(N - 1, negLast);
251  }
252 
253  for (int d = 0; d < N; ++d)
254  {
255  if (diagonal[d] <= (Real)0)
256  {
257  return false;
258  }
259 
260  extent[d] = ((Real)1) / sqrt(diagonal[d]);
261  axis[d] = rotation.GetCol(d);
262  }
263 
264  return true;
265 }
266 
267 template <int N, typename Real>
269  std::array<Real, (N + 1)*(N + 2) / 2> const& coeff, Matrix<N, N, Real>& A,
270  Vector<N, Real>& B, Real& C)
271 {
272  int i = 0;
273  C = coeff[i++];
274 
275  for (int j = 0; j < N; ++j)
276  {
277  B[j] = coeff[i++];
278  }
279 
280  for (int r = 0; r < N; ++r)
281  {
282  for (int c = 0; c < r; ++c)
283  {
284  A(r, c) = A(c, r);
285  }
286 
287  A(r, r) = coeff[i++];
288 
289  for (int c = r + 1; c < N; ++c)
290  {
291  A(r, c) = coeff[i++] * (Real)0.5;
292  }
293  }
294 }
295 
296 template <int N, typename Real>
298  Vector<N, Real> const& B, Real C,
299  std::array<Real, (N + 1)*(N + 2) / 2>& coeff)
300 {
301  int i = 0;
302  coeff[i++] = C;
303 
304  for (int j = 0; j < N; ++j)
305  {
306  coeff[i++] = B[j];
307  }
308 
309  for (int r = 0; r < N; ++r)
310  {
311  coeff[i++] = A(r, r);
312  for (int c = r + 1; c < N; ++c)
313  {
314  coeff[i++] = A(r, c) * (Real)2;
315  }
316  }
317 }
318 
319 template <int N, typename Real>
321  Hyperellipsoid const& hyperellipsoid) const
322 {
323  return center == hyperellipsoid.center && axis == hyperellipsoid.axis
324  && extent == hyperellipsoid.extent;
325 }
326 
327 template <int N, typename Real>
329  Hyperellipsoid const& hyperellipsoid) const
330 {
331  return !operator==(hyperellipsoid);
332 }
333 
334 template <int N, typename Real>
336  Hyperellipsoid const& hyperellipsoid) const
337 {
338  if (center < hyperellipsoid.center)
339  {
340  return true;
341  }
342 
343  if (center > hyperellipsoid.center)
344  {
345  return false;
346  }
347 
348  if (axis < hyperellipsoid.axis)
349  {
350  return true;
351  }
352 
353  if (axis > hyperellipsoid.axis)
354  {
355  return false;
356  }
357 
358  return extent < hyperellipsoid.extent;
359 }
360 
361 template <int N, typename Real>
363  Hyperellipsoid const& hyperellipsoid) const
364 {
365  return operator<(hyperellipsoid) || operator==(hyperellipsoid);
366 }
367 
368 template <int N, typename Real>
370  Hyperellipsoid const& hyperellipsoid) const
371 {
372  return !operator<=(hyperellipsoid);
373 }
374 
375 template <int N, typename Real>
377  Hyperellipsoid const& hyperellipsoid) const
378 {
379  return !operator<(hyperellipsoid);
380 }
381 
382 
383 }
void MakeZero()
Definition: GteVector.h:279
static void Convert(std::array< Real,(N+1)*(N+2)/2 > const &coeff, Matrix< N, N, Real > &A, Vector< N, Real > &B, Real &C)
Vector< NumRows, Real > GetCol(int c) const
Definition: GteMatrix.h:383
void GetM(Matrix< N, N, Real > &M) const
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
void GetMInverse(Matrix< N, N, Real > &MInverse) const
Vector< N, Real > extent
void GetEigenvalues(Real *eigenvalues) const
bool operator!=(Hyperellipsoid const &hyperellipsoid) const
void GetEigenvectors(Real *eigenvectors) const
const GLubyte * c
Definition: glext.h:11671
unsigned int Solve(Real const *input, int sortType)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
bool operator<(Hyperellipsoid const &hyperellipsoid) const
void ToCoefficients(std::array< Real,(N+1)*(N+2)/2 > &coeff) const
void SetCol(int c, Vector< NumRows, Real > const &vec)
Definition: GteMatrix.h:362
bool FromCoefficients(std::array< Real,(N+1)*(N+2)/2 > const &coeff)
bool operator==(Hyperellipsoid const &hyperellipsoid) const
GLenum array
Definition: glext.h:6669
GLboolean r
Definition: glcorearb.h:1217
bool operator>=(Hyperellipsoid const &hyperellipsoid) const
void MakeZero()
Definition: GteMatrix.h:442
bool operator<=(Hyperellipsoid const &hyperellipsoid) const
Quaternion< Real > Inverse(Quaternion< Real > const &d)
bool operator>(Hyperellipsoid const &hyperellipsoid) const
Vector< N, Real > center
std::array< Vector< N, Real >, N > axis


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00