Go to the documentation of this file.00001
00002 #ifndef imesh_kd_tree_txx_
00003 #define imesh_kd_tree_txx_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "imesh_kd_tree.h"
00016
00017 #include <vcl_algorithm.h>
00018 #include <vcl_limits.h>
00019 #include <vcl_cassert.h>
00020
00021
00022
00023
00024
00025
00026 template <class F>
00027 unsigned int
00028 imesh_closest_index(const vgl_point_3d<double>& query,
00029 const vcl_auto_ptr<imesh_kd_tree_node>& kd_root,
00030 F dist,
00031 vcl_vector<imesh_kd_tree_queue_entry>* dists = 0)
00032 {
00033
00034 vcl_vector<imesh_kd_tree_queue_entry> leaf_queue, internal_queue;
00035 imesh_kd_tree_traverse(query,kd_root,leaf_queue,internal_queue);
00036 assert(!leaf_queue.empty());
00037 vcl_make_heap( leaf_queue.begin(), leaf_queue.end() );
00038 vcl_make_heap( internal_queue.begin(), internal_queue.end() );
00039
00040 double closest_dist2 = vcl_numeric_limits<double>::infinity();
00041 unsigned int closest_ind = 0;
00042
00043 if (dists)
00044 dists->clear();
00045
00046
00047
00048 vcl_pop_heap( leaf_queue.begin(), leaf_queue.end() );
00049 vcl_vector<imesh_kd_tree_queue_entry>::iterator back = leaf_queue.end();
00050 --back;
00051 bool break_early = true;
00052 while (back->val_ < closest_dist2)
00053 {
00054 double new_dist2 = dist(query,back->node_->index_);
00055 new_dist2 *= new_dist2;
00056 if (dists)
00057 dists->push_back(imesh_kd_tree_queue_entry(new_dist2,back->node_));
00058 if (new_dist2 < closest_dist2) {
00059 closest_dist2 = new_dist2;
00060 closest_ind = back->node_->index_;
00061 }
00062 if (leaf_queue.begin() == back) {
00063 break_early = false;
00064 break;
00065 }
00066 vcl_pop_heap( leaf_queue.begin(), back );
00067 --back;
00068 }
00069
00070 if (dists && break_early) {
00071 ++back;
00072 vcl_vector<imesh_kd_tree_queue_entry>::iterator itr = leaf_queue.begin();
00073 for (; itr != back; ++itr)
00074 dists->push_back(*itr);
00075 }
00076 assert(!dists || dists->size() == leaf_queue.size());
00077
00078
00079
00080 vcl_pop_heap( internal_queue.begin(), internal_queue.end() );
00081 while (!internal_queue.empty() && internal_queue.back().val_ < closest_dist2)
00082 {
00083 imesh_kd_tree_node* current = internal_queue.back().node_;
00084 internal_queue.pop_back();
00085
00086 if (current->is_leaf())
00087 {
00088 double new_dist2 = dist(query,current->index_);
00089 new_dist2 *= new_dist2;
00090 if (dists)
00091 dists->push_back(imesh_kd_tree_queue_entry(new_dist2,current));
00092 if (new_dist2 < closest_dist2) {
00093 closest_dist2 = new_dist2;
00094 closest_ind = current->index_;
00095 }
00096 }
00097 else
00098 {
00099 double left_dist2 = imesh_min_sq_dist(query,current->left_->inner_box_);
00100 if (left_dist2 < closest_dist2) {
00101 internal_queue.push_back(imesh_kd_tree_queue_entry(left_dist2,
00102 current->left_.get()));
00103 vcl_push_heap(internal_queue.begin(), internal_queue.end());
00104 }
00105 else if (dists)
00106 dists->push_back(imesh_kd_tree_queue_entry(left_dist2,current->left_.get()));
00107
00108 double right_dist2 = imesh_min_sq_dist(query,current->right_->inner_box_);
00109 if (right_dist2 < closest_dist2) {
00110 internal_queue.push_back(imesh_kd_tree_queue_entry(right_dist2,
00111 current->right_.get()));
00112 vcl_push_heap(internal_queue.begin(), internal_queue.end());
00113 }
00114 else if (dists)
00115 dists->push_back(imesh_kd_tree_queue_entry(right_dist2,current->right_.get()));
00116 }
00117
00118 if (!internal_queue.empty())
00119 vcl_pop_heap( internal_queue.begin(), internal_queue.end() );
00120 }
00121 if (dists) {
00122 vcl_vector<imesh_kd_tree_queue_entry>::iterator itr = internal_queue.begin();
00123 for (; itr != internal_queue.end(); ++itr)
00124 dists->push_back(*itr);
00125 }
00126
00127 return closest_ind;
00128 }
00129
00130
00131 #endif // imesh_kd_tree_txx_