TriangleFEMForceField.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/forcefield/TriangleFEMForceField.h>
00026 #include <sofa/core/ObjectFactory.h>
00027 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00028 #include <sofa/helper/gl/template.h>
00029 #include <fstream> // for reading the file
00030 #include <iostream> //for debugging
00031 #include <vector>
00032 #include <sofa/defaulttype/Vec3Types.h>
00033 
00034 
00035 #ifdef _WIN32
00036 #include <windows.h>
00037 #endif
00038 
00039 
00040 // #define DEBUG_TRIANGLEFEM
00041 
00042 namespace sofa
00043 {
00044 
00045 namespace component
00046 {
00047 
00048 namespace forcefield
00049 {
00050 
00051 using namespace sofa::defaulttype;
00052 
00053 using std::cerr;
00054 using std::cout;
00055 using std::endl;
00056 
00057 template <class DataTypes>
00058 TriangleFEMForceField<DataTypes>::
00059 TriangleFEMForceField()
00060 : _mesh(NULL)
00061 , _indexedElements(NULL)
00062 , _initialPoints(initData(&_initialPoints, "initialPoints", "Initial Position"))
00063 , method(LARGE)
00064 , f_method(initData(&f_method,std::string("large"),"method","large: large displacements, small: small displacements"))
00065 , f_poisson(initData(&f_poisson,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00066 , f_young(initData(&f_young,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00067 , f_damping(initData(&f_damping,(Real)0.,"damping","Ratio damping/stiffness"))
00068 {}
00069 
00070 template <class DataTypes>
00071 TriangleFEMForceField<DataTypes>::~TriangleFEMForceField()
00072 {
00073 }
00074 
00075 
00076 template <class DataTypes>
00077 void TriangleFEMForceField<DataTypes>::init()
00078 {
00079   this->Inherited::init();
00080   if (f_method.getValue() == "small")
00081       method = SMALL;
00082   else if (f_method.getValue() == "large")
00083       method = LARGE;
00084 
00085   cerr<<"TriangleFEMForceField<DataTypes>::init(), node = "<<this->getContext()->getName()<<endl;
00086   _mesh = this->getContext()->getMeshTopology();
00087 
00088     if (_mesh==NULL || (_mesh->getTriangles().empty() && _mesh->getNbQuads()<=0))
00089     {
00090         std::cerr << "ERROR(TriangleFEMForceField): object must have a triangular MeshTopology.\n";
00091         return;
00092     }
00093     if (!_mesh->getTriangles().empty())
00094     {
00095         _indexedElements = & (_mesh->getTriangles());
00096     }
00097     else
00098     {
00099         sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles* trias = new sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles;
00100         int nbcubes = _mesh->getNbQuads();
00101         trias->reserve(nbcubes*2);
00102         for (int i=0;i<nbcubes;i++)
00103         {
00104             sofa::core::componentmodel::topology::BaseMeshTopology::Quad q = _mesh->getQuad(i);
00105             trias->push_back(Element(q[0],q[1],q[2]));
00106             trias->push_back(Element(q[0],q[2],q[3]));
00107         }
00108         _indexedElements = trias;
00109     }
00110 
00111     if (_initialPoints.getValue().size() == 0)
00112       {
00113     VecCoord& p = *this->mstate->getX();
00114     _initialPoints.setValue(p);
00115       }
00116 
00117     _strainDisplacements.resize(_indexedElements->size());
00118     _rotations.resize(_indexedElements->size());
00119 
00120     computeMaterialStiffnesses();
00121 
00122     initSmall();
00123     initLarge();
00124 }
00125 
00126 
00127 
00128 template <class DataTypes>
00129         void TriangleFEMForceField<DataTypes>::reinit()
00130 {
00131     if (f_method.getValue() == "small")
00132         method = SMALL;
00133     else if (f_method.getValue() == "large")
00134         method = LARGE;
00135 
00136     computeMaterialStiffnesses();
00137 
00138     initSmall();
00139     initLarge();
00140 }
00141 
00142 
00143 template <class DataTypes>
00144     void TriangleFEMForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& /*v*/)
00145 {
00146     f.resize(x.size());
00147 
00148     if(f_damping.getValue() != 0)
00149     {
00150         if(method == SMALL)
00151         {
00152             for( unsigned int i=0; i<_indexedElements->size(); i+=3 )
00153             {
00154                 accumulateForceSmall( f, x, i/3, true );
00155                 accumulateDampingSmall( f, i/3 );
00156             }
00157         }
00158         else
00159         {
00160             for( unsigned int i=0; i<_indexedElements->size(); i+=3 )
00161             {
00162                 accumulateForceLarge( f, x, i/3, true );
00163                 accumulateDampingLarge( f, i/3 );
00164             }
00165         }
00166     }
00167     else
00168     {
00169         if(method==SMALL)
00170         {
00171             typename VecElement::const_iterator it;
00172             unsigned int i(0);
00173 
00174             for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00175             {
00176                 accumulateForceSmall( f, x, i, true );
00177             }
00178         }
00179         else
00180         {
00181             typename VecElement::const_iterator it;
00182             unsigned int i(0);
00183 
00184             for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00185             {
00186                 accumulateForceLarge( f, x, i, true );
00187             }
00188         }
00189     }
00190 }
00191 
00192 
00193 template <class DataTypes>
00194     void TriangleFEMForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00195 {
00196     Real h=1;
00197     df.resize(dx.size());
00198 
00199     if (method == SMALL)
00200     {
00201         applyStiffnessSmall( df,h,dx );
00202     }
00203     else
00204     {
00205         applyStiffnessLarge( df,h,dx );
00206     }
00207 }
00208 
00209 template <class DataTypes>
00210     double TriangleFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord& /*x*/)
00211 {
00212     cerr<<"TriangleFEMForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00213     return 0;
00214 }
00215 
00216 template <class DataTypes>
00217 void TriangleFEMForceField<DataTypes>::applyStiffness( VecCoord& v, Real h, const VecCoord& x )
00218 {
00219     if (method == SMALL)
00220     {
00221         applyStiffnessSmall( v,h,x );
00222     }
00223     else
00224     {
00225         applyStiffnessLarge( v,h,x );
00226     }
00227 }
00228 
00229 
00230 template <class DataTypes>
00231 void TriangleFEMForceField<DataTypes>::computeStrainDisplacement( StrainDisplacement &J, Coord /*a*/, Coord b, Coord c )
00232 {
00233 #ifdef DEBUG_TRIANGLEFEM
00234     std::cout << "TriangleFEMForceField::computeStrainDisplacement\n";
00235 #endif
00236 
00237     //Coord ab_cross_ac = cross(b, c);
00238     Real determinant = b[0] * c[1]; // Surface
00239 
00240     J[0][0] = J[1][2] = -c[1] / determinant;
00241     J[0][2] = J[1][1] = (c[0] - b[0]) / determinant;
00242     J[2][0] = J[3][2] = c[1] / determinant;
00243     J[2][2] = J[3][1] = -c[0] / determinant;
00244     J[4][0] = J[5][2] = 0;
00245     J[4][2] = J[5][1] = b[0] / determinant;
00246     J[1][0] = J[3][0] = J[5][0] = J[0][1] = J[2][1] = J[4][1] = 0;
00247 }
00248 
00249 
00250 template <class DataTypes>
00251 void TriangleFEMForceField<DataTypes>::computeMaterialStiffnesses()
00252 {
00253     _materialsStiffnesses.resize(_indexedElements->size());
00254 
00255     for(unsigned i = 0; i < _indexedElements->size(); ++i)
00256     {
00257         _materialsStiffnesses[i][0][0] = 1;
00258         _materialsStiffnesses[i][0][1] = f_poisson.getValue();
00259         _materialsStiffnesses[i][0][2] = 0;
00260         _materialsStiffnesses[i][1][0] = f_poisson.getValue();
00261         _materialsStiffnesses[i][1][1] = 1;
00262         _materialsStiffnesses[i][1][2] = 0;
00263         _materialsStiffnesses[i][2][0] = 0;
00264         _materialsStiffnesses[i][2][1] = 0;
00265         _materialsStiffnesses[i][2][2] = 0.5f * (1 - f_poisson.getValue());
00266 
00267         _materialsStiffnesses[i] *= (f_young.getValue() / (12 * (1 - f_poisson.getValue() * f_poisson.getValue())));
00268     }
00269 }
00270 
00271 
00272 template <class DataTypes>
00273 void TriangleFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const MaterialStiffness &K, const StrainDisplacement &J )
00274 {
00275     Mat<3,6,Real> Jt;
00276     Jt.transpose( J );
00277 
00278     Vec<3,Real> JtD;
00279 
00280     // Optimisations: The following values are 0 (per computeStrainDisplacement )
00281 
00282     // Jt[0][1]
00283     // Jt[0][3]
00284     // Jt[0][4]
00285     // Jt[0][5]
00286     // Jt[1][0]
00287     // Jt[1][2]
00288     // Jt[1][4]
00289     // Jt[2][5]
00290 
00291 
00292     //  JtD = Jt * Depl;
00293 
00294     JtD[0] = Jt[0][0] * Depl[0] + /* Jt[0][1] * Depl[1] + */ Jt[0][2] * Depl[2]
00295              /* + Jt[0][3] * Depl[3] + Jt[0][4] * Depl[4] + Jt[0][5] * Depl[5] */ ;
00296 
00297     JtD[1] = /* Jt[1][0] * Depl[0] + */ Jt[1][1] * Depl[1] + /* Jt[1][2] * Depl[2] + */
00298              Jt[1][3] * Depl[3] + /* Jt[1][4] * Depl[4] + */ Jt[1][5] * Depl[5];
00299 
00300     JtD[2] = Jt[2][0] * Depl[0] + Jt[2][1] * Depl[1] + Jt[2][2] * Depl[2] +
00301              Jt[2][3] * Depl[3] + Jt[2][4] * Depl[4] /* + Jt[2][5] * Depl[5] */ ;
00302 
00303     Vec<3,Real> KJtD;
00304 
00305     //  KJtD = K * JtD;
00306 
00307     // Optimisations: The following values are 0 (per computeMaterialStiffnesses )
00308 
00309     // K[0][2]
00310     // K[1][2]
00311     // K[2][0]
00312     // K[2][1]
00313 
00314     KJtD[0] = K[0][0] * JtD[0] + K[0][1] * JtD[1] /* + K[0][2] * JtD[2] */;
00315 
00316     KJtD[1] = K[1][0] * JtD[0] + K[1][1] * JtD[1] /* + K[1][2] * JtD[2] */;
00317 
00318     KJtD[2] = /* K[2][0] * JtD[0] + K[2][1] * JtD[1] */ + K[2][2] * JtD[2];
00319 
00320     //  F = J * KJtD;
00321 
00322 
00323     // Optimisations: The following values are 0 (per computeStrainDisplacement )
00324 
00325     // J[0][1]
00326     // J[1][0]
00327     // J[2][1]
00328     // J[3][0]
00329     // J[4][0]
00330     // J[4][1]
00331     // J[5][0]
00332     // J[5][2]
00333 
00334     F[0] = J[0][0] * KJtD[0] + /* J[0][1] * KJtD[1] + */ J[0][2] * KJtD[2];
00335 
00336     F[1] = /* J[1][0] * KJtD[0] + */ J[1][1] * KJtD[1] + J[1][2] * KJtD[2];
00337 
00338     F[2] = J[2][0] * KJtD[0] + /* J[2][1] * KJtD[1] + */ J[2][2] * KJtD[2];
00339 
00340     F[3] = /* J[3][0] * KJtD[0] + */ J[3][1] * KJtD[1] + J[3][2] * KJtD[2];
00341 
00342     F[4] = /* J[4][0] * KJtD[0] + J[4][1] * KJtD[1] + */ J[4][2] * KJtD[2];
00343 
00344     F[5] = /* J[5][0] * KJtD[0] + */ J[5][1] * KJtD[1] /* + J[5][2] * KJtD[2] */ ;
00345 }
00346 
00347 
00348 /*
00349 ** SMALL DEFORMATION METHODS
00350 */
00351 
00352 
00353 template <class DataTypes>
00354 void TriangleFEMForceField<DataTypes>::initSmall()
00355 {
00356 
00357 #ifdef DEBUG_TRIANGLEFEM
00358     std::cout << "TriangleFEMForceField::initSmall\n";
00359 #endif
00360 
00361 }
00362 
00363 
00364 template <class DataTypes>
00365 void TriangleFEMForceField<DataTypes>::accumulateForceSmall( VecCoord &f, const VecCoord &p, Index elementIndex, bool implicit )
00366 {
00367 
00368 #ifdef DEBUG_TRIANGLEFEM
00369     std::cout << "TriangleFEMForceField::accumulateForceSmall\n";
00370 #endif
00371 
00372     Index a = (*_indexedElements)[elementIndex][0];
00373     Index b = (*_indexedElements)[elementIndex][1];
00374     Index c = (*_indexedElements)[elementIndex][2];
00375 
00376     Coord deforme_a, deforme_b, deforme_c;
00377     deforme_b = p[b]-p[a];
00378     deforme_c = p[c]-p[a];
00379     deforme_a = Coord(0,0,0);
00380 
00381     // displacements
00382     Displacement D;
00383     D[0] = 0;
00384     D[1] = 0;
00385     D[2] = (_initialPoints.getValue()[b][0]-_initialPoints.getValue()[a][0]) - deforme_b[0];
00386     D[3] = 0;
00387     D[4] = (_initialPoints.getValue()[c][0]-_initialPoints.getValue()[a][0]) - deforme_c[0];
00388     D[5] = (_initialPoints.getValue()[c][1]-_initialPoints.getValue()[a][1]) - deforme_c[1];
00389 
00390 
00391     StrainDisplacement J;
00392     computeStrainDisplacement(J,deforme_a,deforme_b,deforme_c);
00393     if (implicit)
00394         _strainDisplacements[elementIndex] = J;
00395 
00396     // compute force on element
00397     Displacement F;
00398     computeForce( F, D, _materialsStiffnesses[elementIndex], J );
00399 
00400     f[a] += Coord( F[0], F[1], 0);
00401     f[b] += Coord( F[2], F[3], 0);
00402     f[c] += Coord( F[4], F[5], 0);
00403 }
00404 
00405 
00406 template <class DataTypes>
00407 void TriangleFEMForceField<DataTypes>::accumulateDampingSmall(VecCoord&, Index )
00408 {
00409 
00410 #ifdef DEBUG_TRIANGLEFEM
00411     std::cout << "TriangleFEMForceField::accumulateDampingSmall\n";
00412 #endif
00413 
00414 }
00415 
00416 
00417 template <class DataTypes>
00418 void TriangleFEMForceField<DataTypes>::applyStiffnessSmall(VecCoord &v, Real h, const VecCoord &x)
00419 {
00420 
00421 #ifdef DEBUG_TRIANGLEFEM
00422     std::cout << "TriangleFEMForceField::applyStiffnessSmall\n";
00423 #endif
00424 
00425     typename VecElement::const_iterator it;
00426     unsigned int i(0);
00427 
00428     for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00429     {
00430         Index a = (*it)[0];
00431         Index b = (*it)[1];
00432         Index c = (*it)[2];
00433 
00434         Displacement X;
00435 
00436         X[0] = x[a][0];
00437         X[1] = x[a][1];
00438 
00439         X[2] = x[b][0];
00440         X[3] = x[b][1];
00441 
00442         X[4] = x[c][0];
00443         X[5] = x[c][1];
00444 
00445         Displacement F;
00446         computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i] );
00447 
00448         v[a] += Coord(-h*F[0], -h*F[1], 0);
00449         v[b] += Coord(-h*F[2], -h*F[3], 0);
00450         v[c] += Coord(-h*F[4], -h*F[5], 0);
00451     }
00452 }
00453 
00454 
00455 /*
00456 ** LARGE DEFORMATION METHODS
00457 */
00458 
00459 template <class DataTypes>
00460 void TriangleFEMForceField<DataTypes>::initLarge()
00461 {
00462 
00463 #ifdef DEBUG_TRIANGLEFEM
00464     std::cout << "TriangleFEMForceField::initLarge\n";
00465 #endif
00466 
00467     _rotatedInitialElements.resize(_indexedElements->size());
00468 
00469     typename VecElement::const_iterator it;
00470     unsigned int i(0);
00471 
00472     for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00473     {
00474         Index a = (*it)[0];
00475         Index b = (*it)[1];
00476         Index c = (*it)[2];
00477 
00478         // Rotation matrix (initial triangle/world)
00479         // first vector on first edge
00480         // second vector in the plane of the two first edges
00481         // third vector orthogonal to first and second
00482         Transformation R_0_1;
00483         //cerr<<"TriangleFEMForceField<DataTypes>::initLarge(), x.size() = "<<_object->getX()->size()<<", _initialPoints.getValue().size() = "<<_initialPoints.getValue().size()<<endl;
00484         computeRotationLarge( R_0_1, _initialPoints.getValue(), a, b, c );
00485 
00486         _rotatedInitialElements[i][0] = R_0_1 * _initialPoints.getValue()[a];
00487         _rotatedInitialElements[i][1] = R_0_1 * _initialPoints.getValue()[b];
00488         _rotatedInitialElements[i][2] = R_0_1 * _initialPoints.getValue()[c];
00489 
00490         _rotatedInitialElements[i][1] -= _rotatedInitialElements[i][0];
00491         _rotatedInitialElements[i][2] -= _rotatedInitialElements[i][0];
00492         _rotatedInitialElements[i][0] = Coord(0,0,0);
00493     }
00494 }
00495 
00496 
00497 template <class DataTypes>
00498 void TriangleFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, const VecCoord &p, const Index &a, const Index &b, const Index &c)
00499 {
00500 
00501 #ifdef DEBUG_TRIANGLEFEM
00502     std::cout << "TriangleFEMForceField::computeRotationLarge\n";
00503 #endif
00504 
00505     // first vector on first edge
00506     // second vector in the plane of the two first edges
00507     // third vector orthogonal to first and second
00508 
00509     Coord edgex = p[b] - p[a];
00510     edgex.normalize();
00511 
00512     Coord edgey = p[c] - p[a];
00513     edgey.normalize();
00514 
00515     Coord edgez;
00516     edgez = cross(edgex, edgey);
00517     edgez.normalize();
00518 
00519     edgey = cross(edgez, edgex);
00520     edgey.normalize();
00521 
00522     r[0][0] = edgex[0];
00523     r[0][1] = edgex[1];
00524     r[0][2] = edgex[2];
00525     r[1][0] = edgey[0];
00526     r[1][1] = edgey[1];
00527     r[1][2] = edgey[2];
00528     r[2][0] = edgez[0];
00529     r[2][1] = edgez[1];
00530     r[2][2] = edgez[2];
00531 }
00532 
00533 
00534 template <class DataTypes>
00535 void TriangleFEMForceField<DataTypes>::accumulateForceLarge(VecCoord &f, const VecCoord &p, Index elementIndex, bool implicit )
00536 {
00537 
00538 #ifdef DEBUG_TRIANGLEFEM
00539     std::cout << "TriangleFEMForceField::accumulateForceLarge\n";
00540 #endif
00541 
00542     Index a = (*_indexedElements)[elementIndex][0];
00543     Index b = (*_indexedElements)[elementIndex][1];
00544     Index c = (*_indexedElements)[elementIndex][2];
00545 
00546     // Rotation matrix (deformed and displaced Triangle/world)
00547     Transformation R_2_0, R_0_2;
00548     computeRotationLarge( R_0_2, p, a, b, c);
00549     R_2_0.transpose(R_0_2);
00550 
00551 
00552     // positions of the deformed and displaced Tetrahedre in its frame
00553     Coord deforme_a, deforme_b, deforme_c;
00554     //deforme_a = R_0_2 * p[a];
00555     //deforme_b = R_0_2 * p[b];
00556     //deforme_c = R_0_2 * p[c];
00557     //deforme_b -= deforme_a;
00558     //deforme_c -= deforme_a;
00559     //deforme_a = Coord(0,0,0);
00560     deforme_b = R_0_2 * (p[b]-p[a]);
00561     deforme_c = R_0_2 * (p[c]-p[a]);
00562 
00563     // displacements
00564     Displacement D;
00565     D[0] = 0;
00566     D[1] = 0;
00567     D[2] = _rotatedInitialElements[elementIndex][1][0] - deforme_b[0];
00568     D[3] = 0;
00569     D[4] = _rotatedInitialElements[elementIndex][2][0] - deforme_c[0];
00570     D[5] = _rotatedInitialElements[elementIndex][2][1] - deforme_c[1];
00571 
00572     // shape functions matrix
00573     StrainDisplacement J;
00574     computeStrainDisplacement(J,deforme_a,deforme_b,deforme_c);
00575 
00576     if(implicit)
00577     {
00578         _strainDisplacements[elementIndex] = J;
00579         _rotations[elementIndex] = R_2_0 ;
00580     }
00581 
00582     // compute force on element
00583     Displacement F;
00584     computeForce( F, D, _materialsStiffnesses[elementIndex], J );
00585 
00586     f[a] += R_2_0 * Coord(F[0], F[1], 0);
00587     f[b] += R_2_0 * Coord(F[2], F[3], 0);
00588     f[c] += R_2_0 * Coord(F[4], F[5], 0);
00589 }
00590 
00591 
00592 template <class DataTypes>
00593 void TriangleFEMForceField<DataTypes>::accumulateDampingLarge(VecCoord &, Index )
00594 {
00595 
00596 #ifdef DEBUG_TRIANGLEFEM
00597     std::cout << "TriangleFEMForceField::accumulateDampingLarge\n";
00598 #endif
00599 
00600 }
00601 
00602 
00603 template <class DataTypes>
00604 void TriangleFEMForceField<DataTypes>::applyStiffnessLarge(VecCoord &v, Real h, const VecCoord &x)
00605 {
00606 
00607 #ifdef DEBUG_TRIANGLEFEM
00608     std::cout << "TriangleFEMForceField::applyStiffnessLarge\n";
00609 #endif
00610 
00611     typename VecElement::const_iterator it;
00612     unsigned int i(0);
00613 
00614     for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00615     {
00616         Index a = (*it)[0];
00617         Index b = (*it)[1];
00618         Index c = (*it)[2];
00619 
00620         Transformation R_0_2;
00621         R_0_2.transpose(_rotations[i]);
00622 
00623         Displacement X;
00624         Coord x_2;
00625 
00626         x_2 = R_0_2 * x[a];
00627         X[0] = x_2[0];
00628         X[1] = x_2[1];
00629 
00630         x_2 = R_0_2 * x[b];
00631         X[2] = x_2[0];
00632         X[3] = x_2[1];
00633 
00634         x_2 = R_0_2 * x[c];
00635         X[4] = x_2[0];
00636         X[5] = x_2[1];
00637 
00638         Displacement F;
00639         computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i] );
00640 
00641         v[a] += _rotations[i] * Coord(-h*F[0], -h*F[1], 0);
00642         v[b] += _rotations[i] * Coord(-h*F[2], -h*F[3], 0);
00643         v[c] += _rotations[i] * Coord(-h*F[4], -h*F[5], 0);
00644     }
00645 }
00646 
00647 
00648 template<class DataTypes>
00649 void TriangleFEMForceField<DataTypes>::draw()
00650 {
00651     if (!getContext()->getShowForceFields())
00652         return;
00653 //     if (!this->_object)
00654 //         return;
00655 
00656     if (getContext()->getShowWireFrame())
00657         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00658 
00659     const VecCoord& x = *this->mstate->getX();
00660 
00661     glDisable(GL_LIGHTING);
00662 
00663     glBegin(GL_TRIANGLES);
00664     typename VecElement::const_iterator it;
00665     for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it)
00666     {
00667         Index a = (*it)[0];
00668         Index b = (*it)[1];
00669         Index c = (*it)[2];
00670 
00671         glColor4f(0,1,0,1);
00672         helper::gl::glVertexT(x[a]);
00673         glColor4f(0,0.5,0.5,1);
00674         helper::gl::glVertexT(x[b]);
00675         glColor4f(0,0,1,1);
00676         helper::gl::glVertexT(x[c]);
00677     }
00678     glEnd();
00679 
00680     if (getContext()->getShowWireFrame())
00681         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00682 }
00683 
00684 SOFA_DECL_CLASS(TriangleFEMForceField)
00685 
00686 using namespace sofa::defaulttype;
00687 
00688 
00689 
00690 // Register in the Factory
00691 int TriangleFEMForceFieldClass = core::RegisterObject("Triangular finite elements")
00692 #ifndef SOFA_FLOAT
00693 .add< TriangleFEMForceField<Vec3dTypes> >()
00694 #endif
00695 #ifndef SOFA_DOUBLE
00696 .add< TriangleFEMForceField<Vec3fTypes> >()
00697 #endif
00698 ;
00699 
00700 #ifndef SOFA_FLOAT
00701 template class TriangleFEMForceField<Vec3dTypes>;
00702 #endif
00703 #ifndef SOFA_DOUBLE
00704 template class TriangleFEMForceField<Vec3fTypes>;
00705 #endif
00706 
00707 } // namespace forcefield
00708 
00709 } // namespace component
00710 
00711 } // namespace sofa

Generated on Sun Nov 23 03:14:48 2008 for Sofa by  doxygen 1.5.7.1