00001 #ifndef OPENTISSUE_COLLISION_SPATIAL_HASHING_SPATIAL_HASHING_QUERY_H
00002 #define OPENTISSUE_COLLISION_SPATIAL_HASHING_SPATIAL_HASHING_QUERY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <boost/cast.hpp>
00013
00014 #include <list>
00015 #include <map>
00016 #include <cassert>
00017
00018 namespace OpenTissue
00019 {
00020 namespace spatial_hashing
00021 {
00022
00087 template<typename child_type,typename hash_grid, typename collision_policy>
00088 class Query
00089 : public hash_grid
00090 , public collision_policy
00091 {
00092 protected:
00093
00094 typedef typename hash_grid::cell_type cell_type;
00095 typedef typename hash_grid::triplet_type triplet_type;
00096 typedef typename hash_grid::point_type point_type;
00097 typedef typename hash_grid::real_type real_type;
00098 typedef typename hash_grid::data_type data_type;
00099 typedef typename std::list<cell_type*> cell_queue;
00100 typedef typename std::map<data_type*,bool> data_tag_queue;
00101
00102 protected:
00103
00104 size_t m_query_stamp;
00105
00106 public:
00107
00115 struct no_collisions_tag {};
00116
00125 struct all_tag {};
00126
00127 public:
00128
00141 template< typename data_iterator, typename query_iterator,typename result_container,typename report_type >
00142 void operator()(
00143 data_iterator d0
00144 , data_iterator d1
00145 , query_iterator q0
00146 , query_iterator q1
00147 , result_container & results
00148 , report_type const & type
00149 )
00150 {
00151 child_type & self = static_cast<child_type &>(*this);
00152 this->clear();
00153 self.first_pass(d0,d1);
00154
00155 reset(results);
00156 init_query();
00157 for(query_iterator q=q0;q!=q1;++q)
00158 query( (*q), results, type);
00159 }
00160
00174 template< typename query_iterator,typename result_container,typename report_type >
00175 void operator()(
00176 query_iterator q0
00177 , query_iterator q1
00178 , result_container & results
00179 , report_type const & type
00180 )
00181 {
00182 reset(results);
00183 init_query();
00184 for(query_iterator q=q0;q!=q1;++q)
00185 query( (*q), results, type );
00186 }
00187
00200 template< typename query_type,typename result_container,typename report_type >
00201 void operator()(
00202 query_type const & q
00203 , result_container & results
00204 , report_type const & type
00205 )
00206 {
00207 reset(results);
00208 query(q, results, type );
00209 }
00210
00228 template< typename data_iterator >
00229 void init_data( data_iterator d0, data_iterator d1 )
00230 {
00231 child_type & self = static_cast<child_type &>(*this);
00232 this->clear();
00233 self.first_pass(d0,d1);
00234 init_query();
00235 }
00236
00244 template< typename data_iterator >
00245 void add_data( data_iterator d0, data_iterator d1 )
00246 {
00247 child_type & self = static_cast<child_type &>(*this);
00248 self.first_pass(d0,d1);
00249 }
00250
00251 template< typename data_iterator >
00252 void remove_data( data_iterator d0, data_iterator d1 )
00253 {
00254 child_type & self = static_cast<child_type &>(*this);
00255 self.remove_data(d0,d1);
00256 }
00257
00272 template<typename iterator >
00273 void auto_init_settings ( iterator begin, iterator end)
00274 {
00275 using std::max;
00276 using std::min;
00277
00278 size_t cnt = 0;
00279 point_type mean;
00280 mean.clear();
00281
00282 for(iterator cur = begin;cur!=end;++cur,++cnt)
00283 {
00284 point_type d = max_coord(*cur) - min_coord(*cur);
00285 mean += d;
00286 }
00287 mean /= boost::numeric_cast<typename point_type::value_type>( cnt );
00288 size_t size = cnt;
00289 real_type spacing = max (mean(0), max( mean(1), mean(2) ) );
00290 this->resize( size );
00291 set_spacing( spacing );
00292 }
00293
00294 protected:
00295
00296 void init_query()
00297 {
00298 m_query_stamp = 0;
00299 typename hash_grid::cell_iterator Cbegin = this->begin();
00300 typename hash_grid::cell_iterator Cend = this->end();
00301 for( typename hash_grid::cell_iterator cell = Cbegin;cell!=Cend;++cell)
00302 cell->m_query_stamp = m_query_stamp;
00303 }
00304
00305 template< typename query_type,typename result_container >
00306 void query(query_type const & query, result_container & results, no_collisions_tag )
00307 {
00308 assert(m_query_stamp<~0u || !"Query stamp overflow, did you forget to map data?");
00309
00310 ++m_query_stamp;
00311
00312 point_type min_corner = min_coord(query);
00313 point_type max_corner = max_coord(query);
00314 triplet_type m = get_triplet(min_corner);
00315 triplet_type M = get_triplet(max_corner);
00316
00317 assert( m(0) <= M(0) || !"Minimum was larger than maximum");
00318 assert( m(1) <= M(1) || !"Minimum was larger than maximum");
00319 assert( m(2) <= M(2) || !"Minimum was larger than maximum");
00320
00321 triplet_type triplet(m);
00322 data_tag_queue data_tag;
00323 for ( triplet(0)= m(0) ; triplet(0) <= M(0); ++triplet(0) )
00324 for ( triplet(1)= m(1) ; triplet(1) <= M(1); ++triplet(1) )
00325 for ( triplet(2)= m(2) ; triplet(2) <= M(2); ++triplet(2) )
00326 {
00327 cell_type & cell = get_cell(triplet);
00328
00329 if(cell.empty())
00330 continue;
00331
00332 if(cell.m_query_stamp==m_query_stamp)
00333 continue;
00334 cell.m_query_stamp=m_query_stamp;
00335
00336 typename cell_type::data_iterator Dbegin = cell.begin();
00337 typename cell_type::data_iterator Dend = cell.end();
00338 for( typename cell_type::data_iterator data = Dbegin;data!=Dend;++data)
00339 {
00340 bool & seen_before = data_tag[ &(*data) ];
00341 if(seen_before)
00342 continue;
00343 seen_before = true;
00344
00345 report( (*data), query, results);
00346 }
00347 }
00348 }
00349
00350 template< typename query_type,typename result_container >
00351 void query(query_type const & query, result_container & results, all_tag )
00352 {
00353 assert(m_query_stamp<~0u || !"Query stamp overflow, did you forget to map data?");
00354
00355 ++m_query_stamp;
00356
00357 point_type min_corner = min_coord(query);
00358 point_type max_corner = max_coord(query);
00359 triplet_type m = get_triplet(min_corner);
00360 triplet_type M = get_triplet(max_corner);
00361
00362 assert( m(0) <= M(0) || !"Minimum was larger than maximum");
00363 assert( m(1) <= M(1) || !"Minimum was larger than maximum");
00364 assert( m(2) <= M(2) || !"Minimum was larger than maximum");
00365
00366 triplet_type triplet(m);
00367 for ( triplet(0)= m(0) ; triplet(0) <= M(0); ++triplet(0) )
00368 for ( triplet(1)= m(1) ; triplet(1) <= M(1); ++triplet(1) )
00369 for ( triplet(2)= m(2) ; triplet(2) <= M(2); ++triplet(2) )
00370 {
00371 cell_type & cell = get_cell(triplet);
00372
00373 if(cell.empty())
00374 continue;
00375
00376 if(cell.m_query_stamp==m_query_stamp)
00377 continue;
00378 cell.m_query_stamp=m_query_stamp;
00379
00380 typename cell_type::data_iterator Dbegin = cell.begin();
00381 typename cell_type::data_iterator Dend = cell.end();
00382 for(typename cell_type::data_iterator data = Dbegin;data!=Dend;++data)
00383 report( (*data), query, results);
00384 }
00385 }
00386
00387 };
00388
00389 }
00390 }
00391
00392
00393 #endif