GteApprQuadratic3.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>
11 #include <Mathematics/GteVector3.h>
14 
15 namespace gte
16 {
17 
18 // The quadratic fit is
19 //
20 // 0 = C[0] + C[1]*X + C[2]*Y + C[3]*Z + C[4]*X^2 + C[5]*Y^2
21 // + C[6]*Z^2 + C[7]*X*Y + C[8]*X*Z + C[9]*Y*Z
22 //
23 // subject to Length(C) = 1. Minimize E(C) = C^t M C with Length(C) = 1
24 // and M = (sum_i V_i)(sum_i V_i)^t where
25 //
26 // V = (1, X, Y, Z, X^2, Y^2, Z^2, X*Y, X*Z, Y*Z)
27 //
28 // The minimum value is the smallest eigenvalue of M and C is a corresponding
29 // unit length eigenvector.
30 //
31 // Input:
32 // n = number of points to fit
33 // p[0..n-1] = array of points to fit
34 //
35 // Output:
36 // c[0..9] = coefficients of quadratic fit (the eigenvector)
37 // return value of function is nonnegative and a measure of the fit
38 // (the minimum eigenvalue; 0 = exact fit, positive otherwise)
39 
40 // Canonical forms. The quadratic equation can be factored into
41 // P^T A P + B^T P + K = 0 where P = (X,Y,Z), K = C[0], B = (C[1],C[2],C[3]),
42 // and A is a 3x3 symmetric matrix with A00 = C[4], A11 = C[5], A22 = C[6],
43 // A01 = C[7]/2, A02 = C[8]/2, and A12 = C[9]/2. Matrix A = R^T D R where
44 // R is orthogonal and D is diagonal (using an eigendecomposition). Define
45 // V = R P = (v0,v1,v2), E = R B = (e0,e1,e2), D = diag(d0,d1,d2), and f = K
46 // to obtain
47 //
48 // d0 v0^2 + d1 v1^2 + d2 v^2 + e0 v0 + e1 v1 + e2 v2 + f = 0
49 //
50 // The characterization depends on the signs of the d_i.
51 
52 template <typename Real>
54 {
55 public:
56  Real operator()(int numPoints, Vector3<Real> const* points,
57  Real coefficidents[10]);
58 };
59 
60 
61 // If you think your points are nearly spherical, use this. Sphere is of form
62 // C'[0]+C'[1]*X+C'[2]*Y+C'[3]*Z+C'[4]*(X^2+Y^2+Z^2) where Length(C') = 1.
63 // Function returns C = (C'[0]/C'[4],C'[1]/C'[4],C'[2]/C'[4],C'[3]/C'[4]), so
64 // fitted sphere is C[0]+C[1]*X+C[2]*Y+C[3]*Z+X^2+Y^2+Z^2. Center is
65 // (xc,yc,zc) = -0.5*(C[1],C[2],C[3]) and radius is rad =
66 // sqrt(xc*xc+yc*yc+zc*zc-C[0]).
67 template <typename Real>
69 {
70 public:
71  Real operator()(int numPoints, Vector3<Real> const* points,
72  Sphere3<Real>& sphere);
73 };
74 
75 
76 template <typename Real>
78  Vector3<Real> const* points, Real coefficients[10])
79 {
81  for (int i = 0; i < numPoints; ++i)
82  {
83  Real x = points[i][0];
84  Real y = points[i][1];
85  Real z = points[i][2];
86  Real x2 = x*x;
87  Real y2 = y*y;
88  Real z2 = z*z;
89  Real xy = x*y;
90  Real xz = x*z;
91  Real yz = y*z;
92  Real x3 = x*x2;
93  Real xy2 = x*y2;
94  Real xz2 = x*z2;
95  Real x2y = x*xy;
96  Real x2z = x*xz;
97  Real xyz = x*y*z;
98  Real y3 = y*y2;
99  Real yz2 = y*z2;
100  Real y2z = y*yz;
101  Real z3 = z*z2;
102  Real x4 = x*x3;
103  Real x2y2 = x*xy2;
104  Real x2z2 = x*xz2;
105  Real x3y = x*x2y;
106  Real x3z = x*x2z;
107  Real x2yz = x*xyz;
108  Real y4 = y*y3;
109  Real y2z2 = y*yz2;
110  Real xy3 = x*y3;
111  Real xy2z = x*y2z;
112  Real y3z = y*y2z;
113  Real z4 = z*z3;
114  Real xyz2 = x*yz2;
115  Real xz3 = x*z3;
116  Real yz3 = y*z3;
117 
118  A(0, 1) += x;
119  A(0, 2) += y;
120  A(0, 3) += z;
121  A(0, 4) += x2;
122  A(0, 5) += y2;
123  A(0, 6) += z2;
124  A(0, 7) += xy;
125  A(0, 8) += xz;
126  A(0, 9) += yz;
127  A(1, 4) += x3;
128  A(1, 5) += xy2;
129  A(1, 6) += xz2;
130  A(1, 7) += x2y;
131  A(1, 8) += x2z;
132  A(1, 9) += xyz;
133  A(2, 5) += y3;
134  A(2, 6) += yz2;
135  A(2, 9) += y2z;
136  A(3, 6) += z3;
137  A(4, 4) += x4;
138  A(4, 5) += x2y2;
139  A(4, 6) += x2z2;
140  A(4, 7) += x3y;
141  A(4, 8) += x3z;
142  A(4, 9) += x2yz;
143  A(5, 5) += y4;
144  A(5, 6) += y2z2;
145  A(5, 7) += xy3;
146  A(5, 8) += xy2z;
147  A(5, 9) += y3z;
148  A(6, 6) += z4;
149  A(6, 7) += xyz2;
150  A(6, 8) += xz3;
151  A(6, 9) += yz3;
152  A(9, 9) += y2z2;
153  }
154 
155  A(0, 0) = static_cast<Real>(numPoints);
156  A(1, 1) = A(0, 4);
157  A(1, 2) = A(0, 7);
158  A(1, 3) = A(0, 8);
159  A(2, 2) = A(0, 5);
160  A(2, 3) = A(0, 9);
161  A(2, 4) = A(1, 7);
162  A(2, 7) = A(1, 5);
163  A(2, 8) = A(1, 9);
164  A(3, 3) = A(0, 6);
165  A(3, 4) = A(1, 8);
166  A(3, 5) = A(2, 9);
167  A(3, 7) = A(1, 9);
168  A(3, 8) = A(1, 6);
169  A(3, 9) = A(2, 6);
170  A(7, 7) = A(4, 5);
171  A(7, 8) = A(4, 9);
172  A(7, 9) = A(5, 8);
173  A(8, 8) = A(4, 6);
174  A(8, 9) = A(6, 7);
175  A(9, 9) = A(5, 6);
176 
177  for (int row = 0; row < 10; ++row)
178  {
179  for (int col = 0; col < row; ++col)
180  {
181  A(row, col) = A(col, row);
182  }
183  }
184 
185  Real invNumPoints = ((Real)1) / static_cast<Real>(numPoints);
186  for (int row = 0; row < 10; ++row)
187  {
188  for (int col = 0; col < 10; ++col)
189  {
190  A(row, col) *= invNumPoints;
191  }
192  }
193 
194  SymmetricEigensolver<Real> es(10, 1024);
195  es.Solve(&A[0], +1);
196  es.GetEigenvector(0, &coefficients[0]);
197 
198  // For an exact fit, numeric round-off errors might make the minimum
199  // eigenvalue just slightly negative. Return the absolute value since
200  // the application might rely on the return value being nonnegative.
201  return std::abs(es.GetEigenvalue(0));
202 }
203 
204 template <typename Real>
206  Vector3<Real> const* points, Sphere3<Real>& sphere)
207 {
209  for (int i = 0; i < numPoints; ++i)
210  {
211  Real x = points[i][0];
212  Real y = points[i][1];
213  Real z = points[i][2];
214  Real x2 = x*x;
215  Real y2 = y*y;
216  Real z2 = z*z;
217  Real xy = x*y;
218  Real xz = x*z;
219  Real yz = y*z;
220  Real r2 = x2 + y2 + z2;
221  Real xr2 = x*r2;
222  Real yr2 = y*r2;
223  Real zr2 = z*r2;
224  Real r4 = r2*r2;
225 
226  A(0, 1) += x;
227  A(0, 2) += y;
228  A(0, 3) += z;
229  A(0, 4) += r2;
230  A(1, 1) += x2;
231  A(1, 2) += xy;
232  A(1, 3) += xz;
233  A(1, 4) += xr2;
234  A(2, 2) += y2;
235  A(2, 3) += yz;
236  A(2, 4) += yr2;
237  A(3, 3) += z2;
238  A(3, 4) += zr2;
239  A(4, 4) += r4;
240  }
241 
242  A(0, 0) = static_cast<Real>(numPoints);
243 
244  for (int row = 0; row < 5; ++row)
245  {
246  for (int col = 0; col < row; ++col)
247  {
248  A(row, col) = A(col, row);
249  }
250  }
251 
252  Real invNumPoints = ((Real)1) / static_cast<Real>(numPoints);
253  for (int row = 0; row < 5; ++row)
254  {
255  for (int col = 0; col < 5; ++col)
256  {
257  A(row, col) *= invNumPoints;
258  }
259  }
260 
261  SymmetricEigensolver<Real> es(5, 1024);
262  es.Solve(&A[0], +1);
263  Vector<5, Real> evector;
264  es.GetEigenvector(0, &evector[0]);
265 
266  Real inv = ((Real)1) / evector[4]; // TODO: Guard against zero divide?
267  Real coefficients[4];
268  for (int row = 0; row < 4; ++row)
269  {
270  coefficients[row] = inv * evector[row];
271  }
272 
273  sphere.center[0] = ((Real)-0.5) * coefficients[1];
274  sphere.center[1] = ((Real)-0.5) * coefficients[2];
275  sphere.center[2] = ((Real)-0.5) * coefficients[3];
276  sphere.radius = sqrt(std::abs(Dot(sphere.center, sphere.center) -
277  coefficients[0]));
278 
279  // For an exact fit, numeric round-off errors might make the minimum
280  // eigenvalue just slightly negative. Return the absolute value since
281  // the application might rely on the return value being nonnegative.
282  return std::abs(es.GetEigenvalue(0));
283 }
284 
285 
286 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
void GetEigenvector(int c, Real *eigenvector) const
GLfixed GLfixed GLfixed y2
Definition: glext.h:4952
GLint GLenum GLint x
Definition: glcorearb.h:404
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
GLenum GLenum GLsizei void * row
Definition: glext.h:2725
unsigned int Solve(Real const *input, int sortType)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:843
GLfixed GLfixed x2
Definition: glext.h:4952
Real operator()(int numPoints, Vector3< Real > const *points, Sphere3< Real > &sphere)
Vector< N, Real > center
GLint y
Definition: glcorearb.h:98
Real operator()(int numPoints, Vector3< Real > const *points, Real coefficidents[10])


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