BarycentricPenalityContact.inl

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_BARYCENTRICPENALITYCONTACT_INL
00026 #define SOFA_COMPONENT_COLLISION_BARYCENTRICPENALITYCONTACT_INL
00027 
00028 #include <sofa/component/collision/BarycentricPenalityContact.h>
00029 
00030 namespace sofa
00031 {
00032 
00033 namespace component
00034 {
00035 
00036 namespace collision
00037 {
00038 
00039 using namespace sofa::defaulttype;
00040 using namespace core::componentmodel::collision;
00041 
00042 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00043 BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::BarycentricPenalityContact(CollisionModel1* model1, CollisionModel2* model2, Intersection* intersectionMethod)
00044 : model1(model1), model2(model2), intersectionMethod(intersectionMethod), ff(NULL), parent(NULL)
00045 {
00046     mapper1.setCollisionModel(model1);
00047     mapper2.setCollisionModel(model2);
00048 }
00049 
00050 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00051 BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::~BarycentricPenalityContact()
00052 {
00053 }
00054 
00055 
00056 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00057 void BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::cleanup()
00058 {
00059     if (ff!=NULL)
00060     {
00061         ff->cleanup();
00062         if (parent!=NULL) parent->removeObject(ff);
00063         delete ff;
00064         parent = NULL;
00065         ff = NULL;
00066         mapper1.cleanup();
00067         mapper2.cleanup();
00068     }
00069 }
00070 
00071 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00072 void BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::setDetectionOutputs(OutputVector* o)
00073 {
00074     TOutputVector& outputs = *static_cast<TOutputVector*>(o);
00075     const bool printLog = this->f_printLog.getValue();
00076     if (ff==NULL)
00077     {
00078         MechanicalState1* mstate1 = mapper1.createMapping();
00079         MechanicalState2* mstate2 = mapper2.createMapping();
00080         ff = new ResponseForceField(mstate1,mstate2);
00081         ff->setName( getName() );
00082     }
00083 
00084     int insize = outputs.size();
00085 
00086     // old index for each contact
00087     // >0 indicate preexisting contact
00088     // 0  indicate new contact
00089     // -1 indicate ignored duplicate contact
00090     std::vector<int> oldIndex(insize);
00091 
00092     int nbnew = 0;
00093 
00094     for (int i=0; i<insize; i++)
00095     {
00096         DetectionOutput* o = &outputs[i];
00097         // find this contact in contactIndex, possibly creating a new entry initialized by 0
00098         int& index = contactIndex[o->id];
00099         if (index < 0) // duplicate contact
00100         {
00101             int i2 = -1-index;
00102             DetectionOutput* o2 = &outputs[i2];
00103             if (o2->value <= o->value)
00104             {
00105                 // current contact is ignored
00106                 oldIndex[i] = -1;
00107                 continue;
00108             }
00109             else
00110             {
00111                 // previous contact is replaced
00112                 oldIndex[i] = oldIndex[i2];
00113                 oldIndex[i2] = -1;
00114             }
00115         }
00116         else
00117         {
00118             oldIndex[i] = index;
00119             if (!index)
00120             {
00121                 ++nbnew;
00122                 if (printLog) std::cout << "BarycentricPenalityContact: New contact "<<o->id<<std::endl;
00123             }
00124         }
00125         index = -1-i; // save this index as a negative value in contactIndex map.
00126     }
00127 
00128     // compute new index of each contact
00129     std::vector<int> newIndex(insize);
00130     // number of final contacts used in the response
00131     int size = 0;
00132     for (int i=0; i<insize; i++)
00133     {
00134         if (oldIndex[i] >= 0)
00135         {
00136             ++size;
00137             newIndex[i] = size;
00138         }
00139     }
00140 
00141     // update contactMap
00142     for (ContactIndexMap::iterator it = contactIndex.begin(), itend = contactIndex.end(); it != itend; )
00143     {
00144         int& index = it->second;
00145         if (index >= 0)
00146         {
00147             if (printLog) std::cout << "BarycentricPenalityContact: Removed contact "<<it->first<<std::endl;
00148             ContactIndexMap::iterator oldit = it;
00149             ++it;
00150             contactIndex.erase(oldit);
00151         }
00152         else
00153         {
00154             index = newIndex[-1-index]; // write the final contact index
00155             ++it;
00156         }
00157     }
00158     if (printLog) std::cout << "BarycentricPenalityContact: "<<insize<<" input contacts, "<<size<<" contacts used for response ("<<nbnew<<" new)."<<std::endl;
00159 
00160     //int size = contacts.size();
00161     ff->clear(size);
00162     mapper1.resize(size);
00163     mapper2.resize(size);
00164     //int i = 0;
00165     const double d0 = intersectionMethod->getContactDistance() + model1->getProximity() + model2->getProximity(); // - 0.001;
00166     //for (std::vector<DetectionOutput>::iterator it = outputs.begin(); it!=outputs.end(); it++)
00167     //{
00168     //    DetectionOutput* o = &*it;
00169     for (int i=0; i<insize; i++)
00170     {
00171         int index = oldIndex[i];
00172         if (index < 0) continue; // this contact is ignored
00173         DetectionOutput* o = &outputs[i];
00174         CollisionElement1 elem1(o->elem.first);
00175         CollisionElement2 elem2(o->elem.second);
00176         int index1 = elem1.getIndex();
00177         int index2 = elem2.getIndex();
00178     typename DataTypes1::Real r1 = 0.0;
00179         typename DataTypes2::Real r2 = 0.0;
00180         // Create mapping for first point
00181         index1 = mapper1.addPoint(o->point[0], index1, r1);
00182         // Create mapping for second point
00183         index2 = mapper2.addPoint(o->point[1], index2, r2);
00184 
00185         double distance = d0 + r1 + r2;
00186         double stiffness = (elem1.getContactStiffness() * elem2.getContactStiffness());
00187     if (distance != 0.0) stiffness /= distance;
00188 
00189         double mu_v = (elem1.getContactFriction() + elem2.getContactFriction());
00190         ff->addContact(index1, index2, elem1.getIndex(), elem2.getIndex(), o->normal, distance, stiffness, mu_v/* *distance */, mu_v, index);
00191     }
00192     // Update mappings
00193     mapper1.update();
00194     mapper2.update();
00195 }
00196 
00197 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00198 void BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::createResponse(core::objectmodel::BaseContext* group)
00199 {
00200     if (ff!=NULL)
00201     {
00202         if (parent!=NULL)
00203         {
00204             parent->removeObject(this);
00205             parent->removeObject(ff);
00206         }
00207         parent = group;
00208         if (parent!=NULL)
00209         {
00210             //std::cout << "Attaching contact response to "<<parent->getName()<<std::endl;
00211             parent->addObject(this);
00212             parent->addObject(ff);
00213         }
00214     }
00215 }
00216 
00217 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00218 void BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::removeResponse()
00219 {
00220     if (ff!=NULL)
00221     {
00222         if (parent!=NULL)
00223         {
00224             //std::cout << "Removing contact response from "<<parent->getName()<<std::endl;
00225             parent->removeObject(this);
00226             parent->removeObject(ff);
00227         }
00228         parent = NULL;
00229     }
00230 }
00231 
00232 template < class TCollisionModel1, class TCollisionModel2, class ResponseDataTypes >
00233 void BarycentricPenalityContact<TCollisionModel1,TCollisionModel2,ResponseDataTypes>::draw()
00234 {
00235     //  if (ff!=NULL)
00236     //      ff->draw();
00237 }
00238 
00239 } // namespace collision
00240 
00241 } // namespace component
00242 
00243 } // namespace sofa
00244 
00245 #endif

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