SpringEdgeDataForceField.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_SPRINGEDGEDATAFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_SPRINGEDGEDATAFORCEFIELD_INL
00027 
00028 #include <sofa/component/forcefield/SpringEdgeDataForceField.h>
00029 #include <sofa/helper/io/MassSpringLoader.h>
00030 #include <sofa/core/objectmodel/KeypressedEvent.h>
00031 #include <sofa/component/topology/TopologyChangedEvent.h>
00032 #include <sofa/helper/system/config.h>
00033 #include <assert.h>
00034 #include <iostream>
00035 #include <GL/gl.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 using namespace sofa::core::componentmodel::behavior;
00050 
00051 template<class DataTypes>
00052 void springCreationFunction(int index, 
00053                             void* param, typename SpringEdgeDataForceField<DataTypes>::Spring& t, 
00054                             const component::topology::Edge& ,  
00055                             const std::vector< unsigned int > &ancestors,
00056                             const std::vector< double >& coefs)
00057 {
00058     SpringEdgeDataForceField<DataTypes> *ff= static_cast<SpringEdgeDataForceField<DataTypes> *>(param);
00059     if (ff) {
00060         sofa::component::topology::EdgeSetTopology<DataTypes>* topology = dynamic_cast<sofa::component::topology::EdgeSetTopology<DataTypes>*>(ff->getContext()->getMainTopology());
00061         if (topology) {
00062             component::topology::EdgeSetGeometryAlgorithms<DataTypes> *ga=topology->getEdgeSetGeometryAlgorithms();
00063             t.restLength=ga->computeRestEdgeLength(index);
00064             if  ((ancestors!= (const std::vector< unsigned int >)0) &&  (ancestors.size()>0)) {
00065                 t.kd=t.ks=0;
00066                 const component::topology::EdgeData<typename SpringEdgeDataForceField<DataTypes>::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 template <class DataTypes>
00080 class SpringEdgeDataForceField<DataTypes>::Loader : public helper::io::MassSpringLoader
00081 {
00082     public:
00083         SpringEdgeDataForceField<DataTypes>* dest;
00084         Loader(SpringEdgeDataForceField<DataTypes>* dest) : dest(dest) {}
00085         virtual void addSpring(int m1, int m2, SReal ks, SReal kd, SReal initpos)
00086         {
00087             dest->addSpring(m1,m2,ks,kd,initpos);
00088         }
00089         virtual void setNumSprings(int n) {
00090         dest->resizeArray((unsigned int )n);
00091         }
00092 
00093 };
00094 
00095 template <class DataTypes>
00096 bool SpringEdgeDataForceField<DataTypes>::load(const char *filename)
00097 {
00098     if (filename && filename[0])
00099     {
00100         Loader loader(this);
00101         return loader.load(filename);
00102     }
00103     else return false;
00104 }
00105 
00106 template <class DataTypes>
00107 void SpringEdgeDataForceField<DataTypes>::resizeArray(unsigned int n) 
00108 {
00109     springArray.resize(n);
00110 }
00111 template <class DataTypes>
00112     void SpringEdgeDataForceField<DataTypes>::addSpring(int m1, int m2, SReal ks, SReal kd, SReal initpos)
00113 {
00114     sofa::component::topology::EdgeSetTopology<DataTypes> *topology = dynamic_cast<sofa::component::topology::EdgeSetTopology<DataTypes>*>(object->getContext()->getMainTopology());
00115     component::topology::EdgeSetTopologyContainer *container=topology->getEdgeSetTopologyContainer();
00116 
00117     int e=container->getEdgeIndex((unsigned int)m1,(unsigned int)m2);
00118     if (e>=0)
00119         springArray[e]=Spring((Real)ks,(Real)kd,(Real)initpos);
00120 }
00121 template <class DataTypes>
00122 SpringEdgeDataForceField<DataTypes>::SpringEdgeDataForceField(core::componentmodel::behavior::MechanicalState<DataTypes>* _object)
00123     : core::componentmodel::behavior::ForceField<DataTypes>(_object),object(_object),
00124     m_filename( dataField(&m_filename,std::string("untitled"),"filename","File name from which the spring informations are loaded") ),
00125     m_stiffness( dataField(&m_stiffness,1.0,"stiffness","Default edge stiffness used in absence of file information") ),
00126     m_viscosity( dataField(&m_viscosity,1.0,"viscosity","Default edge viscosity used in absence of file information") )
00127     {
00128         springArray.setCreateFunction(springCreationFunction<DataTypes>);
00129         springArray.setCreateParameter( (void *) this );
00130     }
00131     
00132 
00133 template <class DataTypes>
00134 void SpringEdgeDataForceField<DataTypes>::init()
00135 {
00136     ForceField<DataTypes>::init();
00137     topology = dynamic_cast<sofa::component::topology::EdgeSetTopology<DataTypes>*>(getContext()->getMainTopology());
00138     assert(topology!=0);
00140     if (m_filename.getValue()!="untitled")
00141         // load the springs from a file
00142         load(( const char *)(m_filename.getValue().c_str()));
00143     else {
00144         // create springs based on the mesh topology
00145         createDefaultSprings();
00146     }
00147     f_listening.setValue(true);
00148 }
00149 template < class T , class DataTypes>
00150 class EdgeLengthArrayInterface: public component::topology::BasicArrayInterface<T> {
00151 protected:
00152      component::topology::EdgeData<typename SpringEdgeDataForceField<DataTypes>::Spring> &springArray;
00153 public:
00154     EdgeLengthArrayInterface( component::topology::EdgeData<typename SpringEdgeDataForceField<DataTypes>::Spring> &_sa) : springArray(_sa) {
00155     }
00156     // Access to i-th element.
00157     virtual T & operator[](int i)
00158     {
00159         return springArray[i].restLength;
00160     }
00161 };
00162 
00163 template <class DataTypes>
00164 void SpringEdgeDataForceField<DataTypes>::createDefaultSprings() 
00165 {
00166     component::topology::EdgeSetTopologyContainer *container=topology->getEdgeSetTopologyContainer();
00167     const std::vector<component::topology::Edge> &ea=container->getEdgeArray();
00168     springArray.resize(ea.size());
00169     component::topology::EdgeSetGeometryAlgorithms<DataTypes> *ga=topology->getEdgeSetGeometryAlgorithms();
00170     EdgeLengthArrayInterface<Real,DataTypes> elai(springArray);
00171     ga->computeEdgeLength(elai);
00172     unsigned int i;
00173     for (i=0;i<ea.size();++i) {
00174         springArray[i].ks=(Real)m_stiffness.getValue();
00175         springArray[i].kd=(Real)m_viscosity.getValue();
00176     }
00177 
00178 }
00179 template<class DataTypes>
00180 void SpringEdgeDataForceField<DataTypes>::handleEvent( Event* e )
00181 {
00182     if( KeypressedEvent* ke = dynamic_cast<KeypressedEvent*>( e ) )
00183     {
00185         if (ke->getKey()=='D') {
00186             if (topology->getEdgeSetTopologyContainer()->getNumberOfEdges()>12) {
00187                 component::topology::EdgeSetTopologyAlgorithms<DataTypes> *esta=topology->getEdgeSetTopologyAlgorithms();
00188                 std::vector<unsigned int> edgeArray;
00189                 edgeArray.push_back(12);
00190                 esta->removeEdges(edgeArray);
00191             }
00192 //          esta->splitEdges(edgeArray);
00193         }
00194     } else {
00195         component::topology::TopologyChangedEvent *tce=dynamic_cast<component::topology::TopologyChangedEvent *>(e);
00197         if ((tce) && (tce->getTopology()== getContext()->getMainTopology())) {
00198             core::componentmodel::topology::BaseTopology *topology = static_cast<core::componentmodel::topology::BaseTopology *>(getContext()->getMainTopology());
00199 
00200             std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itBegin=topology->firstChange();
00201             std::list<const core::componentmodel::topology::TopologyChange *>::const_iterator itEnd=topology->lastChange();
00203             springArray.handleTopologyEvents(itBegin,itEnd);
00204         }
00205     }
00206 
00207 }
00208 template<class DataTypes>
00209 void SpringEdgeDataForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& p, const VecDeriv& v)
00210 {
00211     assert(this->object);
00212     m_potentialEnergy = 0;
00213     component::topology::EdgeSetTopologyContainer *container=topology->getEdgeSetTopologyContainer();
00214     const std::vector<component::topology::Edge> &ea=container->getEdgeArray();
00215     Coord u;
00216     Real d,inverseLength,elongation,elongationVelocity,forceIntensity;
00217     
00218     Deriv relativeVelocity,force;
00219     for (unsigned int i=0; i<ea.size(); i++)
00220     {
00221         const component::topology::Edge &e=ea[i];
00222         const Spring &s=springArray[i];
00223         u = p[e.second]-p[e.first];
00224         d = u.norm();
00225         inverseLength = 1.0f/d;
00226         u *= inverseLength;
00227         elongation = (Real)(d - s.restLength);
00228         m_potentialEnergy += elongation * elongation * s.ks /2;
00229         relativeVelocity = v[e.second]-v[e.first];
00230         elongationVelocity = dot(u,relativeVelocity);
00231         forceIntensity = (Real)(s.ks*elongation+s.kd*elongationVelocity);
00232         force = u*forceIntensity;
00233         f[e.first]+=force;
00234         f[e.second]-=force;
00235     }
00236     updateMatrix=true;
00237 }
00238 
00239 template<class DataTypes>
00240 void SpringEdgeDataForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00241 {
00242     assert(this->object);
00243     const VecCoord& p = *object->getX();
00244     const VecDeriv& v = *object->getV();
00245     component::topology::EdgeSetTopologyContainer *container=topology->getEdgeSetTopologyContainer();
00246     const std::vector<component::topology::Edge> &ea=container->getEdgeArray();
00247     Deriv dforce,d;
00248     unsigned int i;
00249 
00250 
00251 
00252     if (updateMatrix==true) {
00253         updateMatrix=false;
00254         int j,k;
00255         Real d,inverseLength,elongation,elongationVelocity,forceIntensity,tgt;
00256         Deriv relativeVelocity;
00257         Coord u;
00258 
00259 
00260         for (i=0; i<ea.size(); i++)
00261         {
00262             const component::topology::Edge &e=ea[i];
00263             Spring &s=springArray[i];
00264             u = p[e.second]-p[e.first];
00265             d = u.norm();
00266             inverseLength = 1.0f/d;
00267             u *= inverseLength;
00268             elongation = (Real)(d - s.restLength);
00269             relativeVelocity = v[e.second]-v[e.first];
00270             elongationVelocity = dot(u,relativeVelocity);
00271             forceIntensity = (Real)(s.ks*elongation+s.kd*elongationVelocity);
00272             tgt = forceIntensity * inverseLength;
00273             for(  j=0; j<3; ++j )
00274             {
00275                 for(  k=0; k<3; ++k )
00276                 {
00277                     s.dfdx[j][k] = ((Real)s.ks-tgt) * u[j] * u[k];
00278                 }
00279                 s.dfdx[j][j] += tgt;
00280             }
00281         }
00282     }
00283 
00284     for ( i=0; i<ea.size(); i++)
00285     {
00286         const component::topology::Edge &e=ea[i];
00287         const Spring &s=springArray[i];
00288         d = dx[e.second]-dx[e.first];
00289         dforce = (s.dfdx)*d;
00290         df[e.first]+=dforce;
00291         df[e.second]-=dforce;
00292     }
00293 
00294 }
00295 
00296 template<class DataTypes>
00297 void SpringEdgeDataForceField<DataTypes>::draw()
00298 {
00299     if (getContext()->getShowForceFields()==false) 
00300         return;
00301     const VecCoord& p = *this->object->getX();
00302     component::topology::EdgeSetTopologyContainer *container=topology->getEdgeSetTopologyContainer();
00303     const std::vector<component::topology::Edge> &ea=container->getEdgeArray();
00304 
00305     glDisable(GL_LIGHTING);
00306     
00307     glBegin(GL_LINES);
00308     for (unsigned int i=0; i<springArray.size(); i++)
00309     {
00310         const component::topology::Edge &e=ea[i];
00311         const Spring &s=springArray[i];
00312 
00313         Real d = (p[e.second]-p[e.first]).norm();
00314 
00315         if (d<s.restLength*0.9999)
00316             glColor4f(1,0.5f,0,1);
00317         else
00318             glColor4f(0,1,0.5f,1);
00319 
00320         glVertex3d(p[e.first][0],p[e.first][1],p[e.first][2]);
00321         glVertex3d(p[e.second][0],p[e.second][1],p[e.second][2]);
00322     }
00323     glEnd();
00324 }
00325 
00326 } // namespace forcefield
00327 
00328 } // namespace component
00329 
00330 } // namespace sofa
00331 
00332 #endif

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