Go to the documentation of this file.00001 #ifndef OPENTISSUE_COLLISION_SPATIAL_HASHING_SPATIAL_HASHING_GRID_H
00002 #define OPENTISSUE_COLLISION_SPATIAL_HASHING_SPATIAL_HASHING_GRID_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <boost/iterator/indirect_iterator.hpp>
00013
00014 #include <vector>
00015 #include <cassert>
00016
00017 namespace OpenTissue
00018 {
00019 namespace spatial_hashing
00020 {
00021
00051 template <
00052 typename real_vector3
00053 , typename int_vector3
00054 , typename data_type_
00055 , typename hash_function_type
00056 >
00057 class Grid
00058 {
00059 public:
00060 typedef data_type_ data_type;
00061 typedef typename real_vector3::value_type real_type;
00062 typedef int_vector3 triplet_type;
00063 typedef real_vector3 point_type;
00064
00065 protected:
00066
00067 typedef std::vector<data_type*> data_ptr_container;
00068 typedef typename data_ptr_container::iterator data_ptr_iterator;
00069 typedef typename data_ptr_container::const_iterator const_data_ptr_iterator;
00070
00071 protected:
00072
00073 class Cell
00074 {
00075 public:
00076
00077 typedef boost::indirect_iterator<data_ptr_iterator,data_type> data_iterator;
00078
00079 public:
00080
00081 size_t m_time_stamp;
00082 Grid * m_owner;
00083 data_ptr_container m_data;
00084 size_t m_query_stamp;
00085 size_t m_next;
00086
00087
00088 public:
00089
00090 Cell()
00091 : m_time_stamp(0)
00092 , m_owner(0)
00093 , m_query_stamp(0)
00094 {
00095 m_next= 0;
00096 m_data.resize(16);
00097 }
00098
00099 Cell( Grid * owner )
00100 : m_time_stamp(0)
00101 , m_owner(owner)
00102 , m_query_stamp(0)
00103 {
00104 m_next= 0;
00105 m_data.resize(16);
00106 }
00107
00108 Cell( Cell const & cell ) { *this = cell; }
00109
00110 Cell & operator=(Cell const & cell )
00111 {
00112 m_time_stamp = cell.m_time_stamp;
00113 m_owner = cell.m_owner;
00114 m_data = cell.m_data;
00115 m_query_stamp = cell.m_query_stamp;
00116 m_next = cell.m_next;
00117 return *this;
00118 }
00119
00120 public:
00121
00122 data_iterator begin()
00123 {
00124 assert(m_owner);
00125 if (m_time_stamp == m_owner->m_time_stamp)
00126 return data_iterator(m_data.begin());
00127 return data_iterator(m_data.end());
00128 }
00129
00130 data_iterator end()
00131 {
00132 assert(m_owner);
00133
00134 return data_iterator(m_data.begin()+m_next);
00135 }
00136
00137 public:
00138
00139 void add(data_type const & data)
00140 {
00141 assert(m_owner);
00142 if( m_owner->m_time_stamp != m_time_stamp )
00143 {
00144
00145 m_next = 0;
00146 m_time_stamp = m_owner->m_time_stamp;
00147 }
00148 if(m_next==m_data.size())
00149 {
00150 data_ptr_container tmp;
00151 tmp = m_data;
00152 m_data.resize(2*m_next);
00153 std::copy(tmp.begin(),tmp.end(),m_data.begin());
00154 }
00155 m_data[m_next] = const_cast<data_type*>(&data);
00156 ++m_next;
00157
00158
00159 }
00160
00161 bool remove(data_type & data)
00162 {
00163 data_type * tmp = const_cast<data_type*>(&data);
00164 assert(m_owner || !"Cell::remove(): owner was null");
00165
00166 if( m_owner->m_time_stamp != m_time_stamp )
00167 return false;
00168
00169 if(m_next == 0)
00170 return false;
00171
00172 assert(m_next>0 || !"Cell::remove(): no data?");
00173
00174 bool found = false;
00175 size_t target = 0;
00176 for(size_t i=0;i<m_next;++i)
00177 {
00178 if( m_data[i] == tmp )
00179 {
00180 found = true;
00181 target = i;
00182 break;
00183 }
00184 }
00185 if(found)
00186 {
00187 m_data[target] = m_data[m_next-1];
00188 m_data[m_next-1] = 0;
00189 --m_next;
00190 return true;
00191 }
00192 return false;
00193 }
00194
00195 bool empty() const
00196 {
00197 assert(m_owner);
00198 return (m_time_stamp != m_owner->m_time_stamp);
00199 }
00200
00201 size_t size() const
00202 {
00203 if(empty())
00204 return 0;
00205
00206 return m_next;
00207 }
00208 };
00209
00210 public:
00211
00212 typedef Cell cell_type;
00213 typedef typename std::vector< cell_type > cell_storage;
00214
00215 protected:
00216
00217 size_t m_time_stamp;
00218 real_type m_delta;
00219 hash_function_type m_hash_function;
00220 cell_storage m_cells;
00221
00222 public:
00223
00224 typedef typename cell_storage::iterator cell_iterator;
00225
00226 cell_iterator begin(){return m_cells.begin();}
00227 cell_iterator end(){return m_cells.end();}
00228
00229 public:
00230
00231 Grid( )
00232 : m_time_stamp(0)
00233 , m_delta(5.0)
00234 {
00235 resize(1000);
00236 }
00237
00238 Grid( size_t size )
00239 : m_time_stamp(0)
00240 , m_delta(5.0)
00241 {
00242 resize( size );
00243 }
00244
00245 public:
00246
00247 void resize( size_t size )
00248 {
00249 m_hash_function.resize(size);
00250 m_cells.resize( m_hash_function.size(), Cell(this) );
00251 }
00252
00253 size_t size( ) const { return m_hash_function.size(); }
00254
00273 void set_spacing( real_type delta )
00274 {
00275 assert( delta > 0 );
00276 m_delta = delta;
00277 }
00278
00279 real_type get_spacing( ) const { return m_delta; }
00280
00290 triplet_type get_triplet( point_type const & point )const
00291 {
00292 typedef typename triplet_type::value_type value_type;
00293 assert( m_delta > 0 );
00294 return triplet_type(
00295 static_cast<value_type>( std::floor( point(0) / m_delta ) ),
00296 static_cast<value_type>( std::floor( point(1) / m_delta ) ),
00297 static_cast<value_type>( std::floor( point(2) / m_delta ) )
00298 );
00299 }
00300
00304 cell_type & get_cell(point_type const & p)
00305 {
00306 triplet_type triplet = get_triplet(p);
00307 size_t hash_key = m_hash_function( triplet(0), triplet(1), triplet(2) );
00308 return m_cells[ hash_key ];
00309 }
00310
00314 cell_type & get_cell(triplet_type const & triplet)
00315 {
00316 size_t hash_key = m_hash_function( triplet(0), triplet(1), triplet(2) );
00317 return m_cells[ hash_key ];
00318 }
00319
00320 void clear()
00321 {
00322 ++m_time_stamp;
00323 }
00324 };
00325
00326 }
00327
00328 }
00329
00330
00331 #endif