PrecomputedConstraintCorrection.inl

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 #ifndef SOFA_CORE_COMPONENTMODEL_COLLISION_CONTACTCORRECTION_INL
00026 #define SOFA_CORE_COMPONENTMODEL_COLLISION_CONTACTCORRECTION_INL
00027 
00028 #include "PrecomputedConstraintCorrection.h"
00029 #include <sofa/defaulttype/RigidTypes.h>
00030 #include <sofa/simulation/tree/GNode.h>
00031 #include <sofa/component/mass/UniformMass.h>
00032 #include <sofa/simulation/common/MechanicalVisitor.h>
00033 
00034 //compliance computation include
00035 #include <sofa/component/odesolver/CGImplicitSolver.h>
00036 //#include <glib.h>
00037 #include <sstream>
00038 #include <list>
00039 
00040 namespace sofa
00041 {
00042 
00043   namespace component
00044   {
00045 
00046     namespace constraint
00047     {
00048 #define MAX_NUM_CONSTRAINT_PER_NODE 100
00049 #define EPS_UNITARY_FORCE 0.01
00050 
00051       using namespace sofa::component::odesolver;
00052 
00053       template<class DataTypes>
00054       PrecomputedConstraintCorrection<DataTypes>::PrecomputedConstraintCorrection(behavior::MechanicalState<DataTypes> *mm)
00055   : _rotations(false)
00056   , f_rotations(initDataPtr(&f_rotations,&_rotations,"rotations",""))
00057   , _restRotations(false)
00058   , f_restRotations(initDataPtr(&f_restRotations,&_restRotations,"restDeformations",""))
00059   , mstate(mm)
00060   , appCompliance(NULL)
00061   , _indexNodeSparseCompliance(NULL)
00062       {
00063       }
00064 
00065       template<class DataTypes>
00066       PrecomputedConstraintCorrection<DataTypes>::~PrecomputedConstraintCorrection()
00067       {
00068     if(appCompliance != NULL)
00069       delete [] appCompliance;
00070     if(_indexNodeSparseCompliance != NULL)
00071       delete [] _indexNodeSparseCompliance;
00072       }
00073 
00074 
00075 
00077       //   Precomputation of the Constraint Correction for all type of data
00079 
00080       template<class DataTypes>
00081       void PrecomputedConstraintCorrection<DataTypes>::init()
00082       {
00083 
00084     f_rotations.beginEdit();
00085     f_restRotations.beginEdit();
00086     mstate = dynamic_cast< behavior::MechanicalState<DataTypes>* >(getContext()->getMechanicalState());
00087     const VecDeriv& v0 = *mstate->getV();
00088 
00089     nbNodes = v0.size();
00090     
00091     if (nbNodes==0){
00092       std::cout << "WARNING : No degree of freedom" << endl;;
00093       return;
00094     }
00095     dof_on_node = v0[0].size();
00096 
00097 
00098     nbRows = nbNodes*dof_on_node;
00099     nbCols = nbNodes*dof_on_node;
00100     std::cout << "size : " << nbRows << " " << nbCols << std::endl;
00101     appCompliance = new Real[nbRows * nbCols];
00102 
00103     
00104     double dt = this->getContext()->getDt();
00105 
00106     std::stringstream ss;
00107     
00108     ss << this->getContext()->getName() << ".comp";
00109     
00110     std::ifstream compFileIn(ss.str().c_str(), std::ifstream::binary);
00111     
00112     std::cout << "try to open : " << ss.str() << endl;
00113     
00114     if(compFileIn.good())
00115       {
00116         std::cout << "file open : " << ss.str() << " compliance being loaded" << endl;
00117         //complianceLoaded = true;
00118         compFileIn.read((char*)appCompliance, nbCols * nbRows*sizeof(double));
00119         compFileIn.close();
00120       }
00121     else 
00122       {
00123         std::cout << "can not open : " << ss.str() << " compliance being built" << endl;
00124     
00125         // for the intial computation, the gravity has to be put at 0
00126         const Vec3d gravity = this->getContext()->getGravityInWorld();
00127         const Vec3d gravity_zero(0.0,0.0,0.0);
00128         this->getContext()->setGravityInWorld(gravity_zero);
00129 
00130         //complianceLoaded = true;
00131         VecDeriv& force = *mstate->getExternalForces();
00132         force.clear();
00133         force.resize(nbNodes);
00134         //v.clear();
00135         //v.resize(v0.size());//computeDf
00136         CGImplicitSolver* odeSolver = dynamic_cast<CGImplicitSolver*>(dynamic_cast<simulation::tree::GNode *>(this->getContext())->solver[0]);
00137 
00138         if (odeSolver==NULL){
00139           std::cout << "WARNING : PrecomputedContactCorrection Must be associated with CGImplicitSolver for the precomputation " << std::endl;
00140           std::cout << "No Precomputation " << std::endl;
00141           return;
00142         }           
00143         else
00144           std::cout << "use solver CGImplicitSolver " << std::endl;
00145 
00147         double buf_tolerance = (double) odeSolver->f_tolerance.getValue();
00148         int    buf_maxIter   = (int) odeSolver->f_maxIter.getValue();
00149         double buf_threshold = (double) odeSolver->f_smallDenominatorThreshold.getValue();
00150         odeSolver->f_tolerance.setValue(1e-20);
00151         odeSolver->f_maxIter.setValue(500);
00152         odeSolver->f_smallDenominatorThreshold.setValue(1e-35);
00154 
00155         VecDeriv& velocity = *mstate->getV();
00156         VecCoord& pos=*mstate->getX();
00157         VecCoord& pos0=*mstate->getX0();
00158 
00159 
00160 
00161         for(unsigned int f = 0 ; f < nbNodes ; f++){
00162           std::cout << "inverse cols node : " << f << std::endl;
00163           Deriv unitary_force;
00164 
00165           for (unsigned int i=0; i<dof_on_node; i++)    {
00166         unitary_force.clear();
00167         unitary_force[i]=1.0;
00168         force[f] = unitary_force;
00170         velocity.clear();
00171         velocity.resize(nbNodes);
00172         for (unsigned int n=0; n<nbNodes; n++)
00173           pos[n] = pos0[n];
00175 
00176 
00177         //odeSolver->computeContactForce(force);
00178         odeSolver->solve(dt);
00179         velocity = *mstate->getV();
00180 
00181         for (unsigned int v=0; v<nbNodes; v++){
00182 
00183           for (unsigned int j=0; j<dof_on_node; j++)    {
00184             appCompliance[(v*dof_on_node+j)*nbCols + (f*dof_on_node+i) ] = velocity[v][j] / unitary_force[i];
00185           } 
00186         }
00187           }
00188           unitary_force.clear();
00189           force[f] = unitary_force;
00190         }
00192         // gravity is reset at its previous value
00193         this->getContext()->setGravityInWorld(gravity);     
00194         odeSolver->f_tolerance.setValue(buf_tolerance);
00195         odeSolver->f_maxIter.setValue(buf_maxIter);
00196         odeSolver->f_smallDenominatorThreshold.setValue(buf_threshold);
00198         std::ofstream compFileOut(ss.str().c_str(), std::fstream::out | std::fstream::binary);
00199         compFileOut.write((char*)appCompliance, nbCols * nbRows*sizeof(double));
00200         compFileOut.close();
00201       }
00202 
00203     // Optimisation for the computation of W
00204     _indexNodeSparseCompliance = new int[v0.size()];
00205     _sparseCompliance.resize(v0.size()*MAX_NUM_CONSTRAINT_PER_NODE);
00206 
00207 
00209     //std::cout << "Matrix compliance" ;
00210 
00211     //for (unsigned int i=0; i<100 && i<nbCols; i++){
00212     //  std::cout << std::endl;
00213     //  for (unsigned int j=0; j<100 && j<nbCols; j++)
00214     //  { 
00215     //      std::cout <<" \t "<< appCompliance[j*nbCols + i];
00216     //  }
00217     //}
00218     //std::cout << "quit init "  << endl;
00219 
00220     std::cout << "----------- Test Quaternions --------------" << std::endl;
00221 
00222     // rotation de -Pi/2 autour de z en init
00223     Quat q0(0,0,-0.7071067811865475, 0.7071067811865475);
00224     q0.normalize();
00225 
00226 
00227     // rotation de -Pi/2 autour de x dans le repËre dÈfini par q0; (=rotation Pi/2 autour de l'axe y dans le repËre global)
00228     Quat q_q0(-0.7071067811865475,0,0,0.7071067811865475);
00229     q_q0.normalize();
00230 
00231 
00232     // calcul de la rotation Èquivalente dans le repËre global;
00233     Quat q = q0 * q_q0;
00234     q.normalize();
00235 
00236     // test des rotations:
00237     std::cout<<"VecX = "<<q.rotate( Vec3d(1.0,0.0,0.0) )<<std::endl;
00238     std::cout<<"VecY = "<<q.rotate( Vec3d(0.0,1.0,0.0) )<<std::endl;
00239     std::cout<<"VecZ = "<<q.rotate( Vec3d(0.0,0.0,1.0) )<<std::endl;
00240 
00241 
00242     // on veut maintenant retrouver l'Èquivalent de q_q0 dans le repËre global
00243     // c'est ‡ dire une rotation de Pi/2 autour de l'axe y
00244     Quat q_test = q * q0.inverse();
00245 
00246     std::cout<<"q_test = "<<q_test<<std::endl;
00247 
00248     std::cout<<"Alpha = "<<q_test.toEulerVector()<< " doit valoir une rotation de Pi/2 autour de l'axe y"<<std::endl;
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257       }
00258 
00259       template<>
00260       PrecomputedConstraintCorrection<defaulttype::Vec3Types>::~PrecomputedConstraintCorrection()
00261       {
00262     delete [] appCompliance;
00263       }
00264 
00265 
00266       template<class DataTypes>
00267       void PrecomputedConstraintCorrection<DataTypes>::getCompliance(defaulttype::BaseMatrix* W)
00268       {
00269 
00270     VecConst& constraints = *mstate->getC();
00271     
00272     unsigned int numConstraints = constraints.size();
00273 
00275     //gatherConstraints();
00277 
00279     if(_rotations)  
00280       rotateConstraints();
00282 
00283 
00285     std::list<int> activeDof;
00286     for(unsigned int c1 = 0; c1 < numConstraints; c1++)
00287       {         
00288         for(unsigned int i = 0; i < constraints[c1].size(); i++)
00289           activeDof.push_back(constraints[c1][i].index);
00290       }
00291     //unsigned int numNodes1 = activeDof.size();
00292     //std::cout<< "numNodes : avant = "<<numNodes1;
00293     activeDof.sort();
00294     activeDof.unique();
00295     //  unsigned int numNodes = activeDof.size();
00296     //std::cout<< " apres = "<<numNodes<<std::endl;
00297 
00298 
00300     unsigned int offset, offset2;
00301     unsigned int i,j,ii,jj, curRowConst, curColConst, sizeCurColConst, sizeCurRowConst, it;
00302     Deriv Vbuf;
00303     int indexCurColConst, indexCurRowConst;
00304     it=0;
00305 
00307     //std::vector<Deriv> sparseCompliance;
00308     std::list<int>::iterator IterateurListe;
00309     for(IterateurListe=activeDof.begin();IterateurListe!=activeDof.end();IterateurListe++){
00310       int NodeIdx = (*IterateurListe);
00311       _indexNodeSparseCompliance[NodeIdx]=it;
00312       for(curColConst = 0; curColConst < numConstraints; curColConst++)
00313         {
00314           sizeCurColConst = constraints[curColConst].size();
00315           indexCurColConst = mstate->getConstraintId()[curColConst];
00316 
00317           const Const& c2 = constraints[curColConst];
00318 
00319           Vbuf.clear();
00320           for(j = 0; j < sizeCurColConst; j++)
00321         {
00322           const Deriv& n2 = c2[j].data;
00323           offset = dof_on_node*(NodeIdx * nbCols +  c2[j].index);
00324 
00325           for (ii=0; ii<dof_on_node; ii++)
00326             {
00327               offset2 = offset+ii*nbCols;
00328               for (jj=0; jj<dof_on_node; jj++)
00329             {
00330               Vbuf[ii] += appCompliance[offset2 + jj] * n2[jj];
00331             }
00332             }
00333         }
00334           _sparseCompliance[it]=Vbuf;
00335           it++;
00336         }
00337     }
00338 
00339 
00340     for(curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00341       {
00342         sizeCurRowConst = constraints[curRowConst].size(); //number of nodes in constraint
00343         indexCurRowConst = mstate->getConstraintId()[curRowConst];//global index of constraint
00344 
00345         const Const& c1 = constraints[curRowConst];
00346         for(i = 0; i < sizeCurRowConst; i++)
00347           {
00348             
00349         const int NodeIdx  = c1[i].index;
00350         const Deriv& n1 = c1[i].data;           
00351 
00352         unsigned int toto =(unsigned int) _indexNodeSparseCompliance[NodeIdx];
00353 
00354         for(curColConst = curRowConst; curColConst < numConstraints; curColConst++)
00355           {     
00356             indexCurColConst = mstate->getConstraintId()[curColConst];
00357             double w = _sparseCompliance[toto + curColConst]*n1;
00358             //W[indexCurRowConst][indexCurColConst] += w;
00359             //std::cout << "W("<<indexCurRowConst<<","<<indexCurColConst<<") = "<<w<<std::endl;
00360             W->add(indexCurRowConst, indexCurColConst, w);
00361             if (indexCurRowConst != indexCurColConst)
00362               W->add(indexCurColConst, indexCurRowConst, w);
00363           }
00364           }
00365         /*      
00366         //Compliance matrix is symetric ?
00367         for(unsigned int curColConst = curRowConst+1; curColConst < numConstraints; curColConst++)
00368         {
00369         int indexCurColConst = mstate->getConstraintId()[curColConst];
00370         W[indexCurColConst][indexCurRowConst] = W[indexCurRowConst][indexCurColConst];
00371         }
00372         */
00373       }
00374       }
00375 
00376       template<class DataTypes>
00377       void PrecomputedConstraintCorrection<DataTypes>::applyContactForce(const defaulttype::BaseVector *f)
00378       {
00379     VecDeriv& force = *mstate->getExternalForces();
00380     VecConst& constraints = *mstate->getC();
00381     unsigned int numConstraints = constraints.size();
00382 
00383     VecDeriv& dx = *mstate->getDx();
00384     VecCoord& x = *mstate->getX();
00385     VecDeriv& v = *mstate->getV();
00386     VecDeriv v_free = *mstate->getVfree();
00387     VecCoord x_free = *mstate->getXfree();
00388     double dt = this->getContext()->getDt();
00389 
00390 
00391     // ici on fait comme avant 
00392     // Euler integration... will be done in the "integrator" as soon as it exists !
00393     dx.clear();
00394     dx.resize(v.size());
00395     
00396     force.clear();
00397     force.resize(x_free.size());
00398 
00399     std::list<int> activeDof;
00400 
00401     //  std::cout<<"First list:"<<std::endl;
00402     for(unsigned int c1 = 0; c1 < numConstraints; c1++)
00403       {
00404         int indexC1 = mstate->getConstraintId()[c1];
00405 
00406             double fC1 = (Real)f->element(indexC1);
00407             //std::cout << "fC("<<indexC1<<")="<<fC1<<std::endl;
00408 
00409         if (fC1 != 0.0)
00410           {
00411             
00412         const int sizeC1 = constraints[c1].size();
00413         for(int i = 0; i < sizeC1; i++)
00414           { 
00415             //on ne fait pas passer les forces du repere courant a celui initial ? 
00416             // <-non, car elles ont deja ete tournees car on utilise une reference dans getCompliance !!!
00417             const Deriv& toto =  constraints[c1][i].data * fC1;
00418             force[constraints[c1][i].index] += toto;
00419             activeDof.push_back(constraints[c1][i].index);
00420           }
00421           }
00422       }
00423 
00424     activeDof.sort();
00425     activeDof.unique();
00426 
00427     //for (unsigned int i=0; i< force.size(); i++)
00428     //    std::cout << "f("<<i<<")="<<force[i]<<std::endl;
00429 
00430     std::list<int>::iterator IterateurListe;
00431     unsigned int i;
00432     unsigned int offset, offset2;
00433     for(IterateurListe=activeDof.begin();IterateurListe!=activeDof.end();IterateurListe++){
00434       int f = (*IterateurListe);
00435 
00436       for (i=0; i< dof_on_node; i++)
00437         {
00438           Fbuf[i] = force[f][i];
00439         }
00440       for(unsigned int v = 0 ; v < dx.size() ; v++)
00441         {
00442           offset =  v * dof_on_node * nbCols + f*dof_on_node;
00443           for (unsigned int j=0; j< dof_on_node; j++)
00444         {
00445           offset2 = offset+ j*nbCols;
00446           DXbuf=0.0;
00447           for (i=0; i< dof_on_node; i++)
00448             {
00449               DXbuf += appCompliance[ offset2 + i ] * Fbuf[i];
00450             }
00451           dx[v][j]+=DXbuf;
00452         }
00453         }
00454     }
00455 
00456 
00457     force.clear();
00458     force.resize(x_free.size());
00459 
00460     if(_rotations)
00461       rotateResponse();
00462 
00463 
00464     for (unsigned int i=0; i< dx.size(); i++)
00465       {
00466         //std::cout << "dx("<<i<<")="<<dx[i]<<std::endl;
00467         x[i] = x_free[i];
00468         v[i] = v_free[i];
00469 
00470         x[i] += dx[i];
00471         v[i] += dx[i]*(1/dt);
00472       }
00473       }
00474 
00475 
00476 
00477       /*
00478     template<>
00479     void PrecomputedConstraintCorrection<defaulttype::Rigid3Types>::applyContactForce(double *f)
00480     {
00481     VecDeriv& force = *mstate->getExternalForces();
00482     const VecConst& constraints = *mstate->getC();
00483     Deriv weighedNormal;
00484 
00485     const sofa::defaulttype::Rigid3Mass* massValue;
00486 
00487     simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00488 
00489     if (node != NULL)
00490     {
00491     core::componentmodel::behavior::BaseMass*_m = node->mass;
00492     component::mass::UniformMass<defaulttype::Rigid3Types, defaulttype::Rigid3Mass> *m = dynamic_cast<component::mass::UniformMass<defaulttype::Rigid3Types, defaulttype::Rigid3Mass>*> (_m);
00493     massValue = &( m->getMass());
00494     }
00495     else
00496     {
00497     massValue = new sofa::defaulttype::Rigid3Mass();
00498     printf("\n WARNING : node is not found => massValue could be false in getCompliance function");
00499     }
00500 
00501 
00502     double dt = this->getContext()->getDt();
00503 
00504     force.resize(0);
00505     force.resize(1);
00506     force[0] = Deriv();
00507 
00508     int numConstraints = constraints.size();
00509 
00510     for(int c1 = 0; c1 < numConstraints; c1++)
00511     {
00512     int indexC1 = mstate->getConstraintId()[c1];
00513 
00514     if (f[indexC1] != 0.0)
00515     {
00516     int sizeC1 = constraints[c1].size();
00517     for(int i = 0; i < sizeC1; i++)
00518     {   
00519     weighedNormal = constraints[c1][i].data; // weighted normal
00520     force[0].getVCenter() += weighedNormal.getVCenter() * f[indexC1];
00521     force[0].getVOrientation() += weighedNormal.getVOrientation() * f[indexC1];
00522     }
00523     }
00524     }
00525 
00526 
00527     VecDeriv& dx = *mstate->getDx();
00528     VecCoord& x = *mstate->getX();
00529     VecDeriv& v = *mstate->getV();
00530     VecDeriv& v_free = *mstate->getVfree();
00531     VecCoord& x_free = *mstate->getXfree();
00532 
00533 
00534     //  mstate->setX(x_free);
00535     //  mstate->setV(v_free);
00536     x[0]=x_free[0];
00537     v[0]=v_free[0];
00538 
00539     // Euler integration... will be done in the "integrator" as soon as it exists !
00540     dx.resize(v.size());
00541     dx[0] = force[0] / (*massValue);
00542     dx[0] *= dt;
00543     v[0] += dx[0];
00544     dx[0] *= dt;
00545     x[0] += dx[0];
00546     //  simulation::tree::MechanicalPropagateAndAddDxVisitor(dx).execute(this->getContext());
00547 
00548     }
00549 
00550 
00551     template<>
00552     void PrecomputedConstraintCorrection<defaulttype::Vec1dTypes>::applyContactForce(double *f){
00553 
00554 
00555     VecDeriv& force = *mstate->getExternalForces();
00556     const VecConst& constraints = *mstate->getC();
00557     unsigned int numConstraints = constraints.size();
00558 
00559     force.resize((*mstate->getX()).size());
00560 
00561     for(unsigned int c1 = 0; c1 < numConstraints; c1++)
00562     {
00563     int indexC1 = mstate->getConstraintId()[c1];
00564 
00565     if (f[indexC1] != 0.0)
00566     {
00567     int sizeC1 = constraints[c1].size();
00568     for(int i = 0; i < sizeC1; i++)
00569     {   
00570     force[constraints[c1][i].index] += constraints[c1][i].data * f[indexC1];
00571     }
00572     }
00573     }
00574 
00575     VecDeriv& dx = *mstate->getDx();
00576     VecCoord& x = *mstate->getX();
00577     VecDeriv& v = *mstate->getV();
00578     VecDeriv& v_free = *mstate->getVfree();
00579     VecCoord& x_free = *mstate->getXfree();
00580     double dt = this->getContext()->getDt();
00581 
00582 
00583     // Euler integration... will be done in the "integrator" as soon as it exists !
00584     dx.resize(v.size());
00585 
00586     for (unsigned int i=0; i<dx.size(); i++)
00587     {
00588     x[i] = x_free[i];
00589     v[i] = v_free[i];
00590     dx[i] = force[i]/10000.0;
00591     x[i] += dx[i];
00592     v[i] += dx[i]/dt;
00593     }
00594     }
00595 
00596 
00597       */
00598       template<class DataTypes>
00599       void PrecomputedConstraintCorrection<DataTypes>::resetContactForce()
00600       {
00601     VecDeriv& force = *mstate->getExternalForces();
00602     for( unsigned i=0; i<force.size(); ++i )
00603       force[i] = Deriv();
00604       }
00605 
00606       template<class DataTypes>
00607       void PrecomputedConstraintCorrection<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00608       {
00609     this->Inherit::parse(arg);
00610       }
00611 #ifndef SOFA_FLOAT
00612 
00613       template<>
00614       void PrecomputedConstraintCorrection<defaulttype::Vec3dTypes>::rotateConstraints()
00615       {
00616     VecConst& constraints = *mstate->getC();
00617     unsigned int numConstraints = constraints.size();
00618 
00619     simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00620 
00621     sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes>* forceField = NULL;
00622     if (node != NULL)
00623       {
00624         //      core::componentmodel::behavior::BaseForceField* _forceField = node->forceField[1];
00625         forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes> > ();
00626       }
00627     else
00628       {
00629         cout << "No rotation defined : only defined for TetrahedronFEMForceField !";
00630         return;
00631       }
00632 
00633 
00634     //std::cout << "start rotating normals " << g_timer_elapsed(timer, &micro) << std::endl;
00635     //  int sizemax=0;
00636     //  int index_const = -1;
00637     // on fait tourner les normales (en les ramenant dans le "pseudo" repere initial) //
00638     for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00639       {
00640         int sizeCurRowConst = constraints[curRowConst].size(); //number of nodes in constraint
00641 
00642         //Rmk : theres is one constraint for each contact direction, i.e. normal, tangent1, tangent2.
00643         for(int i = 0; i < sizeCurRowConst; i++)
00644           {
00645         const int localRowNodeIdx = constraints[curRowConst][i].index;
00646         Transformation Ri;
00647         forceField->getRotation(Ri, localRowNodeIdx);
00648         Ri.transpose();
00649         // on passe les normales du repere global au repere local
00650         const Deriv& n_i = Ri * constraints[curRowConst][i].data;
00651         constraints[curRowConst][i].data.x() =  n_i.x();
00652         constraints[curRowConst][i].data.y() =  n_i.y();
00653         constraints[curRowConst][i].data.z() =  n_i.z();
00654           }
00655         /*
00656         // test pour voir si on peut reduire le nombre de contrainte 
00657         if (sizeCurRowConst > sizemax)
00658         {
00659         sizemax = sizeCurRowConst;
00660         index_const = curRowConst;
00661         }
00662         */
00663       }
00664       }
00665 
00666 
00667       template<>
00668       void PrecomputedConstraintCorrection<defaulttype::Rigid3dTypes>::rotateConstraints()
00669       {
00670     VecCoord& x = *mstate->getX();  
00671     VecConst& constraints = *mstate->getC();
00672     VecCoord& x0 = *mstate->getX0();
00673 
00674     unsigned int numConstraints = constraints.size();
00675     //  int sizemax=0;
00676     //  int index_const = -1;
00677     // on fait tourner les normales (en les ramenant dans le "pseudo" repere initial) //
00678     for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00679       {
00680         int sizeCurRowConst = constraints[curRowConst].size(); //number of nodes in constraint
00681 
00682         for(int i = 0; i < sizeCurRowConst; i++)
00683           {
00684         const int localRowNodeIdx = constraints[curRowConst][i].index;
00685         Quat q;
00686         if (_restRotations)
00687           q = x[localRowNodeIdx].getOrientation() * x0[localRowNodeIdx].getOrientation().inverse();
00688         else
00689           q = x[localRowNodeIdx].getOrientation();
00690 
00691 
00692         Vec3d n_i = q.inverseRotate(constraints[curRowConst][i].data.getVCenter());
00693         Vec3d wn_i= q.inverseRotate(constraints[curRowConst][i].data.getVOrientation());
00694 
00695         // on passe les normales du repere global au repere local
00696         constraints[curRowConst][i].data.getVCenter() = n_i;
00697         constraints[curRowConst][i].data.getVOrientation() = wn_i;
00698 
00699           }
00700       }
00701       }
00702 
00703 
00704 
00705       template<>
00706       void PrecomputedConstraintCorrection<defaulttype::Vec1dTypes>::rotateConstraints()
00707       {
00708       }
00709 
00710 
00711       template<>
00712       void PrecomputedConstraintCorrection<defaulttype::Vec3dTypes>::rotateResponse(){
00713     simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00714 
00715     sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes>* forceField = NULL;
00716     if (node != NULL)
00717       {
00718         //      core::componentmodel::behavior::BaseForceField* _forceField = node->forceField[1];
00719         forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes> > ();
00720       }
00721     else
00722       {
00723         cout << "No rotation defined  !";
00724         return;
00725       }
00726     VecDeriv& dx = *mstate->getDx();
00727     for(unsigned int j = 0; j < dx.size(); j++)
00728       {
00729         Transformation Rj;
00730         forceField->getRotation(Rj, j);
00731         // on passe les deplacements du repere local au repere global
00732         const Deriv& toto = Rj * dx[j];
00733         dx[j] = toto;
00734       }
00735       }
00736     
00737     
00738 
00739       template<>
00740       void PrecomputedConstraintCorrection<defaulttype::Rigid3dTypes>::rotateResponse(){
00741     
00742     VecDeriv& dx = *mstate->getDx();
00743     VecCoord& x = *mstate->getX();
00744     VecCoord& x0 = *mstate->getX0();
00745     for(unsigned int j = 0; j < dx.size(); j++)
00746       {
00747         // on passe les deplacements du repere local (au repos) au repere global
00748         Deriv toto ;
00749         Quat q;
00750         if (_restRotations)
00751           q = x[j].getOrientation() * x0[j].getOrientation().inverse();
00752         else
00753           q = x[j].getOrientation();
00754 
00755         toto.getVCenter()       = q.rotate(dx[j].getVCenter());
00756         toto.getVOrientation()  = q.rotate(dx[j].getVOrientation());
00757         dx[j] = toto;
00758       }
00759       }
00760 
00761       template<>
00762       void PrecomputedConstraintCorrection<defaulttype::Vec1dTypes>::rotateResponse()
00763       {
00764       }
00765 #endif
00766 #ifndef SOFA_DOUBLE
00767       template<>
00768       void PrecomputedConstraintCorrection<defaulttype::Vec3fTypes>::rotateConstraints()
00769       {
00770     VecConst& constraints = *mstate->getC();
00771     unsigned int numConstraints = constraints.size();
00772 
00773     simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00774 
00775     sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes>* forceField = NULL;
00776     if (node != NULL)
00777       {
00778         //      core::componentmodel::behavior::BaseForceField* _forceField = node->forceField[1];
00779         forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes> > ();
00780       }
00781     else
00782       {
00783         cout << "No rotation defined : only defined for TetrahedronFEMForceField !";
00784         return;
00785       }
00786 
00787 
00788     //std::cout << "start rotating normals " << g_timer_elapsed(timer, &micro) << std::endl;
00789     //  int sizemax=0;
00790     //  int index_const = -1;
00791     // on fait tourner les normales (en les ramenant dans le "pseudo" repere initial) //
00792     for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00793       {
00794         int sizeCurRowConst = constraints[curRowConst].size(); //number of nodes in constraint
00795 
00796         //Rmk : theres is one constraint for each contact direction, i.e. normal, tangent1, tangent2.
00797         for(int i = 0; i < sizeCurRowConst; i++)
00798           {
00799         const int localRowNodeIdx = constraints[curRowConst][i].index;
00800         Transformation Ri;
00801         forceField->getRotation(Ri, localRowNodeIdx);
00802         Ri.transpose();
00803         // on passe les normales du repere global au repere local
00804         const Deriv& n_i = Ri * constraints[curRowConst][i].data;
00805         constraints[curRowConst][i].data.x() =  n_i.x();
00806         constraints[curRowConst][i].data.y() =  n_i.y();
00807         constraints[curRowConst][i].data.z() =  n_i.z();
00808           }
00809         /*
00810         // test pour voir si on peut reduire le nombre de contrainte 
00811         if (sizeCurRowConst > sizemax)
00812         {
00813         sizemax = sizeCurRowConst;
00814         index_const = curRowConst;
00815         }
00816         */
00817       }
00818       }
00819 
00820       template<>
00821       void PrecomputedConstraintCorrection<defaulttype::Rigid3fTypes>::rotateConstraints()
00822       {
00823     VecCoord& x = *mstate->getX();  
00824     VecConst& constraints = *mstate->getC();
00825     VecCoord& x0 = *mstate->getX0();
00826 
00827     unsigned int numConstraints = constraints.size();
00828     //  int sizemax=0;
00829     //  int index_const = -1;
00830     // on fait tourner les normales (en les ramenant dans le "pseudo" repere initial) //
00831     for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00832     {
00833       int sizeCurRowConst = constraints[curRowConst].size(); //number of nodes in constraint
00834 
00835       for(int i = 0; i < sizeCurRowConst; i++)
00836       {
00837         const int localRowNodeIdx = constraints[curRowConst][i].index;
00838         Quat q;
00839         if (_restRotations)
00840           q = x[localRowNodeIdx].getOrientation() * x0[localRowNodeIdx].getOrientation().inverse();
00841         else
00842           q = x[localRowNodeIdx].getOrientation();
00843 
00844 
00845         Vec3d n_i = q.inverseRotate(constraints[curRowConst][i].data.getVCenter());
00846         Vec3d wn_i= q.inverseRotate(constraints[curRowConst][i].data.getVOrientation());
00847 
00848         // on passe les normales du repere global au repere local
00849         constraints[curRowConst][i].data.getVCenter() = n_i;
00850         constraints[curRowConst][i].data.getVOrientation() = wn_i;
00851 
00852       }
00853     }
00854       }
00855       
00856       template<>
00857       void PrecomputedConstraintCorrection<defaulttype::Vec1fTypes>::rotateConstraints()
00858       {
00859       }
00860 
00861 
00862       template<>
00863       void PrecomputedConstraintCorrection<defaulttype::Vec3fTypes>::rotateResponse(){
00864     simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00865 
00866     sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes>* forceField = NULL;
00867     if (node != NULL)
00868       {
00869         //      core::componentmodel::behavior::BaseForceField* _forceField = node->forceField[1];
00870         forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes> > ();
00871       }
00872     else
00873       {
00874         cout << "No rotation defined  !";
00875         return;
00876       }
00877     VecDeriv& dx = *mstate->getDx();
00878     for(unsigned int j = 0; j < dx.size(); j++)
00879       {
00880         Transformation Rj;
00881         forceField->getRotation(Rj, j);
00882         // on passe les deplacements du repere local au repere global
00883         const Deriv& toto = Rj * dx[j];
00884         dx[j] = toto;
00885       }
00886       }
00887 
00888 
00889       template<>
00890       void PrecomputedConstraintCorrection<defaulttype::Rigid3fTypes>::rotateResponse(){
00891     
00892     VecDeriv& dx = *mstate->getDx();
00893     VecCoord& x = *mstate->getX();
00894     VecCoord& x0 = *mstate->getX0();
00895     for(unsigned int j = 0; j < dx.size(); j++)
00896       {
00897         // on passe les deplacements du repere local (au repos) au repere global
00898         Deriv toto ;
00899         Quat q;
00900         if (_restRotations)
00901           q = x[j].getOrientation() * x0[j].getOrientation().inverse();
00902         else
00903           q = x[j].getOrientation();
00904 
00905         toto.getVCenter()       = q.rotate(dx[j].getVCenter());
00906         toto.getVOrientation()  = q.rotate(dx[j].getVOrientation());
00907         dx[j] = toto;
00908       }
00909       }
00910     
00911       template<>
00912       void PrecomputedConstraintCorrection<defaulttype::Vec1fTypes>::rotateResponse()
00913       {
00914       }
00915 
00916 #endif
00917 
00918     
00919 
00920     } // namespace collision
00921 
00922   } // namespace component
00923 
00924 } // namespace sofa
00925 
00926 #endif

Generated on Sun Nov 23 02:45:39 2008 for Sofa by  doxygen 1.5.7.1