BarycentricContactMapper.h

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 #ifndef SOFA_COMPONENT_COLLISION_BARYCENTRICCONTACTMAPPER_H
00026 #define SOFA_COMPONENT_COLLISION_BARYCENTRICCONTACTMAPPER_H
00027 
00028 #include <sofa/helper/system/config.h>
00029 #include <sofa/helper/Factory.h>
00030 #include <sofa/component/mapping/BarycentricMapping.h>
00031 #include <sofa/component/mapping/IdentityMapping.h>
00032 #include <sofa/component/mapping/RigidMapping.h>
00033 #include <sofa/component/mapping/SubsetMapping.h>
00034 #include <sofa/component/MechanicalObject.h>
00035 #include <sofa/simulation/tree/GNode.h>
00036 #include <sofa/simulation/tree/Simulation.h>
00037 #include <sofa/component/collision/SphereModel.h>
00038 #include <sofa/component/collision/SphereTreeModel.h>
00039 #include <sofa/component/collision/TriangleModel.h>
00040 #include <sofa/component/collision/TetrahedronModel.h>
00041 #include <sofa/component/collision/LineModel.h>
00042 #include <sofa/component/collision/PointModel.h>
00043 #include <sofa/component/collision/DistanceGridCollisionModel.h>
00044 #include <sofa/component/mapping/IdentityMapping.h>
00045 #include <sofa/component/visualmodel/DrawV.h>
00046 #include <iostream>
00047 
00048 
00049 namespace sofa
00050 {
00051 
00052 namespace component
00053 {
00054 
00055 namespace collision
00056 {
00057 
00058 using namespace sofa::defaulttype;
00059 
00061 template < class TCollisionModel, class DataTypes = typename TCollisionModel::DataTypes >
00062 class ContactMapper;
00063 
00065 template <class TDataTypes>
00066 class BaseContactMapper
00067 {
00068 public:
00069     typedef TDataTypes DataTypes;
00070     typedef typename DataTypes::Real Real;
00071     typedef typename DataTypes::Coord Coord;
00072     typedef typename DataTypes::VecCoord VecCoord;
00073     typedef core::componentmodel::behavior::MechanicalState<DataTypes> MMechanicalState;
00074     virtual ~BaseContactMapper() {}
00075     virtual MMechanicalState* createMapping(const char* name = "contactPoints") = 0;
00076     virtual void cleanup() = 0;
00077     virtual void resize(int size) = 0;
00078     virtual int addPoint(const Coord& c, int index, Real& r) = 0;
00079     virtual void update() = 0;
00080 
00081     typedef helper::Factory< std::string, BaseContactMapper<DataTypes>, core::CollisionModel* > ContactMapperFactory;
00082     static BaseContactMapper<DataTypes>* Create(core::CollisionModel* model, const std::string& name = std::string("default"))
00083     {
00084     return ContactMapperFactory::CreateObject(name, model);
00085     }
00086 
00087     template < class TCollisionModel>
00088     static void create( ContactMapper<TCollisionModel, DataTypes>*& obj, core::CollisionModel* arg)
00089     {
00090     TCollisionModel* model = dynamic_cast<TCollisionModel*>(arg);
00091     if (model == NULL) return;
00092     obj = new ContactMapper<TCollisionModel, DataTypes>;
00093     obj->setCollisionModel(model);
00094     }
00095 
00096 };
00097 
00099 template < class TCollisionModel, class DataTypes >
00100 class BarycentricContactMapper : public BaseContactMapper<DataTypes>
00101 {
00102 public:
00103     typedef typename DataTypes::Real Real;
00104     typedef typename DataTypes::Coord Coord;
00105     typedef TCollisionModel MCollisionModel;
00106     typedef typename MCollisionModel::InDataTypes InDataTypes;
00107     typedef typename MCollisionModel::Topology InTopology;
00108     typedef core::componentmodel::behavior::MechanicalState< InDataTypes> InMechanicalState;
00109     typedef core::componentmodel::behavior::MechanicalState<  typename BarycentricContactMapper::DataTypes> MMechanicalState;
00110     typedef component::MechanicalObject<typename BarycentricContactMapper::DataTypes> MMechanicalObject;
00111     typedef mapping::BarycentricMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00112     typedef mapping::TopologyBarycentricMapper<InDataTypes, typename BarycentricContactMapper::DataTypes> MMapper;
00113     MCollisionModel* model;
00114     MMapping* mapping;
00115     MMapper* mapper;
00116     
00117     BarycentricContactMapper()
00118     : model(NULL), mapping(NULL), mapper(NULL)
00119     {
00120     }
00121 
00122     void setCollisionModel(MCollisionModel* model)
00123     {
00124     this->model = model;
00125     }
00126     
00127     void cleanup();
00128     
00129     MMechanicalState* createMapping(const char* name="contactPoints");
00130     
00131     void resize(int size)
00132     {
00133         if (mapping!=NULL)
00134         {
00135             mapper->clear();
00136             mapping->getMechTo()->resize(size);
00137         }
00138     }
00139     
00140     void update()
00141     {
00142         if (mapping!=NULL)
00143         {
00144             mapping->updateMapping();
00145         }
00146     }
00147 };
00148 
00150 template<class DataTypes>
00151 class ContactMapper<LineModel, DataTypes> : public BarycentricContactMapper<LineModel, DataTypes>
00152 {
00153 public:
00154     typedef typename DataTypes::Real Real;
00155     typedef typename DataTypes::Coord Coord;
00156     int addPoint(const Coord& P, int index, Real&)
00157     {
00158         return this->mapper->createPointInLine(P, index, this->model->getMechanicalState()->getX());
00159     }
00160 
00161 };
00162 
00164 template<class DataTypes>
00165 class ContactMapper<TriangleModel, DataTypes> : public BarycentricContactMapper<TriangleModel, DataTypes>
00166 {
00167 public:
00168     typedef typename DataTypes::Real Real;
00169     typedef typename DataTypes::Coord Coord;
00170     int addPoint(const Coord& P, int index, Real&)
00171     {
00172         int nbt = this->model->getMeshTopology()->getNbTriangles();
00173         if (index < nbt)
00174             return this->mapper->createPointInTriangle(P, index, this->model->getMechanicalState()->getX());
00175         else
00176         {
00177             int qindex = (index - nbt)/2;
00178             int nbq = this->model->getMeshTopology()->getNbQuads();
00179             if (qindex < nbq)
00180                 return this->mapper->createPointInQuad(P, qindex, this->model->getMechanicalState()->getX());
00181             else
00182             {
00183                 std::cerr << "ContactMapper<TriangleMeshModel>: ERROR invalid contact element index "<<index<<" on a topology with "<<nbt<<" triangles and "<<nbq<<" quads."<<std::endl;
00184                 std::cerr << "model="<<this->model->getName()<<" size="<<this->model->getSize()<<std::endl;
00185                 return -1;
00186             }
00187         }
00188     }
00189 };
00190 
00192 template<class DataTypes>
00193 class ContactMapper<TetrahedronModel, DataTypes> : public BarycentricContactMapper<TetrahedronModel, DataTypes>
00194 {
00195 public:
00196     typedef typename DataTypes::Real Real;
00197     typedef typename DataTypes::Coord Coord;
00198     int addPoint(const Coord& P, int index, Real&)
00199     {
00200     Tetrahedron t(this->model, index);
00201     Vector3 b = t.getBary(P);
00202     return this->mapper->addPointInTetra(index, b.ptr());
00203     }
00204 };
00205 
00207 template<class TCollisionModel, class DataTypes>
00208 class IdentityContactMapper : public BaseContactMapper<DataTypes>
00209 {
00210 public:
00211     typedef typename DataTypes::Real Real;
00212     typedef typename DataTypes::Coord Coord;
00213     typedef TCollisionModel MCollisionModel;
00214     typedef typename MCollisionModel::InDataTypes InDataTypes;
00215     typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00216     typedef core::componentmodel::behavior::MechanicalState<typename IdentityContactMapper::DataTypes> MMechanicalState;
00217     typedef component::MechanicalObject<typename IdentityContactMapper::DataTypes> MMechanicalObject;
00218     typedef mapping::IdentityMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00219     MCollisionModel* model;
00220     MMapping* mapping;
00221     
00222     IdentityContactMapper()
00223     : model(NULL), mapping(NULL)
00224     {
00225     }
00226     
00227     void setCollisionModel(MCollisionModel* model)
00228     {
00229     this->model = model;
00230     }
00231 
00232     void cleanup();
00233     
00234     MMechanicalState* createMapping(const char* name="contactPoints");
00235     
00236     void resize(int size)
00237     {
00238     }
00239     
00240     int addPoint(const Coord&, int index, Real&)
00241     {
00242         return index;
00243     }
00244     
00245     void update()
00246     {
00247         if (mapping!=NULL)
00248         {
00249             mapping->updateMapping();
00250         }
00251     }
00252 };
00253 
00255 template<class TCollisionModel>
00256 class IdentityContactMapper<TCollisionModel, typename TCollisionModel::InDataTypes> : public BaseContactMapper<typename TCollisionModel::InDataTypes>
00257 {
00258 public:
00259     typedef TCollisionModel MCollisionModel;
00260     typedef typename MCollisionModel::InDataTypes InDataTypes;
00261     typedef typename MCollisionModel::InDataTypes DataTypes;
00262     typedef typename DataTypes::Real Real;
00263     typedef typename DataTypes::Coord Coord;
00264     typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00265     typedef core::componentmodel::behavior::MechanicalState<DataTypes> MMechanicalState;
00266     MCollisionModel* model;
00267     
00268     IdentityContactMapper()
00269     : model(NULL)
00270     {
00271     }
00272     
00273     void setCollisionModel(MCollisionModel* model)
00274     {
00275     this->model = model;
00276     }
00277 
00278     void cleanup()
00279     {
00280     }
00281     
00282     MMechanicalState* createMapping(const char* /*name*/="contactPoints")
00283     {
00284         if (model==NULL) return NULL;
00285         return model->getMechanicalState();
00286     }
00287     
00288     void resize(int /*size*/)
00289     {
00290     }
00291     
00292     int addPoint(const Coord& /*P*/, int index, Real&)
00293     {
00294         return index;
00295     }
00296     
00297     void update()
00298     {
00299     }
00300 };
00301 
00303 template<class DataTypes>
00304 class ContactMapper<PointModel, DataTypes> : public IdentityContactMapper<PointModel, DataTypes>
00305 {
00306 public:
00307 };
00308 
00310 template<class TInDataTypes, class DataTypes>
00311 class ContactMapper<TSphereModel<TInDataTypes>, DataTypes> : public IdentityContactMapper<TSphereModel<TInDataTypes>, DataTypes>
00312 {
00313 public:
00314     typedef typename DataTypes::Real Real;
00315     typedef typename DataTypes::Coord Coord;
00316     int addPoint(const Coord& /*P*/, int index, Real& r)
00317     {
00318     TSphere<TInDataTypes> e(this->model, index);
00319     r = e.r();
00320         return index;
00321     }
00322 };
00323 
00325 template<class DataTypes>
00326 class ContactMapper<SphereTreeModel, DataTypes> : public IdentityContactMapper<SphereTreeModel, DataTypes>
00327 {
00328 public:
00329     typedef typename DataTypes::Real Real;
00330     typedef typename DataTypes::Coord Coord;
00331     int addPoint(const Coord& /*P*/, int index, Real& r)
00332     {
00333     SingleSphere e(this->model, index);
00334     r = e.r();
00335         return index;
00336     }
00337 };
00338 
00340 template < class TCollisionModel, class DataTypes >
00341 class RigidContactMapper : public BaseContactMapper<DataTypes>
00342 {
00343 public:
00344     typedef typename DataTypes::Real Real;
00345     typedef typename DataTypes::Coord Coord;
00346     typedef TCollisionModel MCollisionModel;
00347     typedef typename MCollisionModel::InDataTypes InDataTypes;
00348     typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00349     typedef core::componentmodel::behavior::MechanicalState<typename RigidContactMapper::DataTypes> MMechanicalState;
00350     typedef component::MechanicalObject<typename RigidContactMapper::DataTypes> MMechanicalObject;
00351     typedef mapping::RigidMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00352     MCollisionModel* model;
00353     simulation::tree::GNode* child;
00354     MMapping* mapping;
00355     MMechanicalState* outmodel;
00356     int nbp;
00357 
00358     RigidContactMapper()
00359     : model(NULL), child(NULL), mapping(NULL), outmodel(NULL), nbp(0)
00360     {
00361     }
00362     
00363     void setCollisionModel(MCollisionModel* model)
00364     {
00365     this->model = model;
00366     }
00367 
00368     void cleanup();
00369     
00370     MMechanicalState* createMapping(const char* name="contactPoints");
00371 
00372     void resize(int size)
00373     {
00374         if (mapping!=NULL)
00375             mapping->clear(size);
00376         if (outmodel!=NULL)
00377             outmodel->resize(size);
00378         nbp = 0;
00379     }
00380 
00381     int addPoint(const Coord& P, int index, Real&)
00382     {
00383         int i = nbp++;
00384         if ((int)outmodel->getX()->size() <= i)
00385             outmodel->resize(i+1);
00386         if (mapping)
00387         {
00388             i = mapping->addPoint(P,index);
00389         }
00390         else
00391         {
00392             (*outmodel->getX())[i] = P;
00393         }
00394         return i;
00395     }
00396 
00397     void update()
00398     {
00399         if (mapping!=NULL)
00400         {
00401             mapping->updateMapping();
00402         }
00403     }
00404 
00405 };
00406 
00408 template <class DataTypes>
00409 class ContactMapper<RigidDistanceGridCollisionModel,DataTypes> : public RigidContactMapper<RigidDistanceGridCollisionModel,DataTypes>
00410 {
00411 public:
00412     typedef typename DataTypes::Real Real;
00413     typedef typename DataTypes::Coord Coord;
00414     typedef RigidContactMapper<RigidDistanceGridCollisionModel,DataTypes> Inherit;
00415     typedef typename Inherit::MMechanicalState MMechanicalState;
00416     typedef typename Inherit::MCollisionModel MCollisionModel;
00417     MMechanicalState* createMapping(const char* name="contactPoints");
00418     
00419     int addPoint(const Coord& P, int index, Real& r)
00420     {
00421         int i = Inherit::addPoint(P, index, r);
00422         if (!this->mapping)
00423         {
00424             MCollisionModel* model = this->model;
00425             MMechanicalState* outmodel = this->outmodel;
00426             typename DataTypes::Coord& x = (*outmodel->getX())[i];
00427             typename DataTypes::Deriv& v = (*outmodel->getV())[i];
00428             if (model->isTransformed(index))
00429                 x = model->getTranslation(index) + model->getRotation(index) * P;
00430             else
00431                 x = P;
00432             v = typename DataTypes::Deriv();
00433             
00434             // estimating velocity
00435             double gdt = model->getPrevDt(index);
00436             if (gdt > 0.000001)
00437             {
00438                 if (model->isTransformed(index))
00439                 {
00440                     v = (x - (model->getPrevTranslation(index) + model->    getPrevRotation(index) * P)) * (1.0/gdt);
00441                 }
00442                 DistanceGrid* prevGrid = model->getPrevGrid(index);
00443                 //DistanceGrid* grid = model->getGrid(index);
00444                 //if (prevGrid != NULL && prevGrid != grid && prevGrid->inGrid(P))
00445                 {
00446                     DistanceGrid::Coord coefs;
00447                     int i = prevGrid->index(P, coefs);
00448                     SReal d = prevGrid->interp(i,coefs);
00449                     if (rabs(d) < 0.3) // todo : control threshold
00450                     {
00451                         DistanceGrid::Coord n = prevGrid->grad(i,coefs);
00452                         v += n * (d  / ( n.norm() * gdt));
00453                         //std::cout << "Estimated v at "<<P<<" = "<<v<<" using distance from previous model "<<d<<std::endl;
00454                     }
00455                 }
00456             }
00457         }
00458         return i;
00459     }
00460 };
00461 
00463 template <class DataTypes>
00464 class ContactMapper<FFDDistanceGridCollisionModel,DataTypes> : public BarycentricContactMapper<FFDDistanceGridCollisionModel,DataTypes>
00465 {
00466 public:
00467     typedef typename DataTypes::Real Real;
00468     typedef typename DataTypes::Coord Coord;
00469     int addPoint(const Coord& P, int index, Real&)
00470     {
00471         Vector3 bary;
00472         int elem = this->model->getDeformCube(index).elem; //getDeformGrid()->findCube(P,bary[0],bary[1],bary[2]);
00473         bary = this->model->getDeformCube(index).baryCoords(P);
00474         //if (elem == -1)
00475         //{
00476         //    std::cerr<<"WARNING: BarycentricContactMapper from FFDDistanceGridCollisionModel on point no within any the FFD grid."<<std::endl;
00477         //    elem = model->getDeformGrid()->findNearestCube(P,bary[0],bary[1],bary[2]);
00478         //}
00479         return this->mapper->addPointInCube(elem,bary.ptr());
00480     }
00481 };
00482 
00484 template < class TCollisionModel, class DataTypes >
00485 class SubsetContactMapper : public BaseContactMapper<DataTypes>
00486 {
00487 public:
00488     typedef typename DataTypes::Real Real;
00489     typedef typename DataTypes::Coord Coord;
00490     typedef TCollisionModel MCollisionModel;
00491     typedef typename MCollisionModel::InDataTypes InDataTypes;
00492     typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00493     typedef core::componentmodel::behavior::MechanicalState<typename SubsetContactMapper::DataTypes> MMechanicalState;
00494     typedef component::MechanicalObject<typename SubsetContactMapper::DataTypes> MMechanicalObject;
00495     typedef mapping::SubsetMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00496     MCollisionModel* model;
00497     simulation::tree::GNode* child;
00498     MMapping* mapping;
00499     MMechanicalState* outmodel;
00500     int nbp;
00501     bool needInit;
00502 
00503     SubsetContactMapper()
00504     : model(NULL), child(NULL), mapping(NULL), outmodel(NULL), nbp(0), needInit(false)
00505     {
00506     }
00507     
00508     void setCollisionModel(MCollisionModel* model)
00509     {
00510     this->model = model;
00511     }
00512 
00513     void cleanup();
00514     
00515     MMechanicalState* createMapping(const char* name="contactPoints");
00516 
00517     void resize(int size)
00518     {
00519         if (mapping!=NULL)
00520             mapping->clear(size);
00521         if (outmodel!=NULL)
00522             outmodel->resize(size);
00523         nbp = 0;
00524     }
00525 
00526     int addPoint(const Coord& P, int index, Real&)
00527     {
00528         int i = nbp++;
00529         if ((int)outmodel->getX()->size() <= i)
00530             outmodel->resize(i+1);
00531         if (mapping)
00532         {
00533             i = mapping->addPoint(index);
00534         needInit = true;
00535         }
00536         else
00537         {
00538             (*outmodel->getX())[i] = P;
00539         }
00540         return i;
00541     }
00542 
00543     void update()
00544     {
00545         if (mapping!=NULL)
00546         {
00547         if (needInit)
00548         {
00549         mapping->init();
00550         needInit = false;
00551         }
00552             mapping->updateMapping();
00553         }
00554     }
00555 
00556     //double radius(const typename TCollisionModel::Element& /*e*/)
00557     //{
00558     //    return 0.0;
00559     //}
00560 };
00561 
00562 template < class Mapper >
00563 class ContactMapperCreator : public helper::Creator < typename Mapper::ContactMapperFactory, Mapper >
00564 {
00565 public:
00566     typedef helper::Creator < typename Mapper::ContactMapperFactory, Mapper > Inherit;
00567     ContactMapperCreator(std::string name, bool multi = true)
00568     : Inherit(name, multi)
00569     {
00570     }
00571 };
00572 
00573 } // namespace collision
00574 
00575 } // namespace component
00576 
00577 } // namespace sofa
00578 
00579 #endif

Generated on Sun Nov 23 02:33:00 2008 for Sofa by  doxygen 1.5.7.1