メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ | 関連ページ

TMatrixUtility.h

説明を見る。
00001 #ifndef PTMATRIX_TMATRIXUTILITY
00002 #define PTMATRIX_TMATRIXUTILITY
00003 #include "TVector.h"
00004 #include "TMatrix.h"
00005 /** @file TMatrixUtility.h
00006     行列初期化ユーティリティー.*/
00007 
00008 namespace PTM {
00009 
00010 inline void getAxisMap2D(int& x, int& y, int axis){
00011     switch(axis){
00012     case 'x': case 'X': case '0':
00013         x = 0; y = 1;
00014         break;
00015     case 'y': case 'Y': case '1':
00016         x = 1; y = 0;
00017         break;
00018     default:
00019         x = 0; y = 1;
00020         break;
00021     }
00022 }
00023 /// x/y軸を指定して2×2行列を回転行列に初期化
00024 template <class MD, class AD>
00025 void init_rot(TMatrixBase<DIMENC(2), DIMENC(2), MD>& m,
00026                 const TVectorBase<DIMENC(2), AD>& a,
00027                 char axis){
00028     int x, y;
00029     getAxisMap2D(x, y, axis);
00030     m.col(x) = a.unit();
00031     m.col(y)[0] = -m.col(x)[1];
00032     m.col(y)[1] =  m.col(x)[0];
00033 }
00034 
00035 /// 2×2行列を回転行列に初期化
00036 template <class D>
00037 void init_rot(TMatrixBase<DIMENC(2), DIMENC(2), D>& m, TYPENAME D::element_type th){
00038     TYPENAME D::element_type c = cos(th);
00039     TYPENAME D::element_type s = sin(th);
00040     m[0][0] = c; m[0][1] = -s;
00041     m[1][0] = s; m[1][1] = c;
00042 }
00043 
00044 inline void getAxisMap3D(int& x, int& y, int& z, int axis){
00045     switch(axis){
00046     case 'x': case 'X': case '0':
00047         x = 0; y = 1; z = 2;
00048         break;
00049     case 'y': case 'Y': case '1':
00050         x = 1; y = 2; z = 0;
00051         break;
00052     case 'z': case 'Z': case '2':
00053         x = 2; y = 0; z = 1;
00054         break;
00055     default:
00056         x = 0; y = 1; z = 2;
00057         break;
00058     }
00059 }
00060 /// axis軸, axis++軸を指定して3×3行列を回転行列に初期化
00061 template <class MD, class AD, class BD>
00062 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m,
00063                 const TVectorBase<DIMENC(3), AD>& a,
00064                 const TVectorBase<DIMENC(3), BD>& b,
00065                 char axis){
00066     int x,y,z;
00067     getAxisMap3D(x, y, z, axis);
00068     m.col(x) = a.unit();
00069     m.col(y) = (b - (b*m.col(x))*m.col(x)).unit();
00070     m.col(z) = m.col(x) % m.col(y);
00071 }
00072 /// 3×3行列をx/y/z軸まわり回転行列に初期化
00073 template <class MD>
00074 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, TYPENAME MD::element_type th, char axis){
00075     int x,y,z;
00076     getAxisMap3D(x, y, z, axis);
00077     TYPENAME MD::element_type c = (TYPENAME MD::element_type)cos(th);
00078     TYPENAME MD::element_type s = (TYPENAME MD::element_type)sin(th);
00079     m.item(x,x) = 1; m.item(x, y) = 0; m.item(x, z) = 0;
00080     m.item(y,x) = 0; m.item(y, y) = c; m.item(y, z) = -s;
00081     m.item(z,x) = 0; m.item(z, y) = s; m.item(z, z) = c;
00082 }
00083 /** 3×3行列を任意軸まわり回転行列に初期化
00084         +                                                                      +
00085         |u^2+(1-u^2)cos(th)      uv(1-cos(th))-wsin(th)  wu(1-cos(th))+vsin(th)|
00086     R = |uv(1-cos(th))+wsin(th)  v^2+(1-v^2)cos(th)      vw(1-cos(th))-usin(th)|
00087         |wu(1-cos(th))-vsin(th)  vw(1-cos(th))+usin(th)  w^2+(1-w^2)cos(th)    |
00088         +                                                                      +*/
00089 template <class MD, class AD>
00090 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, TYPENAME MD::element_type th,
00091              const TVectorBase<DIMENC(3), AD>& axis){
00092     TYPENAME MD::element_type s = (TYPENAME MD::element_type) sin(th), c = (TYPENAME MD::element_type) cos(th);
00093     TYPENAME MD::element_type u = axis[0], v = axis[1], w = axis[2];
00094     m.item(0,0) = u*u + (1-u*u)*c;
00095     m.item(1,0) = u*v*(1-c) + w*s;
00096     m.item(2,0) = w*u*(1-c) - v*s;
00097 
00098     m.item(0,1)  = u*v*(1-c) - w*s;
00099     m.item(1,1) = v*v + (1-v*v)*c;
00100     m.item(2,1) = v*w*(1-c) + u*s;
00101     
00102     m.item(0,2) = w*u*(1-c) + v*s;
00103     m.item(1,2) = v*w*(1-c) - u*s;
00104     m.item(2,2) = w*w + (1-w*w)*c;
00105 }
00106 
00107 /** 3×3行列をクォータニオンから任意軸まわり回転行列に初期化    */
00108 template <class MD, class QD>
00109 void init_rot(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, const TVectorBase<DIMENC(4), QD>& q){
00110     typedef TMatrixBase<DIMENC(3), DIMENC(3), MD> MAT;
00111     const int W = 0;
00112     const int X = 1;
00113     const int Y = 2;
00114     const int Z = 3;
00115     TYPENAME MAT::element_type d = q*q;
00116     assert(d);
00117     TYPENAME MAT::element_type s = 2 / d;
00118     TYPENAME MAT::element_type xs = q[X] * s,   ys = q[Y] * s,   zs = q[Z] * s;
00119     TYPENAME MAT::element_type wx = q[W] * xs,  wy = q[W] * ys,  wz = q[W] * zs;
00120     TYPENAME MAT::element_type xx = q[X] * xs,  xy = q[X] * ys,  xz = q[X] * zs;
00121     TYPENAME MAT::element_type yy = q[Y] * ys,  yz = q[Y] * zs,  zz = q[Z] * zs;
00122     m.item(0,0) = 1 - (yy + zz);    m.item(0,1) = xy - wz;          m.item(0,2) = xz + wy;
00123     m.item(1,0) = xy + wz;          m.item(1,1) = 1 - (xx + zz);    m.item(1,2) = yz - wx;
00124     m.item(2,0) = xz - wy;          m.item(2,1) = yz + wx;          m.item(2,2) = 1 - (xx + yy);
00125 }
00126 
00127 /// 2×2行列を単位行列に初期化
00128 template <class D>
00129 void init_unitize(TMatrixBase<DIMENC(2),DIMENC(2),D>& m){
00130     TYPENAME D::element_type z = D::zero(0);
00131     TYPENAME D::element_type u = D::unit(1);
00132     m.item(0,0)=u;  m.item(0,1)=z;
00133     m.item(1,0)=z;  m.item(1,1)=u;
00134 }
00135 /// 3×3行列を単位行列に初期化
00136 template <class D>
00137 void init_unitize(TMatrixBase<DIMENC(3),DIMENC(3),D>& m){
00138     TYPENAME D::element_type z = D::zero(0);
00139     TYPENAME D::element_type u = D::unit(1);
00140     m.item(0,0)=u;  m.item(0,1)=z;  m.item(0,2)=z;
00141     m.item(1,0)=z;  m.item(1,1)=u;  m.item(1,2)=z;
00142     m.item(2,0)=z;  m.item(2,1)=z;  m.item(2,2)=u;
00143 }
00144 /// 4×4行列を単位行列に初期化
00145 template <class D>
00146 void init_unitize(TMatrixBase<DIMENC(4),DIMENC(4),D>& m){
00147     typedef TYPENAME D::zero zero;
00148     typedef TYPENAME D::unit unit;
00149     TYPENAME D::element_type z = zero(0);
00150     TYPENAME D::element_type u = unit(1);
00151     m.item(0,0)=u;  m.item(0,1)=z;  m.item(0,2)=z;  m.item(0,3)=z;
00152     m.item(1,0)=z;  m.item(1,1)=u;  m.item(1,2)=z;  m.item(1,3)=z;
00153     m.item(2,0)=z;  m.item(2,1)=z;  m.item(2,2)=u;  m.item(2,3)=z;
00154     m.item(3,0)=z;  m.item(3,1)=z;  m.item(3,2)=z;  m.item(3,3)=u;
00155 }
00156 /// N×N行列を単位行列に初期化
00157 template <class M>
00158 void init_unitize(MatrixImp<M>& m){
00159     assert(m.width() == m.height());
00160     typedef TYPENAME M::zero zero;
00161     TYPENAME M::element_type z = zero();
00162     m.clear(z);
00163     for(size_t i=0; i<m.width(); i++) m.item(i,i) = 1;
00164 }
00165 /// 3×3行列をベクトルの外積計算になるように初期化(m*b == v^b).
00166 template <class MD, class D>
00167 void init_cross(TMatrixBase<DIMENC(3), DIMENC(3), MD>& m, const TVectorBase<DIMENC(3), D>& v){
00168     m.item(0,0) = 0;        m.item(0,1) = -v[2];    m.item(0,2) =  v[1];
00169     m.item(1,0) = v[2];     m.item(1,1) = 0;        m.item(1,2) = -v[0];
00170     m.item(2,0) = -v[1];    m.item(2,1) =  v[0];    m.item(2,2) = 0;
00171 }
00172 
00173 /// 4×4行列をある点を注視する視点行列に初期化する.
00174 template <class D, class BP>
00175 void init_look_at(TMatrixBase<DIMENC(4), DIMENC(4), D>& a, const TVectorBase<DIMENC(3), BP>& posi){
00176 
00177     typedef TMatrixCol<4,4, TYPENAME D::element_type> TAf;
00178     typedef TVector<3, TYPENAME BP::element_type> TVec;
00179 
00180     TVec relv = posi - a.col(3).sub_vector(TSubVectorDim<0,3>());
00181 
00182     TVector<3, TYPENAME D::element_type> tmp = a.col(0).sub_vector(TSubVectorDim<0,3>());
00183     TYPENAME D::element_type sx = tmp.norm();
00184     tmp = a.col(1).sub_vector(TSubVectorDim<0,3>());
00185     TYPENAME D::element_type sy = tmp.norm();
00186     tmp = a.col(2).sub_vector(TSubVectorDim<0,3>());
00187     TYPENAME D::element_type sz = tmp.norm();
00188 
00189     // y -> x
00190     TVec tv;
00191     tv[0] = relv[0];
00192     tv[1] = 0;
00193     tv[2] = relv[2];
00194     TVec ey;
00195     ey[0] = 0;
00196     ey[1] = 1;
00197     ey[2] = 0;
00198     a.col(0).sub_vector(TSubVectorDim<0,3>()) = (ey % tv.unit()).unit();
00199     a.col(2).sub_vector(TSubVectorDim<0,3>()) = relv.unit();
00200     TVec a1 = a.col(2).sub_vector(TSubVectorDim<0,3>()) % a.col(0).sub_vector(TSubVectorDim<0,3>());
00201     a.col(1).sub_vector(TSubVectorDim<0,3>()) = a1;
00202     if (a.item(1,1) < 0){
00203         TAf rot;
00204         init_rot(rot.sub_matrix(TSubMatrixDim<0,0,3,3>()), (TYPENAME TAf::element_type)M_PI, 'z');
00205         a = a * rot;
00206     }
00207     a.col(0).sub_vector(TSubVectorDim<0,3>()) *= sx;
00208     a.col(1).sub_vector(TSubVectorDim<0,3>()) *= sy;
00209     a.col(2).sub_vector(TSubVectorDim<0,3>()) *= sz;
00210 }
00211 template <class D, class BP, class BT>
00212 void init_look_at(TMatrixBase<DIMENC(4),DIMENC(4),D>& a,
00213                   const TVectorBase<DIMENC(3), BP>& posz,
00214                   const TVectorBase<DIMENC(3), BT>& posy){
00215     typedef TYPENAME D::ret_type TAf;
00216     typedef TYPENAME BP::ret_type TVec;
00217     TYPENAME D::element_type sx = a.col(0).sub_vector(TSubVectorDim<0,3>()).norm();
00218     TYPENAME D::element_type sy = a.col(1).sub_vector(TSubVectorDim<0,3>()).norm();
00219     TYPENAME D::element_type sz = a.col(2).sub_vector(TSubVectorDim<0,3>()).norm();
00220 
00221     TVec relvz = posz - a.col(3).sub_vector(TSubVectorDim<0,3>());
00222     TVec relvy = posy - a.col(3).sub_vector(TSubVectorDim<0,3>());
00223     
00224     a.col(2).sub_vector(TSubVectorDim<0,3>()) = relvz.unit();
00225     relvy = relvy - (relvy * a.col(2).sub_vector(TSubVectorDim<0,3>())) * a.col(2).sub_vector(TSubVectorDim<0,3>());
00226     a.col(1).sub_vector(TSubVectorDim<0,3>()) = relvy.unit();
00227     a.col(0).sub_vector(TSubVectorDim<0,3>()) = a.col(1).sub_vector(TSubVectorDim<0,3>()) % a.col(2).sub_vector(TSubVectorDim<0,3>());
00228     
00229     a.col(0).sub_vector(TSubVectorDim<0,3>()) *= sx;
00230     a.col(1).sub_vector(TSubVectorDim<0,3>()) *= sy;
00231     a.col(2).sub_vector(TSubVectorDim<0,3>()) *= sz;
00232 }
00233 /// 4×4行列をある点を注視する視点行列に初期化する.
00234 template <class D, class BP>
00235 void init_look_at_gl(TMatrixBase<DIMENC(4),DIMENC(4),D>& a, const TVectorBase<DIMENC(3), BP>& posi){
00236     TYPENAME BP::ret_type posi_ = posi - 2 * (posi - a.col(3).sub_vector(TSubVectorDim<0,3>()));
00237     init_look_at(a, posi_);
00238 }
00239 template <class D, class BZ, class BY>
00240 void init_look_at_gl(TMatrixBase<DIMENC(4),DIMENC(4),D>& a,
00241                      const TVectorBase<DIMENC(3), BZ>& posi,
00242                      const TVectorBase<DIMENC(3), BY>& posy){
00243     TYPENAME BZ::ret_type workAroundForBCB6 = a.col(3).sub_vector(TSubVectorDim<0,3>());
00244     TYPENAME BZ::ret_type posi_ = posi - 2 * (posi - workAroundForBCB6);
00245     init_look_at(a, posi_, posy);
00246 }
00247 
00248 template <class D, class SD, class ZD>
00249 void init_projection_gl(TMatrixBase<DIMENC(4),DIMENC(4),D>& a,
00250                         const TVectorBase<DIMENC(3), SD>& screen_,
00251                         const TVectorBase<DIMENC(2), ZD>& size_,
00252                         TYPENAME D::element_type front=1.0f, TYPENAME D::element_type back=10000.0f){
00253     TYPENAME SD::ret_type screen(screen_);
00254     TYPENAME ZD::ret_type size(size_);
00255     if (screen[2] <= 0) screen[2] = size[0];
00256     assert(screen[2] > 0);          //  Check screen's position.
00257     assert(front > 0);              //  Check front clipping plane.
00258     assert(back > front);           //  Check back clipping plane.
00259     
00260     typedef TYPENAME D::element_type ET;
00261     TVector<2,float> center = screen.sub_vector(TSubVectorDim<0,2>());
00262     
00263     center *= front / screen[2];
00264     size *= front / screen[2];
00265     
00266     TYPENAME D::element_type Q = back/(back-front);
00267     a.item(0,0) = 2*front/size[0];      a.item(1,0) = 0;                    a.item(2,0) = 0;            a.item(3,0) = 0;
00268     a.item(0,1) = 0;                    a.item(1,1) = 2*front/size[1];      a.item(2,1) = 0;            a.item(3,1) = 0;
00269     a.item(0,2) = 2*center[0]/size[0];  a.item(1,2) = 2*center[1]/size[1];  a.item(2,2) = -Q;           a.item(3,2) = -1;
00270     a.item(0,3) = 0;                    a.item(1,3) = 0;                    a.item(2,3) = -Q*front;     a.item(3,3) = 0;
00271 }
00272 template <class D, class SD, class ZD>
00273 void init_projection_d3d(TMatrixBase<DIMENC(4), DIMENC(4), D>& a,
00274                          const TVectorBase<DIMENC(3), SD>& screen_,
00275                          const TVectorBase<DIMENC(2), ZD>& size_,
00276                          TYPENAME D::element_type front=1.0f, TYPENAME D::element_type back=10000.0f){
00277     TYPENAME SD::ret_type screen(screen_);
00278     TYPENAME ZD::ret_type size(size_);
00279     if (screen[2] <= 0) screen[2] = size[0];
00280     assert(screen[2] > 0);              //  Check screen's position.
00281     assert(front > 0);                  //  Check front clipping plane.
00282     assert(back > front);               //  Check back clipping plane.
00283     
00284     typedef TYPENAME D::element_type ET;
00285     TSubVector<2, TYPENAME TVectorBase<DIMENC(3), SD>::desc > center = screen.sub_vector(TSubVectorDim<0,2>());
00286     
00287     center *= front / screen[2];
00288     size *= front / screen[2];
00289 
00290     TYPENAME D::element_type Q = back/(back-front);
00291     a.item(0,0) = 2*front/size[0];      a.item(1,0) = 0;                    a.item(2,0) = 0;            a.item(3,0) = 0;
00292     a.item(0,1) = 0;                    a.item(1,1) = 2*front/size[1];      a.item(2,1) = 0;            a.item(3,1) = 0;
00293     a.item(0,2) = 2*center[0]/size[0];  a.item(1,2) = 2*center[1]/size[1];  a.item(2,2) = Q;            a.item(3,2) = 1;
00294     a.item(0,3) = 0;                    a.item(1,3) = 0;                    a.item(2,3) = -Q*front;     a.item(3,3) = 0;
00295 }
00296 
00297 
00298 /** 4行ベクトルを回転をあらわすクォータニオンとして初期化   */
00299 template <class QD, class T, class AD>
00300 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, T angle, const TVectorBase<DIMENC(3),AD>& axis){
00301     TYPENAME QD::element_type d = axis.norm();
00302     assert(d);
00303     TYPENAME QD::element_type s = (TYPENAME QD::element_type)(sin(angle / 2) / d);
00304     q[0] = TVectorBase<DIMENC(4), QD>::element_type( cos(angle / 2) );
00305     q.sub_vector(TSubVectorDim<1,3>()) = s * axis;
00306 }
00307 
00308 /** 4行ベクトルを回転をあらわすクォータニオンとして初期化   */
00309 template <class QD, class AD>
00310 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, const TVectorBase<DIMENC(3),AD>& rot){
00311     typedef TYPENAME QD::element_type ET;
00312     ET angle = rot.norm();
00313     ET s = (ET)(sin(angle / 2));
00314     q[0] = (ET)( cos(angle / 2) );
00315     if (angle > 1e-10f){
00316         q.sub_vector(TSubVectorDim<1,3>()) = s/angle * rot;
00317     }else{
00318         q[1] = (ET)0;
00319         q[2] = (ET)0;
00320         q[3] = (ET)0;
00321     }
00322 }
00323 
00324 /** 4行ベクトルを回転をあらわすクォータニオンとして初期化   */
00325 template <class QD, class T>
00326 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, T angle, char axis){
00327     q[0] = (TYPENAME QD::element_type) cos(angle / 2);
00328     int x,y,z;
00329     getAxisMap3D(x,y,z, axis);
00330     q[x+1] = (TYPENAME QD::element_type) sin(angle / 2);
00331     q[y+1] = 0;
00332     q[z+1] = 0;
00333 }
00334 
00335 /** 4行ベクトルを回転をあらわすクォータニオンとして初期化   */
00336 template <class QD, class MD>
00337 void init_quaternion(TVectorBase<DIMENC(4), QD>& q, TMatrixBase<DIMENC(3), DIMENC(3), MD>& m){
00338     // check the diagonal
00339     double tr = m[0][0] + m[1][1] + m[2][2];
00340     if (tr > 0){
00341         double s = sqrt(tr+1);
00342         typedef TYPENAME QD::element_type QET;
00343         W() = QET(s/2);
00344         s =  QET(0.5/s);
00345         X() = QET((m[1][2] - m[2][1]) * s);
00346         Y() = QET((m[2][0] - m[0][2]) * s);
00347         Z() = QET((m[0][1] - m[1][0]) * s);
00348     }else{  // diagonal is negative
00349         double q[4];
00350         int i, j, k;
00351         int nxt[3] = {1, 2, 0};
00352         i = 0;
00353         if (m[1][1] > m[0][0]) i = 1;
00354         if (m[2][2] > m[i][i]) i = 2;
00355         j = nxt[i];
00356         k = nxt[j];
00357         s = sqrt((m[i][i] - (m[j][j] + m[k][k])) + 1.0f);
00358         q[i] = s * 0.5f;
00359         if (s){
00360             s = 0.5 / s;
00361             q[3] = (m[j][k] - m[k][j]) * s;
00362             q[j] = (m[i][j] + m[j][i]) * s;
00363             q[k] = (m[i][k] + m[k][i]) * s;         
00364             W() = q[0];
00365             X() = q[1];
00366             Y() = q[2];
00367             Z() = q[3];
00368         }else{
00369             W() = 0;
00370             X() = 1;
00371             Y() = 0;
00372             Z() = 0;
00373         }
00374     }
00375 }
00376 
00377 }   //  namespace PTM
00378 #endif

Springheadに対してSun Apr 16 01:57:57 2006に生成されました。  doxygen 1.4.1