Go to the documentation of this file.00001 #ifndef OPENTISSUE_COLLISION_BVH_BVH_BOUNDING_VOLUME_HIERARCHY_H
00002 #define OPENTISSUE_COLLISION_BVH_BVH_BOUNDING_VOLUME_HIERARCHY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/collision/bvh/bvh_bv_node.h>
00013 #include <OpenTissue/collision/bvh/bvh_annotated_bv_node.h>
00014 #include <OpenTissue/collision/bvh/bvh_bv_traversal_iterator.h>
00015 #include <OpenTissue/utility/utility_empty_traits.h>
00016
00017 #include <boost/weak_ptr.hpp>
00018 #include <boost/shared_ptr.hpp>
00019 #include <boost/iterator/indirect_iterator.hpp>
00020
00021 #include <list>
00022 #include <cassert>
00023
00024 namespace OpenTissue
00025 {
00026 namespace bvh
00027 {
00028
00032 template <typename V, typename G, typename T = OpenTissue::utility::EmptyTraits>
00033 class BoundingVolumeHierarchy
00034 {
00035 public:
00036
00037 typedef BoundingVolumeHierarchy<V,G,T> bvh_type;
00038 typedef V volume_type;
00039 typedef G geometry_type;
00040 typedef BV<bvh_type, T> bv_type;
00041 typedef AnnotatedBV<bvh_type, T> annotated_bv_type;
00042 typedef BVTraversalIterator<bvh_type> bv_traversal_iterator;
00043
00044 typedef boost::shared_ptr<bvh_type> bvh_ptr;
00045 typedef boost::weak_ptr<bvh_type> bvh_weak_ptr;
00046 typedef boost::shared_ptr<bvh_type const> bvh_const_ptr;
00047 typedef boost::weak_ptr<bvh_type const> bvh_const_weak_ptr;
00048 typedef boost::shared_ptr<volume_type> volume_ptr;
00049 typedef boost::shared_ptr<geometry_type> geometry_ptr;
00050 typedef boost::shared_ptr<bv_type> bv_ptr;
00051 typedef boost::weak_ptr<bv_type> bv_weak_ptr;
00052 typedef boost::shared_ptr<bv_type const> bv_const_ptr;
00053 typedef boost::weak_ptr<bv_type const> bv_const_weak_ptr;
00054 typedef boost::shared_ptr<annotated_bv_type> annotated_bv_ptr;
00055
00056 typedef typename std::list<bv_ptr> bv_ptr_container;
00057 typedef typename bv_ptr_container::iterator bv_ptr_iterator;
00058 typedef typename bv_ptr_container::const_iterator bv_const_ptr_iterator;
00059
00060 typedef typename std::list<annotated_bv_ptr> annotated_bv_ptr_container;
00061 typedef typename annotated_bv_ptr_container::iterator annotated_bv_ptr_iterator;
00062 typedef typename annotated_bv_ptr_container::const_iterator annotated_bv_const_ptr_iterator;
00063
00064 typedef boost::indirect_iterator<bv_ptr_iterator,bv_type> bv_iterator;
00065 typedef boost::indirect_iterator<bv_const_ptr_iterator,bv_type> bv_const_iterator;
00066 typedef boost::indirect_iterator<bv_ptr_iterator,annotated_bv_type> bv_annotated_iterator;
00067 typedef boost::indirect_iterator<bv_const_ptr_iterator,annotated_bv_type> annotated_bv_const_iterator;
00068
00069 typedef typename std::list<geometry_type> geometry_container;
00070 typedef typename geometry_container::iterator geometry_iterator;
00071 typedef typename geometry_container::const_iterator geometry_const_iterator;
00072
00073 protected:
00074
00075 bv_ptr m_root;
00076 size_t m_subtrees;
00077 size_t m_size;
00078
00079 protected:
00080
00081 bvh_ptr m_this;
00082
00083 struct null_deleter
00084 {
00085 void operator()(void const *) const {}
00086 };
00087
00088 bvh_ptr get_this()
00089 {
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 if(m_this.get() != this)
00106 {
00107
00108
00109 m_this.reset( this , null_deleter());
00110 }
00111 return m_this;
00112 }
00113
00114 public:
00115
00116 bv_traversal_iterator begin() { return bv_traversal_iterator(m_root); }
00117 bv_traversal_iterator end() { return bv_traversal_iterator( bv_ptr() ); }
00118
00119 const bv_traversal_iterator begin() const
00120 {
00121 bv_ptr root = boost::const_pointer_cast<bv_type>(m_root);
00122 return bv_traversal_iterator(root);
00123 }
00124
00125 const bv_traversal_iterator end() const { return bv_traversal_iterator( bv_ptr() ); }
00126
00127 public:
00128
00129 BoundingVolumeHierarchy()
00130 : m_root()
00131 , m_subtrees(0)
00132 , m_size(0)
00133 {}
00134
00135 BoundingVolumeHierarchy( BoundingVolumeHierarchy const & other )
00136 : m_root( other.m_root )
00137 , m_subtrees( other.m_subtrees )
00138 , m_size( other.m_size )
00139 {}
00140
00141 ~BoundingVolumeHierarchy(){ clear(); }
00142
00143 public:
00144
00145 bv_ptr root() { return m_root; }
00146 bv_const_ptr root() const { return m_root; }
00147 size_t size() const { return m_size; }
00148 bool const empty() const { return (m_size==0); }
00149
00158 bv_ptr insert( bv_ptr_container const & children, bool const annotated = false )
00159 {
00160
00161 bv_const_ptr_iterator begin = children.begin();
00162 bv_const_ptr_iterator end = children.end();
00163 for (bv_const_ptr_iterator child = begin; child != end; ++child )
00164 {
00165 if ( !( (*child)->m_parent.expired() ) )
00166 return bv_ptr();
00167 if ( (*child)->m_owner.lock() != this->get_this() )
00168 return bv_ptr();
00169 }
00170
00171
00172
00173 bv_ptr bv ;
00174 if ( annotated )
00175 {
00176 bv = bv_ptr( new annotated_bv_type() );
00177 }
00178 else
00179 {
00180 bv = bv_ptr( new bv_type() );
00181 }
00182 bv->m_owner = this->get_this();
00183 bv->m_parent.reset();
00184
00185 for (bv_const_ptr_iterator child = begin; child != end;++child )
00186 {
00187 (*child)->m_parent = bv;
00188 bv_ptr ptr( *child );
00189 bv->m_children.push_back( ptr );
00190 }
00191
00192
00193 m_subtrees -= children.size() - 1;
00194 if ( m_subtrees == 1 )
00195 m_root = bv;
00196 else
00197 m_root.reset();
00198 ++m_size;
00199 return bv;
00200 }
00201
00210 bv_ptr insert( bv_ptr parent, bool const annotated = false )
00211 {
00212
00213 if ( m_root && !parent )
00214 {
00215 return bv_ptr();
00216 }
00217
00218 else if ( !m_root && !parent )
00219 {
00220 if ( annotated )
00221 {
00222 m_root = bv_ptr( new annotated_bv_type() );
00223 }
00224 else
00225 {
00226 m_root = bv_ptr( new bv_type() );
00227 }
00228 m_root->m_owner = this->get_this();
00229 ++m_size;
00230 return m_root;
00231 }
00232
00233
00234 else if ( m_root && parent && parent->m_owner.lock() == this->get_this() )
00235 {
00236 bv_ptr bv;
00237 if ( annotated )
00238 {
00239 bv = bv_ptr( new annotated_bv_type() );
00240 }
00241 else
00242 {
00243 bv = bv_ptr( new bv_type() );
00244 }
00245 bv->m_owner = this->get_this();
00246 bv->m_parent = parent;
00247 parent->m_children.push_back( bv );
00248 ++m_size;
00249 return bv;
00250 }
00251 return bv_ptr();
00252 }
00253
00260 bool const remove( bv_ptr bv )
00261 {
00262 assert( bv || !"BoundingVolumeHierarchy::remove(): bv pointer was null");
00263 assert( bv->m_owner.lock() == this->get_this() || !"BoundingVolumeHierarchy::remove(): bv belongs to another BVH");
00264 if ( bv->children() )
00265 return false;
00266 bv_ptr parent = bv->m_parent.lock();
00267 if ( parent )
00268 {
00269 parent->m_children.remove( bv );
00270 bv->m_parent.reset();
00271 }
00272 bv->m_owner.reset();
00273 if ( bv == m_root )
00274 m_root.reset();
00275 bv.reset();
00276 --m_size;
00277 return true;
00278 }
00279
00280 void clear()
00281 {
00282 m_root.reset();
00283 m_subtrees = 0;
00284 m_size = 0;
00285 }
00286
00287 };
00288
00289 }
00290 }
00291
00292
00293 #endif