Biomechanical Joint Model
 Author: Anderson Maciel

comemoleculescartilage.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2002 by Anderson Maciel                                 *
00003  *   andi.maciel@gmail.com                                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  **************************************************************************/
00020 
00022 //
00023 //  PROJECT.....: CO-ME
00024 //  RESPONSIBLE.: 
00025 //
00026 //  AUTHOR......: Anderson Maciel
00027 //  DATE........: August/05/2002
00028 //  DESCRIPTION.: Class declaration.
00029 //
00031 
00032 
00033 #include <bio/comemoleculescartilage.h>
00034 #include <bio/comematerial.h>
00035 #include <math.h>
00036 #include <time.h>
00037 #include <algebra/comemesh.h>
00038 #include <algebra/comematrix.h>
00039 #include <libgeom/geom.h>
00040 
00041 //#include <LinAlg/linalg.h>
00042 //using namespace LinAlg;
00043 //#include <MarchingCubes/marching_cubes.h>
00044 //#include <MarchingCubes/blob.h>
00045 using namespace geom;
00046 
00050 COME_MoleculesCartilage::COME_MoleculesCartilage(){
00051 
00052         tissue = new COME_MoleculesTissue();
00053         tissue->setParent(this);
00054         surface = NULL;
00055         hashTable = NULL;
00056         globalHooke = 0.0;
00057         collisionRadius = 1.0;
00058 }
00059 
00060 COME_MoleculesCartilage::~COME_MoleculesCartilage(){
00061 
00062         
00063 }
00064 
00065 void
00066 COME_MoleculesCartilage::setTissue( COME_MoleculesTissue *tissueN ){
00067 
00068         tissue = tissueN;
00069         tissue->setParent(this);
00070 }
00071 
00072 void
00073 COME_MoleculesCartilage::setDeformationFile( string defFile ){
00074 
00075         deformationFile = defFile;
00076 
00077 }
00078 
00079 string
00080 COME_MoleculesCartilage::getDeformationFile(){
00081 
00082         return deformationFile;
00083 }
00084 
00085 COME_MoleculesTissue*
00086 COME_MoleculesCartilage::getTissue(){
00087 
00088         return tissue;
00089 }
00090 
00091 ARRAY2D*
00092 COME_MoleculesCartilage::getMatrixJinv(){
00093 
00094         return matrixJinv;
00095 }
00096 
00097 //Recalculates the Mesh based on the new positions of anchoring the molecules
00098 void 
00099 COME_MoleculesCartilage:: updateSkin(){
00100         if( surface )
00101                 surface->updateSkin();
00102 }
00103 
00107 void
00108 COME_MoleculesCartilage::updateSurface( bool regenerate ){
00109 
00110         // Parameter of the potential filed
00111         //     small values (<1.0) -> implicit surface is big and mesh doesn't follow the form of the spheres
00112         //     big values   (>1.0) -> surface follows the form of the spheres
00113         
00114         // Mesh resouluton[0.1 high resolution mesh generated, 2.0 very corse mesh generated]
00115         
00116         if( regenerate == IMPLICIT ){
00117                 COME_Point3D mins, maxs;
00118                 getEnvelop( mins, maxs );
00119                 double volume = ( maxs.getX() - mins.getX() ) * ( maxs.getY() - mins.getY() ) * ( maxs.getZ() - mins.getZ() );
00120                 double radiusAvg = tissue->getRadiusAverage();
00121 
00122                 updateSurface( 1.0, 1/(radiusAvg/2), sqrt( volume )/20.0 + 0.005 );
00123                 surface->estabilishLinkVerticesFaces();
00124 
00125         } else {
00126                 surface->update();
00127         }
00128   
00129 }
00130 
00131 
00135 void
00136 COME_MoleculesCartilage::updateSurface( double skinSphere, double stiff, double resolution ){
00137 
00138 /*  ///commented in 01 september 2004 because of link errors
00139         printf( "update IMPLICIT CARTILAGE Is IN \n" );
00140         // Metaballs represented as the spheres with Raquel's density function
00141         MetaballsSphere *metaSphere = new MetaballsSphere( skinSphere );
00142         
00143         vector<Primitive*>                      primitives;
00144         VEC                                                     C(3);           // sphere center
00145 
00146         list<COME_Molecule*>::iterator iter;    
00147         for( iter = tissue->getShape()->begin(); iter != tissue->getShape()->end(); iter++ ){
00148                 //read spheres
00149                 COME_Point3D point      = (*iter)->getPosition();
00150 
00151                 C[0] = point.getX();
00152                 C[1] = point.getY();
00153                 C[2] = point.getZ();
00154                 
00155                 //add sphere  
00156                 metaSphere->addSphere( Sphere( C, (*iter)->getRadius(), stiff ) );
00157         }
00158   
00159         //add to primitives
00160         primitives.push_back( metaSphere );
00161 
00162         //create surface
00163         marchingCubes surfaceTriangles( primitives, resolution );
00164 
00165         // copy vertices and triangle indices into the Class Mesh       
00166         
00167         int iPos;
00168 
00169         vector<VEC>     vertexList      = surfaceTriangles.getVertices();
00170         vector<VEC> normalList  = surfaceTriangles.getNormals();
00171 
00172         // copy all vertices and the normals of the triangulated surface 
00173         surface->resetMesh();
00174         for ( iPos = 0; iPos < vertexList.size(); iPos++ ){
00175                 
00176                 COME_Vector3D normal = COME_Vector3D( normalList[ iPos ][ 0 ], normalList[ iPos ][ 1 ], normalList[ iPos ][ 2 ] );
00177                 surface->addVertex( COME_Vertex3D( vertexList[ iPos ][ 0 ], vertexList[ iPos ][ 1 ], vertexList[ iPos ][ 2 ], normal ) );
00178         }
00179 
00180         //copy all indices of vertices 
00181         vector<Triangle>        trianglesList   = surfaceTriangles.getTriangles();
00182         for (vector<Triangle>::const_iterator tri=trianglesList.begin(); tri!=trianglesList.end(); tri++){     
00183                 
00184                 vector<int>                     indicesTriangles;
00185 
00186                 indicesTriangles.push_back( tri->indices[0] );
00187                 indicesTriangles.push_back( tri->indices[1] );
00188                 indicesTriangles.push_back( tri->indices[2] );
00189 
00190                 surface->addFaceAsIndices( indicesTriangles );
00191         }
00192 */
00193 }
00194 
00198 void
00199 COME_MoleculesCartilage::getEnvelop( COME_Point3D& mins, COME_Point3D& maxs ){
00200 
00201         tissue->getEnvelop( mins, maxs );
00202 }
00203 
00207 bool
00208 COME_MoleculesCartilage::update( double timestep, double simClock ){
00209 
00210         if( COME::flagNumIntegration == RUNGE_KUTTA4 ){
00211                 if( tissue->update( timestep, simClock, deformationFile ) ){
00213                         updateSkin(); 
00214                         return true;
00215                 }
00216         } else {
00217                 if( COME::flagNumIntegration == EULER )
00218                 if( tissue->updateEuler( timestep, simClock, deformationFile ) ){
00220                         updateSkin(); 
00221                         return true;
00222                 }
00223         }
00224         return false;
00225 }
00226 
00227 
00233 void
00234 COME_MoleculesCartilage::initializeSkinning(){
00235 
00236         if( this->getSurface() == NULL ){
00237                 surface = new COME_Mesh();
00238                 surface->setParent( this );
00239                 updateSurface( IMPLICIT );
00240                 printf( "update IMPLICIT CARTILAGE done \n" );
00241                 return;
00242         }
00243                 
00244         this->getSurface()->anchorToMolecules( this->getTissue(), 4 );
00245         
00246         vector<COME_Vertex3D>* localVertices = surface->getVerticesPt();
00247         for( int i = 0; i < localVertices->size(); i++ ){
00248 
00249                 vector<COME_Molecule*> localAnchors = (*localVertices)[i].getAnchors();
00250                 for( int j = 0; j < localAnchors.size(); j++ ){
00251 
00252                         localAnchors[j]->initializeOrthogonalNeighbors();
00253                 
00254                         //(*localVertices)[i].addLocalPosition( (*localVertices)[i] - localAnchors[j]->getPosition() );
00255                         COME_Matrix MX_INVERSE = localAnchors[j]->getLocalFrame()->getInverse();
00256                         (*localVertices)[i].addLocalPosition( MX_INVERSE * (*localVertices)[i] );
00257 
00258                 }
00259         }
00260         cout << "initialising Faces Neighbours...";
00261         this->getPointerToSurface()->initFacesNeighbours();
00262         cout << "done \ninitialising Vertices Neighbours...";
00263         this->getPointerToSurface()->initVerticesNeighbours();
00264         cout << "done\n";
00265         
00267         //printf( "initializing jacobian... " );
00268         //initializeJacobian();
00269         //printf( "done.\n" );
00270 }
00271 
00272 void
00273 COME_MoleculesCartilage::discretize( int type, double dist, double radius ){
00274 
00275         // Reset tissue
00276         if( tissue ){
00277                 delete tissue;
00278         }
00279         tissue = new COME_MoleculesTissue();
00280         tissue->setParent(this);
00281         
00282         if( type == BEST ){
00283 
00284                 COME_Point3D mins, maxs;
00285                 COME_Material *discrMaterial = new COME_Material( COME_Vector3D( 1.0, 1.0, 1.0 ), 1.0, 0.3, 1000.0, 1.0, 0.0, 0.0  );
00286                 COME_Material *fixedMaterial = new COME_Material( COME_Vector3D( 1.0, 0.4, 0.4 ), 1.0, 0.3, 1000.0, 1.0, 0.0, 0.0  );
00287                 surface->getEnvelop( mins, maxs );
00288                 
00289                 // Marchig grid to create surface balls
00290                 vector<COME_Point3D> *allIntersections = new vector<COME_Point3D>;
00291                 for( double xMgrid = mins.getX(); xMgrid <= maxs.getX(); xMgrid += dist ){
00292                         for( double yMgrid = mins.getY(); yMgrid <= maxs.getY(); yMgrid += dist ){
00293                                 surface->findIntersections( COME_Point3D( xMgrid, yMgrid, mins.getZ() ), COME_Point3D( xMgrid, yMgrid, maxs.getZ() ), allIntersections );
00294                         }
00295                         for( double zMgrid = mins.getZ(); zMgrid <= maxs.getZ(); zMgrid += dist ){
00296                                 surface->findIntersections( COME_Point3D( xMgrid, mins.getY(), zMgrid ), COME_Point3D( xMgrid, maxs.getY(), zMgrid ), allIntersections );
00297                         }
00298                 }
00299                 for( double zMgrid = mins.getZ(); zMgrid <= maxs.getZ(); zMgrid += dist ){
00300                         for( double yMgrid = mins.getY(); yMgrid <= maxs.getY(); yMgrid += dist ){
00301                                 surface->findIntersections( COME_Point3D( mins.getX(), yMgrid, zMgrid ), COME_Point3D( maxs.getX(), yMgrid, zMgrid ), allIntersections );
00302                         }
00303                 }
00304                 printf( "%d intersections found on the surface.\n", allIntersections->size() );
00305                 
00306                 // Add molecules on surface points (they are fixed)
00307                 for( int i = 0; i < allIntersections->size(); i++ ){
00308                         if( ! tissue->isTooClose( (*allIntersections)[i], dist/10 ) ){
00309                         
00310                                 COME_Molecule *molecule = new COME_Molecule( (*allIntersections)[i], (dist/2.0)+(dist/5.0), 0.02, fixedMaterial, COME_Vector3D(), (COME_BioStructure *)this );
00311                                 molecule->setFixed( true );
00312                                 tissue->addMolecule( molecule );
00313                         }
00314                 }
00315                 delete allIntersections;
00316                 printf( "%d molecules added on the surface.\n", tissue->getShape()->size() );
00317                 
00318                 // Marchig cubes to create internal balls
00319                 for( double xMcubes = mins.getX(); xMcubes <= maxs.getX(); xMcubes += dist ){
00320                         for( double yMcubes = mins.getY(); yMcubes <= maxs.getY(); yMcubes += dist ){
00321                                 for( double zMcubes = mins.getZ(); zMcubes <= maxs.getZ(); zMcubes += dist ){
00322         
00323                                         COME_Point3D currentPoint( xMcubes, yMcubes, zMcubes );
00324                                         if( ( surface->isInside( currentPoint ) ) && ( ! tissue->isTooClose( currentPoint, dist/1.5 ) ) ){
00325                                                 
00326                                                 // Attention: Using always the same material
00327                                                 COME_Molecule *molecule = new COME_Molecule( currentPoint, (dist/2.0)+(dist/10.0), 0.02, discrMaterial, COME_Vector3D(), this );
00328                                                 molecule->setFixed( false );
00329                                                 tissue->addMolecule( molecule );
00330                                         }
00331                                 }
00332                         }
00333                 }
00334                 printf( "%d molecules have been created for this object.\n", tissue->getShape()->size() );
00335                 list<COME_Molecule*>::iterator iter, dead;
00336                 for (iter = tissue->getShape()->begin(); iter != tissue->getShape()->end(); iter++){
00337                         // Reconfigure molecules
00338                         (*iter)->setRadius(radius);
00339                         // Reconfigure links for pseudo-simulation
00340                         list<COME_MoleculeLink*>::iterator iterThis;
00341                         for (iterThis = (*iter)->getConnectionList()->begin(); !( iterThis == (*iter)->getConnectionList()->end() ); iterThis++){
00342                                 (*iterThis)->setNominalDist(dist);
00343                         }
00344                 }
00345         }
00346 }
00347 
00348 void
00349 COME_MoleculesCartilage::respondCollision(){
00350 
00351 //printf( "Entrou cartilage::respondcollision \n" );
00352 
00353         list<COME_Molecule*>::iterator iter;
00354         for( iter = tissue->getShape()->begin(); iter != tissue->getShape()->end(); iter++ ){
00355         
00356                 COME_Point3D reseting = (*iter)->getPosition();
00357                 //(*iter)->setINITPosition( reseting );
00358                 if( !(*iter)->isFixed() ){      
00359                         double sumDists = 0.0;
00360                         COME_Point3D newPos = (*iter)->getPosition();
00361                         vector<COME_Vertex3D*> *vertices = (*iter)->getBuois();
00362                         int i;
00363                         int count = 1;
00364                         for( i = 0; i < vertices->size(); i++ ){
00365                                 sumDists += pow( (*vertices)[i]->vpDistance( (*iter)->getPosition() ), 2.0 );
00366                         }
00367                         
00368                         count = i-1;
00369                         
00370                         for( i = 0; i < vertices->size(); i++ ){
00371                                 double w = ( 1.0 - ( pow( (*vertices)[i]->vpDistance( (*iter)->getPosition() ), 2.0 ) / sumDists ) ) / (count*2.0);
00372                                 newPos =  newPos + ( (*vertices)[i]->getCollisionDispAvg() * w );
00373                                 
00374                                 //printf("TOTAL: %f AVG: %f\n",(*vertices)[i]->getCollisionDisp().vpModule(), (*vertices)[i]->getCollisionDispAvg().vpModule() );
00375                         }
00376                         
00377                         if( (*iter)->getPosition().vpDistance( newPos ) != 0.0 ){
00378                                 COME_Vector3D zero;
00379                                 (*iter)->setVelocity( zero );
00380                                 (*iter)->setAcceleration( zero );
00381                                 (*iter)->setPosition( newPos );
00382                         }
00383                         //(*iter)->setINITPosition( newPos ); //TEMP for testing RESPONSE
00384                 }
00385         }
00386 }
00387 
00388 void
00389 COME_MoleculesCartilage::initializeJacobian(){
00390 
00391         int lines = surface->getVerticesPt()->size();
00392         int columns = tissue->getShape()->size();
00393         
00394         // initialize matrix J
00395         ARRAY2D *matrixJ = array2d_creation (lines*3,  columns*3);
00396         matrixJinv = array2d_creation (lines*3,  columns*3);
00397         array2d_nul( matrixJ );
00398         //matrixJ = (double*) malloc((unsigned) columns*3*lines*3*sizeof(double)); 
00399         //for( int initialize=0; initialize < (columns*3*lines*3) ; initialize++ ) matrixJ[initialize] = 0.0;
00400         
00401         // Add molecules x vertices relations to the J matrix
00402         list<COME_Molecule*>::iterator iter;
00403         iter = tissue->getShape()->begin();
00404         for( int mi = 0; iter != tissue->getShape()->end(); mi++, iter++ ){
00405                 vector<COME_Vertex3D*>* buois = (*iter)->getBuois();
00406                 vector<int>* bInd = (*iter)->getBuoisIndices();
00407                 
00408                 double sumDists = 0.0;
00409                 for( int i = 0; i < buois->size(); i++ ){
00410                         sumDists += pow( (*buois)[i]->vpDistance( (*iter)->getGlobalPosition() ), 2.0 );
00411                 }
00412                 for( int bi = 0; bi < buois->size(); bi++ ){
00413                         
00414                         double wj = ( 1.0 - ( pow( (*buois)[bi]->vpDistance( (*iter)->getGlobalPosition() ), 2.0 ) / sumDists ) );
00415                         AIJ(matrixJ, ( (*bInd)[bi] * 3+0 ), ( mi*3+0 ) ) = wj;
00416                         AIJ(matrixJ, ( (*bInd)[bi] * 3+1 ), ( mi*3+1 ) ) = wj;
00417                         AIJ(matrixJ, ( (*bInd)[bi] * 3+2 ), ( mi*3+2 ) ) = wj;
00418                         
00419                         //matrixJ[ ( (*bInd)[bi] * 3+0 )*(columns*3) + ( mi*3+0 ) ] = wj;
00420                         //matrixJ[ ( (*bInd)[bi] * 3+1 )*(columns*3) + ( mi*3+1 ) ] = wj;
00421                         //matrixJ[ ( (*bInd)[bi] * 3+2 )*(columns*3) + ( mi*3+2 ) ] = wj;
00422                 }
00423         }
00424         
00425         FILE    *file = fopen( "/home/amaciel/Desktop/matrixJ.txt", "wt" );
00426         array2d_write ( matrixJ, file);
00427         fclose( file );
00428         
00429         // Inverse the matrix using libgeom functions
00430         time_t start,end;
00431         double dif;
00432         time (&start);
00433 
00434         array2d_damped_least_square_inverse ( matrixJinv, matrixJ, 0.0 );
00435         
00436         time (&end);
00437         dif = difftime (end,start);
00438         printf ("It has taken %.2lf seconds to inverse the matrix of %d lines and %d columns.\n", dif, lines*3, columns*3 );
00439         
00440         file = fopen( "/home/amaciel/Desktop/matrixJinv.txt", "wt" );
00441         array2d_write ( matrixJinv, file);
00442         fclose( file );
00443 }

Generated on Thu Dec 1 10:13:35 2005 for COME - Biomechanical Joint Model by  doxygen 1.4.5