Go to the documentation of this file.00001 #ifndef OPENTISSUE_COLLISION_SDF_SDF_TOP_DOWN_POLICY_H
00002 #define OPENTISSUE_COLLISION_SDF_SDF_TOP_DOWN_POLICY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/geometry/geometry_compute_smallest_sphere.h>
00013
00014 namespace OpenTissue
00015 {
00016
00017 namespace sdf
00018 {
00019
00024 template<typename bvh_type>
00025 class TopDownPolicy
00026 {
00027 public:
00028
00029 typedef TopDownPolicy<bvh_type> top_down_type;
00030 typedef typename bvh_type::bv_ptr bv_ptr;
00031 typedef typename bvh_type::annotated_bv_type annotated_bv_type;
00032 typedef typename bvh_type::annotated_bv_ptr annotated_bv_ptr;
00033 typedef typename bvh_type::volume_type volume_type;
00034 typedef typename bvh_type::geometry_type geometry_type;
00035 typedef typename std::vector<geometry_type> geometry_container;
00036
00037 typedef typename volume_type::vector3_type vector3_type;
00038
00039 protected:
00040
00041 geometry_container m_geometry;
00042
00043 public:
00044
00045 class partition_type
00046 {
00047 public:
00048
00049 friend class TopDownPolicy<bvh_type>;
00050
00051 public:
00052
00053 typedef std::vector<partition_type> partition_container;
00054 typedef typename partition_container::iterator partition_iterator;
00055
00056 protected:
00057
00058 partition_container m_sub_partitions;
00059 top_down_type * m_owner;
00060 unsigned int m_left;
00061 unsigned int m_right;
00062
00063 public:
00064
00065 partition_type()
00066 : m_owner(0)
00067 , m_left(0)
00068 , m_right(0)
00069 {}
00070
00071 partition_type(top_down_type * owner,unsigned int left,unsigned int right)
00072 : m_owner(owner)
00073 , m_left(left)
00074 , m_right(right)
00075 {}
00076
00077 bool annotated() const{ return size()==1; }
00078 unsigned int size() const{ return ( m_right-m_left+1); }
00079 bool empty() { return (size()==0); }
00080 void split() { m_owner->split((*this)); }
00081 partition_iterator sub_partition_begin() { return m_sub_partitions.begin(); }
00082 partition_iterator sub_partition_end() { return m_sub_partitions.end(); }
00083 void fit(bv_ptr bv) { m_owner->fit(bv,(*this)); }
00084 };
00085
00086 public:
00087 typedef typename partition_type::partition_container partition_container;
00088 typedef typename partition_type::partition_iterator partition_iterator;
00089 public:
00090
00091 partition_type all() { return partition_type(this,0, static_cast<unsigned int>(m_geometry.size()-1)); }
00092
00093 template<typename iterator>
00094 void init(iterator begin, iterator end)
00095 {
00096 unsigned int N = std::distance(begin,end);
00097 m_geometry.resize(N);
00098 unsigned int idx = 0;
00099 for(iterator geometry = begin;geometry!=end;++geometry,++idx)
00100 m_geometry[idx] = &(*geometry);
00101
00102
00103 }
00104
00105 protected:
00106
00107 void split(partition_type & partition)
00108 {
00109 using std::min;
00110
00111
00112 unsigned int total_size = partition.size();
00113 if(total_size<=8u)
00114 {
00115 unsigned int cnt = min(total_size,8u);
00116 unsigned int subset_size = total_size/cnt;
00117 assert(subset_size==1);
00118 partition.m_sub_partitions.resize(cnt);
00119 for(unsigned int i=0;i<cnt;++i)
00120 {
00121 unsigned int left = i*subset_size;
00122 unsigned int right = (i==cnt-1)?total_size - 1:(i+1)*subset_size - 1;
00123 left += + partition.m_left;
00124 right += + partition.m_left;
00125 partition.m_sub_partitions[i] = partition_type(this,left,right);
00126 assert(!partition.m_sub_partitions[i].empty());
00127 }
00128 return;
00129 }
00130
00131 vector3_type center = vector3_type(0,0,0);
00132 for(unsigned int local_idx=0;local_idx<total_size;++local_idx)
00133 {
00134 unsigned int global_idx = local_idx + partition.m_left;
00135 center += (*m_geometry[global_idx]);
00136 }
00137 center /= total_size;
00138
00139 geometry_container tmp[8];
00140 for(unsigned int local_idx=0;local_idx<total_size;++local_idx)
00141 {
00142 unsigned int global_idx = local_idx + partition.m_left;
00143 vector3_type diff = (*m_geometry[global_idx]) - center;
00144 int mask = ((diff(2)>=0)<<2) | ((diff(1)>=0)<<1) | (diff(0)>=0);
00145 assert(mask>=0);
00146 assert(mask<8);
00147 tmp[mask].push_back(m_geometry[global_idx]);
00148 }
00149
00150 unsigned int i=0;
00151 unsigned int cnt = 0;
00152 for(i=0;i<8u;++i)
00153 {
00154 if(tmp[i].size()>0)
00155 ++cnt;
00156 };
00157 assert(cnt>1);
00158 partition.m_sub_partitions.resize(cnt);
00159 unsigned int global_left_idx = partition.m_left;
00160 unsigned int j=0;
00161 for(i=0;i<8u;++i)
00162 {
00163 if(tmp[i].empty())
00164 continue;
00165 unsigned int size = static_cast<unsigned int>( tmp[i].size() );
00166 for(unsigned int local_idx=0;local_idx<size;++local_idx)
00167 {
00168 unsigned int global_idx = local_idx + global_left_idx;
00169 m_geometry[global_idx] = tmp[i][local_idx];
00170 }
00171 unsigned int global_right_idx = global_left_idx + size - 1;
00172 partition.m_sub_partitions[j] = partition_type(this, global_left_idx, global_right_idx);
00173 ++j;
00174 global_left_idx = global_right_idx + 1;
00175 }
00176 assert(global_left_idx==partition.m_right+1);
00177 }
00178
00179 void fit(bv_ptr bv,partition_type & partition)
00180 {
00181 if(partition.annotated())
00182 {
00183 annotated_bv_ptr A = boost::static_pointer_cast<annotated_bv_type>(bv);
00184
00185 A->insert( m_geometry[partition.m_left] );
00186 }
00187 vector3_type * points = new vector3_type[partition.size()];
00188 for(unsigned int i=0;i<partition.size();++i)
00189 points[i] = *(m_geometry[i + partition.m_left]);
00190 OpenTissue::geometry::compute_smallest_sphere( points, points + partition.size(), bv->volume() );
00191 delete [] points;
00192 }
00193 };
00194
00195
00196 }
00197
00198 }
00199
00200
00201 #endif