ParticleSink.h
Go to the documentation of this file.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_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 , double time)
00110 {
00111
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)
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
00147 for (unsigned int i = 0; i < remove.size(); ++i)
00148 {
00149 --n;
00150 object->replaceValue(n, remove[i] );
00151 }
00152
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
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
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 , double )
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
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
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
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 }
00260
00261 }
00262
00263 #endif
00264