00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00036
00037
00038
00039 template<typename _ScalarType>
00040 class Quadric
00041 {
00042 public:
00043 typedef _ScalarType ScalarType;
00044 ScalarType a[6];
00045 ScalarType b[3];
00046 ScalarType c;
00047
00048 inline Quadric() { c = -1; }
00049
00050 bool IsValid() const { return c>=0; }
00051 void SetInvalid() { c = -1.0; }
00052
00053
00054 template< class PlaneType >
00055 void ByPlane( const PlaneType & p )
00056 {
00057 a[0] = (ScalarType)p.Direction()[0]*p.Direction()[0];
00058 a[1] = (ScalarType)p.Direction()[1]*p.Direction()[0];
00059 a[2] = (ScalarType)p.Direction()[2]*p.Direction()[0];
00060 a[3] = (ScalarType)p.Direction()[1]*p.Direction()[1];
00061 a[4] = (ScalarType)p.Direction()[2]*p.Direction()[1];
00062 a[5] = (ScalarType)p.Direction()[2]*p.Direction()[2];
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
00071
00072
00073
00074 template< class LineType >
00075 void ByLine( const LineType & r )
00076 {
00077 ScalarType K = (ScalarType)(r.Origin()*r.Direction());
00078 a[0] = (ScalarType)1.0-r.Direction()[0]*r.Direction()[0];
00079 a[1] = (ScalarType)-r.Direction()[0]*r.Direction()[1];
00080 a[2] = (ScalarType)-r.Direction()[0]*r.Direction()[2];
00081 a[3] = (ScalarType)1.0-r.Direction()[1]*r.Direction()[1];
00082 a[4] = (ScalarType)-r.Direction()[1]*r.Direction()[2];
00083 a[5] = (ScalarType)1.0-r.Direction()[2]*r.Direction()[2];
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 )
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
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
00175
00176
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
00189
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
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;
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)
00220 {
00221 int ma = i;
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;
00234 if(i!=ma)
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++)
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
00252 if( math::Abs(C[3-1][3- 1])<eps)
00253 return false;
00254
00255 for (i=3-1; i>=0; i--)
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
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 }
00339 }
00340
00341 #endif