ParticleSource.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: ParticleSource
00027 //
00028 // Description:
00029 //
00030 //
00031 // Author: Jeremie Allard, (C) 2007
00032 //
00033 // Copyright: See COPYING file that comes with this distribution
00034 //
00035 //
00036 #ifndef SOFA_COMPONENT_MISC_PARTICLESOURCE_H
00037 #define SOFA_COMPONENT_MISC_PARTICLESOURCE_H
00038 
00039 #include <sofa/core/componentmodel/behavior/Constraint.h>
00040 #include <sofa/core/componentmodel/behavior/MechanicalState.h>
00041 #include <sofa/core/objectmodel/Event.h>
00042 #include <sofa/simulation/common/AnimateBeginEvent.h>
00043 #include <sofa/simulation/common/AnimateEndEvent.h>
00044 #include <sofa/component/topology/PointSubset.h>
00045 #include <sofa/component/topology/PointSetTopologyModifier.h>
00046 #include <sofa/component/topology/PointSetTopologyChange.h>
00047 #include <vector>
00048 #include <iterator>
00049 #include <iostream>
00050 #include <ostream>
00051 #include <algorithm>
00052 
00053 namespace sofa
00054 {
00055 
00056 namespace component
00057 {
00058 
00059 template<class TDataTypes>
00060 class ParticleSource : public core::componentmodel::behavior::Constraint<TDataTypes>, public virtual core::objectmodel::BaseObject
00061 {
00062 public:
00063     typedef TDataTypes DataTypes;
00064     typedef typename DataTypes::Real Real;
00065     typedef typename DataTypes::Coord Coord;
00066     typedef typename DataTypes::VecCoord VecCoord;
00067     typedef typename DataTypes::Deriv Deriv;
00068     typedef typename DataTypes::VecDeriv VecDeriv;
00069     typedef helper::vector<Real> VecDensity;
00070     
00071     typedef core::componentmodel::behavior::MechanicalState<DataTypes> MechanicalModel;
00072     
00073     Data<Coord> f_translation;
00074     Data<Real> f_scale;
00075     Data< helper::vector<Coord> > f_center;
00076     Data<Coord> f_radius;
00077     Data<Deriv> f_velocity;
00078     Data<Real> f_delay;
00079     Data<Real> f_start;
00080     Data<Real> f_stop;
00081 
00082     ParticleSource()
00083     : f_translation(initData(&f_translation,Coord(),"translation","translation applied to center(s)") )
00084     , f_scale(initData(&f_scale,(Real)1.0,"scale","scale applied to center(s)") )
00085     , f_center(initData(&f_center, "center","Source center(s)") )
00086     , f_radius(initData(&f_radius, Coord(), "radius", "Source radius"))
00087     , f_velocity(initData(&f_velocity, Deriv(), "velocity", "Particle initial velocity"))
00088     , f_delay(initData(&f_delay, (Real)0.01, "delay", "Delay between particles creation"))
00089     , f_start(initData(&f_start, (Real)0, "start", "Source starting time"))
00090     , f_stop(initData(&f_stop, (Real)1e10, "stop", "Source stopping time"))
00091     {
00092         f_listening.setValue(true);
00093         f_center.beginEdit()->push_back(Coord()); f_center.endEdit();
00094     }
00095     
00096     virtual ~ParticleSource()
00097     {
00098     }
00099     
00100     int N;
00101     Real lasttime;
00102     //int lastparticle;
00103     topology::PointSubset lastparticles;
00104     helper::vector<Coord> lastpos;
00105     
00106     virtual void init()
00107     {
00108         this->core::componentmodel::behavior::Constraint<TDataTypes>::init();
00109         if (!this->mstate) return;
00110         N = f_center.getValue().size();
00111         lasttime = f_start.getValue()-f_delay.getValue();
00112         //lastparticle = -1;
00113         lastpos.resize(N);
00114 
00115     lastparticles.setTestFunction(PSTestNewPointFunction);
00116     lastparticles.setRemovalFunction(PSRemovalFunction);
00117 
00118     lastparticles.setTestParameter( (void *) this );
00119     lastparticles.setRemovalParameter( (void *) this );
00120 
00121         std::cout << "ParticleSource: center="<<f_center.getValue()<<" radius="<<f_radius.getValue()<<" delay="<<f_delay.getValue()<<" start="<<f_start.getValue()<<" stop="<<f_stop.getValue()<<std::endl;
00122     }
00123     
00124     virtual void reset()
00125     {
00126         this->mstate->resize(1);
00127         lasttime = f_start.getValue()-f_delay.getValue();
00128         lastparticles.clear();
00129         lastpos.clear();
00130     }
00131     
00132     Real rrand()
00133     {
00134         return (Real)(rand()*1.0/RAND_MAX);
00135     }
00136     
00137     virtual void animateBegin(double /*dt*/, double time)
00138     {
00139         //std::cout << "ParticleSource: animate begin time="<<time<<std::endl;
00140         if (!this->mstate) return;
00141         if (time < f_start.getValue() || time > f_stop.getValue()) return;
00142         int i0 = this->mstate->getX()->size();
00143         if (i0==1) i0=0; // ignore the first point if it is the only one
00144         int nparticles = (int)((time - lasttime) / f_delay.getValue());
00145         if (nparticles>0)
00146         {
00147             //std::cout << "ParticleSource: Creating "<<nparticles<<" particles, total "<<i0+nparticles<<" particles."<<std::endl;
00148             sofa::core::componentmodel::topology::BaseMeshTopology* _topology;
00149             _topology = this->getContext()->getMeshTopology();  
00150 
00151             sofa::component::topology::PointSetTopologyModifier* pointMod; 
00152             this->getContext()->get(pointMod);  
00153 
00154             if (pointMod != NULL)
00155             {
00156                 int n = i0+nparticles*N - this->mstate->getX()->size();
00157                 pointMod->addPointsWarning(n);
00158                 pointMod->addPointsProcess(n);
00159                 pointMod->propagateTopologicalChanges();
00160             }
00161             else
00162             {
00163                 this->mstate->resize(i0+nparticles*N);
00164             }
00165             VecCoord& x = *this->mstate->getX();
00166             VecDeriv& v = *this->mstate->getV();
00167             for (int i=0; i<nparticles; i++)
00168             {
00169                 lasttime += f_delay.getValue();
00170                 int lastparticle = i0+i*N;
00171                 lastparticles.resize(N);
00172                 for (int s=0; s<N; s++)
00173                 {
00174                     lastpos[s] = f_center.getValue()[s]*f_scale.getValue() + f_translation.getValue();
00175                     for (unsigned int c = 0; c < lastpos[s].size(); c++)
00176                         lastpos[s][c] += f_radius.getValue()[c] * rrand();
00177                     x[lastparticle+s] = lastpos[s];
00178                     v[lastparticle+s] = f_velocity.getValue();
00179                     x[lastparticle+s] += v[lastparticle+s]*(time - lasttime); // account for particle initial motion
00180                     lastparticles[s] = lastparticle+s;
00181                 }
00182             }
00183         }
00184     }
00185     
00187 void handleTopologyChange()
00188 {
00189     sofa::core::componentmodel::topology::BaseMeshTopology* topology = getContext()->getMeshTopology();
00190     std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itBegin=topology->firstChange();
00191     std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itEnd=topology->lastChange();
00192     if (itBegin != itEnd)
00193     {
00194         if (this->f_printLog.getValue())
00195         {
00196             std::cout << "ParticleSource: handleTopologyChange()"<<std::endl;
00197             std::cout << "lastparticles = ";
00198             std::copy(lastparticles.begin(),lastparticles.end(),std::ostream_iterator<unsigned int>(std::cout," "));
00199             std::cout << std::endl;
00200         }
00201         int s1 = lastparticles.size();
00202         lastparticles.handleTopologyEvents(itBegin, itEnd, this->mstate->getSize());
00203         int s2 = lastparticles.size();
00204         if (s2 > s1) std::cout << "ParticleSource: handleTopologyChange(): "<<s2-s1<<" points added!"<<std::endl;
00205         if (s2 < s1) std::cout << "ParticleSource: handleTopologyChange(): "<<s1-s2<<" points removed!"<<std::endl;
00206         if (this->f_printLog.getValue())
00207         {
00208             std::cout << "NEW lastparticles = ";
00209             std::copy(lastparticles.begin(),lastparticles.end(),std::ostream_iterator<unsigned int>(std::cout," "));
00210             std::cout << std::endl;
00211         }
00212     }
00213 }
00214 
00215     virtual void projectResponse(VecDeriv& res) 
00216     {
00217         if (!this->mstate) return;
00218         if (lastparticles.empty()) return;
00219         //std::cout << "ParticleSource: projectResponse of last particle ("<<lastparticle<<")."<<std::endl;
00220         double time = getContext()->getTime();
00221         if (time < f_start.getValue() || time > f_stop.getValue()) return;
00222         // constraint the last value
00223         for (unsigned int s=0; s<lastparticles.size(); s++)
00224       {
00225         //HACK: TODO understand why these conditions can be reached
00226         if (lastparticles[s] >= res.size()) continue;
00227 
00228             res[lastparticles[s]] = Deriv();
00229       }
00230     }
00231     
00232     virtual void projectVelocity(VecDeriv& res) 
00233     {
00234         if (!this->mstate) return;
00235         if (lastparticles.empty()) return;
00236         double time = getContext()->getTime();
00237         if (time < f_start.getValue() || time > f_stop.getValue()) return;
00238         // constraint the last value
00239         for (unsigned int s=0; s<lastparticles.size(); s++)
00240       {
00241         //HACK: TODO understand why these conditions can be reached
00242         if ( lastparticles[s] >= res.size() ) continue;
00243             res[lastparticles[s]] = f_velocity.getValue();
00244       }
00245     }
00246     
00247     virtual void projectPosition(VecCoord& x) 
00248     {
00249         if (!this->mstate) return;
00250         if (lastparticles.empty()) return;
00251         double time = getContext()->getTime();
00252         if (time < f_start.getValue() || time > f_stop.getValue()) return;
00253         // constraint the last value
00254         for (unsigned int s=0; s<lastparticles.size(); s++)
00255         {
00256       //HACK: TODO understand why these conditions can be reached
00257       if (lastpos.size() >= s || lastparticles[s] >= x.size()) continue;
00258             x[lastparticles[s]] = lastpos[s];
00259             x[lastparticles[s]] += f_velocity.getValue()*(time - lasttime); // account for particle initial motion
00260         }
00261     }
00262     
00263     virtual void animateEnd(double /*dt*/, double /*time*/)
00264     {
00265         
00266     }
00267     
00268     virtual void handleEvent(sofa::core::objectmodel::Event* event)
00269     {
00270         if (simulation::AnimateBeginEvent* ev = dynamic_cast<simulation::AnimateBeginEvent*>(event))
00271             animateBegin(ev->getDt(), getContext()->getTime());
00272         if (simulation::AnimateEndEvent* ev = dynamic_cast<simulation::AnimateEndEvent*>(event))
00273             animateEnd(ev->getDt(), getContext()->getTime());
00274     }
00275 
00276 
00277 protected :
00278     static bool PSTestNewPointFunction(int, void*, const sofa::helper::vector< unsigned int > &, const sofa::helper::vector< double >& )
00279     {
00280         return false;
00281     }
00282 
00283     static void PSRemovalFunction (int index, void* p)
00284     {
00285         ParticleSource* ps = (ParticleSource*)p;
00286         topology::PointSubset::const_iterator it = std::find(ps->lastparticles.begin(),ps->lastparticles.end(), (unsigned int)index);
00287         if (it != ps->lastparticles.end())
00288         {
00289             ps->lastpos.erase( ps->lastpos.begin()+(it-ps->lastparticles.begin()) );
00290             //ps->lastparticles.getArray().erase(it);
00291             helper::removeValue(ps->lastparticles,(unsigned int)index);
00292         }
00293     }
00294 
00295 };
00296 
00297 
00298 } // namespace component
00299 
00300 } // namespace sofa
00301 
00302 #endif
00303 

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