contrib/brl/bbas/imesh/algo/imesh_kd_tree.h
Go to the documentation of this file.
00001 // This is brl/bbas/imesh/algo/imesh_kd_tree.h
00002 #ifndef imesh_kd_tree_h_
00003 #define imesh_kd_tree_h_
00004 //:
00005 // \file
00006 // \brief A KD-Tree for mesh faces
00007 // \author Matt Leotta (mleotta@lems.brown.edu)
00008 // \date June 2, 2008
00009 
00010 #include <imesh/imesh_mesh.h>
00011 #include <vgl/vgl_box_3d.h>
00012 #include <vgl/vgl_point_3d.h>
00013 
00014 
00015 //: The minimum square distance between \a p and any point in \a b
00016 double imesh_min_sq_dist(const vgl_point_3d<double>& p,
00017                          const vgl_box_3d<double>& b);
00018 
00019 //: The maximum square distance between \a p and any point in \a b
00020 double imesh_max_sq_dist(const vgl_point_3d<double>& p,
00021                          const vgl_box_3d<double>& b);
00022 
00023 
00024 //: A node in the KD-Tree
00025 struct imesh_kd_tree_node
00026 {
00027   //: Constructor for internal node
00028   imesh_kd_tree_node( const vgl_box_3d<double>& outer_box,
00029                       const vgl_box_3d<double>& inner_box,
00030                       vcl_auto_ptr<imesh_kd_tree_node> left,
00031                       vcl_auto_ptr<imesh_kd_tree_node> right)
00032     : outer_box_(outer_box), inner_box_(inner_box),
00033       index_(static_cast<unsigned int>(-1)),
00034       left_(left), right_(right) {}
00035 
00036   //: Constructor for leaf node
00037   imesh_kd_tree_node( const vgl_box_3d<double>& outer_box,
00038                       const vgl_box_3d<double>& inner_box,
00039                       unsigned int index )
00040     : outer_box_(outer_box), inner_box_(inner_box),
00041       index_(index), left_(0), right_(0) {}
00042 
00043   //: Copy Constructor (makes a deep copy recursively)
00044   imesh_kd_tree_node(const imesh_kd_tree_node& other)
00045     : outer_box_(other.outer_box_),
00046       inner_box_(other.inner_box_),
00047       index_(other.index_),
00048       left_(other.left_.get() ? new imesh_kd_tree_node(*other.left_) : 0),
00049       right_(other.right_.get() ? new imesh_kd_tree_node(*other.right_) : 0) {}
00050 
00051 
00052   //: Return true if this node is a leaf node
00053   bool is_leaf() const {return !left_.get() && !right_.get();}
00054 
00055   //: Outer bounding box
00056   vgl_box_3d<double> outer_box_;
00057   //: Inner bounding box
00058   vgl_box_3d<double> inner_box_;
00059   //: index into original data vector (at leaf nodes)
00060   //  Additional indices are assigned to internal nodes
00061   unsigned int index_;
00062   //: Left child
00063   vcl_auto_ptr<imesh_kd_tree_node> left_;
00064   //: Right child
00065   vcl_auto_ptr<imesh_kd_tree_node> right_;
00066 };
00067 
00068 
00069 //: Construct a kd-tree (in 3d) of axis aligned boxes
00070 vcl_auto_ptr<imesh_kd_tree_node>
00071 imesh_build_kd_tree(const vcl_vector<vgl_box_3d<double> >& boxes);
00072 
00073 
00074 //: construct a kd-tree of mesh faces
00075 vcl_auto_ptr<imesh_kd_tree_node>
00076 imesh_build_kd_tree(const imesh_vertex_array<3>& verts,
00077                     const imesh_face_array_base& faces);
00078 
00079 
00080 //: construct a kd-tree of mesh faces
00081 inline vcl_auto_ptr<imesh_kd_tree_node>
00082 imesh_build_kd_tree(const imesh_mesh& mesh)
00083 {
00084   return imesh_build_kd_tree(mesh.vertices<3>(), mesh.faces());
00085 }
00086 
00087 
00088 //: A class used for sorting a queue of tree nodes by an assigned value
00089 //  In the most common case this value is a distance measure
00090 class imesh_kd_tree_queue_entry
00091 {
00092  public:
00093   //: Constructor
00094   imesh_kd_tree_queue_entry() {}
00095   //: Constructor
00096   imesh_kd_tree_queue_entry( double val, imesh_kd_tree_node* node )
00097     : val_(val), node_(node) {}
00098 
00099   //: Used in sorting by distance
00100   bool operator< ( const imesh_kd_tree_queue_entry& right ) const
00101   { return right.val_ < this->val_; }
00102 
00103   //: The value
00104   double val_;
00105   //: pointer to the node
00106   imesh_kd_tree_node* node_;
00107 };
00108 
00109 //: compute the closest point on the mesh using the kd-tree
00110 //  \returns the index of the closest triangle
00111 //  \param dists (if specified) returns a vector of all explored nodes
00112 //        and the closest square distance found so far
00113 unsigned int
00114 imesh_kd_tree_closest_point(const vgl_point_3d<double>& query,
00115                             const imesh_mesh& mesh,
00116                             const vcl_auto_ptr<imesh_kd_tree_node>& root,
00117                             vgl_point_3d<double>& cp,
00118                             vcl_vector<imesh_kd_tree_queue_entry>* dists = 0);
00119 
00120 
00121 //: Traverse the tree looking for leaf nodes that contain the query
00122 //  Returns a vector of leaf nodes paired with min square distance to the inner box
00123 //  Also returns a vector of the unexplored internal node-distance^2 pairs
00124 //  Resulting vectors are unsorted
00125 void imesh_kd_tree_traverse(const vgl_point_3d<double>& query,
00126                             const vcl_auto_ptr<imesh_kd_tree_node>& root,
00127                             vcl_vector<imesh_kd_tree_queue_entry>& internal,
00128                             vcl_vector<imesh_kd_tree_queue_entry>& leaf);
00129 
00130 
00131 #endif // imesh_kd_tree_h_