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_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 ,
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
00061
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 , 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 ) {
00093
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
00169 load(( const char *)(m_filename.getValue().c_str()));
00170 return;
00171 }
00172
00173 if (_topology != NULL)
00174 {
00175
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
00203
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
00229 }
00230 } else {
00231 sofa::component::topology::TopologyChangedEvent *tce=dynamic_cast<sofa::component::topology::TopologyChangedEvent *>(e);
00233 if ((tce) && edgeMod ) {
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
00245 void VectorSpringForceField<DataTypes>::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2)
00246 {
00247
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
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
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
00293 void VectorSpringForceField<DataTypes>::addDForce(VecDeriv& df1, VecDeriv& df2, const VecDeriv& dx1, const VecDeriv& dx2, double kFactor, double )
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
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
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
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 }
00370
00371 }
00372
00373 }
00374
00375 #endif