SpatialGridContainer.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
00037 #ifndef SOFA_COMPONENT_CONTAINER_SPATIALGRIDCONTAINER_H
00038 #define SOFA_COMPONENT_CONTAINER_SPATIALGRIDCONTAINER_H
00039
00040 #include <sofa/helper/system/config.h>
00041 #include <sofa/defaulttype/Vec3Types.h>
00042 #include <sofa/core/objectmodel/BaseObject.h>
00043 #include <sofa/core/objectmodel/Event.h>
00044 #include <sofa/core/componentmodel/behavior/MechanicalState.h>
00045 #include <sofa/helper/rmath.h>
00046 #include <list>
00047
00048
00049
00050 #ifndef HASH_NAMESPACE
00051 # ifdef _MSC_VER
00052 # if _MSC_VER >= 1300
00053 # include <hash_map>
00054
00055 # define HASH_NAMESPACE stdext
00056
00057
00058
00059 # else
00060 # include <map>
00061 # define HASH_NAMESPACE std
00062 # endif
00063 # else
00064 # if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 3 ))
00065 # include <tr1/unordered_map>
00066 # define HASH_NAMESPACE std::tr1
00067 # else
00068 # include <ext/hash_map>
00069 # define HASH_NAMESPACE __gnu_cxx
00070 # endif
00071 # endif
00072 #endif
00073
00074 namespace sofa
00075 {
00076
00077 namespace component
00078 {
00079
00080 namespace container
00081 {
00082
00083 using namespace sofa::defaulttype;
00084
00085 class EmptyClass
00086 {
00087 public:
00088 void clear() {}
00089 };
00090
00091 template<class TDataTypes>
00092 class SpatialGridTypes
00093 {
00094 public:
00095 typedef TDataTypes DataTypes;
00096 typedef typename DataTypes::VecCoord VecCoord;
00097 typedef typename DataTypes::Coord Coord;
00098 typedef typename DataTypes::Real Real;
00099
00100 typedef EmptyClass GridData;
00101 typedef EmptyClass ParticleField;
00102 class CellData
00103 {
00104 public:
00105 void clear()
00106 {
00107 }
00108 void add(ParticleField* , int , Real , Real )
00109 {
00110 }
00111 };
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 enum { GRIDDIM_LOG2 = 3 };
00122 };
00123
00124 template<class DataTypes>
00125 class SpatialGrid
00126 {
00127 public:
00128 typedef typename DataTypes::Real Real;
00129 typedef typename DataTypes::Coord Coord;
00130 typedef typename DataTypes::VecCoord VecCoord;
00131 typedef typename DataTypes::CellData CellData;
00132 typedef typename DataTypes::GridData GridData;
00133
00134 typedef typename DataTypes::ParticleField ParticleField;
00135
00136 public:
00137 SpatialGrid(Real cellWidth);
00138
00139 void begin();
00140
00141 void add(int i, const Coord& pos, bool allNeighbors = false);
00142
00143 void end();
00144
00145 void update(const VecCoord& x)
00146 {
00147 begin();
00148 for (unsigned int i=0;i<x.size();i++)
00149 {
00150 add(i, x[i]);
00151 }
00152 end();
00153 }
00154
00155 void draw();
00156
00157 template<class NeighborListener>
00158 void findNeighbors(NeighborListener* dest, Real dist);
00159
00160 void computeField(ParticleField* field, Real dist);
00161
00165 void reorderIndices(helper::vector<unsigned int>* old2new, helper::vector<unsigned int>* new2old);
00166
00167 enum { GRIDDIM_LOG2 = DataTypes::GRIDDIM_LOG2, GRIDDIM = 1<<GRIDDIM_LOG2 };
00168 enum { NCELL = GRIDDIM*GRIDDIM*GRIDDIM };
00169 enum { DX = 1, DY = GRIDDIM, DZ = GRIDDIM*GRIDDIM };
00170
00171 class Entry
00172 {
00173 public:
00174 int index;
00175 Coord pos;
00176 Entry(int i, const Coord& p) : index(i), pos(p) {}
00177 };
00178
00179 class Cell
00180 {
00181 public:
00182 std::list<Entry> plist;
00183 CellData data;
00184 void clear()
00185 {
00186 plist.clear();
00187 data.clear();
00188 }
00189 };
00190
00191 class Grid
00192 {
00193 public:
00194 Cell cell[NCELL];
00195 const Grid* neighbors[6];
00196 bool empty;
00197 GridData data;
00198 Grid() : empty(true) { std::fill(neighbors,neighbors+6, this); }
00199 void clear()
00200 {
00201 empty = true;
00202 for (unsigned int i=0; i<NCELL; i++)
00203 cell[i].clear();
00204 data.clear();
00205 }
00206 };
00207
00208 static Grid emptyGrid;
00209
00210 class Key : public helper::fixed_array<int, 3>
00211 {
00212 public:
00213 Key() {}
00214 Key(int i1, int i2, int i3) { (*this)[0] = i1; (*this)[1] = i2; (*this)[2] = i3; };
00215 bool operator==(const Key& a) const
00216 {
00217 return (*this)[0] == a[0] && (*this)[1] == a[1] && (*this)[2] == a[2];
00218 }
00219 };
00220
00221 static std::size_t hash(const Key& x)
00222 {
00223
00224 const unsigned int p0 = 73856093;
00225 const unsigned int p1 = 19349663;
00226 const unsigned int p2 = 83492791;
00227 return (p0*x[0])^(p1*x[1])^(p2*x[2]);
00228 }
00229
00230 class key_hash_fun
00231 #ifdef _MSC_VER
00232 : public HASH_NAMESPACE::hash_compare<Key>
00233 {
00234 public:
00235
00236
00237
00238
00239
00240 inline bool operator()(const Key& s1, const Key& s2) const
00241 {
00242 for (unsigned int i=0;i<s1.size();++i)
00243 if (s1[i] < s2[i]) return true;
00244 else if (s1[i] > s2[i]) return false;
00245 return false;
00246 }
00247 #else
00248 {
00249 public:
00250 #endif
00251 inline std::size_t operator()(const Key &s) const
00252 {
00253 return hash(s);
00254 }
00255 };
00256
00257
00258 #ifndef _MSC_VER
00259 # if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 3 )) //hash_map is deprecated since gcc-4.3
00260 typedef HASH_NAMESPACE::unordered_map<Key, Grid*, key_hash_fun> Map;
00261 # else
00262 typedef HASH_NAMESPACE::hash_map<Key, Grid*, key_hash_fun> Map;
00263 # endif
00264 #else
00265 typedef HASH_NAMESPACE::hash_map<Key, Grid*, key_hash_fun> Map;
00266 #endif
00267
00268
00269
00270 typedef typename Map::const_iterator const_iterator;
00271 typedef typename Map::iterator iterator;
00272
00273 const_iterator gridBegin() const { return map.begin(); }
00274 const_iterator gridEnd() const { return map.end(); }
00275
00276 iterator gridBegin() { return map.begin(); }
00277 iterator gridEnd() { return map.end(); }
00278
00279 Real getCellWidth() const { return cellWidth; }
00280 Real getInvCellWidth() const { return invCellWidth; }
00281
00282 protected:
00283 Map map;
00284 const Real cellWidth;
00285 const Real invCellWidth;
00286
00287 const Grid* findGrid(const Key& k) const;
00288
00289 Grid* getGrid(const Key& k);
00290
00291 Cell* getCell(const Coord& x);
00292
00293 const Cell* getCell(const Grid* g, int x, int y, int z);
00294
00295 template<class NeighborListener>
00296 void findNeighbors(NeighborListener* dest, const Real dist2, const Cell** cellsBegin, const Cell** cellsEnd);
00297
00298 };
00299
00300 template<class DataTypes>
00301 class SpatialGridContainer : public virtual core::objectmodel::BaseObject
00302 {
00303 public:
00304 typedef typename DataTypes::Real Real;
00305 typedef typename DataTypes::Coord Coord;
00306 typedef typename DataTypes::VecCoord VecCoord;
00307 typedef SpatialGridTypes<DataTypes> GridTypes;
00308 typedef SpatialGrid< GridTypes > Grid;
00309 Grid* grid;
00310 Data<Real> d_cellWidth;
00311 Data<bool> d_showGrid;
00312 Data<bool> d_autoUpdate;
00313 Data<bool> d_sortPoints;
00314
00317 template<class T>
00318 static bool canCreate(T*& obj, core::objectmodel::BaseContext* context, core::objectmodel::BaseObjectDescription* arg)
00319 {
00320 if (dynamic_cast<core::componentmodel::behavior::MechanicalState<DataTypes>*>(context->getMechanicalState()) == NULL)
00321 return false;
00322 return core::objectmodel::BaseObject::canCreate(obj, context, arg);
00323 }
00324
00325 SpatialGridContainer();
00326 virtual ~SpatialGridContainer();
00327
00328 virtual void init();
00329 virtual void reinit();
00330 virtual void draw();
00331 virtual void handleEvent(sofa::core::objectmodel::Event* event);
00332
00333 Grid* getGrid() { return grid; }
00334 void updateGrid(const VecCoord& x)
00335 {
00336 grid->update(x);
00337
00338
00339
00340
00341
00342
00343 }
00344 template<class NeighborListener>
00345 void findNeighbors(NeighborListener* listener, Real r)
00346 {
00347 grid->findNeighbors(listener, r);
00348 }
00349 bool sortPoints();
00350
00351 virtual std::string getTemplateName() const
00352 {
00353 return templateName(this);
00354 }
00355
00356 static std::string templateName(const SpatialGridContainer<DataTypes>* = NULL)
00357 {
00358 return DataTypes::Name();
00359 }
00360 protected:
00361 core::componentmodel::behavior::MechanicalState<DataTypes>* mstate;
00362 };
00363
00364 }
00365
00366 }
00367
00368 }
00369
00370 #endif