From 0de1362e093cfa3ab7c924bea5dee50e88d5b01d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Jun 2017 00:34:02 +0200 Subject: [PATCH] Use cache if available for NEAREST neighbor search --- .../Orthogonal_incremental_neighbor_search.h | 152 +++++++++++++----- 1 file changed, 110 insertions(+), 42 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 13eca80ece1..13f65c8aa5a 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -17,6 +17,7 @@ // // // Author(s) : Hans Tangelder () +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH #define CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH @@ -29,6 +30,8 @@ #include #include +#include + namespace CGAL { template m_distance_helper; FT multiplication_factor; @@ -88,6 +92,8 @@ namespace CGAL { FT rd; + int m_dim; + Tree const& m_tree; class Priority_higher { public: @@ -143,27 +149,30 @@ namespace CGAL { FT Eps=FT(0.0), bool search_nearest=true) : traits(tree.traits()),number_of_neighbours_computed(0), number_of_internal_nodes_visited(0), number_of_leaf_nodes_visited(0), number_of_items_visited(0), - Orthogonal_distance_instance(tr), multiplication_factor(Orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)), + orthogonal_distance_instance(tr), + m_distance_helper(orthogonal_distance_instance), + multiplication_factor(orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)), query_point(q), search_nearest_neighbour(search_nearest), PriorityQueue(Priority_higher(search_nearest)), Item_PriorityQueue(Distance_smaller(search_nearest)), - reference_count(1) + reference_count(1), + m_tree(tree) { - if (tree.empty()) return; + if (m_tree.empty()) return; typename SearchTraits::Construct_cartesian_const_iterator_d ccci=traits.construct_cartesian_const_iterator_d_object(); - int dim = static_cast(std::distance(ccci(q), ccci(q,0))); + m_dim = static_cast(std::distance(ccci(q), ccci(q,0))); - dists.resize(dim); - for(int i=0 ; i + bool search_in_leaf(typename Tree::Leaf_node_const_handle node); + + // With cache + template<> + bool search_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + + for (; it_node_point != node->end(); ++it_node_point) + { + number_of_items_visited++; + FT distance_to_query_point = + m_distance_helper.transformed_distance_from_coordinates( + query_point, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + + Point_with_transformed_distance *NN_Candidate = + new Point_with_transformed_distance(*it_node_point, distance_to_query_point); + Item_PriorityQueue.push(NN_Candidate); + + cache_point_begin += m_dim; + } + // old top of PriorityQueue has been processed, + // hence update rd + + bool next_neighbour_found; + if (!(PriorityQueue.empty())) + { + rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); + next_neighbour_found = + (multiplication_factor*rd > + Item_PriorityQueue.top()->second); + } + else // priority queue empty => last neighbour found + { + next_neighbour_found = true; + } + + number_of_neighbours_computed++; + return next_neighbour_found; + } + + // Without cache + template<> + bool search_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + + for (; it_node_point != node->end(); ++it_node_point) + { + number_of_items_visited++; + FT distance_to_query_point= + orthogonal_distance_instance.transformed_distance(query_point, *it_node_point); + + Point_with_transformed_distance *NN_Candidate = + new Point_with_transformed_distance(*it_node_point, distance_to_query_point); + Item_PriorityQueue.push(NN_Candidate); + } + // old top of PriorityQueue has been processed, + // hence update rd + + bool next_neighbour_found; + if (!(PriorityQueue.empty())) + { + rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); + next_neighbour_found = + (multiplication_factor*rd > + Item_PriorityQueue.top()->second); + } + else // priority queue empty => last neighbour found + { + next_neighbour_found=true; + } + + number_of_neighbours_computed++; + return next_neighbour_found; + } + + void Compute_the_next_nearest_neighbour() { @@ -287,7 +377,7 @@ namespace CGAL { FT diff2 = val - node->lower_high_value(); if (diff1 + diff2 < FT(0.0)) { new_rd= - Orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); + orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); CGAL_assertion(new_rd >= copy_rd); dists[new_cut_dim] = diff1; @@ -299,7 +389,7 @@ namespace CGAL { } else { // compute new distance - new_rd=Orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); + new_rd=orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); CGAL_assertion(new_rd >= copy_rd); dists[new_cut_dim] = diff2; Node_with_distance *Lower_Child = @@ -313,31 +403,9 @@ namespace CGAL { typename Tree::Leaf_node_const_handle node = static_cast(N); number_of_leaf_nodes_visited++; - if (node->size() > 0) { - for (typename Tree::iterator it=node->begin(); it != node->end(); it++) { - number_of_items_visited++; - FT distance_to_query_point= - Orthogonal_distance_instance.transformed_distance(query_point,*it); - Point_with_transformed_distance *NN_Candidate= - new Point_with_transformed_distance(*it,distance_to_query_point); - Item_PriorityQueue.push(NN_Candidate); - } - // old top of PriorityQueue has been processed, - // hence update rd - - if (!(PriorityQueue.empty())) { - rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); - next_neighbour_found = - (multiplication_factor*rd > - Item_PriorityQueue.top()->second); - } - else // priority queue empty => last neighbour found - { - next_neighbour_found=true; - } - - number_of_neighbours_computed++; - } + if (node->size() > 0) + next_neighbour_found = + search_in_leaf::type::value>::value>(node); } // next_neighbour_found or priority queue is empty // in the latter case also the item priority quee is empty } @@ -374,7 +442,7 @@ namespace CGAL { if (diff1 + diff2 < FT(0.0)) { diff1 = val - node->upper_high_value(); new_rd= - Orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); + orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); Node_with_distance *Lower_Child = new Node_with_distance(node->lower(), copy_rd, dists); PriorityQueue.push(Lower_Child); @@ -385,7 +453,7 @@ namespace CGAL { } else { // compute new distance diff2 = val - node->lower_low_value(); - new_rd=Orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); + new_rd=orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); Node_with_distance *Upper_Child = new Node_with_distance(node->upper(), copy_rd, dists); PriorityQueue.push(Upper_Child); @@ -402,7 +470,7 @@ namespace CGAL { for (typename Tree::iterator it=node->begin(); it != node->end(); it++) { number_of_items_visited++; FT distance_to_query_point= - Orthogonal_distance_instance.transformed_distance(query_point,*it); + orthogonal_distance_instance.transformed_distance(query_point,*it); Point_with_transformed_distance *NN_Candidate= new Point_with_transformed_distance(*it,distance_to_query_point); Item_PriorityQueue.push(NN_Candidate);