ParticleSink.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 //
00026 // C++ Interface: ParticleSink
00027 //
00028 // Description:
00029 //
00030 //
00031 // Author: Jeremie Allard, (C) 2008
00032 //
00033 // Copyright: See COPYING file that comes with this distribution
00034 //
00035 //
00036 #ifndef SOFA_COMPONENT_MISC_PARTICLESINK_H
00037 #define SOFA_COMPONENT_MISC_PARTICLESINK_H
00038 
00039 #include <sofa/helper/system/config.h>
00040 #include <sofa/helper/gl/template.h>
00041 #include <sofa/core/componentmodel/behavior/Constraint.h>
00042 #include <sofa/core/componentmodel/behavior/MechanicalState.h>
00043 #include <sofa/core/objectmodel/Event.h>
00044 #include <sofa/simulation/common/AnimateBeginEvent.h>
00045 #include <sofa/simulation/common/AnimateEndEvent.h>
00046 #include <sofa/component/topology/PointSubset.h>
00047 #include <sofa/component/topology/PointSetTopologyModifier.h>
00048 #include <sofa/component/topology/PointSetTopologyChange.h>
00049 #include <sofa/component/MechanicalObject.h>
00050 #include <vector>
00051 #include <iterator>
00052 #include <iostream>
00053 #include <ostream>
00054 #include <algorithm>
00055 
00056 namespace sofa
00057 {
00058 
00059 namespace component
00060 {
00061 
00062 template<class TDataTypes>
00063 class ParticleSink : public core::componentmodel::behavior::Constraint<TDataTypes>, public virtual core::objectmodel::BaseObject
00064 {
00065 public:
00066     typedef TDataTypes DataTypes;
00067     typedef typename DataTypes::Real Real;
00068     typedef typename DataTypes::Coord Coord;
00069     typedef typename DataTypes::VecCoord VecCoord;
00070     typedef typename DataTypes::Deriv Deriv;
00071     typedef typename DataTypes::VecDeriv VecDeriv;
00072     typedef helper::vector<Real> VecDensity;
00073     
00074     typedef core::componentmodel::behavior::MechanicalState<DataTypes> MechanicalModel;
00075 
00076     Data<Deriv> planeNormal;
00077     Data<Real> planeD0;
00078     Data<Real> planeD1;
00079     Data<defaulttype::Vec3f> color;
00080     Data<bool> showPlane;
00081 
00082     topology::PointSubset fixed;
00083 
00084     ParticleSink()
00085     : planeNormal(initData(&planeNormal, "normal", "plane normal"))
00086     , planeD0(initData(&planeD0, (Real)0, "d0", "plane d coef at which particles acceleration is constrained to 0"))
00087     , planeD1(initData(&planeD1, (Real)0, "d1", "plane d coef at which particles are removed"))
00088     , color(initData(&color, defaulttype::Vec3f(0.0f,.5f,.2f), "color", "plane color"))
00089     , showPlane(initData(&showPlane, false, "showPlane", "enable/disable drawing of plane"))
00090     {
00091         f_listening.setValue(true);
00092     Deriv n;
00093     DataTypes::set(n, 0, 1, 0);
00094     planeNormal.setValue(n);
00095     }
00096     
00097     virtual ~ParticleSink()
00098     {
00099     }
00100     
00101     virtual void init()
00102     {
00103         this->core::componentmodel::behavior::Constraint<TDataTypes>::init();
00104         if (!this->mstate) return;
00105 
00106         std::cout << "ParticleSink: normal="<<planeNormal.getValue()<<" d0="<<planeD0.getValue()<<" d1="<<planeD1.getValue()<<std::endl;
00107     }
00108     
00109     virtual void animateBegin(double /*dt*/, double time)
00110     {
00111         //std::cout << "ParticleSink: animate begin time="<<time<<std::endl;
00112         if (!this->mstate) return;
00113     const VecCoord& x = *this->mstate->getX();
00114     const VecDeriv& v = *this->mstate->getV();
00115         int n = x.size();
00116     helper::vector<unsigned int> remove;
00117     const bool log = this->f_printLog.getValue();
00118     for (int i=n-1; i>=0; --i) // always remove points in reverse order
00119     {
00120         Real d = x[i]*planeNormal.getValue()-planeD1.getValue();
00121         if (d<0)
00122         {
00123         if (log)
00124             std::cout << "SINK particle "<<i<<" time "<<time<<" position "<<x[i]<<" velocity "<<v[i]<<std::endl;
00125         remove.push_back(i);
00126         }
00127     }
00128     if (!remove.empty())
00129     {
00130             sofa::core::componentmodel::topology::BaseMeshTopology* _topology;
00131             _topology = this->getContext()->getMeshTopology();  
00132 
00133             sofa::component::topology::PointSetTopologyModifier* pointMod; 
00134             this->getContext()->get(pointMod);  
00135             
00136             if (pointMod != NULL)
00137             {
00138                 std::cout << "ParticleSink: remove "<<remove.size()<<" particles using PointSetTopologyModifier."<<std::endl;
00139                 pointMod->removePointsWarning(remove);
00140                 pointMod->propagateTopologicalChanges();
00141                 pointMod->removePointsProcess(remove);
00142             }
00143         else if(MechanicalObject<DataTypes>* object = dynamic_cast<MechanicalObject<DataTypes>*>(this->mstate))
00144         {
00145         std::cout << "ParticleSink: remove "<<remove.size()<<" particles using MechanicalObject."<<std::endl;
00146         // deleting the vertices
00147         for (unsigned int i = 0; i < remove.size(); ++i)
00148           {         
00149             --n;
00150             object->replaceValue(n, remove[i] ); 
00151           }
00152         // resizing the state vectors
00153                 this->mstate->resize(n);
00154         }
00155         else
00156         {
00157         std::cout << "ERROR(ParticleSink): no external object supporting removing points!"<<std::endl;
00158         }
00159     }
00160     }
00161     
00163     void handleTopologyChange()
00164     {
00165     sofa::core::componentmodel::topology::BaseMeshTopology* topology = getContext()->getMeshTopology();
00166     std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itBegin=topology->firstChange();
00167     std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itEnd=topology->lastChange();
00168     if (itBegin != itEnd)
00169     {
00170         fixed.handleTopologyEvents(itBegin, itEnd, this->mstate->getSize());
00171     }
00172     }
00173 
00174     virtual void projectResponse(VecDeriv& res) 
00175     {
00176         if (!this->mstate) return;
00177         if (fixed.empty()) return;
00178         // constraint the last value
00179         for (unsigned int s=0; s<fixed.size(); s++)
00180             res[fixed[s]] = Deriv();
00181     }
00182     
00183     virtual void projectVelocity(VecDeriv&) 
00184     {
00185     }
00186     
00187     virtual void projectPosition(VecCoord& x) 
00188     {
00189         if (!this->mstate) return;
00190         fixed.clear();
00191         // constraint the last value
00192         for (unsigned int i=0; i<x.size(); i++)
00193     {
00194         Real d = x[i]*planeNormal.getValue()-planeD0.getValue();
00195         if (d<0)
00196         {
00197         fixed.push_back(i);
00198         }
00199     }
00200     }
00201     
00202     virtual void animateEnd(double /*dt*/, double /*time*/)
00203     {
00204         
00205     }
00206     
00207     virtual void handleEvent(sofa::core::objectmodel::Event* event)
00208     {
00209         if (simulation::AnimateBeginEvent* ev = dynamic_cast<simulation::AnimateBeginEvent*>(event))
00210             animateBegin(ev->getDt(), getContext()->getTime());
00211         if (simulation::AnimateEndEvent* ev = dynamic_cast<simulation::AnimateEndEvent*>(event))
00212             animateEnd(ev->getDt(), getContext()->getTime());
00213     }
00214 
00215     virtual void draw()
00216     {
00217     if (!showPlane.getValue()) return;
00218     defaulttype::Vec3d normal; normal = planeNormal.getValue();
00219     
00220     // find a first vector inside the plane
00221     defaulttype::Vec3d v1;
00222     if( 0.0 != normal[0] ) v1 = defaulttype::Vec3d(-normal[1]/normal[0], 1.0, 0.0);
00223     else if ( 0.0 != normal[1] ) v1 = defaulttype::Vec3d(1.0, -normal[0]/normal[1],0.0);
00224     else if ( 0.0 != normal[2] ) v1 = defaulttype::Vec3d(1.0, 0.0, -normal[0]/normal[2]);
00225     v1.normalize();
00226     // find a second vector inside the plane and orthogonal to the first
00227     defaulttype::Vec3d v2;
00228     v2 = v1.cross(normal);
00229     v2.normalize();
00230     const float size=1.0f;
00231     defaulttype::Vec3d center = normal*planeD0.getValue();
00232     defaulttype::Vec3d corners[4];
00233     corners[0] = center-v1*size-v2*size;
00234     corners[1] = center+v1*size-v2*size;
00235     corners[2] = center+v1*size+v2*size;
00236     corners[3] = center-v1*size+v2*size;
00237     
00238     // glEnable(GL_LIGHTING);
00239     glDisable(GL_LIGHTING);
00240     glEnable(GL_CULL_FACE);
00241     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00242     glCullFace(GL_FRONT);
00243     
00244     glColor3f(color.getValue()[0],color.getValue()[1],color.getValue()[2]);
00245     
00246     glBegin(GL_QUADS);
00247     helper::gl::glVertexT(corners[0]);
00248     helper::gl::glVertexT(corners[1]);
00249     helper::gl::glVertexT(corners[2]);
00250     helper::gl::glVertexT(corners[3]);
00251     glEnd();
00252     
00253     glDisable(GL_CULL_FACE);
00254     
00255     glColor4f(1,0,0,1);
00256     }
00257 };
00258 
00259 } // namespace component
00260 
00261 } // namespace sofa
00262 
00263 #endif
00264 

Generated on Sun Nov 23 03:42:35 2008 for Sofa by  doxygen 1.5.7.1