Biomechanical Joint Model
 Author: Anderson Maciel

moments.H

Go to the documentation of this file.
00001 #ifndef MOMENTS_H
00002 #define MOMENTS_H
00003 
00004 #include "matvec.H"
00005 #include "obb.H"
00006 
00007 struct moment
00008 {
00009   double A;  
00010   double m[3];
00011   double s[3][3];
00012 };
00013 
00014 struct accum
00015 {
00016   double A;
00017   double m[3];
00018   double s[3][3];
00019 };
00020 
00021 inline
00022 void
00023 print_moment(moment &M)
00024 {
00025   fprintf(stderr, "A: %g, m: %g %g %g, s: %g %g %g %g %g %g\n",
00026           M.A,
00027           M.m[0], M.m[1], M.m[2],
00028           M.s[0][0], M.s[0][1], M.s[0][2], M.s[1][1], M.s[1][2], M.s[2][2]);
00029 }
00030 
00031 
00032 inline
00033 void
00034 clear_accum(accum &a)
00035 {
00036   a.m[0] = a.m[1] = a.m[2] = 0.0;
00037   a.s[0][0] = a.s[0][1] = a.s[0][2] = 0.0;
00038   a.s[1][0] = a.s[1][1] = a.s[1][2] = 0.0;
00039   a.s[2][0] = a.s[2][1] = a.s[2][2] = 0.0;
00040   a.A = 0.0;
00041 }
00042 
00043 inline
00044 void
00045 accum_moment(accum &a, moment &b)
00046 {
00047   a.m[0] += b.m[0] * b.A;
00048   a.m[1] += b.m[1] * b.A;
00049   a.m[2] += b.m[2] * b.A;
00050   
00051   a.s[0][0] += b.s[0][0];
00052   a.s[0][1] += b.s[0][1];
00053   a.s[0][2] += b.s[0][2];
00054   a.s[1][0] += b.s[1][0];
00055   a.s[1][1] += b.s[1][1];
00056   a.s[1][2] += b.s[1][2];
00057   a.s[2][0] += b.s[2][0];
00058   a.s[2][1] += b.s[2][1];
00059   a.s[2][2] += b.s[2][2];
00060 
00061   a.A += b.A;
00062 }
00063 
00064 inline
00065 void
00066 mean_from_moment(double M[3], moment &m)
00067 {
00068   M[0] = m.m[0];
00069   M[1] = m.m[1];
00070   M[2] = m.m[2];
00071 }
00072 
00073 inline
00074 void
00075 mean_from_accum(double M[3], accum &a)
00076 {
00077   M[0] = a.m[0] / a.A;
00078   M[1] = a.m[1] / a.A;
00079   M[2] = a.m[2] / a.A;
00080 }
00081 
00082 inline
00083 void
00084 covariance_from_accum(double C[3][3], accum &a)
00085 {
00086   int i,j;
00087   for(i=0; i<3; i++)
00088     for(j=0; j<3; j++)
00089       C[i][j] = a.s[i][j] - a.m[i]*a.m[j]/a.A;
00090 }
00091 
00092 
00093 
00094 inline
00095 void
00096 compute_moment(moment &M, double p[3], double q[3], double r[3])
00097 {
00098   double u[3], v[3], w[3];
00099 
00100   // compute the area of the triangle
00101   VmV(u, q, p);
00102   VmV(v, r, p);
00103   VcrossV(w, u, v);
00104   M.A = 0.5 * Vlength(w);
00105 
00106   if (M.A == 0.0)
00107     {
00108       // This triangle has zero area.  The second order components
00109       // would be eliminated with the usual formula, so, for the 
00110       // sake of robustness we use an alternative form.  These are the 
00111       // centroid and second-order components of the triangle's vertices.
00112 
00113       // centroid
00114       M.m[0] = (p[0] + q[0] + r[0]) /3;
00115       M.m[1] = (p[1] + q[1] + r[1]) /3;
00116       M.m[2] = (p[2] + q[2] + r[2]) /3;
00117 
00118       // second-order components
00119       M.s[0][0] = (p[0]*p[0] + q[0]*q[0] + r[0]*r[0]);
00120       M.s[0][1] = (p[0]*p[1] + q[0]*q[1] + r[0]*r[1]);
00121       M.s[0][2] = (p[0]*p[2] + q[0]*q[2] + r[0]*r[2]);
00122       M.s[1][1] = (p[1]*p[1] + q[1]*q[1] + r[1]*r[1]);
00123       M.s[1][2] = (p[1]*p[2] + q[1]*q[2] + r[1]*r[2]);
00124       M.s[2][2] = (p[2]*p[2] + q[2]*q[2] + r[2]*r[2]);      
00125       M.s[2][1] = M.s[1][2];
00126       M.s[1][0] = M.s[0][1];
00127       M.s[2][0] = M.s[0][2];
00128 
00129       return;
00130     }
00131 
00132   // get the centroid
00133   M.m[0] = (p[0] + q[0] + r[0])/3;
00134   M.m[1] = (p[1] + q[1] + r[1])/3;
00135   M.m[2] = (p[2] + q[2] + r[2])/3;
00136 
00137   // get the second order components -- note the weighting by the area
00138   M.s[0][0] = M.A*(9*M.m[0]*M.m[0]+p[0]*p[0]+q[0]*q[0]+r[0]*r[0])/12;
00139   M.s[0][1] = M.A*(9*M.m[0]*M.m[1]+p[0]*p[1]+q[0]*q[1]+r[0]*r[1])/12;
00140   M.s[1][1] = M.A*(9*M.m[1]*M.m[1]+p[1]*p[1]+q[1]*q[1]+r[1]*r[1])/12;
00141   M.s[0][2] = M.A*(9*M.m[0]*M.m[2]+p[0]*p[2]+q[0]*q[2]+r[0]*r[2])/12;
00142   M.s[1][2] = M.A*(9*M.m[1]*M.m[2]+p[1]*p[2]+q[1]*q[2]+r[1]*r[2])/12;
00143   M.s[2][2] = M.A*(9*M.m[2]*M.m[2]+p[2]*p[2]+q[2]*q[2]+r[2]*r[2])/12;
00144   M.s[2][1] = M.s[1][2];
00145   M.s[1][0] = M.s[0][1];
00146   M.s[2][0] = M.s[0][2];
00147 }
00148 
00149 inline
00150 void
00151 compute_moments(moment *M, tri *tris, int num_tris)
00152 {
00153   int i;
00154 
00155   // first collect all the moments, and obtain the area of the 
00156   // smallest nonzero area triangle.
00157 
00158   double Amin = 0.0;
00159   int zero = 0;
00160   int nonzero = 0;
00161   for(i=0; i<num_tris; i++)
00162     {
00163       compute_moment(M[i], 
00164                      tris[i].p1,
00165                      tris[i].p2, 
00166                      tris[i].p3);  
00167       if (M[i].A == 0.0)
00168         {
00169           zero = 1;
00170         }
00171       else
00172         {
00173           nonzero = 1;
00174           if (Amin == 0.0) Amin = M[i].A;
00175           else if (M[i].A < Amin) Amin = M[i].A;
00176         }
00177     }
00178 
00179   if (zero)
00180     {
00181       fprintf(stderr, "----\n");
00182       fprintf(stderr, "Warning!  Some triangles have zero area!\n");
00183       fprintf(stderr, "----\n");
00184 
00185       // if there are any zero area triangles, go back and set their area
00186       
00187       // if ALL the triangles have zero area, then set the area thingy
00188       // to some arbitrary value.
00189       if (Amin == 0.0) Amin = 1.0;
00190 
00191       for(i=0; i<num_tris; i++)
00192         {
00193           if (M[i].A == 0.0) M[i].A = Amin;
00194         }
00195       
00196     }
00197 }
00198 
00199 #endif

Generated on Thu Dec 1 10:13:39 2005 for COME - Biomechanical Joint Model by  doxygen 1.4.5