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