• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

/home/hauberg/Dokumenter/Capture/humim-tracker-0.1/src/OpenTissue/OpenTissue/collision/bvh/bottom_up_constructor/bvh_graph.h

Go to the documentation of this file.
00001 #ifndef OPENTISSUE_COLLISION_BVH_BOTTOM_UP_CONSTRUCTOR_BVH_GRAPH_H
00002 #define OPENTISSUE_COLLISION_BVH_BOTTOM_UP_CONSTRUCTOR_BVH_GRAPH_H
00003 //
00004 // OpenTissue Template Library
00005 // - A generic toolbox for physics-based modeling and simulation.
00006 // Copyright (C) 2008 Department of Computer Science, University of Copenhagen.
00007 //
00008 // OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php
00009 //
00010 #include <OpenTissue/configuration.h>
00011 
00012 #include <OpenTissue/collision/bvh/bottom_up_constructor/bvh_graph_node.h>
00013 #include <OpenTissue/collision/bvh/bottom_up_constructor/bvh_graph_edge.h>
00014 
00015 #include <boost/shared_ptr.hpp>
00016 #include <boost/iterator/indirect_iterator.hpp>
00017 
00018 #include <cmath>       //Needed for fabs()
00019 #include <list>        //Needed for graph data structure: edges, nodes and volumes
00020 #include <iostream>    //Needed for debug output. NOTE: we should consider implementing a logging fascility!
00021 
00022 namespace OpenTissue
00023 {
00024   namespace bvh
00025   {
00026 
00031     template <typename bvh_type>
00032     class BVHGraph
00033     {
00034     public:
00035 
00036       //--- Conenience stuff for better readability
00037       typedef BVHGraph<bvh_type>                     graph_type;
00038       typedef BVHGraphNode<bvh_type>                 node_type;
00039       typedef BVHGraphEdge<bvh_type>                 edge_type;
00040       //typedef node_type *                            node_ptr_type;
00041       //typedef edge_type *                            edge_ptr_type;
00042       typedef boost::shared_ptr<node_type>           node_ptr_type;
00043       typedef boost::shared_ptr<edge_type>           edge_ptr_type;
00044       typedef boost::shared_ptr<node_type const>     const_node_ptr_type;
00045       typedef boost::shared_ptr<edge_type const>     const_edge_ptr_type;
00046       typedef typename bvh_type::geometry_container  geometry_container;
00047       typedef typename bvh_type::geometry_type       geometry_type;
00048       typedef typename bvh_type::volume_type         volume_type;
00049       typedef typename std::list<volume_type>        volume_container;
00050       typedef float                                  real_type;
00051 
00052     public:
00053 
00054       typedef typename std::list< edge_ptr_type >                           edge_ptr_container;
00055       typedef typename edge_ptr_container::iterator                         edge_ptr_iterator;
00056       typedef typename edge_ptr_container::const_iterator                   const_edge_ptr_iterator;
00057       typedef boost::indirect_iterator<edge_ptr_iterator,edge_type>         edge_iterator;
00058       typedef boost::indirect_iterator<const_edge_ptr_iterator,edge_type>   const_edge_iterator;
00059 
00060       edge_iterator       edge_begin()       { return edge_iterator(m_edges.begin());       }
00061       edge_iterator       edge_end()         { return edge_iterator(m_edges.end());         }
00062       const_edge_iterator edge_begin() const { return const_edge_iterator(m_edges.begin()); }
00063       const_edge_iterator edge_end()   const { return const_edge_iterator(m_edges.end());   }
00064 
00065       edge_ptr_iterator       edge_ptr_begin()       { return m_edges.begin();       }
00066       edge_ptr_iterator       edge_ptr_end()         { return m_edges.end();         }
00067       const_edge_ptr_iterator edge_ptr_begin() const { return m_edges.begin();       }
00068       const_edge_ptr_iterator edge_ptr_end()   const { return m_edges.end();         }
00069 
00070       typedef typename std::list< node_ptr_type >                           node_ptr_container;
00071       typedef typename node_ptr_container::iterator                         node_ptr_iterator;
00072       typedef typename node_ptr_container::const_iterator                   const_node_ptr_iterator;
00073       typedef boost::indirect_iterator<node_ptr_iterator,node_type>         node_iterator;
00074       typedef boost::indirect_iterator<const_node_ptr_iterator,node_type>   const_node_iterator;
00075 
00076       node_iterator node_begin()             { return node_iterator(m_nodes.begin());       }
00077       node_iterator node_end()               { return node_iterator(m_nodes.end());         }
00078       const_node_iterator node_begin() const { return const_node_iterator(m_nodes.begin()); }
00079       const_node_iterator node_end()   const { return const_node_iterator(m_nodes.end());   }
00080 
00081       node_ptr_iterator node_ptr_begin()             { return m_nodes.begin();       }
00082       node_ptr_iterator node_ptr_end()               { return m_nodes.end();         }
00083       const_node_ptr_iterator node_ptr_begin() const { return m_nodes.begin();       }
00084       const_node_ptr_iterator node_ptr_end()   const { return m_nodes.end();         }
00085 
00086     public: // TODO should be protected. However we got a little problem with priority bottom up policy
00087 
00088       edge_ptr_container  m_edges;    
00089 
00090     protected:
00091       node_ptr_container  m_nodes;    
00092 
00093     public:
00094 
00095       BVHGraph(){}
00096 
00097       ~BVHGraph() { clear(); }
00098 
00099     public:
00100 
00106       std::size_t size_edges() const {return m_edges.size();}
00107 
00113       std::size_t size_nodes()const{return m_nodes.size();}
00114 
00122       node_ptr_type insert(geometry_type const & g){ return insert(volume_type(),g); }
00123 
00131       node_ptr_type insert(volume_type const & volume)
00132       {
00133         geometry_container G;
00134         return insert(volume,G);
00135       }
00136 
00145       node_ptr_type insert(volume_type const & volume,geometry_type const & g)
00146       {
00147         geometry_container G;
00148         G.push_back(g);
00149         return insert(volume,G);
00150       }
00151 
00160       node_ptr_type insert(volume_type const & volume,geometry_container & geometry)
00161       {
00162         node_ptr_type node( new node_type() );
00163         node->m_volume = volume;
00164         if(!geometry.empty())
00165         {
00166           //--- KE 13-10-2004: Something wrong copy does not work???
00167           //std::copy(geometry.begin(),geometry.end(),node->m_coverage.begin());
00168           node->m_coverage.insert(node->m_coverage.end(),geometry.begin(),geometry.end());
00169         }
00170         m_nodes.push_back(node);
00171         return node;
00172       }
00173 
00186       edge_ptr_type insert(node_ptr_type A,node_ptr_type B)
00187       {
00188         assert(A!=B);
00189         //--- Test if edge already exist
00190         edge_ptr_iterator e    = A->edge_ptr_begin();
00191         edge_ptr_iterator end  = A->edge_ptr_end();
00192         for(;e!=end;++e)
00193         {
00194           if(( (*e)->A()==A && (*e)->B()==B)||( (*e)->A()==B && (*e)->B()==A))
00195             return edge_ptr_type(*e);
00196         }
00197         edge_ptr_type new_edge(new edge_type());
00198         new_edge->m_A = A ;
00199         A->m_edges.push_back(new_edge);
00200         new_edge->m_B = B;
00201         B->m_edges.push_back(new_edge);
00202         m_edges.push_back(new_edge);
00203         return new_edge;
00204       }
00205 
00210       void clear()
00211       {
00212         m_nodes.clear();
00213         m_edges.clear();
00214       }
00215 
00224       node_ptr_type collapse(edge_ptr_type edge)
00225       {
00226         node_ptr_type C( new node_type() );
00227         node_ptr_type A = edge->A();
00228         node_ptr_type B = edge->B();
00229         //--- Move all edges to new node C
00230         C->m_edges.splice(C->m_edges.end(),A->m_edges);
00231         C->m_edges.splice(C->m_edges.end(),B->m_edges);
00232         assert(A->m_edges.empty());
00233         assert(B->m_edges.empty());
00234         //--- Re-assign node pointers going to A or B
00235         {
00236           edge_iterator e    = C->edge_begin();
00237           edge_iterator end  = C->edge_end();
00238           for(; e != end; ++e)
00239           {
00240             if(e->A() == A)
00241               e->A() = C;
00242             if(e->B() == A)
00243               e->B() = C;
00244             if(e->A() == B)
00245               e->A() = C;
00246             if(e->B()== B)
00247               e->B() = C;
00248           }
00249         }
00250         //--- The move might have caused some inconsistency, so
00251         //--- we need to clean up things, removing self-loops and
00252         //--- multiple defined edges.
00253 
00254         for(edge_ptr_iterator e = C->edge_ptr_begin(); e != C->edge_ptr_end(); )
00255         {
00256           if( (*e)->A() == (*e)->B() )//--- self loop test
00257           {
00258             edge_ptr_type self_loop( *e ); 
00259             remove(self_loop);
00260             e = C->edge_ptr_begin();//--- deletion have invalidated iterator...this is a simple workaround
00261           }
00262           else
00263             ++e;
00264         }
00265 
00266         for(edge_ptr_iterator i=C->edge_ptr_begin();i!=C->edge_ptr_end();++i)
00267         {
00268           edge_ptr_iterator j = i;
00269           ++j;
00270           for(;j!=C->edge_ptr_end();)
00271           {
00272             edge_ptr_iterator k = j;
00273             ++j;
00274             if(
00275               ((*k)->A()==(*i)->A() && (*k)->B()==(*i)->B())
00276               ||
00277               ((*k)->A()==(*i)->B() && (*k)->B()==(*i)->A())
00278               )//--- Redundant edge test
00279             {
00280               edge_ptr_type redundant( *k );
00281               remove(redundant);
00282             }
00283           }
00284         }
00285         //--- Take care of coverage geometry if any...
00286         //C->m_coverage.insert(C->m_coverage.end(),A->m_coverage.begin(),A->m_coverage.end());
00287         //A->m_coverage.clear();
00288         //C->m_coverage.insert(C->m_coverage.end(),B->m_coverage.begin(),B->m_coverage.end());
00289         //B->m_coverage.clear();
00290         C->m_coverage.splice(C->m_coverage.end(),A->m_coverage);
00291         C->m_coverage.splice(C->m_coverage.end(),B->m_coverage);
00292 
00293         //---  Initialize internal data in the new node
00294         C->m_subtree_size = A->m_subtree_size + B->m_subtree_size;
00295         if(!A->size_sub_nodes())
00296           C->m_sub_nodes.push_back(A);
00297         else
00298         {
00299           C->m_sub_nodes.splice(C->m_sub_nodes.end(),A->m_sub_nodes);
00300           remove(A);
00301         }
00302         if(!B->size_sub_nodes())
00303           C->m_sub_nodes.push_back(B);
00304         else
00305         {
00306           C->m_sub_nodes.splice(C->m_sub_nodes.end(),B->m_sub_nodes);
00307           remove(B);
00308         }
00309         C->m_height = C->max_sub_node_height();
00310         m_nodes.push_back(C);
00311         return C;
00312       }
00313 
00314 
00315 
00322       void remove_sub_nodes(node_ptr_type node)
00323       {
00324         if(!node->size_sub_nodes())
00325           return;
00326 
00327         node_ptr_iterator sub_node = node->sub_node_ptr_begin();
00328         node_ptr_iterator end      = node->sub_node_ptr_end();
00329         for(;sub_node!=end;++sub_node)
00330         {
00331           node_ptr_type target( *sub_node );
00332           m_nodes.remove( target );
00333         }
00334         node->m_sub_nodes.clear();
00335       }
00336 
00337     protected:
00338 
00345       void remove(edge_ptr_type edge)
00346       {
00347         assert(edge);
00348         assert(edge->A());
00349         assert(edge->B());
00350 
00351         edge->m_A->m_edges.remove(edge);
00352         edge->m_B->m_edges.remove(edge);
00353 
00354         m_edges.remove(edge);//--- KE 11-10-2004: Preformance could be improved by using iterators
00355 
00356         edge.reset();
00357       }
00358 
00365       void remove(node_ptr_type node)
00366       {
00367         assert(!node->size_sub_nodes() || !"BVHGraph::remove(node_ptr_type): Node has sub nodes!");
00368         assert(!node->size_edges()     || !"BVHGraph::remove(node_ptr_type): Node got incident edges");
00369         m_nodes.remove(node);
00370 
00371         node.reset();
00372       }
00373 
00374     };
00375 
00376   } // namespace bvh
00377 
00378 } // namespace OpenTissue
00379 
00380 // OPENTISSUE_COLLISION_BVH_BOTTOM_UP_CONSTRUCTOR_BVH_GRAPH_H
00381 #endif

Generated on Thu Dec 1 2011 12:50:43 for HUMIM Tracker by  doxygen 1.7.1