quadric.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 #ifndef __VCGLIB_QUADRIC
00024 #define __VCGLIB_QUADRIC
00025 
00026 #include <vcg/space/point3.h>
00027 #include <vcg/space/plane3.h>
00028 #include <vcg/math/matrix33.h>
00029 #include <eigenlib/Eigen/Core>
00030 
00031 namespace vcg {
00032 namespace math {
00033 
00034 /*
00035  *  This class encode a quadric function 
00036  *  f(x) = xAx +bx + c
00037  *  where A is a symmetric 3x3 matrix, b a vector and c a scalar constant.  
00038  */ 
00039 template<typename  _ScalarType>
00040 class Quadric
00041 {
00042 public:
00043   typedef _ScalarType ScalarType;
00044   ScalarType a[6];              // Symmetric Matrix 3x3 : a11 a12 a13 a22 a23 a33
00045   ScalarType b[3];              // Vector r3
00046   ScalarType c;                   // Scalar (-1 means null/un-initialized quadric)
00047   
00048   inline Quadric() { c = -1; }
00049   
00050   bool IsValid() const { return c>=0; }
00051   void SetInvalid() { c = -1.0; }
00052   
00053    // Initialize the quadric to keep the squared distance from a given Plane  
00054   template< class PlaneType >
00055   void ByPlane( const PlaneType & p )
00056   {
00057     a[0] =  (ScalarType)p.Direction()[0]*p.Direction()[0];      // a11
00058     a[1] =  (ScalarType)p.Direction()[1]*p.Direction()[0];      // a12 (=a21)
00059     a[2] =  (ScalarType)p.Direction()[2]*p.Direction()[0];      // a13 (=a31)
00060     a[3] =  (ScalarType)p.Direction()[1]*p.Direction()[1];      // a22
00061     a[4] =  (ScalarType)p.Direction()[2]*p.Direction()[1];      // a23 (=a32)
00062     a[5] =  (ScalarType)p.Direction()[2]*p.Direction()[2];      // a33
00063     b[0] =  (ScalarType)(-2.0)*p.Offset()*p.Direction()[0];
00064     b[1] =  (ScalarType)(-2.0)*p.Offset()*p.Direction()[1];
00065     b[2] =  (ScalarType)(-2.0)*p.Offset()*p.Direction()[2];
00066     c    =  (ScalarType)p.Offset()*p.Offset();
00067   }
00068   
00069   /* 
00070    * Initializes the quadric as the squared distance from a given line.
00071    * Note that this code also works for a vcg::Ray<T>, even though the (squared) distance
00072    * from a ray is different "before" its origin.
00073    */
00074   template< class LineType >
00075   void ByLine( const LineType & r ) // Init dato un raggio
00076   {
00077     ScalarType K = (ScalarType)(r.Origin()*r.Direction());
00078     a[0] = (ScalarType)1.0-r.Direction()[0]*r.Direction()[0]; // a11
00079     a[1] = (ScalarType)-r.Direction()[0]*r.Direction()[1]; // a12 (=a21)
00080     a[2] = (ScalarType)-r.Direction()[0]*r.Direction()[2]; // a13 (=a31)
00081     a[3] = (ScalarType)1.0-r.Direction()[1]*r.Direction()[1]; // a22
00082     a[4] = (ScalarType)-r.Direction()[1]*r.Direction()[2]; // a23 (=a32)
00083     a[5] = (ScalarType)1.0-r.Direction()[2]*r.Direction()[2]; // a33
00084     b[0] = (ScalarType)2.0*(r.Direction()[0]*K - r.Origin()[0]);
00085     b[1] = (ScalarType)2.0*(r.Direction()[1]*K - r.Origin()[1]);
00086     b[2] = (ScalarType)2.0*(r.Direction()[2]*K - r.Origin()[2]);
00087     c = -K*K + (ScalarType)(r.Origin()*r.Origin());
00088   }
00089 
00090   void SetZero()
00091   {
00092     a[0] = 0;
00093     a[1] = 0;
00094     a[2] = 0;
00095     a[3] = 0;
00096     a[4] = 0;
00097     a[5] = 0;
00098     b[0] = 0;
00099     b[1] = 0;
00100     b[2] = 0;
00101     c    = 0;
00102   }
00103   
00104   void operator = ( const Quadric & q )
00105   {
00106     assert( q.IsValid() );
00107     
00108     a[0] = q.a[0];
00109     a[1] = q.a[1];
00110     a[2] = q.a[2];
00111     a[3] = q.a[3];
00112     a[4] = q.a[4];
00113     a[5] = q.a[5];
00114     b[0] = q.b[0];
00115     b[1] = q.b[1];
00116     b[2] = q.b[2];
00117     c    = q.c;
00118   }
00119   
00120   void operator += ( const Quadric & q )
00121   {
00122     assert( IsValid() );
00123     assert( q.IsValid() );
00124     
00125     a[0] += q.a[0];
00126     a[1] += q.a[1];
00127     a[2] += q.a[2];
00128     a[3] += q.a[3];
00129     a[4] += q.a[4];
00130     a[5] += q.a[5];
00131     b[0] += q.b[0];
00132     b[1] += q.b[1];
00133     b[2] += q.b[2];
00134     c    += q.c;
00135   }
00136   
00137   void operator *= ( const ScalarType & w )                     // Amplifica una quadirca
00138   {
00139     assert( IsValid() );
00140     
00141     a[0] *= w;
00142     a[1] *= w;
00143     a[2] *= w;
00144     a[3] *= w;
00145     a[4] *= w;
00146     a[5] *= w;
00147     b[0] *= w;
00148     b[1] *= w;
00149     b[2] *= w;
00150     c    *= w;
00151   }
00152   
00153   
00154   
00155   /* Evaluate a quadric over a point p.
00156    */
00157   template <class ResultScalarType>
00158   ResultScalarType Apply( const Point3<ResultScalarType> & p ) const
00159   {
00160     assert( IsValid() );
00161     return ResultScalarType (
00162             p[0]*p[0]*a[0] + 2*p[0]*p[1]*a[1] + 2*p[0]*p[2]*a[2] + p[0]*b[0]
00163         +   p[1]*p[1]*a[3] + 2*p[1]*p[2]*a[4] + p[1]*b[1]
00164         +   p[2]*p[2]*a[5] + p[2]*b[2]  + c);
00165   }
00166   
00167   
00168   static double &RelativeErrorThr()
00169   {
00170     static double _err = 0.000001;
00171     return _err;
00172   }
00173   
00174   // Find the point minimizing the quadric xAx + bx + c 
00175   // by solving the first derivative 2 Ax + b = 0 
00176   // return true if the found solution fits the system. 
00177   
00178   template <class ReturnScalarType>
00179   bool Minimum(Point3<ReturnScalarType> &x)
00180   {
00181     Eigen::Matrix3d A;
00182     Eigen::Vector3d be;
00183     A << a[0], a[1], a[2],
00184          a[1], a[3], a[4],
00185          a[2], a[4], a[5];
00186     be << -b[0]/2, -b[1]/2, -b[2]/2;
00187   
00188   //  Eigen::Vector3d xe = A.colPivHouseholderQr().solve(bv);
00189   //  Eigen::Vector3d xe = A.partialPivLu().solve(bv);
00190     Eigen::Vector3d xe = A.fullPivLu().solve(be);
00191     double relative_error = (A*xe - be).norm() / be.norm();
00192     if(relative_error> Quadric<ScalarType>::RelativeErrorThr() ) 
00193       return false;
00194     
00195     x.FromEigenVector(xe);
00196     return true;
00197   }
00198   
00199   
00200   
00201   
00202   
00203 // spostare..risolve un sistema 3x3
00204 template<class FLTYPE>
00205 bool Gauss33( FLTYPE x[], FLTYPE C[3][3+1] )
00206 {
00207     const FLTYPE keps = (FLTYPE)1e-3;
00208     int i,j,k;
00209 
00210     FLTYPE eps;                                 // Determina valore cond.
00211                 eps = math::Abs(C[0][0]);
00212     for(i=1;i<3;++i)
00213     {
00214                 FLTYPE t = math::Abs(C[i][i]);
00215                 if( eps<t ) eps = t;
00216     }
00217     eps *= keps;
00218 
00219     for (i = 0; i < 3 - 1; ++i)                 // Ciclo di riduzione
00220     {
00221         int ma = i;                             // Ricerca massimo pivot
00222         FLTYPE vma = math::Abs( C[i][i] );
00223         for (k = i + 1; k < 3; k++)
00224         {
00225             FLTYPE t = math::Abs( C[k][i] );
00226             if (t > vma)
00227             {
00228                 vma = t;
00229                 ma  = k;
00230             }
00231         }
00232         if (vma<eps)
00233             return false;                               // Matrice singolare
00234         if(i!=ma)                               // Swap del massimo pivot
00235             for(k=0;k<=3;k++)
00236             {
00237                 FLTYPE t = C[i][k];
00238                 C[i][k] = C[ma][k];
00239                 C[ma][k] = t;
00240             }
00241         for (k = i + 1; k < 3; k++)             //  Riduzione
00242         {
00243             FLTYPE s;
00244             s = C[k][i] / C[i][i];
00245             for (j = i+1; j <= 3; j++)
00246                 C[k][j] -= C[i][j] * s;
00247             C[k][i] = 0.0;
00248         }
00249     }
00250 
00251         // Controllo finale singolarita'
00252     if( math::Abs(C[3-1][3- 1])<eps)
00253         return false;
00254 
00255     for (i=3-1; i>=0; i--)                      // Sostituzione
00256     {
00257         FLTYPE t;
00258         for (t = 0.0, j = i + 1; j < 3; j++)
00259             t += C[i][j] * x[j];
00260         x[i] = (C[i][3] - t) / C[i][i];
00261     }
00262 
00263     return true;
00264 }
00265 
00266 
00267 
00268 template <class ReturnScalarType>
00269 bool MinimumOld(Point3<ReturnScalarType> &x)
00270 {
00271                 ReturnScalarType C[3][4];
00272                 C[0][0]=a[0]; C[0][1]=a[1]; C[0][2]=a[2];
00273                 C[1][0]=a[1]; C[1][1]=a[3]; C[1][2]=a[4];
00274                 C[2][0]=a[2]; C[2][1]=a[4]; C[2][2]=a[5];
00275 
00276                 C[0][3]=-b[0]/2;
00277                 C[1][3]=-b[1]/2;
00278                 C[2][3]=-b[2]/2;
00279                 return Gauss33(&(x[0]),C);
00280 }
00281 
00282 // determina il punto di errore minimo vincolato nel segmento (a,b)
00283 bool Minimum(Point3<ScalarType> &x,Point3<ScalarType> &pa,Point3<ScalarType> &pb){
00284 ScalarType      t1,t2, t4, t5, t8, t9,
00285         t11,t12,t14,t15,t17,t18,t25,t26,t30,t34,t35,
00286         t41,t42,t44,t45,t50,t52,t54,
00287         t56,t21,t23,t37,t64,lambda;
00288 
00289           t1 = a[4]*pb.z();
00290           t2 = t1*pa.y();
00291       t4 = a[1]*pb.y();
00292       t5 = t4*pa.x();
00293       t8 = a[1]*pa.y();
00294       t9 = t8*pa.x();
00295       t11 = a[4]*pa.z();
00296       t12 = t11*pa.y();
00297       t14 = pa.z()*pa.z();
00298       t15 = a[5]*t14;
00299       t17 = a[2]*pa.z();
00300       t18 = t17*pa.x();
00301       t21 = 2.0*t11*pb.y();
00302       t23 = a[5]*pb.z()*pa.z();
00303       t25 = a[2]*pb.z();
00304       t26 = t25*pa.x();
00305       t30 = a[0]*pb.x()*pa.x();
00306       t34 = 2.0*a[3]*pb.y()*pa.y();
00307       t35 = t17*pb.x();
00308       t37 = t8*pb.x();
00309       t41 = pa.x()*pa.x();
00310       t42 = a[0]*t41;
00311       t44 = pa.y()*pa.y();
00312       t45 = a[3]*t44;
00313       t50 = 2.0*t30+t34+2.0*t35+2.0*t37-(-b[2]/2)*pa.z()-(-b[0]/2)*pa.x()-2.0*t42-2.0*t45+(-b[1]/2)*pb.y()
00314 +(-b[0]/2)*pb.x()-(-b[1]/2)*pa.y();
00315       t52 = pb.y()*pb.y();
00316       t54 = pb.z()*pb.z();
00317       t56 = pb.x()*pb.x();
00318       t64 = t5+t37-t9+t30-t18+t35+t26-t25*pb.x()+t2-t1*pb.y()+t23;
00319       lambda = (2.0*t2+2.0*t5+(-b[2]/2)*pb.z()-4.0*t9-4.0*t12-2.0*t15-4.0*t18+t21+2.0*t23+
00320 2.0*t26+t50)/(-t45-a[3]*t52-a[5]*t54-a[0]*t56-t15-t42+t34-2.0*t12+t21-2.0*t4*pb.x()+
00321 2.0*t64)/2.0;
00322 
00323           if(lambda<0)  lambda=0;  else   if(lambda>1)   lambda = 1;
00324 
00325                  x = pa*(1.0-lambda)+pb*lambda;
00326                  return true;
00327         }
00328 
00329 };
00330 
00331 typedef Quadric<short>  Quadrics;
00332 typedef Quadric<int>      Quadrici;
00333 typedef Quadric<float>  Quadricf;
00334 typedef Quadric<double> Quadricd;
00335 
00336 
00337 
00338         } // end namespace math
00339 } // end namespace vcg
00340 
00341 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:34:50