PMLReader.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 
00026 /***************************************************************************
00027  *                                                                         *
00028  *   This program is free software; you can redistribute it and/or modify  *
00029  *   it under the terms of the GNU General Public License as published by  *
00030  *   the Free Software Foundation; either version 2 of the License, or     *
00031  *   (at your option) any later version.                                   *
00032  *                                                                         *
00033  ***************************************************************************/
00034 
00035 #include "PMLReader.h"
00036 
00037 #include <MultiComponent.h>
00038 
00039 #include "PMLRigidBody.h"
00040 #include "PMLFemForceField.h"
00041 #include "PMLStiffSpringForceField.h"
00042 #include "PMLInteractionForceField.h"
00043 #include "PMLMappedBody.h"
00044 
00045 #include "sofa/component/collision/DefaultPipeline.h"
00046 #include "sofa/component/collision/DefaultContactManager.h"
00047 #include "sofa/component/collision/NewProximityIntersection.h"
00048 #include "sofa/component/collision/DefaultCollisionGroupManager.h"
00049 #include "sofa/component/collision/BruteForceDetection.h"
00050 #include "sofa/simulation/common/VisualVisitor.h"
00051 #include "sofa/simulation/tree/Simulation.h"
00052 
00053 using namespace sofa::component::collision;
00054 using namespace sofa::simulation::tree;
00055 using namespace sofa::simulation;
00056 
00057 namespace sofa
00058 {
00059  
00060 namespace filemanager
00061 {
00062 
00063 namespace pml
00064 {
00065 
00066 //build sofa structure from a pml file
00067 void PMLReader::BuildStructure(const char* filename, GNode* root){
00068 
00069     if (!filename) return;
00070 
00071     if(pm) { 
00072         delete pm;
00073         pm = NULL;
00074     }
00075     pm = new PhysicalModel(filename);
00076 
00077     if (!pm){
00078         cerr<<"PML reader error : failed to load PML file "<<filename<<endl;
00079         return;
00080     }
00081 
00082     if (pm->getNumberOfAtoms()==0){
00083         cerr<<"PML reader error : PML file "<<filename<<" not valid"<<endl;
00084         return;
00085     }
00086 
00087     this->BuildStructure(root);
00088 }
00089 
00090 //build sofa structure from a physicalModel
00091 void PMLReader::BuildStructure(PhysicalModel * model, GNode* root){
00092 
00093     if(pm) delete pm;
00094     pm = model;
00095     this->BuildStructure(root);
00096 }
00097 
00098 //really build the sofa structure
00099 void PMLReader::BuildStructure(GNode* root){
00100 
00101     bodiesList.clear();
00102 
00103     //get the MultiComponent "Bodies"
00104     MultiComponent * bodies = (MultiComponent*) (pm->getExclusiveComponents()->getComponentByName("Bodies"));
00105     //if none, the physical model is not properly defined, so we exit...
00106     if(!bodies) return;
00107 
00108     bool collisionsExist = false;
00109 
00110     //get each body
00111     PMLBody * body;
00112     for (unsigned int i=0 ; i<bodies->getNumberOfSubComponents() ; i++ ) 
00113     {
00114         //create the under structure (mech model, topology, etc) to create the body
00115         body = createBody( (StructuralComponent*) bodies->getSubComponent(i), root );
00116 
00117         //if no problem, we put it in the scene graph
00118         if (body) { 
00119             bodiesList.push_back(body);
00120             if (body->hasCollisions()) 
00121                 collisionsExist = true;
00122         }
00123     }
00124 
00125     //if at least one of the bodies wants to detect contacts, we create all objects to do this
00126     if (collisionsExist){
00127         DefaultPipeline * ps = new DefaultPipeline;
00128         BruteForceDetection * bfd = new BruteForceDetection;
00129         NewProximityIntersection * mpi = new NewProximityIntersection;
00130         //computes the distance contact from the bounding box
00131         VisualComputeBBoxVisitor act;
00132         getSimulation()->init(root);
00133         root->execute(act);
00134         SReal dx=(act.maxBBox[0]-act.minBBox[0]);
00135         SReal dy=(act.maxBBox[1]-act.minBBox[1]);
00136         SReal dz=(act.maxBBox[2]-act.minBBox[2]);
00137         SReal dmax = sqrt(dx*dx + dy*dy + dz*dz);
00138         //maybe the ratio should be changed...
00139         mpi->setAlarmDistance(dmax/30);
00140         mpi->setContactDistance(dmax/40);
00141         DefaultContactManager * contactManager = new DefaultContactManager;
00142         DefaultCollisionGroupManager * cgm = new DefaultCollisionGroupManager;
00143 
00144         root->addObject(ps);
00145         root->addObject(bfd);
00146         root->addObject(mpi);
00147         root->addObject(contactManager);
00148         root->addObject(cgm);
00149     }
00150 
00151     //if there is 2 bodies with the same type and some nodes in common, we merge them
00152     processFusions(root);
00153 
00154     sofa::simulation::tree::getSimulation()->init(root);
00155 }
00156 
00157 //create the body structure
00158 //each a new body type is created, this method must be updated to take care of it.
00159 PMLBody* PMLReader::createBody(StructuralComponent* SC, GNode * root) {
00160 
00161     string type = SC->getProperties()->getString("bodyType");
00162 
00163     GNode * child = new GNode(SC->getProperties()->getName());
00164 
00165     if (type == "rigid" ) {
00166         root->addChild(child);
00167         return new PMLRigidBody(SC, child);
00168     }
00169     if (type == "FEM" ){
00170         root->addChild(child);
00171         return new PMLFemForceField(SC, child);
00172     }
00173     if (type == "stiffSpring" ){
00174         root->addChild(child);
00175         return new PMLStiffSpringForceField(SC, child);
00176     }
00177     if (type == "interaction" ){
00178         delete child;
00179         std::string name1 = SC->getProperties()->getString("body1");
00180         std::string name2 = SC->getProperties()->getString("body2");
00181         PMLBody * body1=NULL;
00182         PMLBody * body2=NULL;
00183 
00184         std::vector<PMLBody*>::iterator it = bodiesList.begin();
00185         while((!body1 || !body2) && it != bodiesList.end() )
00186         {
00187             if ( (*it)->getName() == name1)
00188                 body1 = *it;
00189             if ( (*it)->getName() == name2)
00190                 body2 = *it;
00191             it++;
00192         }
00193         if (body1 && body2)
00194             return new PMLInteractionForceField(SC, body1, body2, root);
00195     }
00196     if (type == "mapped"){
00197         std::string name1 = SC->getProperties()->getString("bodyRef");
00198         PMLBody * body1=NULL;
00199         std::vector<PMLBody*>::iterator it = bodiesList.begin();
00200         while( !body1 && it != bodiesList.end() )
00201         {
00202             if ( (*it)->getName() == name1)
00203                 body1 = *it;
00204             it++;
00205         }
00206         if (body1){
00207             body1->parentNode->addChild(child);
00208             return new PMLMappedBody(SC, body1, child);
00209         }else
00210             cerr<<"mapped body : no body ref named "<<name1<<" found"<<endl;
00211     }
00212 
00213     return NULL;
00214 }
00215 
00216 
00217 void PMLReader::processFusions(GNode * root) 
00218 {
00219     std::vector<PMLBody *>::iterator it1 = bodiesList.begin();
00220     std::vector<PMLBody *>::iterator it2 = bodiesList.begin();
00221     
00222     while (it1 != bodiesList.end()) {
00223         it2 = it1;
00224         it2++;
00225         while(it2 != bodiesList.end() ) {
00226             bool Fusion = false;
00227             if ((*it1)->isTypeOf() == (*it2)->isTypeOf() ) {
00228                 map<unsigned int, unsigned int>::iterator ind = (*it1)->AtomsToDOFsIndexes.begin();
00229                 while(ind != (*it1)->AtomsToDOFsIndexes.end() && !Fusion) {
00230                     if((*it2)->AtomsToDOFsIndexes.find(ind->first) != (*it2)->AtomsToDOFsIndexes.end() ) {
00231                         Fusion = (*it1)->FusionBody(*it2);
00232                         if (Fusion) {
00233                             std::vector<PMLBody *>::iterator tmp = it2;
00234                             tmp--;
00235                             (*it1)->parentNode->setName((*it1)->parentNode->getName() + " & "+ (*it2)->parentNode->getName() );
00236                             root->removeChild( (*it2)->parentNode );
00237                             bodiesList.erase(it2);
00238                             it2 = tmp;
00239                         }
00240                     }
00241                     ind++;
00242                 }
00243             }
00244             it2++;
00245         }
00246         it1++;
00247     }
00248 }
00249 
00250 
00251 //save the current scene as a pml filename
00252 void PMLReader::saveAsPML(const char * filename) 
00253 {
00254     std::vector<PMLBody*>::iterator itb = bodiesList.begin();
00255     StructuralComponent * atoms = pm->getAtoms();
00256     Atom * atom;
00257 
00258     while (itb != bodiesList.end())
00259     {
00260         std::map<unsigned int, unsigned int>::iterator itm = (*itb)->AtomsToDOFsIndexes.begin();
00261         while(itm != (*itb)->AtomsToDOFsIndexes.end() )
00262         {
00263             atom = (Atom*) atoms->getStructureByIndex( (*itm).first );
00264             Vector3 pos = (*itb)->getDOF((*itm).second);
00265             atom->setPosition(pos[0], pos[1], pos[2]);
00266 
00267             itm++;
00268         }
00269         itb++;
00270     }
00271     std::ofstream outputFile(filename);
00272     pm->xmlPrint(outputFile);
00273     cout<<"fichier sauvegarde"<<endl;
00274 }
00275 
00276 
00277 //return a point position giving a physical model atom index
00278 Vector3 PMLReader::getAtomPos(unsigned int atomindex)
00279 {
00280   Vector3 pos;
00281     std::vector<PMLBody*>::iterator itb = bodiesList.begin();
00282 
00283     while (itb != bodiesList.end())
00284     {
00285         std::map<unsigned int, unsigned int>::iterator itm = (*itb)->AtomsToDOFsIndexes.begin();
00286         while(itm != (*itb)->AtomsToDOFsIndexes.end())
00287         {
00288             if ( (*itm).first == atomindex ) {
00289                 pos = (*itb)->getDOF((*itm).second);
00290                 return pos;
00291             }
00292             itm++;
00293         }
00294         itb++;
00295     }
00296     return Vector3();
00297 }
00298 
00299 
00300 //update all the physical model atoms positions 
00301 void PMLReader::updatePML() 
00302 {
00303     std::vector<PMLBody*>::iterator itb = bodiesList.begin();
00304     StructuralComponent * atoms = pm->getAtoms();
00305     Atom * atom;
00306 
00307     while (itb != bodiesList.end())
00308     {
00309         if( (*itb)->isTypeOf() != "interaction" )
00310         {
00311             if ((*itb)->isTypeOf() != "rigid" || ((PMLRigidBody*)*itb)->bodyFixed == false)
00312             {
00313                 std::map<unsigned int, unsigned int>::iterator itm = (*itb)->AtomsToDOFsIndexes.begin();
00314                 while(itm != (*itb)->AtomsToDOFsIndexes.end() )
00315                 {
00316                     atom = (Atom*) atoms->getStructureByIndex( (*itm).first );
00317                     Vector3 pos = (*itb)->getDOF((*itm).second);
00318                     atom->setPosition(pos[0], pos[1], pos[2]);
00319 
00320                     itm++;
00321                 }
00322             }
00323         }
00324         itb++;
00325     }
00326 }
00327 
00328 
00329 }
00330 }
00331 }

Generated on Sun Nov 23 03:56:15 2008 for Sofa by  doxygen 1.5.7.1