bestfit.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <math.h>
6 
7 // Geometric Tools, Inc.
8 // http://www.geometrictools.com
9 // Copyright (c) 1998-2006. All Rights Reserved
10 //
11 // The Wild Magic Library (WM3) source code is supplied under the terms of
12 // the license agreement
13 // http://www.geometrictools.com/License/WildMagic3License.pdf
14 // and may not be copied or disclosed except in accordance with the terms
15 // of that agreement.
16 
73 #include "bestfit.h"
74 
76 {
77 
78 class Vec3
79 {
80 public:
81  Vec3(void) { };
82  Vec3(double _x,double _y,double _z) { x = _x; y = _y; z = _z; };
83 
84 
85  double dot(const Vec3 &v)
86  {
87  return x*v.x + y*v.y + z*v.z; // the dot product
88  }
89 
90  double x;
91  double y;
92  double z;
93 };
94 
95 
96 class Eigen
97 {
98 public:
99 
100 
102  {
103  Tridiagonal(); //diagonalize the matrix.
104  QLAlgorithm(); //
105  DecreasingSort();
107  }
108 
109  void Tridiagonal(void)
110  {
111  double fM00 = mElement[0][0];
112  double fM01 = mElement[0][1];
113  double fM02 = mElement[0][2];
114  double fM11 = mElement[1][1];
115  double fM12 = mElement[1][2];
116  double fM22 = mElement[2][2];
117 
118  m_afDiag[0] = fM00;
119  m_afSubd[2] = 0;
120  if (fM02 != (double)0.0)
121  {
122  double fLength = sqrt(fM01*fM01+fM02*fM02);
123  double fInvLength = ((double)1.0)/fLength;
124  fM01 *= fInvLength;
125  fM02 *= fInvLength;
126  double fQ = ((double)2.0)*fM01*fM12+fM02*(fM22-fM11);
127  m_afDiag[1] = fM11+fM02*fQ;
128  m_afDiag[2] = fM22-fM02*fQ;
129  m_afSubd[0] = fLength;
130  m_afSubd[1] = fM12-fM01*fQ;
131  mElement[0][0] = (double)1.0;
132  mElement[0][1] = (double)0.0;
133  mElement[0][2] = (double)0.0;
134  mElement[1][0] = (double)0.0;
135  mElement[1][1] = fM01;
136  mElement[1][2] = fM02;
137  mElement[2][0] = (double)0.0;
138  mElement[2][1] = fM02;
139  mElement[2][2] = -fM01;
140  m_bIsRotation = false;
141  }
142  else
143  {
144  m_afDiag[1] = fM11;
145  m_afDiag[2] = fM22;
146  m_afSubd[0] = fM01;
147  m_afSubd[1] = fM12;
148  mElement[0][0] = (double)1.0;
149  mElement[0][1] = (double)0.0;
150  mElement[0][2] = (double)0.0;
151  mElement[1][0] = (double)0.0;
152  mElement[1][1] = (double)1.0;
153  mElement[1][2] = (double)0.0;
154  mElement[2][0] = (double)0.0;
155  mElement[2][1] = (double)0.0;
156  mElement[2][2] = (double)1.0;
157  m_bIsRotation = true;
158  }
159  }
160 
161  bool QLAlgorithm(void)
162  {
163  const int iMaxIter = 32;
164 
165  for (int i0 = 0; i0 <3; i0++)
166  {
167  int i1;
168  for (i1 = 0; i1 < iMaxIter; i1++)
169  {
170  int i2;
171  for (i2 = i0; i2 <= (3-2); i2++)
172  {
173  double fTmp = fabs(m_afDiag[i2]) + fabs(m_afDiag[i2+1]);
174  if ( fabs(m_afSubd[i2]) + fTmp == fTmp )
175  break;
176  }
177  if (i2 == i0)
178  {
179  break;
180  }
181 
182  double fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((double)2.0) * m_afSubd[i0]);
183  double fR = sqrt(fG*fG+(double)1.0);
184  if (fG < (double)0.0)
185  {
186  fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
187  }
188  else
189  {
190  fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
191  }
192  double fSin = (double)1.0, fCos = (double)1.0, fP = (double)0.0;
193  for (int i3 = i2-1; i3 >= i0; i3--)
194  {
195  double fF = fSin*m_afSubd[i3];
196  double fB = fCos*m_afSubd[i3];
197  if (fabs(fF) >= fabs(fG))
198  {
199  fCos = fG/fF;
200  fR = sqrt(fCos*fCos+(double)1.0);
201  m_afSubd[i3+1] = fF*fR;
202  fSin = ((double)1.0)/fR;
203  fCos *= fSin;
204  }
205  else
206  {
207  fSin = fF/fG;
208  fR = sqrt(fSin*fSin+(double)1.0);
209  m_afSubd[i3+1] = fG*fR;
210  fCos = ((double)1.0)/fR;
211  fSin *= fCos;
212  }
213  fG = m_afDiag[i3+1]-fP;
214  fR = (m_afDiag[i3]-fG)*fSin+((double)2.0)*fB*fCos;
215  fP = fSin*fR;
216  m_afDiag[i3+1] = fG+fP;
217  fG = fCos*fR-fB;
218  for (int i4 = 0; i4 < 3; i4++)
219  {
220  fF = mElement[i4][i3+1];
221  mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF;
222  mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF;
223  }
224  }
225  m_afDiag[i0] -= fP;
226  m_afSubd[i0] = fG;
227  m_afSubd[i2] = (double)0.0;
228  }
229  if (i1 == iMaxIter)
230  {
231  return false;
232  }
233  }
234  return true;
235  }
236 
237  void DecreasingSort(void)
238  {
239  //sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
240  for (int i0 = 0, i1; i0 <= 3-2; i0++)
241  {
242  // locate maximum eigenvalue
243  i1 = i0;
244  double fMax = m_afDiag[i1];
245  int i2;
246  for (i2 = i0+1; i2 < 3; i2++)
247  {
248  if (m_afDiag[i2] > fMax)
249  {
250  i1 = i2;
251  fMax = m_afDiag[i1];
252  }
253  }
254 
255  if (i1 != i0)
256  {
257  // swap eigenvalues
258  m_afDiag[i1] = m_afDiag[i0];
259  m_afDiag[i0] = fMax;
260  // swap eigenvectors
261  for (i2 = 0; i2 < 3; i2++)
262  {
263  double fTmp = mElement[i2][i0];
264  mElement[i2][i0] = mElement[i2][i1];
265  mElement[i2][i1] = fTmp;
267  }
268  }
269  }
270  }
271 
272 
273  void GuaranteeRotation(void)
274  {
275  if (!m_bIsRotation)
276  {
277  // change sign on the first column
278  for (int iRow = 0; iRow <3; iRow++)
279  {
280  mElement[iRow][0] = -mElement[iRow][0];
281  }
282  }
283  }
284 
285  double mElement[3][3];
286  double m_afDiag[3];
287  double m_afSubd[3];
289 };
290 
291 
292 bool getBestFitPlane(unsigned int vcount,
293  const double *points,
294  unsigned int vstride,
295  const double *weights,
296  unsigned int wstride,
297  double *plane)
298 {
299  bool ret = false;
300 
301  Vec3 kOrigin(0,0,0);
302 
303  double wtotal = 0;
304 
305  if ( 1 )
306  {
307  const char *source = (const char *) points;
308  const char *wsource = (const char *) weights;
309 
310  for (unsigned int i=0; i<vcount; i++)
311  {
312 
313  const double *p = (const double *) source;
314 
315  double w = 1;
316 
317  if ( wsource )
318  {
319  const double *ws = (const double *) wsource;
320  w = *ws; //
321  wsource+=wstride;
322  }
323 
324  kOrigin.x+=p[0]*w;
325  kOrigin.y+=p[1]*w;
326  kOrigin.z+=p[2]*w;
327 
328  wtotal+=w;
329 
330  source+=vstride;
331  }
332  }
333 
334  double recip = 1.0f / wtotal; // reciprocol of total weighting
335 
336  kOrigin.x*=recip;
337  kOrigin.y*=recip;
338  kOrigin.z*=recip;
339 
340 
341  double fSumXX=0;
342  double fSumXY=0;
343  double fSumXZ=0;
344 
345  double fSumYY=0;
346  double fSumYZ=0;
347  double fSumZZ=0;
348 
349 
350  if ( 1 )
351  {
352  const char *source = (const char *) points;
353  const char *wsource = (const char *) weights;
354 
355  for (unsigned int i=0; i<vcount; i++)
356  {
357 
358  const double *p = (const double *) source;
359 
360  double w = 1;
361 
362  if ( wsource )
363  {
364  const double *ws = (const double *) wsource;
365  w = *ws; //
366  wsource+=wstride;
367  }
368 
369  Vec3 kDiff;
370 
371  kDiff.x = w*(p[0] - kOrigin.x); // apply vertex weighting!
372  kDiff.y = w*(p[1] - kOrigin.y);
373  kDiff.z = w*(p[2] - kOrigin.z);
374 
375  fSumXX+= kDiff.x * kDiff.x; // sume of the squares of the differences.
376  fSumXY+= kDiff.x * kDiff.y; // sume of the squares of the differences.
377  fSumXZ+= kDiff.x * kDiff.z; // sume of the squares of the differences.
378 
379  fSumYY+= kDiff.y * kDiff.y;
380  fSumYZ+= kDiff.y * kDiff.z;
381  fSumZZ+= kDiff.z * kDiff.z;
382 
383 
384  source+=vstride;
385  }
386  }
387 
388  fSumXX *= recip;
389  fSumXY *= recip;
390  fSumXZ *= recip;
391  fSumYY *= recip;
392  fSumYZ *= recip;
393  fSumZZ *= recip;
394 
395  // setup the eigensolver
396  Eigen kES;
397 
398  kES.mElement[0][0] = fSumXX;
399  kES.mElement[0][1] = fSumXY;
400  kES.mElement[0][2] = fSumXZ;
401 
402  kES.mElement[1][0] = fSumXY;
403  kES.mElement[1][1] = fSumYY;
404  kES.mElement[1][2] = fSumYZ;
405 
406  kES.mElement[2][0] = fSumXZ;
407  kES.mElement[2][1] = fSumYZ;
408  kES.mElement[2][2] = fSumZZ;
409 
410  // compute eigenstuff, smallest eigenvalue is in last position
411  kES.DecrSortEigenStuff();
412 
413  Vec3 kNormal;
414 
415  kNormal.x = kES.mElement[0][2];
416  kNormal.y = kES.mElement[1][2];
417  kNormal.z = kES.mElement[2][2];
418 
419  // the minimum energy
420  plane[0] = kNormal.x;
421  plane[1] = kNormal.y;
422  plane[2] = kNormal.z;
423 
424  plane[3] = 0 - kNormal.dot(kOrigin);
425 
426  return ret;
427 }
428 
429 
430 
431 double getBoundingRegion(unsigned int vcount,const double *points,unsigned int pstride,double *bmin,double *bmax) // returns the diagonal distance
432 {
433 
434  const unsigned char *source = (const unsigned char *) points;
435 
436  bmin[0] = points[0];
437  bmin[1] = points[1];
438  bmin[2] = points[2];
439 
440  bmax[0] = points[0];
441  bmax[1] = points[1];
442  bmax[2] = points[2];
443 
444 
445  for (unsigned int i=1; i<vcount; i++)
446  {
447  source+=pstride;
448  const double *p = (const double *) source;
449 
450  if ( p[0] < bmin[0] ) bmin[0] = p[0];
451  if ( p[1] < bmin[1] ) bmin[1] = p[1];
452  if ( p[2] < bmin[2] ) bmin[2] = p[2];
453 
454  if ( p[0] > bmax[0] ) bmax[0] = p[0];
455  if ( p[1] > bmax[1] ) bmax[1] = p[1];
456  if ( p[2] > bmax[2] ) bmax[2] = p[2];
457 
458  }
459 
460  double dx = bmax[0] - bmin[0];
461  double dy = bmax[1] - bmin[1];
462  double dz = bmax[2] - bmin[2];
463 
464  return sqrt( dx*dx + dy*dy + dz*dz );
465 
466 }
467 
468 
469 bool overlapAABB(const double *bmin1,const double *bmax1,const double *bmin2,const double *bmax2) // return true if the two AABB's overlap.
470 {
471  if ( bmax2[0] < bmin1[0] ) return false; // if the maximum is less than our minimum on any axis
472  if ( bmax2[1] < bmin1[1] ) return false;
473  if ( bmax2[2] < bmin1[2] ) return false;
474 
475  if ( bmin2[0] > bmax1[0] ) return false; // if the minimum is greater than our maximum on any axis
476  if ( bmin2[1] > bmax1[1] ) return false; // if the minimum is greater than our maximum on any axis
477  if ( bmin2[2] > bmax1[2] ) return false; // if the minimum is greater than our maximum on any axis
478 
479 
480  return true; // the extents overlap
481 }
482 
483 }; // end of namespace
ConvexDecomposition::Eigen::m_afSubd
double m_afSubd[3]
Definition: bestfit.cpp:287
ConvexDecomposition::Eigen::m_afDiag
double m_afDiag[3]
Definition: bestfit.cpp:286
ConvexDecomposition::Eigen::GuaranteeRotation
void GuaranteeRotation(void)
Definition: bestfit.cpp:273
ConvexDecomposition::Vec3::z
double z
Definition: bestfit.cpp:92
ConvexDecomposition::Eigen::Tridiagonal
void Tridiagonal(void)
Definition: bestfit.cpp:109
ConvexDecomposition::Vec3::y
double y
Definition: bestfit.cpp:91
ConvexDecomposition::Eigen::DecreasingSort
void DecreasingSort(void)
Definition: bestfit.cpp:237
ConvexDecomposition::Vec3::x
double x
Definition: bestfit.cpp:90
ConvexDecomposition
Definition: bestfit.cpp:75
ConvexDecomposition::getBoundingRegion
double getBoundingRegion(unsigned int vcount, const double *points, unsigned int pstride, double *bmin, double *bmax)
Definition: bestfit.cpp:431
ConvexDecomposition::Vec3::Vec3
Vec3(double _x, double _y, double _z)
Definition: bestfit.cpp:82
ConvexDecomposition::Eigen::mElement
double mElement[3][3]
Definition: bestfit.cpp:285
ConvexDecomposition::Vec3
Definition: bestfit.cpp:78
ConvexDecomposition::Eigen::QLAlgorithm
bool QLAlgorithm(void)
Definition: bestfit.cpp:161
ConvexDecomposition::Vec3::dot
double dot(const Vec3 &v)
Definition: bestfit.cpp:85
ConvexDecomposition::Eigen::m_bIsRotation
bool m_bIsRotation
Definition: bestfit.cpp:288
bestfit.h
ConvexDecomposition::Vec3::Vec3
Vec3(void)
Definition: bestfit.cpp:81
ConvexDecomposition::plane
Definition: planetri.cpp:182
ConvexDecomposition::overlapAABB
bool overlapAABB(const double *bmin1, const double *bmax1, const double *bmin2, const double *bmax2)
Definition: bestfit.cpp:469
ConvexDecomposition::Eigen
Definition: bestfit.cpp:96
ConvexDecomposition::Eigen::DecrSortEigenStuff
void DecrSortEigenStuff(void)
Definition: bestfit.cpp:101
ConvexDecomposition::getBestFitPlane
bool getBestFitPlane(unsigned int vcount, const double *points, unsigned int vstride, const double *weights, unsigned int wstride, double *plane)
Definition: bestfit.cpp:292


convex_decomposition
Author(s): John W. Ratcliff
autogenerated on Wed Mar 2 2022 00:04:59