00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00142 load(( const char *)(m_filename.getValue().c_str()));
00143 else {
00144
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
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
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 }
00327
00328 }
00329
00330 }
00331
00332 #endif