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