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 #include <sofa/component/forcefield/TriangularQuadraticSpringsForceField.h>
00026 #include <fstream>
00027 #include <iostream>
00028 #include <sofa/helper/gl/template.h>
00029 #include <sofa/component/topology/TriangleSetGeometryAlgorithms.h>
00030 #include <sofa/component/topology/TriangleData.inl>
00031 #include <sofa/component/topology/EdgeData.inl>
00032
00033 namespace sofa
00034 {
00035
00036 namespace component
00037 {
00038
00039 namespace forcefield
00040 {
00041
00042 using namespace sofa::defaulttype;
00043 using namespace sofa::component::topology;
00044 using namespace core::componentmodel::topology;
00045
00046 using std::cerr;
00047 using std::cout;
00048 using std::endl;
00049
00050 template< class DataTypes>
00051 void TriangularQuadraticSpringsForceField<DataTypes>::TRQSEdgeCreationFunction(int edgeIndex, void* param, EdgeRestInformation &ei,
00052 const Edge& , const sofa::helper::vector< unsigned int > &,
00053 const sofa::helper::vector< double >&)
00054 {
00055 TriangularQuadraticSpringsForceField<DataTypes> *ff= (TriangularQuadraticSpringsForceField<DataTypes> *)param;
00056 if (ff) {
00057
00058 sofa::component::topology::TriangleSetGeometryAlgorithms<DataTypes>* triangleGeo;
00059 ff->getContext()->get(triangleGeo);
00060
00061
00062 ei.restLength=triangleGeo->computeRestEdgeLength(edgeIndex);
00063 ei.stiffness=0;
00064 }
00065 }
00066
00067
00068
00069 template< class DataTypes>
00070 void TriangularQuadraticSpringsForceField<DataTypes>::TRQSTriangleCreationFunction (int triangleIndex, void* param,
00071 TriangleRestInformation &tinfo,
00072 const Triangle& ,
00073 const sofa::helper::vector< unsigned int > &,
00074 const sofa::helper::vector< double >&)
00075 {
00076 TriangularQuadraticSpringsForceField<DataTypes> *ff= (TriangularQuadraticSpringsForceField<DataTypes> *)param;
00077 if (ff) {
00078 unsigned int j,k,l;
00079
00080 EdgeData<typename TriangularQuadraticSpringsForceField<DataTypes>::EdgeRestInformation> &edgeInfo=ff->getEdgeInfo();
00081 typename DataTypes::Real area,squareRestLength[3],restLength[3],cotangent[3];
00082 typename DataTypes::Real lambda=ff->getLambda();
00083 typename DataTypes::Real mu=ff->getMu();
00084
00086 const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleIndex);
00087
00088 for(j=0;j<3;++j) {
00089 restLength[j]=edgeInfo[te[j]].restLength;
00090 squareRestLength[j]= restLength[j]*restLength[j];
00091 }
00092
00093 area=0;
00094 for(j=0;j<3;++j) {
00095 area+=squareRestLength[j]*(squareRestLength[(j+1)%3] +squareRestLength[(j+2)%3]-squareRestLength[j]);
00096 }
00097 area=sqrt(area)/4;
00098
00099 for(j=0;j<3;++j) {
00100 cotangent[j]=(squareRestLength[(j+1)%3] +squareRestLength[(j+2)%3]-squareRestLength[j])/(4*area);
00101
00102
00103
00104
00105
00106 }
00107 for(j=0;j<3;++j){
00108 k=(j+1)%3;
00109 l=(j+2)%3;
00110 tinfo.gamma[j]=restLength[k]*restLength[l]*(2*cotangent[k]*cotangent[l]*(lambda+mu)-mu)/(8*area);
00111 tinfo.stiffness[j]=restLength[j]*restLength[j]*(2*cotangent[j]*cotangent[j]*(lambda+mu)+mu)/(8*area);
00112 edgeInfo[te[j]].stiffness+=tinfo.stiffness[j];
00113 }
00114
00115 }
00116
00117 }
00118
00119
00120 template< class DataTypes>
00121 void TriangularQuadraticSpringsForceField<DataTypes>::TRQSTriangleDestroyFunction(int triangleIndex, void* param, typename TriangularQuadraticSpringsForceField<DataTypes>::TriangleRestInformation &tinfo)
00122 {
00123 TriangularQuadraticSpringsForceField<DataTypes> *ff= (TriangularQuadraticSpringsForceField<DataTypes> *)param;
00124 if (ff) {
00125 unsigned int j;
00126
00127 EdgeData<typename TriangularQuadraticSpringsForceField<DataTypes>::EdgeRestInformation> &edgeInfo=ff->getEdgeInfo();
00128
00130 const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleIndex);
00131
00132 for(j=0;j<3;++j) {
00133 edgeInfo[te[j]].stiffness -= tinfo.stiffness[j];
00134 }
00135
00136 }
00137 }
00138 template <class DataTypes> TriangularQuadraticSpringsForceField<DataTypes>::TriangularQuadraticSpringsForceField()
00139 : _initialPoints(initData(&_initialPoints,"initialPoints", "Initial Position"))
00140 , updateMatrix(true)
00141 , f_poissonRatio(initData(&f_poissonRatio,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00142 , f_youngModulus(initData(&f_youngModulus,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00143 , f_dampingRatio(initData(&f_dampingRatio,(Real)0.,"dampingRatio","Ratio damping/stiffness"))
00144 , f_useAngularSprings(initData(&f_useAngularSprings,true,"useAngularSprings","If Angular Springs should be used or not"))
00145 , lambda(0)
00146 , mu(0)
00147 {
00148 }
00149
00150 template <class DataTypes> void TriangularQuadraticSpringsForceField<DataTypes>::handleTopologyChange()
00151 {
00152 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00153 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00154
00155 edgeInfo.handleTopologyEvents(itBegin,itEnd);
00156 triangleInfo.handleTopologyEvents(itBegin,itEnd);
00157 }
00158
00159 template <class DataTypes> TriangularQuadraticSpringsForceField<DataTypes>::~TriangularQuadraticSpringsForceField()
00160 {
00161
00162 }
00163
00164 template <class DataTypes> void TriangularQuadraticSpringsForceField<DataTypes>::init()
00165 {
00166 std::cerr << "initializing TriangularQuadraticSpringsForceField" << std::endl;
00167 this->Inherited::init();
00168
00169 _topology = getContext()->getMeshTopology();
00170
00171 if (_topology->getNbTriangles()==0)
00172 {
00173 std::cerr << "ERROR(TriangularQuadraticSpringsForceField): object must have a Triangular Set Topology.\n";
00174 return;
00175 }
00176 updateLameCoefficients();
00177
00179 triangleInfo.resize(_topology->getNbTriangles());
00181 edgeInfo.resize(_topology->getNbEdges());
00182
00183 if (_initialPoints.getValue().size() == 0)
00184 {
00185
00186 VecCoord& p = *this->mstate->getX0();
00187 _initialPoints.setValue(p);
00188 }
00189 int i;
00190 for (i=0;i<_topology->getNbEdges();++i) {
00191 TRQSEdgeCreationFunction(i, (void*) this, edgeInfo[i],
00192 _topology->getEdge(i), (const sofa::helper::vector< unsigned int > )0,
00193 (const sofa::helper::vector< double >)0);
00194 }
00195 for (i=0;i<_topology->getNbTriangles();++i) {
00196 TRQSTriangleCreationFunction(i, (void*) this, triangleInfo[i],
00197 _topology->getTriangle(i), (const sofa::helper::vector< unsigned int > )0,
00198 (const sofa::helper::vector< double >)0);
00199 }
00200
00201 edgeInfo.setCreateFunction(TRQSEdgeCreationFunction);
00202 triangleInfo.setCreateFunction(TRQSTriangleCreationFunction);
00203 triangleInfo.setDestroyFunction(TRQSTriangleDestroyFunction);
00204 edgeInfo.setCreateParameter( (void *) this );
00205 edgeInfo.setDestroyParameter( (void *) this );
00206 triangleInfo.setCreateParameter( (void *) this );
00207 triangleInfo.setDestroyParameter( (void *) this );
00208
00209 }
00210
00211
00212 template <class DataTypes>
00213 double TriangularQuadraticSpringsForceField<DataTypes>::getPotentialEnergy(const VecCoord& )
00214 {
00215 std::cerr<<"TriangularQuadraticSpringsForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00216 return 0;
00217 }
00218 template <class DataTypes>
00219 void TriangularQuadraticSpringsForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& v)
00220 {
00221 unsigned int j,k,l,v0,v1;
00222 int nbEdges=_topology->getNbEdges();
00223 int nbTriangles=_topology->getNbTriangles();
00224
00225 Real val,L;
00226 TriangleRestInformation *tinfo;
00227 EdgeRestInformation *einfo;
00228
00229 assert(this->mstate);
00230
00231 Deriv force;
00232 Coord dp,dv;
00233 Real _dampingRatio=f_dampingRatio.getValue();
00234
00235
00236 for(int i=0; i<nbEdges; i++ )
00237 {
00238 einfo=&edgeInfo[i];
00239 v0=_topology->getEdge(i)[0];
00240 v1=_topology->getEdge(i)[1];
00241 dp=x[v0]-x[v1];
00242 dv=v[v0]-v[v1];
00243 L=einfo->currentLength=dp.norm();
00244 einfo->dl=einfo->currentLength-einfo->restLength +_dampingRatio*dot(dv,dp)/L;
00245
00246
00247
00248
00249 val=einfo->stiffness*(einfo->dl)/L;
00250 f[v1]+=dp*val;
00251 f[v0]-=dp*val;
00252
00253 }
00254 if (f_useAngularSprings.getValue()==true) {
00255 for(int i=0; i<nbTriangles; i++ )
00256 {
00257 tinfo=&triangleInfo[i];
00259 const TriangleEdges &tea= _topology->getEdgeTriangleShell(i);
00261 const Triangle &ta= _topology->getTriangle(i);
00262
00263
00264 for(j=0;j<3;++j) {
00265 k=(j+1)%3;
00266 l=(j+2)%3;
00267 force=(x[ta[k]] - x[ta[l]])*
00268 (edgeInfo[tea[k]].dl * tinfo->gamma[l] +edgeInfo[tea[l]].dl * tinfo->gamma[k])/edgeInfo[tea[j]].currentLength;
00269 f[ta[l]]+=force;
00270 f[ta[k]]-=force;
00271 }
00272 }
00273
00274
00275 }
00276
00277 updateMatrix=true;
00278
00279 }
00280
00281
00282 template <class DataTypes>
00283 void TriangularQuadraticSpringsForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00284 {
00285 unsigned int i,j,k;
00286 int nbTriangles=_topology->getNbTriangles();
00287
00288 TriangleRestInformation *tinfo;
00289
00290
00291
00292
00293 assert(this->mstate);
00294 VecDeriv& x = *this->mstate->getX();
00295
00296
00297 Deriv deltax,res;
00298
00299 if (updateMatrix) {
00300 int u,v;
00301 Real val1,val2,vali,valj,valk;
00302 Coord dpj,dpk,dpi;
00303
00304
00305 updateMatrix=false;
00306 for(int l=0; l<nbTriangles; l++ )
00307 {
00308 tinfo=&triangleInfo[l];
00310 const TriangleEdges &tea= _topology->getEdgeTriangleShell(l);
00312 const Triangle &ta= _topology->getTriangle(l);
00313
00314
00315 for(k=0;k<3;++k) {
00316 i=(k+1)%3;
00317 j=(k+2)%3;
00318 Mat3 &m=tinfo->DfDx[k];
00319 dpk = x[ta[i]]- x[ta[j]];
00320
00321 if (f_useAngularSprings.getValue()==false) {
00322 val1 = -tinfo->stiffness[k]*edgeInfo[tea[k]].dl;
00323 val1/=edgeInfo[tea[k]].currentLength;
00324
00325 val2= -tinfo->stiffness[k]*edgeInfo[tea[k]].restLength;
00326 val2/=edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength;
00327
00328 for (u=0;u<3;++u) {
00329 for (v=0;v<3;++v) {
00330 m[u][v]=dpk[u]*dpk[v]*val2;
00331 }
00332 m[u][u]+=val1;
00333 }
00334
00335 } else {
00336 dpj = x[ta[i]]- x[ta[k]];
00337 dpi = x[ta[j]]- x[ta[k]];
00338
00339 val1 = -(tinfo->stiffness[k]*edgeInfo[tea[k]].dl+
00340 tinfo->gamma[i]*edgeInfo[tea[j]].dl+
00341 tinfo->gamma[j]*edgeInfo[tea[i]].dl);
00342
00343 val2= -val1 - tinfo->stiffness[k]*edgeInfo[tea[k]].restLength;
00344 val1/=edgeInfo[tea[k]].currentLength;
00345 val2/=edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength;
00346 valk=tinfo->gamma[k]/(edgeInfo[tea[j]].currentLength*
00347 edgeInfo[tea[i]].currentLength);
00348 vali=tinfo->gamma[i]/(edgeInfo[tea[j]].currentLength*
00349 edgeInfo[tea[k]].currentLength);
00350 valj=tinfo->gamma[j]/(edgeInfo[tea[k]].currentLength*
00351 edgeInfo[tea[i]].currentLength);
00352
00353
00354 for (u=0;u<3;++u) {
00355 for (v=0;v<3;++v) {
00356 m[u][v]=dpk[u]*dpk[v]*val2
00357 +dpj[u]*dpi[v]*valk
00358 -dpj[u]*dpk[v]*vali
00359 +dpk[u]*dpi[v]*valj;
00360
00361 }
00362 m[u][u]+=val1;
00363 }
00364 }
00365 }
00366 }
00367
00368 }
00369
00370 for(int l=0; l<nbTriangles; l++ )
00371 {
00372 tinfo=&triangleInfo[l];
00374 const Triangle &ta= _topology->getTriangle(l);
00375
00376
00377 for(k=0;k<3;++k) {
00378 i=(k+1)%3;
00379 j=(k+2)%3;
00380 deltax= dx[ta[i]] -dx[ta[j]];
00381 res=tinfo->DfDx[k]*deltax;
00382 df[ta[i]]+=res;
00383 df[ta[j]]-= tinfo->DfDx[k].transposeMultiply(deltax);
00384 }
00385 }
00386 }
00387
00388
00389 template<class DataTypes>
00390 void TriangularQuadraticSpringsForceField<DataTypes>::updateLameCoefficients()
00391 {
00392 lambda= f_youngModulus.getValue()*f_poissonRatio.getValue()/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00393 mu = f_youngModulus.getValue()*(1-f_poissonRatio.getValue())/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00394
00395 }
00396
00397
00398 template<class DataTypes>
00399 void TriangularQuadraticSpringsForceField<DataTypes>::draw()
00400 {
00401 if (!getContext()->getShowForceFields()) return;
00402 if (!this->mstate) return;
00403
00404 if (getContext()->getShowWireFrame())
00405 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00406
00407 VecCoord& x = *this->mstate->getX();
00408 int nbTriangles=_topology->getNbTriangles();
00409
00410 glDisable(GL_LIGHTING);
00411
00412 glBegin(GL_TRIANGLES);
00413 for(int i=0;i<nbTriangles; ++i)
00414 {
00415 int a = _topology->getTriangle(i)[0];
00416 int b = _topology->getTriangle(i)[1];
00417 int c = _topology->getTriangle(i)[2];
00418
00419 glColor4f(0,1,0,1);
00420 helper::gl::glVertexT(x[a]);
00421 glColor4f(0,0.5,0.5,1);
00422 helper::gl::glVertexT(x[b]);
00423 glColor4f(0,0,1,1);
00424 helper::gl::glVertexT(x[c]);
00425 }
00426 glEnd();
00427
00428
00429 if (getContext()->getShowWireFrame())
00430 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00431 }
00432
00433 }
00434
00435 }
00436
00437 }