00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_UTIL_MESH_VOLUME_INTEGRATOR_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_UTIL_MESH_VOLUME_INTEGRATOR_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 namespace OpenTissue
00013 {
00014 namespace mesh
00015 {
00016
00017 template<typename mesh_type>
00018 class VolumeIntegrator
00019 {
00020 public:
00021
00022 typedef typename mesh_type::math_types math_types;
00023 typedef typename math_types::value_traits value_traits;
00024 typedef typename math_types::vector3_type vector3_type;
00025 typedef typename math_types::real_type real_type;
00026 typedef typename mesh_type::const_face_iterator const_face_iterator;
00027 typedef typename mesh_type::const_face_vertex_circulator const_face_vertex_circulator;
00028
00029 protected:
00030
00031 real_type P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
00032 real_type Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
00033 real_type T0;
00034 real_type T1[3];
00035 real_type T2[3];
00036 real_type TP[3];
00037
00038 public:
00039
00040 VolumeIntegrator( mesh_type const & mesh )
00041 {
00042 compute_volume_integrals(mesh);
00043 };
00044
00045 public:
00046
00047 template<typename real_type2>
00048 void get_volume( real_type2 & volume ) const
00049 {
00050 volume = T0;
00051 }
00052
00053 template<typename real_type2>
00054 void get_mass(real_type2 const & density, real_type2 & mass) const
00055 {
00056 mass = density*T0;
00057 }
00058
00059 template<typename real_type2,typename vector3_type2>
00060 void get_center_of_mass(real_type2 const & ,vector3_type2 & r) const
00061 {
00062 r(0) = T1[0] / T0;
00063 r(1) = T1[1] / T0;
00064 r(2) = T1[2] / T0;
00065 }
00066
00067 template<typename real_type2,typename matrix3x3_type>
00068 void get_inertia_tensor(real_type2 const & density,matrix3x3_type & I) const
00069 {
00070 I(0,0) = density * (T2[1] + T2[2]);
00071 I(1,1) = density * (T2[2] + T2[0]);
00072 I(2,2) = density * (T2[0] + T2[1]);
00073 I(0,1) = I(1,0) = - density * TP[0];
00074 I(1,2) = I(2,1) = - density * TP[1];
00075 I(2,0) = I(0,2) = - density * TP[2];
00076 }
00077
00078 protected:
00079
00080 void compute_projection_integrals(const_face_iterator face,int A,int B,int )
00081 {
00082 real_type a0, a1, da, b0, b1, db;
00083 real_type a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
00084 real_type a1_2, a1_3, b1_2, b1_3;
00085 real_type C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
00086 real_type Cab, Kab, Caab, Kaab, Cabb, Kabb;
00087 P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = static_cast<real_type>(0.0);
00088
00089 const_face_vertex_circulator cur(*face),end;
00090 const_face_vertex_circulator next(*face);++next;
00091 for(;cur!=end;++cur,++next)
00092 {
00093 a0 = cur->m_coord(A);
00094 b0 = cur->m_coord(B);
00095 a1 = next->m_coord(A);
00096 b1 = next->m_coord(B);
00097
00098 da = a1 - a0;
00099 db = b1 - b0;
00100 a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0;
00101 b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0;
00102 a1_2 = a1 * a1; a1_3 = a1_2 * a1;
00103 b1_2 = b1 * b1; b1_3 = b1_2 * b1;
00104 C1 = a1 + a0;
00105 Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4;
00106 Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4;
00107 Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2;
00108 Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3;
00109 Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
00110 Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
00111 P1 += db*C1;
00112 Pa += db*Ca;
00113 Paa += db*Caa;
00114 Paaa += db*Caaa;
00115 Pb += da*Cb;
00116 Pbb += da*Cbb;
00117 Pbbb += da*Cbbb;
00118 Pab += db*(b1*Cab + b0*Kab);
00119 Paab += db*(b1*Caab + b0*Kaab);
00120 Pabb += da*(a1*Cabb + a0*Kabb);
00121 }
00122
00123 P1 /= 2.0;
00124 Pa /= 6.0;
00125 Paa /= 12.0;
00126 Paaa /= 20.0;
00127 Pb /= -6.0;
00128 Pbb /= -12.0;
00129 Pbbb /= -20.0;
00130 Pab /= 24.0;
00131 Paab /= 60.0;
00132 Pabb /= -60.0;
00133 };
00134
00135 void compute_face_integrals(const_face_iterator face, vector3_type const & n, int A, int B, int C)
00136 {
00137 real_type w, k1, k2, k3, k4;
00138
00139 compute_projection_integrals(face,A,B,C);
00140
00141
00142 const_face_vertex_circulator p(*face);
00143 w = -n*p->m_coord;
00144
00145 k1 = 1 / n(C);
00146 k2 = k1 * k1;
00147 k3 = k2 * k1;
00148 k4 = k3 * k1;
00149
00150 Fa = k1 * Pa;
00151 Fb = k1 * Pb;
00152 Fc = -k2 * (n(A)*Pa + n(B)*Pb + w*P1);
00153
00154 Faa = k1 * Paa;
00155 Fbb = k1 * Pbb;
00156 Fcc = k3 * ((n(A)*n(A))*Paa + 2*n(A)*n(B)*Pab +(n(B)*n(B))*Pbb + w*(2*(n(A)*Pa + n(B)*Pb) + w*P1));
00157
00158 Faaa = k1 * Paaa;
00159 Fbbb = k1 * Pbbb;
00160 Fccc = -k4 * ((n(A)*n(A)*n(A))*Paaa + 3*(n(A)*n(A))*n(B)*Paab
00161 + 3*n(A)*(n(B)*n(B))*Pabb + (n(B)*n(B)*n(B))*Pbbb
00162 + 3*w*((n(A)*n(A))*Paa + 2*n(A)*n(B)*Pab + (n(B)*n(B))*Pbb)
00163 + w*w*(3*(n(A)*Pa + n(B)*Pb) + w*P1));
00164
00165 Faab = k1 * Paab;
00166 Fbbc = -k2 * (n(A)*Pabb + n(B)*Pbbb + w*Pbb);
00167 Fcca = k3 * ((n(A)*n(A))*Paaa + 2*n(A)*n(B)*Paab + (n(B)*n(B))*Pabb
00168 + w*(2*(n(A)*Paa + n(B)*Pab) + w*Pa));
00169 };
00170
00171 void compute_volume_integrals(mesh_type const & mesh)
00172 {
00173 T0 = T1[0] = T1[1] = T1[2] = T2[0] = T2[1] = T2[2] = TP[0] = TP[1] = TP[2] = static_cast<real_type>(0.0);
00174
00175 const_face_iterator end = mesh.face_end();
00176 const_face_iterator f = mesh.face_begin();
00177 for (;f!=end;++f)
00178 {
00179 vector3_type n;
00180 compute_face_normal(*f,n);
00181
00182 real_type nx = std::fabs(n(0));
00183 real_type ny = std::fabs(n(1));
00184 real_type nz = std::fabs(n(2));
00185
00186 enum { X = 0, Y = 1, Z = 2};
00187 int A,B,C;
00188
00189 if(nx > ny && nx > nz)
00190 C = X;
00191 else
00192 C = (ny > nz) ? Y : Z;
00193 A = (C + 1) % 3;
00194 B = (C + 2) % 3;
00195
00196 compute_face_integrals(f,n,A,B,C);
00197
00198 T0 += n(0) * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));
00199 T1[A] += n(A) * Faa;
00200 T1[B] += n(B) * Fbb;
00201 T1[C] += n(C) * Fcc;
00202 T2[A] += n(A) * Faaa;
00203 T2[B] += n(B) * Fbbb;
00204 T2[C] += n(C) * Fccc;
00205 TP[A] += n(A) * Faab;
00206 TP[B] += n(B) * Fbbc;
00207 TP[C] += n(C) * Fcca;
00208 }
00209 T1[0] /= 2; T1[1] /= 2; T1[2] /= 2;
00210 T2[0] /= 3; T2[1] /= 3; T2[2] /= 3;
00211 TP[0] /= 2; TP[1] /= 2; TP[2] /= 2;
00212 };
00213
00214 };
00215
00216 }
00217 }
00218
00219
00220 #endif