VectorSpringForceField.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_COMPONENT_FORCEFIELD_VECTORSPRINGFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_VECTORSPRINGFORCEFIELD_INL
00027 
00028 #include "VectorSpringForceField.h"
00029 #include <sofa/helper/io/MassSpringLoader.h>
00030 #include <sofa/core/objectmodel/KeypressedEvent.h>
00031 #include <sofa/component/topology/EdgeData.inl>
00032 #include <sofa/component/topology/TopologyChangedEvent.h>
00033 #include <sofa/helper/system/config.h>
00034 #include <sofa/helper/system/gl.h>
00035 #include <assert.h>
00036 #include <iostream>
00037 using std::cerr;
00038 using std::endl;
00039 
00040 namespace sofa
00041 {
00042 
00043 namespace component
00044 {
00045 
00046 namespace forcefield
00047 {
00048 
00049 template<class DataTypes>
00050 void VectorSpringForceField<DataTypes>::springCreationFunction(int /*index*/,
00051     void* param, Spring& t,
00052     const topology::Edge& e,
00053     const sofa::helper::vector< unsigned int > &ancestors,
00054     const sofa::helper::vector< double >& coefs)
00055 {
00056     VectorSpringForceField<DataTypes> *ff= static_cast<VectorSpringForceField<DataTypes> *>(param);
00057     if (ff) {       
00058         
00059         
00060         //EdgeSetGeometryAlgorithms<DataTypes> *ga=topology->getEdgeSetGeometryAlgorithms();
00061         //t.restLength=ga->computeRestEdgeLength(index);
00062         const typename DataTypes::VecCoord& x0 = *ff->getObject1()->getX0();
00063         t.restVector = x0[e[1]] - x0[e[0]];
00064         if (ancestors.size()>0) {
00065             t.kd=t.ks=0;
00066             const topology::EdgeData<Spring> &sa=ff->getSpringArray();
00067             unsigned int i;
00068             for (i=0;i<ancestors.size();++i) {
00069                 t.kd+=(typename DataTypes::Real)(sa[i].kd*coefs[i]);
00070                 t.ks+=(typename DataTypes::Real)(sa[i].ks*coefs[i]);
00071             }
00072         } else {
00073             t.kd=ff->getStiffness();
00074             t.ks=ff->getViscosity();
00075         }
00076         
00077     }
00078 }
00079 
00080 template <class DataTypes>
00081 class VectorSpringForceField<DataTypes>::Loader : public sofa::helper::io::MassSpringLoader
00082 {
00083     public:
00084         typedef typename DataTypes::Real Real;
00085         typedef typename DataTypes::Coord Coord;
00086         VectorSpringForceField<DataTypes>* dest;
00087         Loader(VectorSpringForceField<DataTypes>* dest) : dest(dest) {}
00088     virtual void addVectorSpring(int m1, int m2, SReal ks, SReal kd, SReal /*initpos*/, SReal restx, SReal resty, SReal restz)
00089         {
00090       dest->addSpring(m1,m2,ks,kd,Coord((Real)restx,(Real)resty,(Real)restz));
00091         }
00092         virtual void setNumSprings(int /*n*/) {
00093         //dest->resizeArray((unsigned int )n);
00094         }
00095 
00096 };
00097 
00098 template <class DataTypes>
00099 bool VectorSpringForceField<DataTypes>::load(const char *filename)
00100 {
00101     if (filename && filename[0])
00102     {
00103         Loader loader(this);
00104         return loader.load(filename);
00105     }
00106     else return false;
00107 }
00108 
00109 template <class DataTypes>
00110 void VectorSpringForceField<DataTypes>::resizeArray(unsigned int n) 
00111 {
00112     springArray.resize(n);
00113 }
00114 
00115 template <class DataTypes>
00116     void VectorSpringForceField<DataTypes>::addSpring(int m1, int m2, SReal ks, SReal kd, Coord restVector)
00117 {
00118     if (useTopology && _topology)
00119     {
00120         int e=_topology->getEdgeIndex((unsigned int)m1,(unsigned int)m2);
00121         if (e>=0)
00122             springArray[e]=Spring((Real)ks,(Real)kd,restVector);
00123     }
00124     else
00125     {
00126         springArray.push_back(Spring((Real)ks, (Real)kd, restVector));
00127         edgeArray.push_back(topology::Edge(m1,m2));
00128     }
00129 }
00130 
00131 template <class DataTypes>
00132 VectorSpringForceField<DataTypes>::VectorSpringForceField(MechanicalState* _object)
00133 : Inherit(_object, _object)
00134 , m_potentialEnergy( 0.0 ), useTopology( false )
00135 , m_filename( initData(&m_filename,std::string(""),"filename","File name from which the spring informations are loaded") )
00136 , m_stiffness( initData(&m_stiffness,1.0,"stiffness","Default edge stiffness used in absence of file information") )
00137 , m_viscosity( initData(&m_viscosity,1.0,"viscosity","Default edge viscosity used in absence of file information") )
00138 {
00139     springArray.setCreateFunction(springCreationFunction);
00140     springArray.setCreateParameter( (void *) this );
00141 }
00142 
00143 template <class DataTypes>
00144 VectorSpringForceField<DataTypes>::VectorSpringForceField(MechanicalState* _object1, MechanicalState* _object2)
00145 : Inherit(_object1, _object2)
00146 , m_potentialEnergy( 0.0 ), useTopology( false )
00147 , m_filename( initData(&m_filename,std::string(""),"filename","File name from which the spring informations are loaded") )
00148 , m_stiffness( initData(&m_stiffness,1.0,"stiffness","Default edge stiffness used in absence of file information") )
00149 , m_viscosity( initData(&m_viscosity,1.0,"viscosity","Default edge viscosity used in absence of file information") )
00150 {
00151     springArray.setCreateFunction(springCreationFunction);
00152     springArray.setCreateParameter( (void *) this );
00153 }
00154 
00155 template <class DataTypes>
00156 void VectorSpringForceField<DataTypes>::init()
00157 {
00158     _topology = this->getContext()->getMeshTopology();  
00159     this->getContext()->get(edgeGeo);   
00160     this->getContext()->get(edgeMod);   
00161 
00162     this->Inherit::init();
00163 
00164     if (springArray.empty())
00165     {       
00166         if (!m_filename.getValue().empty())
00167         {
00168             // load the springs from a file
00169             load(( const char *)(m_filename.getValue().c_str()));
00170             return;
00171         }
00172 
00173         if (_topology != NULL)
00174         {
00175             // create springs based on the mesh topology
00176             useTopology = true;
00177             createDefaultSprings();
00178             f_listening.setValue(true);
00179         }
00180         else 
00181         {
00182             int n = this->mstate1->getSize();
00183             springArray.resize(n);
00184             edgeArray.resize(n);
00185             for (int i=0;i<n;++i)
00186             {
00187                 edgeArray[i][0] = i;
00188                 edgeArray[i][1] = i;
00189                 springArray[i].ks=(Real)m_stiffness.getValue();
00190                 springArray[i].kd=(Real)m_viscosity.getValue();
00191                 springArray[i].restVector = Coord();
00192             }
00193         }
00194     }
00195 }
00196 
00197 template <class DataTypes>
00198 void VectorSpringForceField<DataTypes>::createDefaultSprings() 
00199 {   
00200     std::cout << "Creating "<< _topology->getNbEdges() <<" Vector Springs from EdgeSetTopology"<<std::endl;
00201     springArray.resize(_topology->getNbEdges());
00202     //EdgeLengthArrayInterface<Real,DataTypes> elai(springArray);
00203     //edgeGEO->computeEdgeLength(elai);
00204     const VecCoord& x0 = *this->mstate1->getX0();
00205     int i;
00206     for (i=0;i<_topology->getNbEdges();++i) {
00207         springArray[i].ks=(Real)m_stiffness.getValue();
00208         springArray[i].kd=(Real)m_viscosity.getValue();
00209         springArray[i].restVector = x0[_topology->getEdge(i)[1]]-x0[_topology->getEdge(i)[0]];
00210     }
00211 
00212 }
00213 template<class DataTypes>
00214 void VectorSpringForceField<DataTypes>::handleEvent( Event* e )
00215 {
00216     if (useTopology)
00217     {
00218         if( sofa::core::objectmodel::KeypressedEvent* ke = dynamic_cast<sofa::core::objectmodel::KeypressedEvent*>( e ) )
00219         {
00221             if (ke->getKey()=='D') {
00222                 if (_topology->getNbEdges()>12) {
00223                     
00224                     sofa::helper::vector<unsigned int> edgeArray;
00225                     edgeArray.push_back(12);
00226                     edgeMod->removeEdges(edgeArray);
00227                 }
00228     //            edgeMod->splitEdges(edgeArray);
00229             }
00230         } else {
00231             sofa::component::topology::TopologyChangedEvent *tce=dynamic_cast<sofa::component::topology::TopologyChangedEvent *>(e);
00233             if ((tce) && edgeMod /*&& (tce->getMeshTopology()== _topology )*/) {
00234                 std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00235                 std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00237                 springArray.handleTopologyEvents(itBegin,itEnd);
00238             }
00239         }
00240     }
00241 }
00242 
00243 template<class DataTypes>
00244 //void VectorSpringForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& p, const VecDeriv& v)
00245 void VectorSpringForceField<DataTypes>::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2)
00246 {
00247     //assert(this->mstate);
00248     m_potentialEnergy = 0;
00249    
00250     Coord u;
00251 
00252     f1.resize(x1.size());
00253     f2.resize(x2.size());
00254 
00255     if(useTopology){    
00256 
00257         Deriv relativeVelocity,force;
00258         for (int i=0; i<_topology->getNbEdges(); i++)
00259         {
00260             const topology::Edge &e=_topology->getEdge(i);
00261             const Spring &s=springArray[i];
00262             // paul---------------------------------------------------------------
00263             Deriv current_direction = x2[e[1]]-x1[e[0]];
00264             Deriv squash_vector = current_direction - s.restVector;
00265             Deriv relativeVelocity = v2[e[1]]-v1[e[0]];
00266             force = (squash_vector * s.ks) + (relativeVelocity * s.kd);
00267 
00268             f1[e[0]]+=force;
00269             f2[e[1]]-=force;
00270         }
00271 
00272     }else{
00273 
00274         Deriv relativeVelocity,force;
00275         for (unsigned int i=0; i<edgeArray.size(); i++)
00276         {
00277             const topology::Edge &e=edgeArray[i];
00278             const Spring &s=springArray[i];
00279             // paul---------------------------------------------------------------
00280             Deriv current_direction = x2[e[1]]-x1[e[0]];
00281             Deriv squash_vector = current_direction - s.restVector;
00282             Deriv relativeVelocity = v2[e[1]]-v1[e[0]];
00283             force = (squash_vector * s.ks) + (relativeVelocity * s.kd);
00284 
00285             f1[e[0]]+=force;
00286             f2[e[1]]-=force;
00287         }
00288     }
00289 }
00290 
00291 template<class DataTypes>
00292 //void VectorSpringForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00293 void VectorSpringForceField<DataTypes>::addDForce(VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double /*bFactor*/)
00294 {
00295     Deriv dforce,d;
00296 
00297     df1.resize(dx1.size());
00298     df2.resize(dx2.size());
00299 
00300     if(useTopology){
00301 
00302         for (int i=0; i<_topology->getNbEdges(); i++)
00303         {
00304             const topology::Edge &e=_topology->getEdge(i);
00305             const Spring &s=springArray[i];
00306             d = dx2[e[1]]-dx1[e[0]];
00307             dforce = d*(s.ks*kFactor);
00308             df1[e[0]]+=dforce;
00309             df2[e[1]]-=dforce;
00310         }
00311 
00312     }else{
00313 
00314         for (unsigned int i=0; i<edgeArray.size(); i++)
00315         {
00316             const topology::Edge &e=edgeArray[i];
00317             const Spring &s=springArray[i];
00318             d = dx2[e[1]]-dx1[e[0]];
00319             dforce = d*(s.ks*kFactor);
00320             df1[e[0]]+=dforce;
00321             df2[e[1]]-=dforce;
00322         }
00323     }
00324 
00325 }
00326 
00327 template<class DataTypes>
00328 void VectorSpringForceField<DataTypes>::draw()
00329 {
00330     if (!((this->mstate1 == this->mstate2)?getContext()->getShowForceFields():getContext()->getShowInteractionForceFields()))
00331         return;
00332     //const VecCoord& p = *this->mstate->getX();
00333     const VecCoord& x1 = *this->mstate1->getX();
00334     const VecCoord& x2 = *this->mstate2->getX();
00335 
00336     glDisable(GL_LIGHTING);
00337     
00338     glBegin(GL_LINES);
00339 
00340     if(useTopology){
00341         for (unsigned int i=0; i<springArray.size(); i++)
00342         {
00343             const topology::Edge &e=_topology->getEdge(i);
00344             //const Spring &s=springArray[i];
00345 
00346             glColor4f(0,1,1,0.5f);
00347 
00348             glVertex3d(x1[e[0]][0],x1[e[0]][1],x1[e[0]][2]);
00349             glVertex3d(x2[e[1]][0],x2[e[1]][1],x2[e[1]][2]);
00350         }
00351 
00352     }else{
00353 
00354         for (unsigned int i=0; i<springArray.size(); i++)
00355         {
00356             const topology::Edge &e=edgeArray[i];
00357             //const Spring &s=springArray[i];
00358 
00359             glColor4f(0,1,1,0.5f);
00360 
00361             glVertex3d(x1[e[0]][0],x1[e[0]][1],x1[e[0]][2]);
00362             glVertex3d(x2[e[1]][0],x2[e[1]][1],x2[e[1]][2]);
00363         }
00364     }
00365 
00366     glEnd();
00367 }
00368 
00369 } // namespace forcefield
00370 
00371 } // namespace component
00372 
00373 } // namespace sofa
00374 
00375 #endif

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