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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef SOFA_COMPONENT_FORCEFIELD_TRIANGULARBENDINGSPRINGS_INL
00037 #define SOFA_COMPONENT_FORCEFIELD_TRIANGULARBENDINGSPRINGS_INL
00038
00039 #include <sofa/component/forcefield/TriangularBendingSprings.h>
00040 #include <sofa/component/topology/PointSetTopologyChange.h>
00041 #include <fstream>
00042 #include <iostream>
00043
00044 #include <sofa/helper/gl/template.h>
00045 #include <sofa/component/topology/TriangleData.inl>
00046 #include <sofa/component/topology/EdgeData.inl>
00047
00048 namespace sofa
00049 {
00050
00051 namespace component
00052 {
00053
00054 namespace forcefield
00055 {
00056
00057 using namespace sofa::defaulttype;
00058 using namespace sofa::component::topology;
00059 using namespace core::componentmodel::topology;
00060
00061 using std::cerr;
00062 using std::cout;
00063 using std::endl;
00064
00065 using namespace core::componentmodel::behavior;
00066 using core::componentmodel::topology::BaseMeshTopology;
00067 typedef BaseMeshTopology::TriangleEdges TriangleEdges;
00068
00069 template< class DataTypes>
00070 void TriangularBendingSprings<DataTypes>::TriangularBSEdgeCreationFunction(int , void* param, EdgeInformation &ei,
00071 const Edge& , const sofa::helper::vector< unsigned int > &,
00072 const sofa::helper::vector< double >&)
00073 {
00074 TriangularBendingSprings<DataTypes> *ff= (TriangularBendingSprings<DataTypes> *)param;
00075 if (ff) {
00076
00077 unsigned int u,v;
00079 for (u=0;u<3;++u) {
00080 for (v=0;v<3;++v) {
00081 ei.DfDx[u][v]=0;
00082 }
00083 }
00084
00085 ei.is_activated=false;
00086 ei.is_initialized=false;
00087
00088 }
00089 }
00090
00091 template< class DataTypes>
00092 void TriangularBendingSprings<DataTypes>::TriangularBSTriangleCreationFunction (const sofa::helper::vector<unsigned int> &triangleAdded,
00093 void* param, vector<EdgeInformation> &edgeData)
00094 {
00095
00096 TriangularBendingSprings<DataTypes> *ff= (TriangularBendingSprings<DataTypes> *)param;
00097 if (ff) {
00098
00099 double m_ks=ff->getKs();
00100 double m_kd=ff->getKd();
00101
00102 unsigned int u,v;
00103
00104 unsigned int nb_activated = 0;
00105
00106 const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00107
00108 for (unsigned int i=0;i<triangleAdded.size();++i) {
00109
00111 TriangleEdges te2 = ff->_topology->getEdgeTriangleShell(triangleAdded[i]);
00113 Triangle t2 = ff->_topology->getTriangle(triangleAdded[i]);
00114
00115 for(unsigned int j=0;j<3;++j) {
00116
00117 EdgeInformation &ei = edgeData[te2[j]];
00118 if(!(ei.is_initialized)){
00119
00120 unsigned int edgeIndex = te2[j];
00121 ei.is_activated=true;
00122
00124 for (u=0;u<3;++u) {
00125 for (v=0;v<3;++v) {
00126 ei.DfDx[u][v]=0;
00127 }
00128 }
00129
00130 const sofa::helper::vector< unsigned int > shell = ff->_topology->getTriangleEdgeShell(edgeIndex);
00131 if (shell.size()==2) {
00132
00133 nb_activated+=1;
00134
00135 TriangleEdges te1;
00136 Triangle t1;
00137
00138 if(shell[0] == triangleAdded[i]){
00139
00140 te1 = ff->_topology->getEdgeTriangleShell(shell[1]);
00141 t1 = ff->_topology->getTriangle(shell[1]);
00142
00143 }else{
00144
00145 te1 = ff->_topology->getEdgeTriangleShell(shell[0]);
00146 t1 = ff->_topology->getTriangle(shell[0]);
00147 }
00148
00149 int i1 = ff->_topology->getEdgeIndexInTriangle(te1, edgeIndex);
00150 int i2 = ff->_topology->getEdgeIndexInTriangle(te2, edgeIndex);
00151
00152 ei.m1 = t1[i1];
00153 ei.m2 = t2[i2];
00154
00155
00156 ei.ks=m_ks;
00157 ei.kd=m_kd;
00158
00159 Coord u = (*restPosition)[ei.m1] - (*restPosition)[ei.m2];
00160
00161 Real d = u.norm();
00162
00163 ei.restlength=(double) d;
00164
00165 ei.is_activated=true;
00166
00167 }else{
00168
00169 ei.is_activated=false;
00170
00171 }
00172
00173 ei.is_initialized = true;
00174 }
00175 }
00176
00177 }
00178
00179 }
00180
00181 }
00182
00183 template< class DataTypes>
00184 void TriangularBendingSprings<DataTypes>::TriangularBSTriangleDestructionFunction (const sofa::helper::vector<unsigned int> &triangleRemoved,
00185 void* param, vector<EdgeInformation> &edgeData)
00186 {
00187 TriangularBendingSprings<DataTypes> *ff= (TriangularBendingSprings<DataTypes> *)param;
00188 if (ff) {
00189
00190 double m_ks=ff->getKs();
00191 double m_kd=ff->getKd();
00192
00193
00194
00195 const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00196
00197 for (unsigned int i=0;i<triangleRemoved.size();++i) {
00199 TriangleEdges te = ff->_topology->getEdgeTriangleShell(triangleRemoved[i]);
00201 Triangle t = ff->_topology->getTriangle(triangleRemoved[i]);
00202
00203
00204 for(unsigned int j=0;j<3;++j) {
00205
00206 EdgeInformation &ei = edgeData[te[j]];
00207 if(ei.is_initialized){
00208
00209 unsigned int edgeIndex = te[j];
00210
00211 const sofa::helper::vector< unsigned int > shell = ff->_topology->getTriangleEdgeShell(edgeIndex);
00212 if (shell.size()==3) {
00213
00214 TriangleEdges te1;
00215 Triangle t1;
00216 TriangleEdges te2;
00217 Triangle t2;
00218
00219 if(shell[0] == triangleRemoved[i]){
00220 te1 = ff->_topology->getEdgeTriangleShell(shell[1]);
00221 t1 = ff->_topology->getTriangle(shell[1]);
00222 te2 = ff->_topology->getEdgeTriangleShell(shell[2]);
00223 t2 = ff->_topology->getTriangle(shell[2]);
00224
00225 }else{
00226
00227 if(shell[1] == triangleRemoved[i]){
00228
00229 te1 = ff->_topology->getEdgeTriangleShell(shell[2]);
00230 t1 = ff->_topology->getTriangle(shell[2]);
00231 te2 = ff->_topology->getEdgeTriangleShell(shell[0]);
00232 t2 = ff->_topology->getTriangle(shell[0]);
00233
00234 }else{
00235
00236 te1 = ff->_topology->getEdgeTriangleShell(shell[0]);
00237 t1 = ff->_topology->getTriangle(shell[0]);
00238 te2 = ff->_topology->getEdgeTriangleShell(shell[1]);
00239 t2 = ff->_topology->getTriangle(shell[1]);
00240
00241 }
00242 }
00243
00244 int i1 = ff->_topology->getEdgeIndexInTriangle(te1, edgeIndex);
00245 int i2 = ff->_topology->getEdgeIndexInTriangle(te2, edgeIndex);
00246
00247 ei.m1 = t1[i1];
00248 ei.m2 = t2[i2];
00249
00250
00251 ei.ks=m_ks;
00252 ei.kd=m_kd;
00253
00254 Coord u = (*restPosition)[ei.m1] - (*restPosition)[ei.m2];
00255 Real d = u.norm();
00256
00257 ei.restlength=(double) d;
00258
00259 ei.is_activated=true;
00260
00261 }else{
00262
00263 ei.is_activated=false;
00264 ei.is_initialized = false;
00265
00266 }
00267
00268 }else{
00269
00270 ei.is_activated=false;
00271 ei.is_initialized = false;
00272
00273 }
00274 }
00275
00276 }
00277
00278 }
00279 }
00280
00281
00282 template<class DataTypes>
00283 TriangularBendingSprings<DataTypes>::TriangularBendingSprings( )
00284 : updateMatrix(true)
00285 , f_ks(initData(&f_ks,(double) 100000.0,"stiffness","uniform stiffness for the all springs"))
00286 , f_kd(initData(&f_kd,(double) 1.0,"damping","uniform damping for the all springs"))
00287 {
00288
00289 }
00290
00291 template<class DataTypes>
00292 TriangularBendingSprings<DataTypes>::~TriangularBendingSprings()
00293 {}
00294
00295
00296 template <class DataTypes> void TriangularBendingSprings<DataTypes>::handleTopologyChange()
00297 {
00298 bool debug_mode = false;
00299
00300 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00301 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00302
00303 edgeInfo.handleTopologyEvents(itBegin,itEnd);
00304
00305 while( itBegin != itEnd )
00306 {
00307 core::componentmodel::topology::TopologyChangeType changeType = (*itBegin)->getChangeType();
00308
00309 if(changeType == core::componentmodel::topology::POINTSREMOVED){
00310
00311 unsigned int last = _topology->getNbPoints() -1;
00312 unsigned int i,j;
00313
00314 const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRemoved * >( *itBegin ) )->getArray();
00315
00316 sofa::helper::vector<unsigned int> lastIndexVec;
00317 for(unsigned int i_init = 0; i_init < tab.size(); ++i_init){
00318
00319 lastIndexVec.push_back(last - i_init);
00320 }
00321
00322 for ( i = 0; i < tab.size(); ++i)
00323 {
00324
00325 unsigned int i_next = i;
00326 bool is_reached = false;
00327 while( (!is_reached) && (i_next < lastIndexVec.size() - 1)){
00328
00329 i_next += 1 ;
00330 is_reached = is_reached || (lastIndexVec[i_next] == tab[i]);
00331 }
00332
00333 if(is_reached){
00334
00335 lastIndexVec[i_next] = lastIndexVec[i];
00336
00337 }
00338
00339 const sofa::helper::vector<unsigned int> &shell= _topology->getTriangleVertexShell(lastIndexVec[i]);
00340 for (j=0;j<shell.size();++j) {
00341
00342 Triangle tj = _topology->getTriangle(shell[j]);
00343
00344 int vertexIndex = _topology->getVertexIndexInTriangle(tj, lastIndexVec[i]);
00345
00346 TriangleEdges tej = _topology->getEdgeTriangleShell(shell[j]);
00347
00348 unsigned int ind_j = tej[vertexIndex];
00349
00350 if (edgeInfo[ind_j].m1 == (int) last){
00351 edgeInfo[ind_j].m1=(int) tab[i];
00352
00353 }else{
00354 if (edgeInfo[ind_j].m2 == (int) last){
00355 edgeInfo[ind_j].m2=(int) tab[i];
00356
00357 }
00358 }
00359 }
00360
00361 if(debug_mode){
00362
00363 for (unsigned int j_loc=0;j_loc<edgeInfo.size();++j_loc) {
00364
00365 bool is_forgotten = false;
00366 if (edgeInfo[j_loc].m1 == (int) last){
00367 edgeInfo[j_loc].m1 =(int) tab[i];
00368 is_forgotten=true;
00369
00370
00371 }else{
00372 if (edgeInfo[j_loc].m2 ==(int) last){
00373 edgeInfo[j_loc].m2 =(int) tab[i];
00374 is_forgotten=true;
00375
00376
00377 }
00378
00379 }
00380
00381 }
00382 }
00383
00384 --last;
00385 }
00386
00387 }else{
00388
00389 if(changeType == core::componentmodel::topology::POINTSRENUMBERING){
00390
00391 const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRenumbering * >( *itBegin ) )->getinv_IndexArray();
00392
00393 for (int i = 0; i < _topology->getNbEdges(); ++i)
00394 {
00395 if(edgeInfo[i].is_activated){
00396 edgeInfo[i].m1 = tab[edgeInfo[i].m1];
00397 edgeInfo[i].m2 = tab[edgeInfo[i].m2];
00398 }
00399 }
00400 }
00401 }
00402
00403 ++itBegin;
00404 }
00405 }
00406
00407
00408 template<class DataTypes>
00409 void TriangularBendingSprings<DataTypes>::init()
00410 {
00411
00412 this->Inherited::init();
00413
00414 _topology = getContext()->getMeshTopology();
00415
00416 if (_topology->getNbTriangles()==0)
00417 {
00418 std::cerr << "ERROR(TriangularBendingSprings): object must have a Triangular Set Topology.\n";
00419 return;
00420 }
00421
00423 edgeInfo.resize(_topology->getNbEdges());
00424
00425 int i;
00426
00427 for (i=0;i<_topology->getNbEdges();++i) {
00428
00429 TriangularBSEdgeCreationFunction(i, (void*) this, edgeInfo[i],
00430 _topology->getEdge(i), (const sofa::helper::vector< unsigned int > )0,
00431 (const sofa::helper::vector< double >)0);
00432 }
00433
00434
00435 sofa::helper::vector<unsigned int> triangleAdded;
00436 for (i=0;i<_topology->getNbTriangles();++i){
00437 triangleAdded.push_back(i);
00438 }
00439 TriangularBSTriangleCreationFunction(triangleAdded,(void*) this,
00440 edgeInfo);
00441
00442 edgeInfo.setCreateFunction(TriangularBSEdgeCreationFunction);
00443 edgeInfo.setCreateTriangleFunction(TriangularBSTriangleCreationFunction);
00444 edgeInfo.setDestroyTriangleFunction(TriangularBSTriangleDestructionFunction);
00445 edgeInfo.setCreateParameter( (void *) this );
00446 edgeInfo.setDestroyParameter( (void *) this );
00447
00448 }
00449
00450 template <class DataTypes>
00451 double TriangularBendingSprings<DataTypes>::getPotentialEnergy(const VecCoord& )
00452 {
00453 std::cerr<<"TriangularBendingSprings::getPotentialEnergy-not-implemented !!!"<<endl;
00454 return 0;
00455 }
00456
00457
00458 template<class DataTypes>
00459 void TriangularBendingSprings<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& v)
00460 {
00461 int nbEdges=_topology->getNbEdges();
00462
00463 EdgeInformation *einfo;
00464
00465
00466
00467 f.resize(x.size());
00468 m_potentialEnergy = 0;
00469
00470
00471 #if 0
00472 const VecCoord& x_rest = *this->mstate->getX0();
00473 #endif
00474
00475 for(int i=0; i<nbEdges; i++ )
00476 {
00477 einfo=&edgeInfo[i];
00478
00479
00480 #if 0
00481 {
00482 EdgeInformation e2;
00483 const sofa::helper::vector< unsigned int > shell = _topology->getTriangleEdgeShell(i);
00484 if (shell.size() != 2)
00485 e2.is_activated = false;
00486 else
00487 {
00488 e2.is_activated = true;
00489 e2.m1 = -1;
00490 e2.m2 = -1;
00491 for (int j=0;j<3;j++)
00492 if (_topology->getTriangle(shell[0]][j] != getEdge(i)[0] && _topology->getTriangle(shell[0])[j] != getEdge(i)[1])
00493 e2.m1 = _topology->getTriangle(shell[0])[j];
00494 for (int j=0;j<3;j++)
00495 if (_topology->getTriangle(shell[1])[j] != getEdge(i)[0] && _topology->getTriangle(shell[1])[j] != getEdge(i)[1])
00496 e2.m2 = _topology->getTriangle(shell[1])[j];
00497 if (e2.m1 >= 0 && e2.m2 >= 0)
00498 {
00499 e2.restlength = (x_rest[e2.m2]-x_rest[e2.m1]).norm();
00500 }
00501 }
00502
00503 if (e2.is_activated != einfo->is_activated) std::cerr << "ERROR: EdgeInfo["<<i<<"].is_activated = "<<einfo->is_activated<<" while it should be "<<e2.is_activated<<"\n";
00504 else if (e2.is_activated)
00505 {
00506 if (!((e2.m1 == einfo->m1 && e2.m2 == einfo->m2) || (e2.m1 == einfo->m2 && e2.m2 == einfo->m1)))
00507 std::cerr << "ERROR: EdgeInfo["<<i<<"] points = "<<einfo->m1<<"-"<<einfo->m2<<" while it should be "<<e2.m1<<"-"<<e2.m2<<"\n";
00508 if (e2.restlength != einfo->restlength)
00509 std::cerr << "ERROR: EdgeInfo["<<i<<"] length = "<<einfo->restlength<<" while it should be "<<e2.restlength<<"\n";
00510 }
00511 }
00512
00513 #endif
00514
00515
00516
00517 if(einfo->is_activated){
00518
00519
00520 int a = einfo->m1;
00521 int b = einfo->m2;
00522 Coord u = x[b]-x[a];
00523 Real d = u.norm();
00524 if( d>1.0e-4 )
00525 {
00526 Real inverseLength = 1.0f/d;
00527 u *= inverseLength;
00528 Real elongation = (Real)(d - einfo->restlength);
00529 m_potentialEnergy += elongation * elongation * einfo->ks / 2;
00530
00531
00532
00533 Deriv relativeVelocity = v[b]-v[a];
00534 Real elongationVelocity = dot(u,relativeVelocity);
00535 Real forceIntensity = (Real)(einfo->ks*elongation+einfo->kd*elongationVelocity);
00536 Deriv force = u*forceIntensity;
00537 f[a]+=force;
00538 f[b]-=force;
00539
00540 updateMatrix=true;
00541
00542 Mat3& m = einfo->DfDx;
00543 Real tgt = forceIntensity * inverseLength;
00544 for( int j=0; j<3; ++j )
00545 {
00546 for( int k=0; k<3; ++k )
00547 {
00548 m[j][k] = ((Real)einfo->ks-tgt) * u[j] * u[k];
00549 }
00550 m[j][j] += tgt;
00551 }
00552 }
00553 else
00554 {
00555 Mat3& m = einfo->DfDx;
00556 for( int j=0; j<3; ++j )
00557 {
00558 for( int k=0; k<3; ++k )
00559 {
00560 m[j][k] = 0;
00561 }
00562 }
00563 }
00564 }
00565 }
00566
00567
00568
00569
00570
00571
00572
00573 }
00574
00575 template<class DataTypes>
00576 void TriangularBendingSprings<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00577 {
00578 int nbEdges=_topology->getNbEdges();
00579
00580 EdgeInformation *einfo;
00581
00582 df.resize(dx.size());
00583
00584
00585
00586
00587 for(int i=0; i<nbEdges; i++ )
00588 {
00589 einfo=&edgeInfo[i];
00590
00591
00592
00593 if(einfo->is_activated){
00594
00595
00596 const int a = einfo->m1;
00597 const int b = einfo->m2;
00598 const Coord d = dx[b]-dx[a];
00599 const Deriv dforce = einfo->DfDx*d;
00600 df[a]+=dforce;
00601 df[b]-=dforce;
00602
00603
00604 if(updateMatrix){
00605
00606 }
00607 updateMatrix=false;
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 template<class DataTypes>
00631 void TriangularBendingSprings<DataTypes>::draw()
00632 {
00633 unsigned int i;
00634 if (!getContext()->getShowForceFields()) return;
00635 if (!this->mstate) return;
00636
00637 if (getContext()->getShowWireFrame())
00638 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00639
00640 VecCoord& x = *this->mstate->getX();
00641
00642
00643
00644 glDisable(GL_LIGHTING);
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 unsigned int nb_to_draw = 0;
00664
00665 glBegin(GL_LINES);
00666 for(i=0;i<edgeInfo.size(); ++i)
00667 {
00668 if(edgeInfo[i].is_activated){
00669
00670
00671 bool external=true;
00672 Real d = (x[edgeInfo[i].m2]-x[edgeInfo[i].m1]).norm();
00673 if (external)
00674 {
00675 if (d<edgeInfo[i].restlength*0.9999)
00676 glColor4f(1,0,0,1);
00677 else
00678 glColor4f(0,1,0,1);
00679 }
00680 else
00681 {
00682 if (d<edgeInfo[i].restlength*0.9999)
00683 glColor4f(1,0.5f,0,1);
00684 else
00685 glColor4f(0,1,0.5f,1);
00686 }
00687
00688
00689 nb_to_draw+=1;
00690
00691
00692 helper::gl::glVertexT(x[edgeInfo[i].m1]);
00693 helper::gl::glVertexT(x[edgeInfo[i].m2]);
00694
00695 }
00696 }
00697 glEnd();
00698
00699
00700 if (getContext()->getShowWireFrame())
00701 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00702 }
00703
00704
00705 }
00706
00707 }
00708
00709 }
00710
00711 #endif