Vec.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #ifndef SOFA_DEFAULTTYPE_VEC_H
00028 #define SOFA_DEFAULTTYPE_VEC_H
00029 
00030 #include <sofa/helper/fixed_array.h>
00031 #include <sofa/helper/static_assert.h>
00032 #include <sofa/helper/rmath.h>
00033 #include <functional>
00034 
00035 
00036 #define EQUALITY_THRESHOLD 1e-6
00037 
00038 namespace sofa
00039 {
00040 
00041 namespace defaulttype
00042 {
00043 
00044 enum NoInit { NOINIT }; 
00045 
00046 template <int N, typename real=float>
00047 class Vec : public helper::fixed_array<real,N>
00048 {
00049 public:
00050 
00052         Vec()
00053         {
00054             this->clear();
00055         }
00056 
00058         explicit Vec(NoInit)
00059         {
00060         }
00061 
00063         explicit Vec(real r1)
00064         {
00065             BOOST_STATIC_ASSERT(N==1);
00066             this->elems[0]=r1;
00067         }
00068 
00070         void operator=(real r1)
00071         {
00072             BOOST_STATIC_ASSERT(N == 1);
00073             this->elems[0]=r1;
00074         }
00075 
00077         Vec(real r1, real r2)
00078         {
00079                 BOOST_STATIC_ASSERT(N == 2);
00080                 this->elems[0]=r1;
00081                 this->elems[1]=r2;
00082         }
00083 
00085         Vec(real r1, real r2, real r3)
00086         {
00087                 BOOST_STATIC_ASSERT(N == 3);
00088                 this->elems[0]=r1;
00089                 this->elems[1]=r2;
00090                 this->elems[2]=r3;
00091         }
00092 
00094         Vec(real r1, real r2, real r3, real r4)
00095         {
00096                 BOOST_STATIC_ASSERT(N == 4);
00097                 this->elems[0]=r1;
00098                 this->elems[1]=r2;
00099                 this->elems[2]=r3;
00100                 this->elems[3]=r4;
00101         }
00102 
00104         Vec(real r1, real r2, real r3, real r4, real r5, real r6)
00105         {
00106             BOOST_STATIC_ASSERT(N == 6);
00107             this->elems[0]=r1;
00108             this->elems[1]=r2;
00109             this->elems[2]=r3;
00110             this->elems[3]=r4;
00111             this->elems[4]=r5;
00112             this->elems[5]=r6;
00113         }
00114 
00116         Vec(real r1, real r2, real r3, real r4, real r5, real r6, real r7, real r8)
00117         {
00118                 BOOST_STATIC_ASSERT(N == 8);
00119                 this->elems[0]=r1;
00120                 this->elems[1]=r2;
00121                 this->elems[2]=r3;
00122                 this->elems[3]=r4;
00123                 this->elems[4]=r5;
00124                 this->elems[5]=r6;
00125                 this->elems[6]=r7;
00126                 this->elems[7]=r8;
00127         }
00128         
00130         Vec(real r1, real r2, real r3, real r4, real r5, real r6, real r7, real r8, real r9)
00131         {
00132             BOOST_STATIC_ASSERT(N == 9);
00133             this->elems[0]=r1;
00134             this->elems[1]=r2;
00135             this->elems[2]=r3;
00136             this->elems[3]=r4;
00137             this->elems[4]=r5;
00138             this->elems[5]=r6;
00139             this->elems[6]=r7;
00140             this->elems[7]=r8;
00141             this->elems[8]=r9;
00142         }
00143         
00144 
00146         Vec(const Vec<N-1,real>& v, real r1)
00147         {
00148                 BOOST_STATIC_ASSERT(N > 1);
00149                 for(int i=0;i<N-1;i++)
00150                         this->elems[i] = v[i];
00151                 this->elems[N-1]=r1;
00152         }
00153 
00154         template<typename real2>
00155         Vec(const Vec<N, real2>& p)
00156         {
00157                 //std::copy(p.begin(), p.end(), this->begin());
00158                 for(int i=0;i<N;i++)
00159                         this->elems[i] = (real)p(i);
00160         }
00161 
00163         template<typename real2>
00164         explicit Vec(const real2* p)
00165         {
00166                 //std::copy(p, p+N, this->begin());
00167                 for(int i=0;i<N;i++)
00168                         this->elems[i] = (real)p[i];
00169         }
00170 
00172         real& x()
00173         {
00174                 BOOST_STATIC_ASSERT(N >= 1);
00175                 return this->elems[0];
00176         }
00178         real& y()
00179         {
00180                 BOOST_STATIC_ASSERT(N >= 2);
00181                 return this->elems[1];
00182         }
00184         real& z()
00185         {
00186                 BOOST_STATIC_ASSERT(N >= 3);
00187                 return this->elems[2];
00188         }
00190         real& w()
00191         {
00192                 BOOST_STATIC_ASSERT(N >= 4);
00193                 return this->elems[3];
00194         }
00195 
00197         const real& x() const
00198         {
00199                 BOOST_STATIC_ASSERT(N >= 1);
00200                 return this->elems[0];
00201         }
00203         const real& y() const
00204         {
00205                 BOOST_STATIC_ASSERT(N >= 2);
00206                 return this->elems[1];
00207         }
00209         const real& z() const
00210         {
00211                 BOOST_STATIC_ASSERT(N >= 3);
00212                 return this->elems[2];
00213         }
00215         const real& w() const
00216         {
00217                 BOOST_STATIC_ASSERT(N >= 4);
00218                 return this->elems[3];
00219         }
00220 
00222         template<typename real2>
00223         void operator=(const real2* p)
00224         {
00225                 //std::copy(p, p+N, this->begin());
00226                 for(int i=0;i<N;i++)
00227                         this->elems[i] = (real)p[i];
00228         }
00229 
00231         template<int M, typename real2>
00232         void operator=(const Vec<M,real2>& v)
00233         {
00234                 //std::copy(v.begin(), v.begin()+(N>M?M:N), this->begin());
00235                 for(int i=0;i<(N>M?M:N);i++)
00236                         this->elems[i] = (real)v(i);
00237         }
00238 
00240     void clear()
00241     {
00242     this->assign(real());
00243     }
00244 
00246         void fill(real r)
00247         {
00248                 this->assign(r);
00249         }
00250 
00251         // Access to i-th element.
00252         // Already in fixed_array
00253         //real& operator[](int i)
00254         //{
00255         //    return this->elems[i];
00256         //}
00257 
00258         // Access to i-th element.
00259         // Already in fixed_array
00261         //const real& operator[](int i) const
00262         //{
00263         //    return this->elems[i];
00264         //}
00265 
00267         real& operator()(int i)
00268         {
00269                 return this->elems[i];
00270         }
00271 
00273         const real& operator()(int i) const
00274         {
00275                 return this->elems[i];
00276         }
00277 
00280         //operator const real*() const
00281         //{
00282         //    return this->elems;
00283         //}
00284 
00287         //operator real*()
00288         //{
00289         //    return this->elems;
00290         //}
00291 
00293         const real* ptr() const
00294         {
00295                 return this->elems;
00296         }
00297 
00299         real* ptr()
00300         {
00301                 return this->elems;
00302         }
00303 
00304         // LINEAR ALGEBRA
00305 
00307     template<class real2>
00308     Vec<N,real> operator*(real2 f) const
00309     {
00310     Vec<N,real> r(NOINIT);
00311     for (int i=0;i<N;i++)
00312         r[i] = this->elems[i]*(real)f;
00313     return r;
00314     }
00315 
00317         template<class real2>
00318         void operator*=(real2 f)
00319         {
00320                 for (int i=0;i<N;i++)
00321                         this->elems[i]*=(real)f;
00322         }
00323 
00325     template<class real2>
00326     Vec<N,real> operator/(real2 f) const
00327     {
00328     Vec<N,real> r(NOINIT);
00329     for (int i=0;i<N;i++)
00330         r[i] = this->elems[i]/(real)f;
00331     return r;
00332     }
00333 
00335         template<class real2>
00336         void operator/=(real2 f)
00337         {
00338                 for (int i=0;i<N;i++)
00339                         this->elems[i]/=(real)f;
00340         }
00341 
00343         template<class real2>
00344         real operator*(const Vec<N,real2>& v) const
00345         {
00346                 real r = (real)(this->elems[0]*v[0]);
00347                 for (int i=1;i<N;i++)
00348                         r += (real)(this->elems[i]*v[i]);
00349                 return r;
00350         }
00351 
00353     template<class real2>
00354     Vec<N,real> linearProduct(const Vec<N,real2>& v) const
00355     {
00356     Vec<N,real> r(NOINIT);
00357     for (int i=0;i<N;i++)
00358         r[i]=this->elems[i]*(real)v[i];
00359     return r;
00360     }
00361     
00362     
00364     template<class real2>
00365     Vec<N,real> linearDivision(const Vec<N,real2>& v) const
00366     {
00367       Vec<N,real> r(NOINIT);
00368       for (int i=0;i<N;i++)
00369     r[i]=this->elems[i]/(real)v[i];
00370       return r;
00371     }
00372 
00374     template<class real2>
00375     Vec<N,real> operator+(const Vec<N,real2>& v) const
00376     {
00377     Vec<N,real> r(NOINIT);
00378     for (int i=0;i<N;i++)
00379         r[i]=this->elems[i]+(real)v[i];
00380     return r;
00381     }
00382 
00384         template<class real2>
00385         void operator+=(const Vec<N,real2>& v)
00386         {
00387                 for (int i=0;i<N;i++)
00388                         this->elems[i]+=(real)v[i];
00389         }
00390 
00392     template<class real2>
00393     Vec<N,real> operator-(const Vec<N,real2>& v) const
00394     {
00395     Vec<N,real> r(NOINIT);
00396     for (int i=0;i<N;i++)
00397         r[i]=this->elems[i]-(real)v[i];
00398     return r;
00399     }
00400 
00402         template<class real2>
00403         void operator-=(const Vec<N,real2>& v)
00404         {
00405                 for (int i=0;i<N;i++)
00406                         this->elems[i]-=(real)v[i];
00407         }
00408 
00410     Vec<N,real> operator-() const
00411     {
00412     Vec<N,real> r(NOINIT);
00413     for (int i=0;i<N;i++)
00414         r[i]=-this->elems[i];
00415     return r;
00416     }
00417 
00419         real norm2() const
00420         {
00421                 real r = this->elems[0]*this->elems[0];
00422                 for (int i=1;i<N;i++)
00423                         r += this->elems[i]*this->elems[i];
00424                 return r;
00425         }
00426 
00428     real norm() const
00429     {
00430         return helper::rsqrt(norm2());
00431     }
00432 
00434         void normalize()
00435         {
00436                 real r = norm();
00437                 if (r>1e-10)
00438                         for (int i=0;i<N;i++)
00439                                 this->elems[i]/=r;
00440         }
00441 
00442         Vec cross( const Vec& b ) const
00443         {
00444                 BOOST_STATIC_ASSERT(N == 3);
00445                 return Vec(
00446                                (*this)[1]*b[2] - (*this)[2]*b[1],
00447                                (*this)[2]*b[0] - (*this)[0]*b[2],
00448                                (*this)[0]*b[1] - (*this)[1]*b[0]
00449                        );
00450         }
00451 
00452         
00454     real sum() const
00455     {
00456         real sum = 0.0;
00457         for (int i=0;i<N;i++)
00458             sum += this->elems[i];
00459         return sum;
00460     }
00461         
00462         
00465 
00466     bool operator==(const Vec& b) const
00467     {
00468         for (int i=0;i<N;i++)
00469             if ( fabs( this->elems[i] - b[i] ) > EQUALITY_THRESHOLD ) return false;
00470         return true;
00471     }
00472 
00473     bool operator!=(const Vec& b) const
00474     {
00475         for (int i=0;i<N;i++)
00476             if ( fabs( this->elems[i] - b[i] ) > EQUALITY_THRESHOLD ) return true;
00477         return false;
00478     }
00479 
00481 };
00482 
00484 template <int N, typename real=float>
00485 class VecNoInit : public Vec<N,real>
00486 {
00487 public:
00488     VecNoInit()
00489     : Vec<N,real>(NOINIT)
00490     {
00491     }
00492 
00494     template<typename real2>
00495     void operator=(const real2* p)
00496     {
00497     this->Vec<N,real>::operator=(p);
00498     }
00499 
00501     template<int M, typename real2>
00502     void operator=(const Vec<M,real2>& v)
00503     {
00504     this->Vec<N,real>::operator=(v);
00505     }
00506 };
00507 
00509 template<int N,typename Real>
00510 std::istream& operator >> ( std::istream& in, Vec<N,Real>& v )
00511 {
00512         for( int i=0; i<N; ++i )
00513                 in>>v[i];
00514         return in;
00515 }
00516 
00518 template<int N,typename Real>
00519 std::ostream& operator << ( std::ostream& out, const Vec<N,Real>& v )
00520 {
00521         for( int i=0; i<N-1; ++i )
00522                 out<<v[i]<<" ";
00523         out<<v[N-1];
00524         return out;
00525 }
00526 
00528 template<typename real>
00529 inline Vec<3,real> cross(const Vec<3,real>& a, const Vec<3,real>& b)
00530 {
00531         return Vec<3,real>(a.y()*b.z() - a.z()*b.y(),
00532                            a.z()*b.x() - a.x()*b.z(),
00533                            a.x()*b.y() - a.y()*b.x());
00534 }
00535 
00537 template <typename real>
00538 real cross(const defaulttype::Vec<2,real>& a, const defaulttype::Vec<2,real>& b )
00539 {
00540     return a[0]*b[1] - a[1]*b[0];
00541 }
00542 
00544 template<int N,typename real>
00545 inline real dot(const Vec<N,real>& a, const Vec<N,real>& b)
00546 {
00547         return a*b;
00548 }
00549 
00550 typedef Vec<1,float> Vec1f;
00551 typedef Vec<1,double> Vec1d;
00552 
00553 
00554 typedef Vec<2,float> Vec2f;
00555 typedef Vec<2,double> Vec2d;
00556 
00557 
00558 typedef Vec<3,float> Vec3f;
00559 typedef Vec<3,double> Vec3d;
00560 
00561 
00562 typedef Vec<4,float> Vec4f;
00563 typedef Vec<4,double> Vec4d;
00564 
00565 
00566 typedef Vec<6,float> Vec6f;
00567 typedef Vec<6,double> Vec6d;
00568 
00569 
00570 #ifdef SOFA_FLOAT
00571 typedef Vec1f Vector1; 
00572 typedef Vec2f Vector2; 
00573 typedef Vec3f Vector3; 
00574 typedef Vec4f Vector4; 
00575 typedef Vec6f Vector6; 
00576 #else
00577 typedef Vec1d Vector1; 
00578 typedef Vec2d Vector2; 
00579 typedef Vec3d Vector3; 
00580 typedef Vec4d Vector4; 
00581 typedef Vec6d Vector6; 
00582 #endif
00583 } // namespace defaulttype
00584 
00585 } // namespace sofa
00586 
00588 template <int N, typename real>
00589 sofa::defaulttype::Vec<N,real> operator*(real r, const sofa::defaulttype::Vec<N,real>& v)
00590 {
00591   return v*r;
00592 }
00593 
00594 
00595 // Specialization of the std comparison function, to use Vec as std::map key
00596 namespace std
00597 {
00598 
00599 // template <>
00600 template<int N, class T>
00601 struct less< sofa::defaulttype::Vec<N,T> > : public binary_function< sofa::defaulttype::Vec<N,T>,  sofa::defaulttype::Vec<N,T>, bool>
00602 {
00603     bool operator()(const  sofa::defaulttype::Vec<N,T>& x, const  sofa::defaulttype::Vec<N,T>& y) const
00604     {
00605         //std::cerr<<"specialized std::less, x = "<<x<<", y = "<<y<<std::endl;
00606         for( unsigned i=0; i<N; ++i ) {
00607                 if( x[i]<y[i] )
00608                         return true;
00609                 else if( y[i]<x[i] )
00610                         return false;
00611         }
00612         return false;
00613     }
00614 };
00615 
00616 } // namespace std
00617 
00618 #endif
00619 

Generated on Sun Nov 23 02:29:29 2008 for Sofa by  doxygen 1.5.7.1