SphereForceField.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_FORCEFIELD_SPHEREFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_SPHEREFORCEFIELD_INL
00027 
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include "SphereForceField.h"
00030 #include <sofa/helper/system/config.h>
00031 #include <sofa/helper/rmath.h>
00032 #include <sofa/helper/system/gl.h>
00033 #include <sofa/helper/system/glut.h>
00034 #include <assert.h>
00035 #include <iostream>
00036 
00037 namespace sofa
00038 {
00039 
00040 namespace component
00041 {
00042 
00043 namespace forcefield
00044 {
00045 
00046 // f  = -stiffness * (x -c ) * (|x-c|-r)/|x-c|
00047 // fi = -stiffness * (xi-ci) * (|x-c|-r)/|x-c|
00048 // dfi/dxj = -stiffness * ( (xi-ci) * d((|x-c|-r)/|x-c|)/dxj + d(xi-ci)/dxj * (|x-c|-r)/|x-c| )
00049 // d(xi-ci)/dxj = 1 if i==j, 0 otherwise
00050 // d((|x-c|-r)/|x-c|)/dxj = (|x-c|*d(|x-c|-r)/dxj - d(|x-c|)/dxj * (|x-c|-r))/|x-c|^2
00051 //                        = (d(|x-c|)/dxj * (|x-c| - |x-c| + r))/|x-c|^2
00052 //                        = r/|x-c|^2 * d(|x-c|)/dxj
00053 //                        = r/|x-c|^2 * d(sqrt(sum((xi-ci)^2)))/dxj
00054 //                        = r/|x-c|^2 * 1/2 * 1/sqrt(sum((xi-ci)^2)) * d(sum(xi-ci)^2)/dxj
00055 //                        = r/|x-c|^2 * 1/2 * 1/|x-c| * d((xj-cj)^2)/dxj
00056 //                        = r/|x-c|^2 * 1/2 * 1/|x-c| * (2(xj-cj))
00057 //                        = r/|x-c|^2 * (xj-cj)/|x-c|
00058 // dfi/dxj = -stiffness * ( (xi-ci) * r/|x-c|^2 * (xj-cj)/|x-c| + (i==j) * (|x-c|-r)/|x-c| )
00059 //         = -stiffness * ( (xi-ci)/|x-c| * (xj-cj)/|x-c| * r/|x-c| + (i==j) * (1 - r/|x-c|) )
00060 // df = -stiffness * ( (x-c)/|x-c| * dot(dx,(x-c)/|x-c|) * r/|x-c|   + dx * (1 - r/|x-c|) )
00061 
00062 template<class DataTypes>
00063 void SphereForceField<DataTypes>::addForce(VecDeriv& f1, const VecCoord& p1, const VecDeriv& v1)
00064 {
00065     const Coord center = sphereCenter.getValue();
00066     const Real r = sphereRadius.getValue();
00067     const Real r2 = r*r;
00068     this->contacts.beginEdit()->clear();
00069     f1.resize(p1.size());
00070     for (unsigned int i=0; i<p1.size(); i++)
00071     {
00072         Coord dp = p1[i] - center;
00073         Real norm2 = dp.norm2();
00074         if (norm2<r2)
00075         {
00076             Real norm = helper::rsqrt(norm2);
00077             Real d = norm - r;
00078             Real forceIntensity = -this->stiffness.getValue()*d;
00079             Real dampingIntensity = -this->damping.getValue()*d;
00080             Deriv force = dp*(forceIntensity/norm) - v1[i]*dampingIntensity;
00081             f1[i]+=force;
00082             Contact c;
00083             c.index = i;
00084             c.normal = dp / norm;
00085             c.fact = r / norm;
00086             this->contacts.beginEdit()->push_back(c);
00087         }
00088     }
00089     this->contacts.endEdit();
00090 }
00091 
00092 template<class DataTypes>
00093 void SphereForceField<DataTypes>::addDForce(VecDeriv& df1, const VecDeriv& dx1, double kFactor, double /*bFactor*/)
00094 {
00095     df1.resize(dx1.size());
00096     const Real fact = (Real)(-this->stiffness.getValue()*kFactor);
00097     for (unsigned int i=0; i<this->contacts.getValue().size(); i++)
00098     {
00099         const Contact& c = (this->contacts.getValue())[i];
00100         assert((unsigned)c.index<dx1.size());
00101         Deriv du = dx1[c.index];
00102         Deriv dforce; dforce = fact*(c.normal * ((du*c.normal)*c.fact) + du * (1 - c.fact));
00103         df1[c.index] += dforce;
00104     }
00105 }
00106 
00107 template<class DataTypes>
00108 void SphereForceField<DataTypes>::updateStiffness( const VecCoord& x )
00109 {
00110     const Coord center = sphereCenter.getValue();
00111     const Real r = sphereRadius.getValue();
00112     const Real r2 = r*r;
00113     this->contacts.beginEdit()->clear();
00114     for (unsigned int i=0; i<x.size(); i++)
00115     {
00116         Coord dp = x[i] - center;
00117         Real norm2 = dp.norm2();
00118         if (norm2<r2)
00119         {
00120             Real norm = helper::rsqrt(norm2);
00121             Contact c;
00122             c.index = i;
00123             c.normal = dp / norm;
00124             c.fact = r / norm;
00125             this->contacts.beginEdit()->push_back(c);
00126         }
00127     }
00128     this->contacts.endEdit();
00129 }
00130 
00131 template <class DataTypes> 
00132     double SphereForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00133 {
00134     std::cerr<<"SphereForceField::getPotentialEnergy-not-implemented !!!"<<std::endl;
00135     return 0;
00136 }
00137 
00138 template<class DataTypes>
00139 void SphereForceField<DataTypes>::draw()
00140 {
00141     if (!getContext()->getShowForceFields()) return;
00142     if (!bDraw.getValue()) return;
00143 
00144     const Coord center = sphereCenter.getValue();
00145     const Real r = sphereRadius.getValue();
00146 
00147     glEnable(GL_LIGHTING);
00148     glEnable(GL_COLOR_MATERIAL);
00149     glColor3f(color.getValue()[0],color.getValue()[1],color.getValue()[2]);
00150     glPushMatrix();
00151     glTranslated(center[0], center[1], center[2]);
00152     glutSolidSphere(r*0.99,32,16); // slightly reduce rendered radius
00153     glPopMatrix();
00154     glDisable(GL_LIGHTING);
00155     glDisable(GL_COLOR_MATERIAL);
00156 }
00157 
00158 
00159 } // namespace forcefield
00160 
00161 } // namespace component
00162 
00163 } // namespace sofa
00164 
00165 #endif

Generated on Sun Nov 23 03:05:45 2008 for Sofa by  doxygen 1.5.7.1