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 #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
00087
00088
00089
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
00098 int& index = contactIndex[o->id];
00099 if (index < 0)
00100 {
00101 int i2 = -1-index;
00102 DetectionOutput* o2 = &outputs[i2];
00103 if (o2->value <= o->value)
00104 {
00105
00106 oldIndex[i] = -1;
00107 continue;
00108 }
00109 else
00110 {
00111
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;
00126 }
00127
00128
00129 std::vector<int> newIndex(insize);
00130
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
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];
00155 ++it;
00156 }
00157 }
00158 if (printLog) std::cout << "BarycentricPenalityContact: "<<insize<<" input contacts, "<<size<<" contacts used for response ("<<nbnew<<" new)."<<std::endl;
00159
00160
00161 ff->clear(size);
00162 mapper1.resize(size);
00163 mapper2.resize(size);
00164
00165 const double d0 = intersectionMethod->getContactDistance() + model1->getProximity() + model2->getProximity();
00166
00167
00168
00169 for (int i=0; i<insize; i++)
00170 {
00171 int index = oldIndex[i];
00172 if (index < 0) continue;
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
00181 index1 = mapper1.addPoint(o->point[0], index1, r1);
00182
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, mu_v, index);
00191 }
00192
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
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
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
00236
00237 }
00238
00239 }
00240
00241 }
00242
00243 }
00244
00245 #endif