inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/a3
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_a3
00005 #define inlib_a3
00006 
00007 #include "sqm"
00008 
00009 #include <cmath> //sqrt
00010 
00011 namespace inlib {
00012 namespace a3 {
00013 
00014 // vec is an a3
00015 
00016 template <class T>
00017 class vec : public array<T> {
00018 public:
00019   vec():array<T>(1,3){}
00020   vec(const T a_vec[3]):array<T>(1,3) {
00021     array<T>::m_vector[0] = a_vec[0];
00022     array<T>::m_vector[1] = a_vec[1];
00023     array<T>::m_vector[2] = a_vec[2];
00024   }
00025   vec(const T& a0,const T& a1,const T& a2):array<T>(1,3) {
00026     array<T>::m_vector[0] = a0;
00027     array<T>::m_vector[1] = a1;
00028     array<T>::m_vector[2] = a2;
00029   }
00030   virtual ~vec() {}
00031 public:
00032   vec(const vec& a_from):array<T>(a_from){}
00033   vec& operator=(const vec& a_from) {
00034     array<T>::operator=(a_from);
00035     return *this;
00036   }
00037 public:
00038   T v0() const { return array<T>::m_vector[0];}
00039   T v1() const { return array<T>::m_vector[1];}
00040   T v2() const { return array<T>::m_vector[2];}
00041 
00042   void v0(const T& a_value) { array<T>::m_vector[0] = a_value;}
00043   void v1(const T& a_value) { array<T>::m_vector[1] = a_value;}
00044   void v2(const T& a_value) { array<T>::m_vector[2] = a_value;}
00045 
00046   void set_value(const T& a1,const T& a2,const T& a3) {
00047     array<T>::m_vector[0] = a1;
00048     array<T>::m_vector[1] = a2;
00049     array<T>::m_vector[2] = a3;
00050   }
00051   void set_value(const T aV[3]) {
00052     array<T>::m_vector[0] = aV[0];
00053     array<T>::m_vector[1] = aV[1];
00054     array<T>::m_vector[2] = aV[2];
00055   }
00056   void value(T& a1,T& a2,T& a3) const {
00057     a1 = array<T>::m_vector[0];
00058     a2 = array<T>::m_vector[1];
00059     a3 = array<T>::m_vector[2];
00060   }    
00061 
00062   bool set_value(unsigned int a_index,const T& a_value) { 
00063     if(a_index>=3) return false;
00064     array<T>::m_vector[a_index] = a_value;
00065     return true;
00066   }
00067 
00068   T length() const {
00069     T m0 = array<T>::m_vector[0];
00070     T m1 = array<T>::m_vector[1];
00071     T m2 = array<T>::m_vector[2];
00072     return (T)::sqrt(m0*m0+m1*m1+m2*m2);
00073   }
00074   T normalize() {
00075     T norme = length();
00076     if(norme==T()) return 0;
00077     divide(norme);
00078     return norme;
00079   }
00080 
00081   T dot(const vec& aV) const {
00082     return (v0() * aV.v0() + 
00083             v1() * aV.v1() + 
00084             v2() * aV.v2());
00085   }   
00086 
00087 public: //operators
00088   //vec operator-(const vec& a_v) const {
00089   //  return vec(v0()-a_v.v0(),
00090   //             v1()-a_v.v1(),
00091   //             v1()-a_v.v2());
00092   //}    
00093 
00094 };
00095 
00096 // sqm is an a33
00097 
00098 template <class T>
00099 class sqm : public inlib::sqm<T> {
00100 public:
00101   sqm():inlib::sqm<T>(3){}
00102   virtual ~sqm() {}
00103 public:
00104   sqm(const sqm& a_from):inlib::sqm<T>(a_from){}
00105   sqm& operator=(const sqm& a_from) {
00106     inlib::sqm<T>::operator=(a_from);
00107     return *this;
00108   }
00109 public:
00110   void v00(const T& a_value) { array<T>::m_vector[0 + 0 * 3] = a_value;}
00111   void v10(const T& a_value) { array<T>::m_vector[1 + 0 * 3] = a_value;}
00112   void v20(const T& a_value) { array<T>::m_vector[2 + 0 * 3] = a_value;}
00113 
00114   void v01(const T& a_value) { array<T>::m_vector[0 + 1 * 3] = a_value;}
00115   void v11(const T& a_value) { array<T>::m_vector[1 + 1 * 3] = a_value;}
00116   void v21(const T& a_value) { array<T>::m_vector[2 + 1 * 3] = a_value;}
00117 
00118   void v02(const T& a_value) { array<T>::m_vector[0 + 2 * 3] = a_value;}
00119   void v12(const T& a_value) { array<T>::m_vector[1 + 2 * 3] = a_value;}
00120   void v22(const T& a_value) { array<T>::m_vector[2 + 2 * 3] = a_value;}
00121 
00122   T v00() const { return array<T>::m_vector[0 + 0 * 3];}
00123   T v10() const { return array<T>::m_vector[1 + 0 * 3];}
00124   T v20() const { return array<T>::m_vector[2 + 0 * 3];}
00125 
00126   T v01() const { return array<T>::m_vector[0 + 1 * 3];}
00127   T v11() const { return array<T>::m_vector[1 + 1 * 3];}
00128   T v21() const { return array<T>::m_vector[2 + 1 * 3];}
00129 
00130   T v02() const { return array<T>::m_vector[0 + 2 * 3];}
00131   T v12() const { return array<T>::m_vector[1 + 2 * 3];}
00132   T v22() const { return array<T>::m_vector[2 + 2 * 3];}
00133 
00134   virtual T determinant() const {
00135     T e00 =  D22(v11(),v12(),v21(),v22());
00136     T e01 = -D22(v01(),v02(),v21(),v22());
00137     T e02 =  D22(v01(),v02(),v11(),v12());
00138     return (  v00() * e00
00139             + v10() * e01
00140             + v20() * e02);
00141 
00142   }
00143 
00144   bool invert(sqm<T>& a_result) const {
00145     a_result.v00(
00146       D22(v11(),v12(),
00147           v21(),v22()));
00148     a_result.v01(
00149       -D22(v01(),v02(),
00150            v21(),v22()));
00151     a_result.v02(
00152       D22(v01(),v02(),
00153           v11(),v12()));
00154                   
00155     T deter =
00156         v00() * a_result.v00()
00157       + v10() * a_result.v01()
00158       + v20() * a_result.v02();
00159 
00160     if(deter==array<T>::zero()) return false;
00161                   
00162     a_result.v10(
00163      -D22(v10(),v12(),
00164           v20(),v22()));
00165     a_result.v11(
00166       D22(v00(),v02(),
00167           v20(),v22()));
00168     a_result.v12(
00169      -D22(v00(),v02(),
00170           v10(),v12()));
00171                     
00172     a_result.v20(
00173       D22(v10(),v11(),
00174           v20(),v21()));
00175     a_result.v21(
00176      -D22(v00(),v01(),
00177           v20(),v21()));
00178     a_result.v22(
00179       D22(v00(),v01(),
00180           v10(),v11()));
00181                     
00182     a_result.multiply(1./deter);  
00183   
00184     return true;
00185   }
00186 private:
00187   T D22(const T& a_11,const T& a_12,const T& a_21,const T& a_22) const {
00188     return (a_11 * a_22 - a_21 * a_12);
00189   }
00190 };
00191 
00192 template <class T>
00193 class cbm : public array<T> { //cbm for cubic matrix.
00194 public:
00195   cbm():array<T>(3,3){}
00196   virtual ~cbm() {}
00197 public:
00198   cbm(const cbm& a_from):array<T>(a_from){}
00199   cbm& operator=(const cbm& a_from){
00200     inlib::array<T>::operator=(a_from);
00201     return *this;
00202   }
00203 public:
00204   T value(unsigned int a1,unsigned int a2,unsigned int a3) const { 
00205     return array<T>::m_vector[a1 + a2 * 3 + a3 * 9];
00206   }
00207 
00208   void value(unsigned int a1,unsigned int a2,unsigned int a3,const T& a_value) { 
00209     array<T>::m_vector[a1 + a2 * 3 + a3 * 9] = a_value;
00210   }
00211 
00212   void v000(const T& a_value) {array<T>::m_vector[0+0*3+0*9] = a_value;}
00213   void v100(const T& a_value) {array<T>::m_vector[1+0*3+0*9] = a_value;}
00214   void v200(const T& a_value) {array<T>::m_vector[2+0*3+0*9] = a_value;}
00215   void v010(const T& a_value) {array<T>::m_vector[0+1*3+0*9] = a_value;}
00216   void v110(const T& a_value) {array<T>::m_vector[1+1*3+0*9] = a_value;}
00217   void v210(const T& a_value) {array<T>::m_vector[2+1*3+0*9] = a_value;}
00218   void v020(const T& a_value) {array<T>::m_vector[0+2*3+0*9] = a_value;}
00219   void v120(const T& a_value) {array<T>::m_vector[1+2*3+0*9] = a_value;}
00220   void v220(const T& a_value) {array<T>::m_vector[2+2*3+0*9] = a_value;}
00221 
00222   void v001(const T& a_value) {array<T>::m_vector[0+0*3+1*9] = a_value;}
00223   void v101(const T& a_value) {array<T>::m_vector[1+0*3+1*9] = a_value;}
00224   void v201(const T& a_value) {array<T>::m_vector[2+0*3+1*9] = a_value;}
00225   void v011(const T& a_value) {array<T>::m_vector[0+1*3+1*9] = a_value;}
00226   void v111(const T& a_value) {array<T>::m_vector[1+1*3+1*9] = a_value;}
00227   void v211(const T& a_value) {array<T>::m_vector[2+1*3+1*9] = a_value;}
00228   void v021(const T& a_value) {array<T>::m_vector[0+2*3+1*9] = a_value;}
00229   void v121(const T& a_value) {array<T>::m_vector[1+2*3+1*9] = a_value;}
00230   void v221(const T& a_value) {array<T>::m_vector[2+2*3+1*9] = a_value;}
00231 
00232   void v002(const T& a_value) {array<T>::m_vector[0+0*3+2*9] = a_value;}
00233   void v102(const T& a_value) {array<T>::m_vector[1+0*3+2*9] = a_value;}
00234   void v202(const T& a_value) {array<T>::m_vector[2+0*3+2*9] = a_value;}
00235   void v012(const T& a_value) {array<T>::m_vector[0+1*3+2*9] = a_value;}
00236   void v112(const T& a_value) {array<T>::m_vector[1+1*3+2*9] = a_value;}
00237   void v212(const T& a_value) {array<T>::m_vector[2+1*3+2*9] = a_value;}
00238   void v022(const T& a_value) {array<T>::m_vector[0+2*3+2*9] = a_value;}
00239   void v122(const T& a_value) {array<T>::m_vector[1+2*3+2*9] = a_value;}
00240   void v222(const T& a_value) {array<T>::m_vector[2+2*3+2*9] = a_value;}
00241 
00242 };
00243 
00244 template <class T>
00245 inline sqm<T> operator-(const sqm<T>& a1,const sqm<T>& a2) {
00246   sqm<T> res(a1);
00247   res.subtract(a2);
00248   return res;
00249 }
00250 template <class T>
00251 inline sqm<T> operator+(const sqm<T>& a1,const sqm<T>& a2) {
00252   sqm<T> res(a1);
00253   res.add(a2);
00254   return res;
00255 }
00256 template <class T>
00257 inline sqm<T> operator*(const sqm<T>& a1,const sqm<T>& a2) {
00258   sqm<T> res;
00259   a1.mx_mul(a2,res);
00260   return res;
00261 }
00262 
00263 template <class T>
00264 inline sqm<T> commutator(const sqm<T>& a1,const sqm<T>& a2) {
00265   return a1*a2-a2*a1;
00266 }
00267 template <class T>
00268 inline sqm<T> anticommutator(const sqm<T>& a1,const sqm<T>& a2) {
00269   return a1*a2+a2*a1;
00270 }
00271 
00275 
00276 //template <class T>
00277 //class point : public vec<T> {
00278 //};
00279 
00280 // Parametric description:
00281 //  l(t) = pos + t * dir
00282 
00283 template <class T>
00284 class line {
00285 public:
00286   line(){}
00287   line(const vec<T>& a_p0,const vec<T>& a_p1) {
00288     // Construct a line from two points lying on the line.  If you
00289     // want to construct a line from a position and a direction, use
00290     // line(p, p + d).
00291     // line is directed from p0 to p1.
00292     m_pos = a_p0;
00293     //m_dir = a_p1-a_p0;
00294     m_dir = a_p0;
00295     m_dir.multiply(-1);
00296     m_dir.add(a_p1);
00297     m_dir.normalize();
00298   }
00299   virtual ~line() {}
00300 public:
00301   line(const line& a_from)
00302   :m_pos(a_from.m_pos)
00303   ,m_dir(a_from.m_dir)
00304   {}
00305   line& operator=(const line& a_from) {
00306     m_pos = a_from.m_pos;
00307     m_dir = a_from.m_dir;
00308     return *this;
00309   }
00310 public:
00311   void set_value(const vec<T>& a_p0,const vec<T>& a_p1) {
00312     // Set that value!
00313     m_pos = a_p0;
00314     //m_dir = a_p1-a_p0;
00315     m_dir = a_p0;
00316     m_dir.multiply(-1);
00317     m_dir.add(a_p1);
00318     m_dir.normalize();
00319   }
00320 
00321   const vec<T>& position() const {return m_pos;}
00322   const vec<T>& direction() const {return m_dir;}
00323 private:
00324   vec<T> m_pos;
00325   vec<T> m_dir; //normalized.
00326 };
00327 
00328 template <class T>
00329 class plane {
00330 public:
00331   plane(){}
00332 
00333   plane(const vec<T>& a_p0,const vec<T>& a_p1,const vec<T>& a_p2) {
00334     // Construct a plane given 3 points.
00335     // Orientation is computed by taking (p1 - p0) x (p2 - p0) and
00336     // pointing the normal in that direction.
00337   
00338     vec<T> P = a_p1;
00339     P.subtract(a_p0);
00340     vec<T> P2 = a_p2;
00341     P2.subtract(a_p0);
00342     m_normal = P.cross(P2);
00343     m_normal.normalize();
00344     m_distance = 
00345       m_normal.v0() * a_p0.v0() + 
00346       m_normal.value1() * a_p0.value1() + 
00347       m_normal.value2() * a_p0.value2();
00348   }
00349 
00350   plane(const vec<T>& a_normal,const T& a_distance){
00351     // Construct a plane given normal and distance from origin along normal.
00352     // Orientation is given by the normal vector n.
00353     m_normal = a_normal;
00354     m_normal.normalize();
00355     m_distance = a_distance;
00356   }
00357 
00358   plane(const vec<T>& a_normal,const vec<T>& a_point){
00359     // Construct a plane given normal and a point to pass through
00360     // Orientation is given by the normal vector n.
00361     m_normal = a_normal;
00362     m_normal.normalize();
00363     m_distance = 
00364       m_normal.v0() * a_point.v0() + 
00365       m_normal.v1() * a_point.v1() + 
00366       m_normal.v2() * a_point.v2();
00367   }
00368 
00369   virtual ~plane() {}
00370 public:
00371   plane(const plane& a_from)
00372   :m_normal(a_from.m_normal)
00373   ,m_distance(a_from.m_distance)
00374   {}
00375   plane& operator=(const plane& a_from) {
00376     m_normal = a_from.m_normal;
00377     m_distance = a_from.m_distance;
00378     return *this;
00379   }
00380 
00381 public:
00382   void offset(const T& a_distance){
00383     // Offset a plane by a given distance.
00384     m_distance += a_distance;
00385   }
00386   
00387   bool intersect(const line<T>& a_line,vec<T>& a_intersection) const {
00388     // Intersect line and plane, returning true if there is an intersection
00389     // false if line is parallel to plane
00390     const vec<T>& pos = a_line.position();
00391     const vec<T>& dir = a_line.direction();
00392     T d = m_normal.dot(dir);
00393     if(d==array<T>::zero()) return false;
00394     T t = (m_distance - m_normal.dot(pos))/d;
00395     a_intersection = dir;
00396     a_intersection.multiply(t);
00397     a_intersection.add(pos);
00398     //a_intersection = pos + t * dir;
00399     return true;
00400   }
00401   
00402   bool is_in_half_space(const vec<T>& a_point) const {
00403     // Returns true if the given point is within the half-space
00404     // defined by the plane
00405     //vec pos = m_normal * m_distance;
00406     vec<T> pos = m_normal;
00407     pos.multiply(-m_distance);
00408     pos.add(a_point);
00409     return (m_normal.dot(pos) >= array<T>::zero() ? true : false);
00410   }
00411   
00412   const vec<T>& normal() const {return m_normal;}
00413   T distance_from_origin() const {return m_distance;}
00414   
00415   T distance(const vec<T>& a_point) const {
00416     // Return the distance from point to plane. Positive distance means
00417     // the point is in the plane's half space.
00418     return a_point.dot(m_normal) - m_distance;
00419   }
00420 private:
00421   vec<T> m_normal; //normalized.
00422   T m_distance;
00423 };
00424 
00425 // not tested yet.
00426 template <class T>
00427 class clip {
00428 public:
00429   clip():m_cur(0){}
00430   virtual ~clip() {}
00431 private:
00432   clip(const clip& a_from):m_cur(0){}
00433   clip& operator=(const clip& a_from){return *this;}
00434 public:
00435   void reset() {
00436     m_data[0].clear();
00437     m_data[1].clear();
00438     m_cur = 0;
00439   }
00440   void add(const vec<T>& a_point) {
00441     m_data[m_cur].push_back(a_point);
00442   }
00443 
00444   void execute(const plane<T>& plane) {
00445     //Clip polygon against plane. This might change the number of
00446     //vertices in the polygon.
00447 
00448     unsigned int n = m_data[m_cur].size();
00449     if (n == 0) return;
00450 
00451     // create a loop :
00452     vec<T> dummy = m_data[m_cur][0];
00453     m_data[m_cur].push_back(dummy);
00454 
00455     const vec<T>& planeN = plane.normal();
00456 
00457     for(unsigned int i = 0; i < n; i++) {
00458       vec<T> v0 = m_data[m_cur][i];
00459       vec<T> v1 = m_data[m_cur][i+1];
00460   
00461       T d0 = plane.distance(v0);
00462       T d1 = plane.distance(v1);
00463   
00464       if (d0 >= 0.0f && d1 < 0.0f) { // exit plane
00465         vec<T> dir = v1-v0;
00466         // we know that v0 != v1 since we got here
00467         dir.normalize();
00468         T dot = dir.dot(planeN);
00469         vec<T> newvertex = v0 - dir * (d0/dot);
00470         out_point(newvertex);
00471       } else if (d0 < 0.0f && d1 >= 0.0f) { // enter plane
00472         vec<T> dir = v1-v0;
00473         // we know that v0 != v1 since we got here
00474         dir.normalize();
00475         T dot = dir.dot(planeN);
00476         vec<T> newvertex = v0 - dir * (d0/dot);
00477         out_point(newvertex);
00478         out_point(v1);
00479       } else if (d0 >= 0.0f && d1 >= 0.0f) { // in plane
00480         out_point(v1);
00481       }
00482     }
00483     m_data[m_cur].clear();
00484     m_cur ^= 1;
00485   }
00486 
00487   const std::vector< vec<T> >& result() const {
00488     return m_data[m_cur];
00489   }
00490 
00491 private:
00492   void out_point(const vec<T>& a_p) {
00493     m_data[m_cur ^ 1].push_back(a_p);
00494   }
00495   
00496 private:
00497   std::vector< vec<T> > m_data[2];
00498   unsigned int m_cur;
00499 };
00500 
00501 }}
00502 
00503 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines