00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef SOFA_HELPER_POLARDECOMPOSE_H
00028 #define SOFA_HELPER_POLARDECOMPOSE_H
00029
00030 #include <sofa/defaulttype/Mat.h>
00031
00032 namespace sofa
00033 {
00034
00035 namespace helper
00036 {
00037
00038
00039
00040
00041
00042
00044 template<class Real>
00045 void adjoint_transpose(const defaulttype::Mat<3,3,Real>& M, defaulttype::Mat<3,3,Real>& MadjT)
00046 {
00047 MadjT[0] = cross(M[1],M[2]);
00048 MadjT[1] = cross(M[2],M[0]);
00049 MadjT[2] = cross(M[0],M[1]);
00050 }
00051
00053 template<class Real>
00054 Real norm_inf(const defaulttype::Mat<3,3,Real>& M)
00055 {
00056 Real sum, max = 0;
00057 for (int i=0;i<3;i++)
00058 {
00059 sum = (Real)(fabs(M[i][0])+fabs(M[i][1])+fabs(M[i][2]));
00060 if (max<sum) max = sum;
00061 }
00062 return max;
00063 }
00064
00066 template<class Real>
00067 Real norm_one(const defaulttype::Mat<3,3,Real>& M)
00068 {
00069 Real sum, max = 0;
00070 for (int i=0;i<3;i++)
00071 {
00072 sum = (Real)(fabs(M[0][i])+fabs(M[1][i])+fabs(M[2][i]));
00073 if (max<sum) max = sum;
00074 }
00075 return max;
00076 }
00077
00079 template<class Real>
00080 int find_max_col(const defaulttype::Mat<3,3,Real>& M)
00081 {
00082 Real abs, max = 0;
00083 int col = -1;
00084 for (int i=0; i<3; i++)
00085 for (int j=0; j<3; j++) {
00086 abs = M[i][j]; if (abs<0.0) abs = -abs;
00087 if (abs>max) {max = abs; col = j;}
00088 }
00089 return col;
00090 }
00091
00093 template<class Real>
00094 void make_reflector(const defaulttype::Vec<3,Real>& v, defaulttype::Vec<3,Real>& u)
00095 {
00096 Real s = (Real)sqrt(dot(v, v));
00097 u[0] = v[0]; u[1] = v[1];
00098 u[2] = v[2] + ((v[2]<0.0) ? -s : s);
00099 s = (Real)sqrt(2.0/dot(u, u));
00100 u[0] = u[0]*s; u[1] = u[1]*s; u[2] = u[2]*s;
00101 }
00102
00104 template<class Real>
00105 void reflect_cols(defaulttype::Mat<3,3,Real>& M, const defaulttype::Vec<3,Real>& u)
00106 {
00107 for (int i=0; i<3; i++)
00108 {
00109 Real s = u[0]*M[0][i] + u[1]*M[1][i] + u[2]*M[2][i];
00110 for (int j=0; j<3; j++)
00111 M[j][i] -= u[j]*s;
00112 }
00113 }
00115 template<class Real>
00116 void reflect_rows(defaulttype::Mat<3,3,Real>& M, const defaulttype::Vec<3,Real>& u)
00117 {
00118 for (int i=0; i<3; i++)
00119 {
00120 Real s = dot(u, M[i]);
00121 for (int j=0; j<3; j++)
00122 M[i][j] -= u[j]*s;
00123 }
00124 }
00125
00127 template<class Real>
00128 void do_rank1(defaulttype::Mat<3,3,Real>& M, defaulttype::Mat<3,3,Real>& Q)
00129 {
00130 defaulttype::Vec<3,Real> v1, v2;
00131 Real s;
00132 int col;
00133 Q.identity();
00134
00135 col = find_max_col(M);
00136 if (col<0) return;
00137 v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];
00138 make_reflector(v1, v1); reflect_cols(M, v1);
00139 v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];
00140 make_reflector(v2, v2); reflect_rows(M, v2);
00141 s = M[2][2];
00142 if (s<0.0) Q[2][2] = -1.0;
00143 reflect_cols(Q, v1); reflect_rows(Q, v2);
00144 }
00145
00147 template<class Real>
00148 void do_rank2(defaulttype::Mat<3,3,Real>& M, defaulttype::Mat<3,3,Real>& MadjT, defaulttype::Mat<3,3,Real>& Q)
00149 {
00150 defaulttype::Vec<3,Real> v1, v2;
00151 Real w, x, y, z, c, s, d;
00152 int col;
00153
00154 col = find_max_col(MadjT);
00155 if (col<0) {do_rank1(M, Q); return;}
00156 v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];
00157 make_reflector(v1, v1); reflect_cols(M, v1);
00158 v2 = cross(M[0], M[1]);
00159 make_reflector(v2, v2); reflect_rows(M, v2);
00160 w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];
00161 if (w*z>x*y)
00162 {
00163 c = z+w; s = y-x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
00164 Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);
00165 }
00166 else
00167 {
00168 c = z-w; s = y+x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
00169 Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;
00170 }
00171 Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;
00172 reflect_cols(Q, v1); reflect_rows(Q, v2);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 template<class Real>
00184 Real polar_decomp(const defaulttype::Mat<3,3,Real>& M, defaulttype::Mat<3,3,Real>& Q, defaulttype::Mat<3,3,Real>& S)
00185 {
00186 defaulttype::Mat<3,3,Real> Mk, MadjTk, Ek;
00187 Real det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2;
00188 Mk.transpose(M);
00189 M_one = norm_one(Mk); M_inf = norm_inf(Mk);
00190 do
00191 {
00192 adjoint_transpose(Mk, MadjTk);
00193 det = dot(Mk[0], MadjTk[0]);
00194 if (det==0.0)
00195 {
00196 do_rank2(Mk, MadjTk, Mk);
00197 break;
00198 }
00199 MadjT_one = norm_one(MadjTk); MadjT_inf = norm_inf(MadjTk);
00200 gamma = (Real)sqrt(sqrt((MadjT_one*MadjT_inf)/(M_one*M_inf))/fabs(det));
00201 g1 = gamma*((Real)0.5);
00202 g2 = ((Real)0.5)/(gamma*det);
00203 Ek = Mk;
00204 Mk = Mk*g1 + MadjTk*g2;
00205 Ek -= Mk;
00206 E_one = norm_one(Ek);
00207 M_one = norm_one(Mk); M_inf = norm_inf(Mk);
00208 }
00209 while (E_one>(M_one*1.0e-6));
00210 Q.transpose(Mk);
00211 S = Mk*M;
00212 for (int i=0; i<3; i++)
00213 for (int j=i+1; j<3; j++)
00214 S[i][j] = S[j][i] = ((Real)0.5)*(S[i][j]+S[j][i]);
00215 return (det);
00216
00217 }
00218
00219
00220 }
00221
00222 }
00223
00224 #endif