Use cache if available for NEAREST neighbor search

This commit is contained in:
Clement Jamin 2017-06-21 00:34:02 +02:00
parent 1cfab77634
commit 0de1362e09
1 changed files with 110 additions and 42 deletions

View File

@ -17,6 +17,7 @@
//
//
// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>)
// Clement Jamin (clement.jamin.pro@gmail.com)
#ifndef CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH
#define CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH
@ -29,6 +30,8 @@
#include <CGAL/Euclidean_distance.h>
#include <CGAL/tuple.h>
#include <CGAL/internal/Search_helpers.h>
namespace CGAL {
template <class SearchTraits,
@ -76,7 +79,8 @@ namespace CGAL {
Distance_vector dists;
Distance Orthogonal_distance_instance;
Distance orthogonal_distance_instance;
internal::Distance_helper<Distance> 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<int>(std::distance(ccci(q), ccci(q,0)));
m_dim = static_cast<int>(std::distance(ccci(q), ccci(q,0)));
dists.resize(dim);
for(int i=0 ; i<dim ; ++i){
dists.resize(m_dim);
for(int i=0 ; i<m_dim ; ++i){
dists[i] = 0;
}
if (search_nearest){
distance_to_root=
Orthogonal_distance_instance.min_distance_to_rectangle(q, tree.bounding_box(),dists);
Node_with_distance *The_Root = new Node_with_distance(tree.root(),
orthogonal_distance_instance.min_distance_to_rectangle(q, m_tree.bounding_box(),dists);
Node_with_distance *The_Root = new Node_with_distance(m_tree.root(),
distance_to_root, dists);
PriorityQueue.push(The_Root);
@ -173,9 +182,9 @@ namespace CGAL {
}
else{
distance_to_root=
Orthogonal_distance_instance.max_distance_to_rectangle(q,
tree.bounding_box(), dists);
Node_with_distance *The_Root = new Node_with_distance(tree.root(),
orthogonal_distance_instance.max_distance_to_rectangle(q,
m_tree.bounding_box(), dists);
Node_with_distance *The_Root = new Node_with_distance(m_tree.root(),
distance_to_root, dists);
PriorityQueue.push(The_Root);
@ -257,6 +266,87 @@ namespace CGAL {
delete The_item_top;
}
template<bool use_cache>
bool search_in_leaf(typename Tree::Leaf_node_const_handle node);
// With cache
template<>
bool search_in_leaf<true>(typename Tree::Leaf_node_const_handle node)
{
typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end();
typename std::vector<FT>::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<false>(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<typename Tree::Leaf_node_const_handle>(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<internal::Has_points_cache<Tree, internal::has_Enable_points_cache<Tree>::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);