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/TriangularTensorMassForceField.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
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 using core::componentmodel::topology::BaseMeshTopology;
00051 typedef BaseMeshTopology::TriangleEdges TriangleEdges;
00052
00053 template< class DataTypes>
00054 void TriangularTensorMassForceField<DataTypes>::TriangularTMEdgeCreationFunction(int , void* param, EdgeRestInformation &ei,
00055 const Edge& , const sofa::helper::vector< unsigned int > &,
00056 const sofa::helper::vector< double >&)
00057 {
00058 TriangularTensorMassForceField<DataTypes> *ff= (TriangularTensorMassForceField<DataTypes> *)param;
00059 if (ff) {
00060
00061 unsigned int u,v;
00063 for (u=0;u<3;++u) {
00064 for (v=0;v<3;++v) {
00065 ei.DfDx[u][v]=0;
00066 }
00067 }
00068
00069 }
00070 }
00071
00072 template< class DataTypes>
00073 void TriangularTensorMassForceField<DataTypes>::TriangularTMTriangleCreationFunction (const sofa::helper::vector<unsigned int> &triangleAdded,
00074 void* param, vector<EdgeRestInformation> &edgeData)
00075 {
00076 TriangularTensorMassForceField<DataTypes> *ff= (TriangularTensorMassForceField<DataTypes> *)param;
00077 if (ff) {
00078
00079 unsigned int i,j,k,l,u,v;
00080
00081 typename DataTypes::Real val1,area,restSquareLength[3],cotangent[3];
00082 typename DataTypes::Real lambda=ff->getLambda();
00083 typename DataTypes::Real mu=ff->getMu();
00084 typename DataTypes::Real lambdastar, mustar;
00085 typename DataTypes::Coord point[3],dpk,dpl;
00086
00087 const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00088
00089 for (i=0;i<triangleAdded.size();++i) {
00090
00092 const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleAdded[i]);
00094 const Triangle &t= ff->_topology->getTriangle(triangleAdded[i]);
00095
00096 for(j=0;j<3;++j)
00097 point[j]=(*restPosition)[t[j]];
00098
00099 for(j=0;j<3;++j) {
00100 restSquareLength[j]= (point[(j+1)%3] -point[(j+2)%3]).norm2();
00101 }
00102
00103 area=0;
00104 for(j=0;j<3;++j) {
00105 area+=restSquareLength[j]*(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j]);
00106 }
00107 area=sqrt(area)/4;
00108 lambdastar=lambda/(4*area);
00109 mustar=mu/(8*area);
00110
00111 for(j=0;j<3;++j) {
00112 cotangent[j]=(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j])/(4*area);
00113 if (ff->f_printLog.getValue()) {
00114 if (cotangent[j]<0)
00115 std::cerr<<"negative cotangent["<<triangleAdded[i]<<"]["<<j<<"]"<<std::endl;
00116 }
00117 }
00118 for(j=0;j<3;++j){
00119 k=(j+1)%3;
00120 l=(j+2)%3;
00121 Mat3 &m=edgeData[te[j]].DfDx;
00122 dpl= point[j]-point[k];
00123 dpk= point[j]-point[l];
00124 val1= -cotangent[j]*(lambda+mu)/2;
00125
00126 if (ff->_topology->getEdge(te[j])[0]==t[l]) {
00127 for (u=0;u<3;++u) {
00128 for (v=0;v<3;++v) {
00129 m[u][v]+= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00130 }
00131 m[u][u]+=val1;
00132 }
00133 } else {
00134 for (u=0;u<3;++u) {
00135 for (v=0;v<3;++v) {
00136 m[v][u]+= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00137 }
00138 m[u][u]+=val1;
00139 }
00140 }
00141 }
00142
00143 }
00144
00145 }
00146 }
00147
00148 template< class DataTypes>
00149 void TriangularTensorMassForceField<DataTypes>::TriangularTMTriangleDestructionFunction (const sofa::helper::vector<unsigned int> &triangleRemoved,
00150 void* param, vector<EdgeRestInformation> &edgeData)
00151 {
00152 TriangularTensorMassForceField<DataTypes> *ff= (TriangularTensorMassForceField<DataTypes> *)param;
00153 if (ff) {
00154
00155 unsigned int i,j,k,l,u,v;
00156
00157 typename DataTypes::Real val1,area,restSquareLength[3],cotangent[3];
00158 typename DataTypes::Real lambda=ff->getLambda();
00159 typename DataTypes::Real mu=ff->getMu();
00160 typename DataTypes::Real lambdastar, mustar;
00161 typename DataTypes::Coord point[3],dpk,dpl;
00162
00163 const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00164
00165 for (i=0;i<triangleRemoved.size();++i) {
00166
00168 const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleRemoved[i]);
00170 const Triangle &t= ff->_topology->getTriangle(triangleRemoved[i]);
00171
00172 for(j=0;j<3;++j)
00173 point[j]=(*restPosition)[t[j]];
00174
00175 for(j=0;j<3;++j) {
00176 restSquareLength[j]= (point[(j+1)%3] -point[(j+2)%3]).norm2();
00177 }
00178
00179 area=0;
00180 for(j=0;j<3;++j) {
00181 area+=restSquareLength[j]*(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j]);
00182 }
00183 area=sqrt(area)/4;
00184 lambdastar=lambda/(4*area);
00185 mustar=mu/(8*area);
00186
00187 for(j=0;j<3;++j) {
00188 cotangent[j]=(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j])/(4*area);
00189 if (ff->f_printLog.getValue()) {
00190 if (cotangent[j]<0)
00191 std::cerr<<"negative cotangent["<<triangleRemoved[i]<<"]["<<j<<"]"<<std::endl;
00192 }
00193 }
00194 for(j=0;j<3;++j){
00195 k=(j+1)%3;
00196 l=(j+2)%3;
00197 Mat3 &m=edgeData[te[j]].DfDx;
00198 dpl= point[j]-point[k];
00199 dpk= point[j]-point[l];
00200 val1= -cotangent[j]*(lambda+mu)/2;
00201
00202 if (ff->_topology->getEdge(te[j])[0]==t[l]) {
00203 for (u=0;u<3;++u) {
00204 for (v=0;v<3;++v) {
00205 m[u][v]-= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00206 }
00207 m[u][u]-=val1;
00208 }
00209 } else {
00210 for (u=0;u<3;++u) {
00211 for (v=0;v<3;++v) {
00212 m[v][u]-= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00213 }
00214 m[u][u]-=val1;
00215 }
00216 }
00217 }
00218
00219 }
00220
00221 }
00222 }
00223
00224
00225 template <class DataTypes> TriangularTensorMassForceField<DataTypes>::TriangularTensorMassForceField()
00226 : _initialPoints(0)
00227 , updateMatrix(true)
00228 , f_poissonRatio(initData(&f_poissonRatio,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00229 , f_youngModulus(initData(&f_youngModulus,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00230 , lambda(0)
00231 , mu(0)
00232 {
00233 }
00234
00235 template <class DataTypes> void TriangularTensorMassForceField<DataTypes>::handleTopologyChange()
00236 {
00237 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00238 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00239
00240 edgeInfo.handleTopologyEvents(itBegin,itEnd);
00241 }
00242
00243 template <class DataTypes> TriangularTensorMassForceField<DataTypes>::~TriangularTensorMassForceField()
00244 {
00245
00246 }
00247
00248 template <class DataTypes> void TriangularTensorMassForceField<DataTypes>::init()
00249 {
00250 std::cerr << "initializing TriangularTensorMassForceField" << std::endl;
00251 this->Inherited::init();
00252
00253 _topology = getContext()->getMeshTopology();
00254
00255 if (_topology->getNbTriangles()==0)
00256 {
00257 std::cerr << "ERROR(TriangularTensorMassForceField): object must have a Triangular Set Topology.\n";
00258 return;
00259 }
00260 updateLameCoefficients();
00261
00263 edgeInfo.resize(_topology->getNbEdges());
00264
00265 if (_initialPoints.size() == 0)
00266 {
00267
00268 VecCoord& p = *this->mstate->getX0();
00269 _initialPoints=p;
00270 }
00271
00272 int i;
00273
00274 for (i=0;i<_topology->getNbEdges();++i) {
00275 TriangularTMEdgeCreationFunction(i, (void*) this, edgeInfo[i],
00276 _topology->getEdge(i), (const sofa::helper::vector< unsigned int > )0,
00277 (const sofa::helper::vector< double >)0);
00278 }
00279
00280 sofa::helper::vector<unsigned int> triangleAdded;
00281 for (i=0;i<_topology->getNbTriangles();++i)
00282 triangleAdded.push_back(i);
00283 TriangularTMTriangleCreationFunction(triangleAdded,(void*) this,
00284 edgeInfo);
00285
00286
00287 edgeInfo.setCreateFunction(TriangularTMEdgeCreationFunction);
00288 edgeInfo.setCreateTriangleFunction(TriangularTMTriangleCreationFunction);
00289 edgeInfo.setDestroyTriangleFunction(TriangularTMTriangleDestructionFunction);
00290 edgeInfo.setCreateParameter( (void *) this );
00291 edgeInfo.setDestroyParameter( (void *) this );
00292
00293 }
00294
00295
00296 template <class DataTypes>
00297 double TriangularTensorMassForceField<DataTypes>::getPotentialEnergy(const VecCoord& )
00298 {
00299 std::cerr<<"TriangularTensorMassForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00300 return 0;
00301 }
00302 template <class DataTypes>
00303 void TriangularTensorMassForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& )
00304 {
00305 unsigned int i,v0,v1;
00306 unsigned int nbEdges=_topology->getNbEdges();
00307
00308 EdgeRestInformation *einfo;
00309
00310 Deriv force;
00311 Coord dp0,dp1,dp;
00312
00313
00314 for(i=0; i<nbEdges; i++ )
00315 {
00316 einfo=&edgeInfo[i];
00317 v0=_topology->getEdge(i)[0];
00318 v1=_topology->getEdge(i)[1];
00319 dp0=x[v0]-_initialPoints[v0];
00320 dp1=x[v1]-_initialPoints[v1];
00321 dp = dp1-dp0;
00322
00323 f[v1]+=einfo->DfDx*dp;
00324 f[v0]-=einfo->DfDx.transposeMultiply(dp);
00325 }
00326
00327 }
00328
00329
00330 template <class DataTypes>
00331 void TriangularTensorMassForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00332 {
00333 unsigned int v0,v1;
00334 int nbEdges=_topology->getNbEdges();
00335
00336 EdgeRestInformation *einfo;
00337
00338
00339 Deriv force;
00340 Coord dp0,dp1,dp;
00341
00342 for(int i=0; i<nbEdges; i++ )
00343 {
00344 einfo=&edgeInfo[i];
00345 v0=_topology->getEdge(i)[0];
00346 v1=_topology->getEdge(i)[1];
00347 dp0=dx[v0];
00348 dp1=dx[v1];
00349 dp = dp1-dp0;
00350
00351 df[v1]+=einfo->DfDx*dp;
00352 df[v0]-=einfo->DfDx.transposeMultiply(dp);
00353 }
00354
00355 }
00356
00357
00358 template<class DataTypes>
00359 void TriangularTensorMassForceField<DataTypes>::updateLameCoefficients()
00360 {
00361 lambda= f_youngModulus.getValue()*f_poissonRatio.getValue()/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00362 mu = f_youngModulus.getValue()*(1-f_poissonRatio.getValue())/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00363
00364 }
00365
00366
00367 template<class DataTypes>
00368 void TriangularTensorMassForceField<DataTypes>::draw()
00369 {
00370 int i;
00371 if (!getContext()->getShowForceFields()) return;
00372 if (!this->mstate) return;
00373
00374 if (getContext()->getShowWireFrame())
00375 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00376
00377 VecCoord& x = *this->mstate->getX();
00378 int nbTriangles=_topology->getNbTriangles();
00379
00380 glDisable(GL_LIGHTING);
00381
00382 glBegin(GL_TRIANGLES);
00383 for(i=0;i<nbTriangles; ++i)
00384 {
00385 int a = _topology->getTriangle(i)[0];
00386 int b = _topology->getTriangle(i)[1];
00387 int c = _topology->getTriangle(i)[2];
00388
00389 glColor4f(0,1,0,1);
00390 helper::gl::glVertexT(x[a]);
00391 glColor4f(0,0.5,0.5,1);
00392 helper::gl::glVertexT(x[b]);
00393 glColor4f(0,0,1,1);
00394 helper::gl::glVertexT(x[c]);
00395 }
00396 glEnd();
00397
00398
00399 if (getContext()->getShowWireFrame())
00400 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00401 }
00402
00403 }
00404
00405 }
00406
00407 }