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
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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 , double time)
00138 {
00139
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;
00144 int nparticles = (int)((time - lasttime) / f_delay.getValue());
00145 if (nparticles>0)
00146 {
00147
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);
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
00220 double time = getContext()->getTime();
00221 if (time < f_start.getValue() || time > f_stop.getValue()) return;
00222
00223 for (unsigned int s=0; s<lastparticles.size(); s++)
00224 {
00225
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
00239 for (unsigned int s=0; s<lastparticles.size(); s++)
00240 {
00241
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
00254 for (unsigned int s=0; s<lastparticles.size(); s++)
00255 {
00256
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);
00260 }
00261 }
00262
00263 virtual void animateEnd(double , double )
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
00291 helper::removeValue(ps->lastparticles,(unsigned int)index);
00292 }
00293 }
00294
00295 };
00296
00297
00298 }
00299
00300 }
00301
00302 #endif
00303