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/TriangularFEMForceField.h>
00026 #include <sofa/core/ObjectFactory.h>
00027 #include <sofa/helper/gl/template.h>
00028 #include <sofa/component/topology/TriangleData.inl>
00029 #include <sofa/component/topology/EdgeData.inl>
00030 #include <sofa/component/topology/PointData.inl>
00031 #include <sofa/helper/system/gl.h>
00032 #include <fstream>
00033 #include <iostream>
00034 #include <vector>
00035 #include <algorithm>
00036 #include <sofa/defaulttype/Vec3Types.h>
00037 #include <assert.h>
00038
00039 #ifdef _WIN32
00040 #include <windows.h>
00041 #endif
00042
00043
00044
00045
00046 namespace sofa
00047 {
00048
00049 namespace component
00050 {
00051
00052 namespace forcefield
00053 {
00054
00055 using namespace sofa::defaulttype;
00056 using namespace sofa::component::topology;
00057 using namespace core::componentmodel::topology;
00058
00059 using std::cerr;
00060 using std::cout;
00061 using std::endl;
00062
00063 template< class DataTypes>
00064 void TriangularFEMForceField<DataTypes>::TRQSTriangleCreationFunction ( int triangleIndex, void* param,
00065 TriangleInformation &,
00066 const Triangle& t,
00067 const sofa::helper::vector< unsigned int > &,
00068 const sofa::helper::vector< double >&)
00069 {
00070 TriangularFEMForceField<DataTypes> *ff= (TriangularFEMForceField<DataTypes> *)param;
00071 if (ff) {
00072 Index a = t[0];
00073 Index b = t[1];
00074 Index c = t[2];
00075
00076 switch(ff->method)
00077 {
00078 case SMALL :
00079 ff->computeMaterialStiffness(triangleIndex,a,b,c);
00080 ff->initSmall();
00081
00082 break;
00083 case LARGE :
00084 ff->computeMaterialStiffness(triangleIndex,a,b,c);
00085 ff->initLarge(triangleIndex,a,b,c);
00086 break;
00087 }
00088 }
00089
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 template <class DataTypes>
00103 TriangularFEMForceField<DataTypes>::TriangularFEMForceField()
00104 : method(LARGE)
00105 , f_method(initData(&f_method,std::string("large"),"method","large: large displacements, small: small displacements"))
00106 , f_poisson(initData(&f_poisson,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00107 , f_young(initData(&f_young,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00108 , f_damping(initData(&f_damping,(Real)0.,"damping","Ratio damping/stiffness"))
00109 , f_fracturable(initData(&f_fracturable,false,"fracturable","the forcefield computes the next fracturable Edge"))
00110 , showStressValue(initData(&showStressValue,false,"showStressValue","Flag activating rendering of stress values as a color in each triangle"))
00111 , showStressVector(initData(&showStressVector,false,"showStressVector","Flag activating rendering of stress directions within each triangle"))
00112 {
00113 }
00114
00115
00116 template <class DataTypes> void TriangularFEMForceField<DataTypes>::handleTopologyChange()
00117 {
00118 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00119 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00120
00121 triangleInfo.handleTopologyEvents(itBegin,itEnd);
00122 edgeInfo.handleTopologyEvents(itBegin,itEnd);
00123 vertexInfo.handleTopologyEvents(itBegin,itEnd);
00124 }
00125
00126 template <class DataTypes>
00127 TriangularFEMForceField<DataTypes>::~TriangularFEMForceField()
00128 {
00129 }
00130
00131 template <class DataTypes>
00132 void TriangularFEMForceField<DataTypes>::init()
00133 {
00134 std::cerr << "initializing TriangularFEMForceField" << std::endl;
00135 this->Inherited::init();
00136
00137 _topology = getContext()->getMeshTopology();
00138
00139 if (f_method.getValue() == "small")
00140 method = SMALL;
00141 else if (f_method.getValue() == "large")
00142 method = LARGE;
00143
00144 if (_topology->getNbTriangles()==0)
00145 {
00146 std::cerr << "ERROR(TriangularFEMForceField): object must have a Triangular Set Topology.\n";
00147 return;
00148 }
00149
00150 lastFracturedEdgeIndex = -1;
00151
00152 reinit();
00153 }
00154
00155
00156 template <class DataTypes>void TriangularFEMForceField<DataTypes>::reinit()
00157 {
00158 if (f_method.getValue() == "small")
00159 method = SMALL;
00160 else if (f_method.getValue() == "large")
00161 method = LARGE;
00162
00164 triangleInfo.resize(_topology->getNbTriangles());
00166 edgeInfo.resize(_topology->getNbEdges());
00167 unsigned int nbPoints=_topology->getNbPoints();
00168
00169 vertexInfo.resize(nbPoints);
00170
00171
00172
00173
00174
00175
00176 _initialPoints = this->mstate->getX0();
00177
00178 for (int i=0;i<_topology->getNbTriangles();++i)
00179 {
00180 TRQSTriangleCreationFunction(i, (void*) this, triangleInfo[i],
00181 _topology->getTriangle(i), (const sofa::helper::vector< unsigned int > )0,
00182 (const sofa::helper::vector< double >)0);
00183 }
00184
00185 triangleInfo.setCreateFunction(TRQSTriangleCreationFunction);
00186 triangleInfo.setCreateParameter( (void *) this );
00187 triangleInfo.setDestroyParameter( (void *) this );
00188 }
00189
00190
00191 template <class DataTypes>
00192 void TriangularFEMForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& )
00193 {
00194 int nbTriangles=_topology->getNbTriangles();
00195
00196
00197
00198
00199
00200 f.resize(x.size());
00201
00202 if(f_damping.getValue() != 0)
00203 {
00204 if(method == SMALL)
00205 {
00206 for( int i=0; i<nbTriangles; i+=3 )
00207 {
00208 accumulateForceSmall( f, x, i/3, true );
00209 accumulateDampingSmall( f, i/3 );
00210 }
00211 }
00212 else
00213 {
00214 for( int i=0; i<nbTriangles; i+=3 )
00215 {
00216 accumulateForceLarge( f, x, i/3, true );
00217 accumulateDampingLarge( f, i/3 );
00218 }
00219 }
00220 }
00221 else
00222 {
00223 if(method==SMALL)
00224 {
00225
00226
00227
00228 for(int i=0; i<nbTriangles; i+=1)
00229 {
00230 accumulateForceSmall( f, x, i, true );
00231 }
00232 }
00233 else
00234 {
00235
00236
00237
00238 for( int i=0; i<nbTriangles; i+=1)
00239 {
00240 accumulateForceLarge( f, x, i, true );
00241 }
00242 }
00243 }
00244
00245 if (f_fracturable.getValue())
00246 {
00247
00248 unsigned int nbPoints=_topology->getNbPoints();
00249
00250 for( unsigned int i=0; i<nbPoints; i++ )
00251 {
00252 const sofa::helper::vector< unsigned int >& triangleNeighbors = _topology->getTriangleVertexShell(i);
00253
00254 sofa::helper::vector< unsigned int >::const_iterator it = triangleNeighbors.begin();
00255 sofa::helper::vector< unsigned int >::const_iterator itEnd = triangleNeighbors.end();
00256 Coord meanStrainDirection, refStrainDirection;
00257 meanStrainDirection.clear();
00258 refStrainDirection.clear();
00259 vertexInfo[i].sumEigenValues = 0.0;
00260
00261 bool b(true);
00262
00263 while (it != itEnd)
00264 {
00265 if (b)
00266 {
00267 refStrainDirection = triangleInfo[*it].principalStrainDirection;
00268 if (refStrainDirection.norm() != 0.0)
00269 b=false;
00270 }
00271
00272 (triangleInfo[*it].principalStrainDirection * refStrainDirection < 0)?
00273 meanStrainDirection -= triangleInfo[*it].principalStrainDirection : meanStrainDirection += triangleInfo[*it].principalStrainDirection;
00274
00275 vertexInfo[i].sumEigenValues += triangleInfo[*it].eigenValue;
00276
00277 ++it;
00278 }
00279
00280
00281
00282 vertexInfo[i].meanStrainDirection = meanStrainDirection / (double)triangleNeighbors.size();
00283 vertexInfo[i].sumEigenValues = (double)vertexInfo[i].sumEigenValues / (double)triangleNeighbors.size();
00284 }
00285
00286
00287
00288
00289 for(int i=0; i<_topology->getNbEdges(); i++ )
00290 edgeInfo[i].fracturable = false;
00291
00292 if (nbPoints > 0)
00293 {
00294 double max = 0;
00295 int mostDeformableVertexIndex = -1;
00296
00297 for( unsigned int i=0; i<nbPoints; i++ )
00298 {
00299 bool vertexOnBorder = _topology->getTriangleVertexShell(i).size() < _topology->getEdgeVertexShell(i).size() && _topology->getTriangleVertexShell(i).size() > 1;
00300
00301 if (vertexOnBorder && vertexInfo[i].sumEigenValues > max)
00302 {
00303 mostDeformableVertexIndex = i;
00304 max = vertexInfo[i].sumEigenValues;
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 const double THRESHOLD = 0.2;
00340
00341 if ((mostDeformableVertexIndex!=-1) && (max > THRESHOLD))
00342 {
00343 std::cout << "max=" << max << std::endl;
00344 double minDotProduct = 1000.0;
00345 unsigned int fracturableIndex = 0;
00346 bool fracture(false);
00347
00348 const sofa::helper::vector< unsigned int >& edgeNeighbors = _topology->getEdgeVertexShell(mostDeformableVertexIndex);
00349
00350 sofa::helper::vector< unsigned int >::const_iterator it = edgeNeighbors.begin();
00351 sofa::helper::vector< unsigned int >::const_iterator itEnd = edgeNeighbors.end();
00352
00353 Index a;
00354 Index b;
00355
00356 Coord n = vertexInfo[mostDeformableVertexIndex].meanStrainDirection;
00357 n.normalize();
00358
00359 while (it != itEnd)
00360 {
00361 a = _topology->getEdge(*it)[0];
00362 b = _topology->getEdge(*it)[1];
00363
00364 if (vertexInfo[mostDeformableVertexIndex].meanStrainDirection.norm() != 0.0)
00365 {
00366 Coord d = x[b]-x[a];
00367 d.normalize();
00368 if (fabs(n * d) < minDotProduct)
00369 {
00370 sofa::helper::vector< unsigned int > triangleEdgeShell = _topology->getTriangleEdgeShell(*it);
00371 if (triangleEdgeShell.size() != 1)
00372 {
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 {
00405 minDotProduct = fabs(n * d);
00406 fracturableIndex = *it;
00407 fracture = true;
00408 }
00409 }
00410 }
00411 }
00412
00413 ++it;
00414 }
00415
00416 if (fracture) {
00417 std::cout << "fracture at edge "<<fracturableIndex<<std::endl;
00418 edgeInfo[fracturableIndex].fracturable = true;
00419 lastFracturedEdgeIndex = fracturableIndex;
00420 }
00421 }
00422 }
00423 }
00424
00425
00426 }
00427
00428
00429 template <class DataTypes>
00430 void TriangularFEMForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00431 {
00432 Real h=1;
00433 df.resize(dx.size());
00434
00435 if (method == SMALL)
00436 {
00437 applyStiffnessSmall( df,h,dx );
00438 }
00439 else
00440 {
00441 applyStiffnessLarge( df,h,dx );
00442 }
00443 }
00444
00445 template <class DataTypes>
00446 double TriangularFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord& )
00447 {
00448 cerr<<"TriangularFEMForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00449 return 0;
00450 }
00451
00452 template <class DataTypes>
00453 void TriangularFEMForceField<DataTypes>::applyStiffness( VecCoord& v, Real h, const VecCoord& x )
00454 {
00455 if (method == SMALL)
00456 {
00457 applyStiffnessSmall( v,h,x );
00458 }
00459 else
00460 {
00461 applyStiffnessLarge( v,h,x );
00462 }
00463 }
00464
00465
00466 template <class DataTypes>
00467 void TriangularFEMForceField<DataTypes>::computeStrainDisplacement( StrainDisplacement &J, Coord , Coord b, Coord c )
00468 {
00469 #ifdef DEBUG_TRIANGLEFEM
00470 std::cout << "TriangularFEMForceField::computeStrainDisplacement\n";
00471 #endif
00472
00473
00474 Real determinant = b[0] * c[1];
00475
00476 J[0][0] = J[1][2] = -c[1] / determinant;
00477 J[0][2] = J[1][1] = (c[0] - b[0]) / determinant;
00478 J[2][0] = J[3][2] = c[1] / determinant;
00479 J[2][2] = J[3][1] = -c[0] / determinant;
00480 J[4][0] = J[5][2] = 0;
00481 J[4][2] = J[5][1] = b[0] / determinant;
00482 J[1][0] = J[3][0] = J[5][0] = J[0][1] = J[2][1] = J[4][1] = 0;
00483 }
00484
00485 template <class DataTypes>
00486 void TriangularFEMForceField<DataTypes>::computeEigenStrain( Coord &v, StrainDisplacement &J, Displacement &Depl, double &maxEigenValue )
00487 {
00488 Mat<3,6,Real> Jt;
00489 Jt.transpose( J );
00490 Vec<3,Real> JtD;
00491
00492 JtD[0] = Jt[0][0] * Depl[0] + Jt[0][2] * Depl[2]
00493 ;
00494
00495 JtD[1] = Jt[1][1] * Depl[1] +
00496 Jt[1][3] * Depl[3] + Jt[1][5] * Depl[5];
00497
00498 JtD[2] = Jt[2][0] * Depl[0] + Jt[2][1] * Depl[1] + Jt[2][2] * Depl[2] +
00499 Jt[2][3] * Depl[3] + Jt[2][4] * Depl[4] ;
00500
00501 NEWMAT::SymmetricMatrix e(2);
00502 e = 0.0;
00503
00504 NEWMAT::DiagonalMatrix D(2);
00505 D = 0.0;
00506
00507 NEWMAT::Matrix V(2,2);
00508 V = 0.0;
00509
00510 e(1,1) = JtD[0];
00511 e(1,2) = JtD[2];
00512 e(2,1) = JtD[2];
00513 e(2,2) = JtD[1];
00514
00515 NEWMAT::Jacobi(e, D, V);
00516
00517 v[0] = (Real)V(1,1);
00518 v[1] = (Real)V(2,1);
00519 v[2] = 0.0;
00520
00521 v.normalize();
00522
00523 maxEigenValue = D(1,1);
00524
00525
00526 }
00527
00528
00529 template <class DataTypes>
00530 void TriangularFEMForceField<DataTypes>::computeMaterialStiffness(int i, Index &, Index &, Index &)
00531 {
00532
00533
00534 TriangleInformation *tinfo = &triangleInfo[i];
00535
00536 tinfo->materialMatrix[0][0] = 1;
00537 tinfo->materialMatrix[0][1] = f_poisson.getValue();
00538 tinfo->materialMatrix[0][2] = 0;
00539 tinfo->materialMatrix[1][0] = f_poisson.getValue();
00540 tinfo->materialMatrix[1][1] = 1;
00541 tinfo->materialMatrix[1][2] = 0;
00542 tinfo->materialMatrix[2][0] = 0;
00543 tinfo->materialMatrix[2][1] = 0;
00544 tinfo->materialMatrix[2][2] = 0.5f * (1 - f_poisson.getValue());
00545
00546 tinfo->materialMatrix *= (f_young.getValue() / (12 * (1 - f_poisson.getValue() * f_poisson.getValue())));
00547
00548 }
00549
00550
00551 template <class DataTypes>
00552 void TriangularFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const MaterialStiffness &K, const StrainDisplacement &J )
00553 {
00554 Mat<3,6,Real> Jt;
00555 Jt.transpose( J );
00556
00557 Vec<3,Real> JtD;
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573 JtD[0] = Jt[0][0] * Depl[0] + Jt[0][2] * Depl[2]
00574 ;
00575
00576 JtD[1] = Jt[1][1] * Depl[1] +
00577 Jt[1][3] * Depl[3] + Jt[1][5] * Depl[5];
00578
00579 JtD[2] = Jt[2][0] * Depl[0] + Jt[2][1] * Depl[1] + Jt[2][2] * Depl[2] +
00580 Jt[2][3] * Depl[3] + Jt[2][4] * Depl[4] ;
00581
00582 Vec<3,Real> KJtD;
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 KJtD[0] = K[0][0] * JtD[0] + K[0][1] * JtD[1] ;
00594
00595 KJtD[1] = K[1][0] * JtD[0] + K[1][1] * JtD[1] ;
00596
00597 KJtD[2] = + K[2][2] * JtD[2];
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 F[0] = J[0][0] * KJtD[0] + J[0][2] * KJtD[2];
00614
00615 F[1] = J[1][1] * KJtD[1] + J[1][2] * KJtD[2];
00616
00617 F[2] = J[2][0] * KJtD[0] + J[2][2] * KJtD[2];
00618
00619 F[3] = J[3][1] * KJtD[1] + J[3][2] * KJtD[2];
00620
00621 F[4] = J[4][2] * KJtD[2];
00622
00623 F[5] = J[5][1] * KJtD[1] ;
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 template <class DataTypes>
00633 void TriangularFEMForceField<DataTypes>::initSmall()
00634 {
00635
00636 #ifdef DEBUG_TRIANGLEFEM
00637 std::cout << "TriangularFEMForceField::initSmall\n";
00638 #endif
00639
00640 }
00641
00642
00643 template <class DataTypes>
00644 void TriangularFEMForceField<DataTypes>::accumulateForceSmall( VecCoord &f, const VecCoord &p, Index elementIndex, bool implicit )
00645 {
00646
00647 #ifdef DEBUG_TRIANGLEFEM
00648 std::cout << "TriangularFEMForceField::accumulateForceSmall\n";
00649 #endif
00650
00651 Index a = _topology->getTriangle(elementIndex)[0];
00652 Index b = _topology->getTriangle(elementIndex)[1];
00653 Index c = _topology->getTriangle(elementIndex)[2];
00654
00655 Coord deforme_a, deforme_b, deforme_c;
00656 deforme_b = p[b]-p[a];
00657 deforme_c = p[c]-p[a];
00658 deforme_a = Coord(0,0,0);
00659
00660
00661 Displacement D;
00662 D[0] = 0;
00663 D[1] = 0;
00664 D[2] = ((*_initialPoints)[b][0]-(*_initialPoints)[a][0]) - deforme_b[0];
00665 D[3] = 0;
00666 D[4] = ((*_initialPoints)[c][0]-(*_initialPoints)[a][0]) - deforme_c[0];
00667 D[5] = ((*_initialPoints)[c][1]-(*_initialPoints)[a][1]) - deforme_c[1];
00668
00669
00670 StrainDisplacement J;
00671 computeStrainDisplacement(J,deforme_a,deforme_b,deforme_c);
00672 if (implicit)
00673 triangleInfo[elementIndex].strainDisplacementMatrix = J;
00674
00675
00676 Displacement F;
00677 computeForce( F, D, triangleInfo[elementIndex].materialMatrix, J );
00678
00679 f[a] += Coord( F[0], F[1], 0);
00680 f[b] += Coord( F[2], F[3], 0);
00681 f[c] += Coord( F[4], F[5], 0);
00682 }
00683
00684
00685 template <class DataTypes>
00686 void TriangularFEMForceField<DataTypes>::accumulateDampingSmall(VecCoord&, Index )
00687 {
00688
00689 #ifdef DEBUG_TRIANGLEFEM
00690 std::cout << "TriangularFEMForceField::accumulateDampingSmall\n";
00691 #endif
00692
00693 }
00694
00695
00696 template <class DataTypes>
00697 void TriangularFEMForceField<DataTypes>::applyStiffnessSmall(VecCoord &v, Real h, const VecCoord &x)
00698 {
00699
00700 #ifdef DEBUG_TRIANGLEFEM
00701 std::cout << "TriangularFEMForceField::applyStiffnessSmall\n";
00702 #endif
00703
00704 int nbTriangles=_topology->getNbTriangles();
00705
00706
00707
00708
00709 for( int i=0; i<nbTriangles; i+=1)
00710 {
00711 Index a = _topology->getTriangle(i)[0];
00712 Index b = _topology->getTriangle(i)[1];
00713 Index c = _topology->getTriangle(i)[2];
00714
00715 Displacement X;
00716
00717 X[0] = x[a][0];
00718 X[1] = x[a][1];
00719
00720 X[2] = x[b][0];
00721 X[3] = x[b][1];
00722
00723 X[4] = x[c][0];
00724 X[5] = x[c][1];
00725
00726 Displacement F;
00727 computeForce( F, X, triangleInfo[i].materialMatrix, triangleInfo[i].strainDisplacementMatrix );
00728
00729 v[a] += Coord(-h*F[0], -h*F[1], 0);
00730 v[b] += Coord(-h*F[2], -h*F[3], 0);
00731 v[c] += Coord(-h*F[4], -h*F[5], 0);
00732 }
00733 }
00734
00735
00736
00737
00738
00739
00740 template <class DataTypes>
00741 void TriangularFEMForceField<DataTypes>::initLarge(int i, Index&a, Index&b, Index&c)
00742 {
00743
00744 #ifdef DEBUG_TRIANGLEFEM
00745 std::cout << "TriangularFEMForceField::initLarge\n";
00746 #endif
00747
00748
00749
00750
00751
00752
00753 TriangleInformation *tinfo = &triangleInfo[i];
00754
00755
00756
00757
00758
00759 Transformation R_0_1;
00760
00761
00762 computeRotationLarge( R_0_1, (*_initialPoints), a, b, c );
00763
00764 tinfo->rotatedInitialElements[0] = R_0_1 * (*_initialPoints)[a];
00765 tinfo->rotatedInitialElements[1] = R_0_1 * (*_initialPoints)[b];
00766 tinfo->rotatedInitialElements[2] = R_0_1 * (*_initialPoints)[c];
00767
00768 tinfo->rotatedInitialElements[1] -= tinfo->rotatedInitialElements[0];
00769 tinfo->rotatedInitialElements[2] -= tinfo->rotatedInitialElements[0];
00770 tinfo->rotatedInitialElements[0] = Coord(0,0,0);
00771 }
00772
00773
00774 template <class DataTypes>
00775 void TriangularFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, const VecCoord &p, const Index &a, const Index &b, const Index &c)
00776 {
00777
00778 #ifdef DEBUG_TRIANGLEFEM
00779 std::cout << "TriangularFEMForceField::computeRotationLarge\n";
00780 #endif
00781
00782
00783
00784
00785
00786 Coord edgex = p[b] - p[a];
00787 edgex.normalize();
00788
00789 Coord edgey = p[c] - p[a];
00790 edgey.normalize();
00791
00792 Coord edgez;
00793 edgez = cross(edgex, edgey);
00794 edgez.normalize();
00795
00796 edgey = cross(edgez, edgex);
00797 edgey.normalize();
00798
00799 r[0][0] = edgex[0];
00800 r[0][1] = edgex[1];
00801 r[0][2] = edgex[2];
00802 r[1][0] = edgey[0];
00803 r[1][1] = edgey[1];
00804 r[1][2] = edgey[2];
00805 r[2][0] = edgez[0];
00806 r[2][1] = edgez[1];
00807 r[2][2] = edgez[2];
00808 }
00809
00810
00811 template <class DataTypes>
00812 void TriangularFEMForceField<DataTypes>::accumulateForceLarge(VecCoord &f, const VecCoord &p, Index elementIndex, bool implicit )
00813 {
00814
00815 #ifdef DEBUG_TRIANGLEFEM
00816 std::cout << "TriangularFEMForceField::accumulateForceLarge\n";
00817 #endif
00818
00819
00820
00821 Index a = _topology->getTriangle(elementIndex)[0];
00822 Index b = _topology->getTriangle(elementIndex)[1];
00823 Index c = _topology->getTriangle(elementIndex)[2];
00824
00825
00826 Transformation R_2_0, R_0_2;
00827 computeRotationLarge( R_0_2, p, a, b, c);
00828 R_2_0.transpose(R_0_2);
00829
00830
00831
00832 Coord deforme_a, deforme_b, deforme_c;
00833
00834
00835
00836
00837
00838
00839 deforme_b = R_0_2 * (p[b]-p[a]);
00840 deforme_c = R_0_2 * (p[c]-p[a]);
00841
00842
00843 Displacement D;
00844 D[0] = 0;
00845 D[1] = 0;
00846 D[2] = triangleInfo[elementIndex].rotatedInitialElements[1][0] - deforme_b[0];
00847 D[3] = 0;
00848 D[4] = triangleInfo[elementIndex].rotatedInitialElements[2][0] - deforme_c[0];
00849 D[5] = triangleInfo[elementIndex].rotatedInitialElements[2][1] - deforme_c[1];
00850
00851
00852 StrainDisplacement J;
00853 computeStrainDisplacement(J,deforme_a,deforme_b,deforme_c);
00854
00855 if(implicit)
00856 {
00857 triangleInfo[elementIndex].strainDisplacementMatrix = J;
00858 triangleInfo[elementIndex].rotation = R_2_0 ;
00859 }
00860
00861
00862 Displacement F;
00863 computeForce( F, D, triangleInfo[elementIndex].materialMatrix, J );
00864
00865 f[a] += R_2_0 * Coord(F[0], F[1], 0);
00866 f[b] += R_2_0 * Coord(F[2], F[3], 0);
00867 f[c] += R_2_0 * Coord(F[4], F[5], 0);
00868
00869 if (f_fracturable.getValue())
00870 {
00871 Coord v, Rv;
00872 double maxEigenValue;
00873 computeEigenStrain(v, J, D, maxEigenValue);
00874
00875
00876
00877 triangleInfo[elementIndex].eigenValue = fabs(maxEigenValue);
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888 Rv = (p[b]-p[a]) * v[0] + (p[c]-p[a]) * v[1];
00889
00890 triangleInfo[elementIndex].principalStrainDirection = Rv;
00891
00892
00893 }
00894 }
00895
00896
00897 template <class DataTypes>
00898 void TriangularFEMForceField<DataTypes>::accumulateDampingLarge(VecCoord &, Index )
00899 {
00900
00901 #ifdef DEBUG_TRIANGLEFEM
00902 std::cout << "TriangularFEMForceField::accumulateDampingLarge\n";
00903 #endif
00904
00905 }
00906
00907
00908 template <class DataTypes>
00909 void TriangularFEMForceField<DataTypes>::applyStiffnessLarge(VecCoord &v, Real h, const VecCoord &x)
00910 {
00911
00912 #ifdef DEBUG_TRIANGLEFEM
00913 std::cout << "TriangularFEMForceField::applyStiffnessLarge\n";
00914 #endif
00915
00916 int nbTriangles=_topology->getNbTriangles();
00917
00918
00919
00920
00921 for(int i=0; i<nbTriangles; i+=1)
00922 {
00923 Index a = _topology->getTriangle(i)[0];
00924 Index b = _topology->getTriangle(i)[1];
00925 Index c = _topology->getTriangle(i)[2];
00926
00927 Transformation R_0_2;
00928 R_0_2.transpose(triangleInfo[i].rotation);
00929
00930 Displacement X;
00931 Coord x_2;
00932
00933 x_2 = R_0_2 * x[a];
00934 X[0] = x_2[0];
00935 X[1] = x_2[1];
00936
00937 x_2 = R_0_2 * x[b];
00938 X[2] = x_2[0];
00939 X[3] = x_2[1];
00940
00941 x_2 = R_0_2 * x[c];
00942 X[4] = x_2[0];
00943 X[5] = x_2[1];
00944
00945 Displacement F;
00946 computeForce( F, X, triangleInfo[i].materialMatrix, triangleInfo[i].strainDisplacementMatrix );
00947
00948 v[a] += triangleInfo[i].rotation * Coord(-h*F[0], -h*F[1], 0);
00949 v[b] += triangleInfo[i].rotation * Coord(-h*F[2], -h*F[3], 0);
00950 v[c] += triangleInfo[i].rotation * Coord(-h*F[4], -h*F[5], 0);
00951 }
00952 }
00953
00954 static Vec3d ColorMap[64] = {
00955 Vec3d( 0.0, 0.0, 0.5625 ),
00956 Vec3d( 0.0, 0.0, 0.625 ),
00957 Vec3d( 0.0, 0.0, 0.6875 ),
00958 Vec3d( 0.0, 0.0, 0.75 ),
00959 Vec3d( 0.0, 0.0, 0.8125 ),
00960 Vec3d( 0.0, 0.0, 0.875 ),
00961 Vec3d( 0.0, 0.0, 0.9375 ),
00962 Vec3d( 0.0, 0.0, 1.0 ),
00963 Vec3d( 0.0, 0.0625, 1.0 ),
00964 Vec3d( 0.0, 0.125, 1.0 ),
00965 Vec3d( 0.0, 0.1875, 1.0 ),
00966 Vec3d( 0.0, 0.25, 1.0 ),
00967 Vec3d( 0.0, 0.3125, 1.0 ),
00968 Vec3d( 0.0, 0.375, 1.0 ),
00969 Vec3d( 0.0, 0.4375, 1.0 ),
00970 Vec3d( 0.0, 0.5, 1.0 ),
00971 Vec3d( 0.0, 0.5625, 1.0 ),
00972 Vec3d( 0.0, 0.625, 1.0 ),
00973 Vec3d( 0.0, 0.6875, 1.0 ),
00974 Vec3d( 0.0, 0.75, 1.0 ),
00975 Vec3d( 0.0, 0.8125, 1.0 ),
00976 Vec3d( 0.0, 0.875, 1.0 ),
00977 Vec3d( 0.0, 0.9375, 1.0 ),
00978 Vec3d( 0.0, 1.0, 1.0 ),
00979 Vec3d( 0.0625, 1.0, 1.0 ),
00980 Vec3d( 0.125, 1.0, 0.9375 ),
00981 Vec3d( 0.1875, 1.0, 0.875 ),
00982 Vec3d( 0.25, 1.0, 0.8125 ),
00983 Vec3d( 0.3125, 1.0, 0.75 ),
00984 Vec3d( 0.375, 1.0, 0.6875 ),
00985 Vec3d( 0.4375, 1.0, 0.625 ),
00986 Vec3d( 0.5, 1.0, 0.5625 ),
00987 Vec3d( 0.5625, 1.0, 0.5 ),
00988 Vec3d( 0.625, 1.0, 0.4375 ),
00989 Vec3d( 0.6875, 1.0, 0.375 ),
00990 Vec3d( 0.75, 1.0, 0.3125 ),
00991 Vec3d( 0.8125, 1.0, 0.25 ),
00992 Vec3d( 0.875, 1.0, 0.1875 ),
00993 Vec3d( 0.9375, 1.0, 0.125 ),
00994 Vec3d( 1.0, 1.0, 0.0625 ),
00995 Vec3d( 1.0, 1.0, 0.0 ),
00996 Vec3d( 1.0, 0.9375, 0.0 ),
00997 Vec3d( 1.0, 0.875, 0.0 ),
00998 Vec3d( 1.0, 0.8125, 0.0 ),
00999 Vec3d( 1.0, 0.75, 0.0 ),
01000 Vec3d( 1.0, 0.6875, 0.0 ),
01001 Vec3d( 1.0, 0.625, 0.0 ),
01002 Vec3d( 1.0, 0.5625, 0.0 ),
01003 Vec3d( 1.0, 0.5, 0.0 ),
01004 Vec3d( 1.0, 0.4375, 0.0 ),
01005 Vec3d( 1.0, 0.375, 0.0 ),
01006 Vec3d( 1.0, 0.3125, 0.0 ),
01007 Vec3d( 1.0, 0.25, 0.0 ),
01008 Vec3d( 1.0, 0.1875, 0.0 ),
01009 Vec3d( 1.0, 0.125, 0.0 ),
01010 Vec3d( 1.0, 0.0625, 0.0 ),
01011 Vec3d( 1.0, 0.0, 0.0 ),
01012 Vec3d( 0.9375, 0.0, 0.0 ),
01013 Vec3d( 0.875, 0.0, 0.0 ),
01014 Vec3d( 0.8125, 0.0, 0.0 ),
01015 Vec3d( 0.75, 0.0, 0.0 ),
01016 Vec3d( 0.6875, 0.0, 0.0 ),
01017 Vec3d( 0.625, 0.0, 0.0 ),
01018 Vec3d( 0.5625, 0.0, 0.0 ) };
01019
01020
01021 template<class DataTypes>
01022 int TriangularFEMForceField<DataTypes>::getFracturedEdge()
01023 {
01024 if (f_fracturable.getValue())
01025 {
01026 int nbEdges = _topology->getNbEdges();
01027
01028 for( int i=0; i<nbEdges; i++ )
01029 {
01030 if (edgeInfo[i].fracturable)
01031 {
01032 return i;
01033 }
01034 }
01035 }
01036
01037 return -1;
01038 }
01039
01040
01041 template<class DataTypes>
01042 void TriangularFEMForceField<DataTypes>::draw()
01043 {
01044 if (!getContext()->getShowForceFields())
01045 return;
01046
01047
01048
01049 if (getContext()->getShowWireFrame())
01050 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01051
01052 const VecCoord& x = *this->mstate->getX();
01053 unsigned int nbTriangles=_topology->getNbTriangles();
01054
01055 glDisable(GL_LIGHTING);
01056 if (!f_fracturable.getValue())
01057 {
01058
01059 glBegin(GL_TRIANGLES);
01060
01061 for(unsigned int i=0;i<nbTriangles; ++i)
01062 {
01063 Index a = _topology->getTriangle(i)[0];
01064 Index b = _topology->getTriangle(i)[1];
01065 Index c = _topology->getTriangle(i)[2];
01066
01067 glColor4f(0,1,0,1);
01068 helper::gl::glVertexT(x[a]);
01069 glColor4f(0,0.5,0.5,1);
01070 helper::gl::glVertexT(x[b]);
01071 glColor4f(0,0,1,1);
01072 helper::gl::glVertexT(x[c]);
01073 }
01074 glEnd();
01075 }
01076 if (f_fracturable.getValue())
01077 {
01078 if (showStressValue.getValue())
01079 {
01080 unsigned int nbPoints = _topology->getNbPoints();
01081
01082 double totalSumEigenValues = vertexInfo[0].sumEigenValues;
01083 double max = vertexInfo[0].sumEigenValues;
01084
01085 for( unsigned int i=1; i<nbPoints; i++ )
01086 {
01087 totalSumEigenValues += vertexInfo[i].sumEigenValues;
01088 if (vertexInfo[i].sumEigenValues > max)
01089 max = vertexInfo[i].sumEigenValues;
01090 }
01091
01092 glBegin(GL_TRIANGLES);
01093
01094 for(unsigned int i=0;i<nbTriangles; ++i)
01095
01096 {
01097 Index a = _topology->getTriangle(i)[0];
01098 Index b = _topology->getTriangle(i)[1];
01099 Index c = _topology->getTriangle(i)[2];
01100
01101 float v = (float)((vertexInfo[a].sumEigenValues + vertexInfo[b].sumEigenValues + vertexInfo[c].sumEigenValues) / 3.0);
01102 v /= (float)max;
01103
01104 Vec3d color = ColorMap[(int)(v*63)];
01105 glColor3dv(color.ptr());
01106
01107 helper::gl::glVertexT(x[a]);
01108 helper::gl::glVertexT(x[b]);
01109 helper::gl::glVertexT(x[c]);
01110 }
01111 glEnd();
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148 }
01149 if (showStressVector.getValue())
01150 {
01151
01152
01153 glColor4f(1,0,1,1);
01154 glBegin(GL_LINES);
01155
01156 for(unsigned int i=0;i<nbTriangles; ++i)
01157 {
01158 Index a = _topology->getTriangle(i)[0];
01159 Index b = _topology->getTriangle(i)[1];
01160 Index c = _topology->getTriangle(i)[2];
01161 Coord center = (x[a]+x[b]+x[c])/3;
01162 Coord d = triangleInfo[i].principalStrainDirection*0.4;
01163 helper::gl::glVertexT(center-d);
01164 helper::gl::glVertexT(center+d);
01165 }
01166 glEnd();
01167 }
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186 }
01187
01188 if (getContext()->getShowWireFrame())
01189 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01190 }
01191
01192
01193 SOFA_DECL_CLASS(TriangularFEMForceField)
01194
01195
01196
01197 int TriangularFEMForceFieldClass = core::RegisterObject("Triangular finite elements")
01198 #ifndef SOFA_FLOAT
01199 .add< TriangularFEMForceField<Vec3dTypes> >()
01200 #endif
01201 #ifndef SOFA_DOUBLE
01202 .add< TriangularFEMForceField<Vec3fTypes> >()
01203 #endif
01204 ;
01205
01206 #ifndef SOFA_FLOAT
01207 template class TriangularFEMForceField<Vec3dTypes>;
01208 #endif
01209 #ifndef SOFA_DOUBLE
01210 template class TriangularFEMForceField<Vec3fTypes>;
01211 #endif
01212
01213
01214 }
01215
01216 }
01217
01218 }