Go to the documentation of this file.00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <assert.h>
00005 #include <math.h>
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00073 #include "bestfit.h"
00074
00075 namespace DoublePrecision
00076 {
00077
00078 class Vec3
00079 {
00080 public:
00081 Vec3(void) { };
00082 Vec3(double _x,double _y,double _z) { x = _x; y = _y; z = _z; };
00083
00084
00085 double dot(const Vec3 &v)
00086 {
00087 return x*v.x + y*v.y + z*v.z;
00088 }
00089
00090 double x;
00091 double y;
00092 double z;
00093 };
00094
00095
00096 class Eigen
00097 {
00098 public:
00099
00100
00101 void DecrSortEigenStuff(void)
00102 {
00103 Tridiagonal();
00104 QLAlgorithm();
00105 DecreasingSort();
00106 GuaranteeRotation();
00107 }
00108
00109 void Tridiagonal(void)
00110 {
00111 double fM00 = mElement[0][0];
00112 double fM01 = mElement[0][1];
00113 double fM02 = mElement[0][2];
00114 double fM11 = mElement[1][1];
00115 double fM12 = mElement[1][2];
00116 double fM22 = mElement[2][2];
00117
00118 m_afDiag[0] = fM00;
00119 m_afSubd[2] = 0;
00120 if (fM02 != (double)0.0)
00121 {
00122 double fLength = sqrt(fM01*fM01+fM02*fM02);
00123 double fInvLength = ((double)1.0)/fLength;
00124 fM01 *= fInvLength;
00125 fM02 *= fInvLength;
00126 double fQ = ((double)2.0)*fM01*fM12+fM02*(fM22-fM11);
00127 m_afDiag[1] = fM11+fM02*fQ;
00128 m_afDiag[2] = fM22-fM02*fQ;
00129 m_afSubd[0] = fLength;
00130 m_afSubd[1] = fM12-fM01*fQ;
00131 mElement[0][0] = (double)1.0;
00132 mElement[0][1] = (double)0.0;
00133 mElement[0][2] = (double)0.0;
00134 mElement[1][0] = (double)0.0;
00135 mElement[1][1] = fM01;
00136 mElement[1][2] = fM02;
00137 mElement[2][0] = (double)0.0;
00138 mElement[2][1] = fM02;
00139 mElement[2][2] = -fM01;
00140 m_bIsRotation = false;
00141 }
00142 else
00143 {
00144 m_afDiag[1] = fM11;
00145 m_afDiag[2] = fM22;
00146 m_afSubd[0] = fM01;
00147 m_afSubd[1] = fM12;
00148 mElement[0][0] = (double)1.0;
00149 mElement[0][1] = (double)0.0;
00150 mElement[0][2] = (double)0.0;
00151 mElement[1][0] = (double)0.0;
00152 mElement[1][1] = (double)1.0;
00153 mElement[1][2] = (double)0.0;
00154 mElement[2][0] = (double)0.0;
00155 mElement[2][1] = (double)0.0;
00156 mElement[2][2] = (double)1.0;
00157 m_bIsRotation = true;
00158 }
00159 }
00160
00161 bool QLAlgorithm(void)
00162 {
00163 const int iMaxIter = 32;
00164
00165 for (int i0 = 0; i0 <3; i0++)
00166 {
00167 int i1;
00168 for (i1 = 0; i1 < iMaxIter; i1++)
00169 {
00170 int i2;
00171 for (i2 = i0; i2 <= (3-2); i2++)
00172 {
00173 double fTmp = fabs(m_afDiag[i2]) + fabs(m_afDiag[i2+1]);
00174 if ( fabs(m_afSubd[i2]) + fTmp == fTmp )
00175 break;
00176 }
00177 if (i2 == i0)
00178 {
00179 break;
00180 }
00181
00182 double fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((double)2.0) * m_afSubd[i0]);
00183 double fR = sqrt(fG*fG+(double)1.0);
00184 if (fG < (double)0.0)
00185 {
00186 fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
00187 }
00188 else
00189 {
00190 fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
00191 }
00192 double fSin = (double)1.0, fCos = (double)1.0, fP = (double)0.0;
00193 for (int i3 = i2-1; i3 >= i0; i3--)
00194 {
00195 double fF = fSin*m_afSubd[i3];
00196 double fB = fCos*m_afSubd[i3];
00197 if (fabs(fF) >= fabs(fG))
00198 {
00199 fCos = fG/fF;
00200 fR = sqrt(fCos*fCos+(double)1.0);
00201 m_afSubd[i3+1] = fF*fR;
00202 fSin = ((double)1.0)/fR;
00203 fCos *= fSin;
00204 }
00205 else
00206 {
00207 fSin = fF/fG;
00208 fR = sqrt(fSin*fSin+(double)1.0);
00209 m_afSubd[i3+1] = fG*fR;
00210 fCos = ((double)1.0)/fR;
00211 fSin *= fCos;
00212 }
00213 fG = m_afDiag[i3+1]-fP;
00214 fR = (m_afDiag[i3]-fG)*fSin+((double)2.0)*fB*fCos;
00215 fP = fSin*fR;
00216 m_afDiag[i3+1] = fG+fP;
00217 fG = fCos*fR-fB;
00218 for (int i4 = 0; i4 < 3; i4++)
00219 {
00220 fF = mElement[i4][i3+1];
00221 mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF;
00222 mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF;
00223 }
00224 }
00225 m_afDiag[i0] -= fP;
00226 m_afSubd[i0] = fG;
00227 m_afSubd[i2] = (double)0.0;
00228 }
00229 if (i1 == iMaxIter)
00230 {
00231 return false;
00232 }
00233 }
00234 return true;
00235 }
00236
00237 void DecreasingSort(void)
00238 {
00239
00240 for (int i0 = 0, i1; i0 <= 3-2; i0++)
00241 {
00242
00243 i1 = i0;
00244 double fMax = m_afDiag[i1];
00245 int i2;
00246 for (i2 = i0+1; i2 < 3; i2++)
00247 {
00248 if (m_afDiag[i2] > fMax)
00249 {
00250 i1 = i2;
00251 fMax = m_afDiag[i1];
00252 }
00253 }
00254
00255 if (i1 != i0)
00256 {
00257
00258 m_afDiag[i1] = m_afDiag[i0];
00259 m_afDiag[i0] = fMax;
00260
00261 for (i2 = 0; i2 < 3; i2++)
00262 {
00263 double fTmp = mElement[i2][i0];
00264 mElement[i2][i0] = mElement[i2][i1];
00265 mElement[i2][i1] = fTmp;
00266 m_bIsRotation = !m_bIsRotation;
00267 }
00268 }
00269 }
00270 }
00271
00272
00273 void GuaranteeRotation(void)
00274 {
00275 if (!m_bIsRotation)
00276 {
00277
00278 for (int iRow = 0; iRow <3; iRow++)
00279 {
00280 mElement[iRow][0] = -mElement[iRow][0];
00281 }
00282 }
00283 }
00284
00285 double mElement[3][3];
00286 double m_afDiag[3];
00287 double m_afSubd[3];
00288 bool m_bIsRotation;
00289 };
00290
00291 };
00292
00293
00294 bool getBestFitPlane(unsigned int vcount,
00295 const double *points,
00296 unsigned int vstride,
00297 const double *weights,
00298 unsigned int wstride,
00299 double *plane)
00300 {
00301 bool ret = false;
00302
00303 DoublePrecision::Vec3 kOrigin(0,0,0);
00304
00305 double wtotal = 0;
00306
00307 if ( 1 )
00308 {
00309 const char *source = (const char *) points;
00310 const char *wsource = (const char *) weights;
00311
00312 for (unsigned int i=0; i<vcount; i++)
00313 {
00314
00315 const double *p = (const double *) source;
00316
00317 double w = 1;
00318
00319 if ( wsource )
00320 {
00321 const double *ws = (const double *) wsource;
00322 w = *ws;
00323 wsource+=wstride;
00324 }
00325
00326 kOrigin.x+=p[0]*w;
00327 kOrigin.y+=p[1]*w;
00328 kOrigin.z+=p[2]*w;
00329
00330 wtotal+=w;
00331
00332 source+=vstride;
00333 }
00334 }
00335
00336 double recip = 1.0f / wtotal;
00337
00338 kOrigin.x*=recip;
00339 kOrigin.y*=recip;
00340 kOrigin.z*=recip;
00341
00342
00343 double fSumXX=0;
00344 double fSumXY=0;
00345 double fSumXZ=0;
00346
00347 double fSumYY=0;
00348 double fSumYZ=0;
00349 double fSumZZ=0;
00350
00351
00352 if ( 1 )
00353 {
00354 const char *source = (const char *) points;
00355 const char *wsource = (const char *) weights;
00356
00357 for (unsigned int i=0; i<vcount; i++)
00358 {
00359
00360 const double *p = (const double *) source;
00361
00362 double w = 1;
00363
00364 if ( wsource )
00365 {
00366 const double *ws = (const double *) wsource;
00367 w = *ws;
00368 wsource+=wstride;
00369 }
00370
00371 DoublePrecision::Vec3 kDiff;
00372
00373 kDiff.x = w*(p[0] - kOrigin.x);
00374 kDiff.y = w*(p[1] - kOrigin.y);
00375 kDiff.z = w*(p[2] - kOrigin.z);
00376
00377 fSumXX+= kDiff.x * kDiff.x;
00378 fSumXY+= kDiff.x * kDiff.y;
00379 fSumXZ+= kDiff.x * kDiff.z;
00380
00381 fSumYY+= kDiff.y * kDiff.y;
00382 fSumYZ+= kDiff.y * kDiff.z;
00383 fSumZZ+= kDiff.z * kDiff.z;
00384
00385
00386 source+=vstride;
00387 }
00388 }
00389
00390 fSumXX *= recip;
00391 fSumXY *= recip;
00392 fSumXZ *= recip;
00393 fSumYY *= recip;
00394 fSumYZ *= recip;
00395 fSumZZ *= recip;
00396
00397
00398 DoublePrecision::Eigen kES;
00399
00400 kES.mElement[0][0] = fSumXX;
00401 kES.mElement[0][1] = fSumXY;
00402 kES.mElement[0][2] = fSumXZ;
00403
00404 kES.mElement[1][0] = fSumXY;
00405 kES.mElement[1][1] = fSumYY;
00406 kES.mElement[1][2] = fSumYZ;
00407
00408 kES.mElement[2][0] = fSumXZ;
00409 kES.mElement[2][1] = fSumYZ;
00410 kES.mElement[2][2] = fSumZZ;
00411
00412
00413 kES.DecrSortEigenStuff();
00414
00415 DoublePrecision::Vec3 kNormal;
00416
00417 kNormal.x = kES.mElement[0][2];
00418 kNormal.y = kES.mElement[1][2];
00419 kNormal.z = kES.mElement[2][2];
00420
00421
00422 plane[0] = kNormal.x;
00423 plane[1] = kNormal.y;
00424 plane[2] = kNormal.z;
00425
00426 plane[3] = 0 - kNormal.dot(kOrigin);
00427
00428 return ret;
00429 }
00430
00431
00432
00433 namespace SinglePrecision
00434 {
00435
00436 class Vec3
00437 {
00438 public:
00439 Vec3(void) { };
00440 Vec3(float _x,float _y,float _z) { x = _x; y = _y; z = _z; };
00441
00442
00443 float dot(const Vec3 &v)
00444 {
00445 return x*v.x + y*v.y + z*v.z;
00446 }
00447
00448 float x;
00449 float y;
00450 float z;
00451 };
00452
00453
00454 class Eigen
00455 {
00456 public:
00457
00458
00459 void DecrSortEigenStuff(void)
00460 {
00461 Tridiagonal();
00462 QLAlgorithm();
00463 DecreasingSort();
00464 GuaranteeRotation();
00465 }
00466
00467 void Tridiagonal(void)
00468 {
00469 float fM00 = mElement[0][0];
00470 float fM01 = mElement[0][1];
00471 float fM02 = mElement[0][2];
00472 float fM11 = mElement[1][1];
00473 float fM12 = mElement[1][2];
00474 float fM22 = mElement[2][2];
00475
00476 m_afDiag[0] = fM00;
00477 m_afSubd[2] = 0;
00478 if (fM02 != (float)0.0)
00479 {
00480 float fLength = sqrt(fM01*fM01+fM02*fM02);
00481 float fInvLength = ((float)1.0)/fLength;
00482 fM01 *= fInvLength;
00483 fM02 *= fInvLength;
00484 float fQ = ((float)2.0)*fM01*fM12+fM02*(fM22-fM11);
00485 m_afDiag[1] = fM11+fM02*fQ;
00486 m_afDiag[2] = fM22-fM02*fQ;
00487 m_afSubd[0] = fLength;
00488 m_afSubd[1] = fM12-fM01*fQ;
00489 mElement[0][0] = (float)1.0;
00490 mElement[0][1] = (float)0.0;
00491 mElement[0][2] = (float)0.0;
00492 mElement[1][0] = (float)0.0;
00493 mElement[1][1] = fM01;
00494 mElement[1][2] = fM02;
00495 mElement[2][0] = (float)0.0;
00496 mElement[2][1] = fM02;
00497 mElement[2][2] = -fM01;
00498 m_bIsRotation = false;
00499 }
00500 else
00501 {
00502 m_afDiag[1] = fM11;
00503 m_afDiag[2] = fM22;
00504 m_afSubd[0] = fM01;
00505 m_afSubd[1] = fM12;
00506 mElement[0][0] = (float)1.0;
00507 mElement[0][1] = (float)0.0;
00508 mElement[0][2] = (float)0.0;
00509 mElement[1][0] = (float)0.0;
00510 mElement[1][1] = (float)1.0;
00511 mElement[1][2] = (float)0.0;
00512 mElement[2][0] = (float)0.0;
00513 mElement[2][1] = (float)0.0;
00514 mElement[2][2] = (float)1.0;
00515 m_bIsRotation = true;
00516 }
00517 }
00518
00519 bool QLAlgorithm(void)
00520 {
00521 const int iMaxIter = 32;
00522
00523 for (int i0 = 0; i0 <3; i0++)
00524 {
00525 int i1;
00526 for (i1 = 0; i1 < iMaxIter; i1++)
00527 {
00528 int i2;
00529 for (i2 = i0; i2 <= (3-2); i2++)
00530 {
00531 float fTmp = fabs(m_afDiag[i2]) + fabs(m_afDiag[i2+1]);
00532 if ( fabs(m_afSubd[i2]) + fTmp == fTmp )
00533 break;
00534 }
00535 if (i2 == i0)
00536 {
00537 break;
00538 }
00539
00540 float fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((float)2.0) * m_afSubd[i0]);
00541 float fR = sqrt(fG*fG+(float)1.0);
00542 if (fG < (float)0.0)
00543 {
00544 fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
00545 }
00546 else
00547 {
00548 fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
00549 }
00550 float fSin = (float)1.0, fCos = (float)1.0, fP = (float)0.0;
00551 for (int i3 = i2-1; i3 >= i0; i3--)
00552 {
00553 float fF = fSin*m_afSubd[i3];
00554 float fB = fCos*m_afSubd[i3];
00555 if (fabs(fF) >= fabs(fG))
00556 {
00557 fCos = fG/fF;
00558 fR = sqrt(fCos*fCos+(float)1.0);
00559 m_afSubd[i3+1] = fF*fR;
00560 fSin = ((float)1.0)/fR;
00561 fCos *= fSin;
00562 }
00563 else
00564 {
00565 fSin = fF/fG;
00566 fR = sqrt(fSin*fSin+(float)1.0);
00567 m_afSubd[i3+1] = fG*fR;
00568 fCos = ((float)1.0)/fR;
00569 fSin *= fCos;
00570 }
00571 fG = m_afDiag[i3+1]-fP;
00572 fR = (m_afDiag[i3]-fG)*fSin+((float)2.0)*fB*fCos;
00573 fP = fSin*fR;
00574 m_afDiag[i3+1] = fG+fP;
00575 fG = fCos*fR-fB;
00576 for (int i4 = 0; i4 < 3; i4++)
00577 {
00578 fF = mElement[i4][i3+1];
00579 mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF;
00580 mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF;
00581 }
00582 }
00583 m_afDiag[i0] -= fP;
00584 m_afSubd[i0] = fG;
00585 m_afSubd[i2] = (float)0.0;
00586 }
00587 if (i1 == iMaxIter)
00588 {
00589 return false;
00590 }
00591 }
00592 return true;
00593 }
00594
00595 void DecreasingSort(void)
00596 {
00597
00598 for (int i0 = 0, i1; i0 <= 3-2; i0++)
00599 {
00600
00601 i1 = i0;
00602 float fMax = m_afDiag[i1];
00603 int i2;
00604 for (i2 = i0+1; i2 < 3; i2++)
00605 {
00606 if (m_afDiag[i2] > fMax)
00607 {
00608 i1 = i2;
00609 fMax = m_afDiag[i1];
00610 }
00611 }
00612
00613 if (i1 != i0)
00614 {
00615
00616 m_afDiag[i1] = m_afDiag[i0];
00617 m_afDiag[i0] = fMax;
00618
00619 for (i2 = 0; i2 < 3; i2++)
00620 {
00621 float fTmp = mElement[i2][i0];
00622 mElement[i2][i0] = mElement[i2][i1];
00623 mElement[i2][i1] = fTmp;
00624 m_bIsRotation = !m_bIsRotation;
00625 }
00626 }
00627 }
00628 }
00629
00630
00631 void GuaranteeRotation(void)
00632 {
00633 if (!m_bIsRotation)
00634 {
00635
00636 for (int iRow = 0; iRow <3; iRow++)
00637 {
00638 mElement[iRow][0] = -mElement[iRow][0];
00639 }
00640 }
00641 }
00642
00643 float mElement[3][3];
00644 float m_afDiag[3];
00645 float m_afSubd[3];
00646 bool m_bIsRotation;
00647 };
00648
00649 };
00650
00651
00652 bool getBestFitPlane(unsigned int vcount,
00653 const float *points,
00654 unsigned int vstride,
00655 const float *weights,
00656 unsigned int wstride,
00657 float *plane)
00658 {
00659 bool ret = false;
00660
00661 SinglePrecision::Vec3 kOrigin(0,0,0);
00662
00663 float wtotal = 0;
00664
00665 if ( 1 )
00666 {
00667 const char *source = (const char *) points;
00668 const char *wsource = (const char *) weights;
00669
00670 for (unsigned int i=0; i<vcount; i++)
00671 {
00672
00673 const float *p = (const float *) source;
00674
00675 float w = 1;
00676
00677 if ( wsource )
00678 {
00679 const float *ws = (const float *) wsource;
00680 w = *ws;
00681 wsource+=wstride;
00682 }
00683
00684 kOrigin.x+=p[0]*w;
00685 kOrigin.y+=p[1]*w;
00686 kOrigin.z+=p[2]*w;
00687
00688 wtotal+=w;
00689
00690 source+=vstride;
00691 }
00692 }
00693
00694 float recip = 1.0f / wtotal;
00695
00696 kOrigin.x*=recip;
00697 kOrigin.y*=recip;
00698 kOrigin.z*=recip;
00699
00700
00701 float fSumXX=0;
00702 float fSumXY=0;
00703 float fSumXZ=0;
00704
00705 float fSumYY=0;
00706 float fSumYZ=0;
00707 float fSumZZ=0;
00708
00709
00710 if ( 1 )
00711 {
00712 const char *source = (const char *) points;
00713 const char *wsource = (const char *) weights;
00714
00715 for (unsigned int i=0; i<vcount; i++)
00716 {
00717
00718 const float *p = (const float *) source;
00719
00720 float w = 1;
00721
00722 if ( wsource )
00723 {
00724 const float *ws = (const float *) wsource;
00725 w = *ws;
00726 wsource+=wstride;
00727 }
00728
00729 SinglePrecision::Vec3 kDiff;
00730
00731 kDiff.x = w*(p[0] - kOrigin.x);
00732 kDiff.y = w*(p[1] - kOrigin.y);
00733 kDiff.z = w*(p[2] - kOrigin.z);
00734
00735 fSumXX+= kDiff.x * kDiff.x;
00736 fSumXY+= kDiff.x * kDiff.y;
00737 fSumXZ+= kDiff.x * kDiff.z;
00738
00739 fSumYY+= kDiff.y * kDiff.y;
00740 fSumYZ+= kDiff.y * kDiff.z;
00741 fSumZZ+= kDiff.z * kDiff.z;
00742
00743
00744 source+=vstride;
00745 }
00746 }
00747
00748 fSumXX *= recip;
00749 fSumXY *= recip;
00750 fSumXZ *= recip;
00751 fSumYY *= recip;
00752 fSumYZ *= recip;
00753 fSumZZ *= recip;
00754
00755
00756 SinglePrecision::Eigen kES;
00757
00758 kES.mElement[0][0] = fSumXX;
00759 kES.mElement[0][1] = fSumXY;
00760 kES.mElement[0][2] = fSumXZ;
00761
00762 kES.mElement[1][0] = fSumXY;
00763 kES.mElement[1][1] = fSumYY;
00764 kES.mElement[1][2] = fSumYZ;
00765
00766 kES.mElement[2][0] = fSumXZ;
00767 kES.mElement[2][1] = fSumYZ;
00768 kES.mElement[2][2] = fSumZZ;
00769
00770
00771 kES.DecrSortEigenStuff();
00772
00773 SinglePrecision::Vec3 kNormal;
00774
00775 kNormal.x = kES.mElement[0][2];
00776 kNormal.y = kES.mElement[1][2];
00777 kNormal.z = kES.mElement[2][2];
00778
00779
00780 plane[0] = kNormal.x;
00781 plane[1] = kNormal.y;
00782 plane[2] = kNormal.z;
00783
00784 plane[3] = 0 - kNormal.dot(kOrigin);
00785
00786 return ret;
00787 }
00788
00789
00790
00791
00792 #define CREATE_MAIN 0
00793
00794 #if CREATE_MAIN
00795
00796 #include "bestfit.h"
00797 #include <stdio.h>
00798
00799 void main(int argc,const char **argv)
00800 {
00801 float points[9] = { 0,0,0, 1,1,1, 0,0,1 };
00802 float plane[4];
00803 getBestFitPlane(3,points,sizeof(float)*3,0,0,plane);
00804 printf("Plane: %f %f %f %f\r\n", plane[0], plane[1], plane[2] );
00805 }
00806 #endif