Allow to enable/disable cache of points

This commit is contained in:
Clement Jamin 2017-05-19 16:06:02 +02:00
parent efce74597e
commit e9c35e3861
3 changed files with 151 additions and 78 deletions

View File

@ -41,7 +41,11 @@
namespace CGAL {
//template <class SearchTraits, class Splitter_=Median_of_rectangle<SearchTraits>, class UseExtendedNode = Tag_true >
template <class SearchTraits, class Splitter_=Sliding_midpoint<SearchTraits>, class UseExtendedNode = Tag_true >
template <
class SearchTraits,
class Splitter_=Sliding_midpoint<SearchTraits>,
class UseExtendedNode = Tag_true,
class EnablePointsCache = Tag_false>
class Kd_tree {
public:
@ -51,11 +55,11 @@ public:
typedef typename Splitter::Container Point_container;
typedef typename SearchTraits::FT FT;
typedef Kd_tree_node<SearchTraits, Splitter, UseExtendedNode > Node;
typedef Kd_tree_leaf_node<SearchTraits, Splitter, UseExtendedNode > Leaf_node;
typedef Kd_tree_internal_node<SearchTraits, Splitter, UseExtendedNode > Internal_node;
typedef Kd_tree<SearchTraits, Splitter> Tree;
typedef Kd_tree<SearchTraits, Splitter,UseExtendedNode> Self;
typedef Kd_tree_node<SearchTraits, Splitter, UseExtendedNode, EnablePointsCache> Node;
typedef Kd_tree_leaf_node<SearchTraits, Splitter, UseExtendedNode, EnablePointsCache> Leaf_node;
typedef Kd_tree_internal_node<SearchTraits, Splitter, UseExtendedNode, EnablePointsCache> Internal_node;
typedef Kd_tree<SearchTraits, Splitter, UseExtendedNode, EnablePointsCache> Tree;
typedef Kd_tree<SearchTraits, Splitter, UseExtendedNode, EnablePointsCache> Self;
typedef Node* Node_handle;
typedef const Node* Node_const_handle;
@ -73,6 +77,8 @@ public:
typedef typename internal::Get_dimension_tag<SearchTraits>::Dimension D;
typedef EnablePointsCache Enable_points_cache;
private:
SearchTraits traits_;
Splitter split;
@ -282,13 +288,18 @@ public:
//Reorder vector for spatial locality
std::vector<Point_d> ptstmp;
ptstmp.resize(pts.size());
points_cache.reserve(dim * pts.size());
for (std::size_t i = 0; i < pts.size(); ++i){
for (std::size_t i = 0; i < pts.size(); ++i)
ptstmp[i] = *data[i];
// Cache?
if (Enable_points_cache::value)
{
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits_.construct_cartesian_const_iterator_d_object();
points_cache.insert(points_cache.end(), construct_it(ptstmp[i]), construct_it(ptstmp[i], 0));
points_cache.reserve(dim * pts.size());
for (std::size_t i = 0; i < pts.size(); ++i)
points_cache.insert(points_cache.end(), construct_it(ptstmp[i]), construct_it(ptstmp[i], 0));
}
for(std::size_t i = 0; i < leaf_nodes.size(); ++i){
std::ptrdiff_t tmp = leaf_nodes[i].begin() - pts.begin();
leaf_nodes[i].data = ptstmp.begin() + tmp;

View File

@ -28,27 +28,27 @@
namespace CGAL {
template <class SearchTraits, class Splitter, class UseExtendedNode>
template <class SearchTraits, class Splitter, class UseExtendedNode, class EnablePointsCache>
class Kd_tree;
template < class TreeTraits, class Splitter, class UseExtendedNode >
template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache >
class Kd_tree_node {
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_const_handle Node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Internal_node_handle Internal_node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Internal_node_const_handle Internal_node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Leaf_node_handle Leaf_node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Leaf_node_const_handle Leaf_node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Node_const_handle Node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Internal_node_handle Internal_node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Internal_node_const_handle Internal_node_const_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Leaf_node_handle Leaf_node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Leaf_node_const_handle Leaf_node_const_handle;
typedef typename TreeTraits::Point_d Point_d;
typedef typename TreeTraits::FT FT;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Point_d_iterator Point_d_iterator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::iterator iterator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::D D;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Point_d_iterator Point_d_iterator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::iterator iterator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::D D;
bool leaf;
@ -264,13 +264,13 @@ namespace CGAL {
};
template < class TreeTraits, class Splitter, class UseExtendedNode >
class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{
template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache >
class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache >{
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::iterator iterator;
typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode> Base;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::iterator iterator;
typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base;
typedef typename TreeTraits::Point_d Point_d;
private:
@ -329,18 +329,18 @@ namespace CGAL {
template < class TreeTraits, class Splitter, class UseExtendedNode>
class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{
template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache>
class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache >{
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode>;
friend class Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>;
typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode> Base;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Node_const_handle Node_const_handle;
typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Node_const_handle Node_const_handle;
typedef typename TreeTraits::FT FT;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode>::D D;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,UseExtendedNode,EnablePointsCache>::D D;
private:
@ -477,18 +477,19 @@ namespace CGAL {
}
};//internal node
template < class TreeTraits, class Splitter>
class Kd_tree_internal_node<TreeTraits,Splitter,Tag_false> : public Kd_tree_node< TreeTraits, Splitter, Tag_false >{
template < class TreeTraits, class Splitter, class EnablePointsCache>
class Kd_tree_internal_node<TreeTraits,Splitter,Tag_false,EnablePointsCache>
: public Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache >
{
friend class Kd_tree<TreeTraits,Splitter,Tag_false,EnablePointsCache>;
friend class Kd_tree<TreeTraits,Splitter,Tag_false>;
typedef Kd_tree_node< TreeTraits, Splitter, Tag_false> Base;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::Node_const_handle Node_const_handle;
typedef Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache> Base;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false,EnablePointsCache>::Node_handle Node_handle;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false,EnablePointsCache>::Node_const_handle Node_const_handle;
typedef typename TreeTraits::FT FT;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false>::D D;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false,EnablePointsCache>::Separator Separator;
typedef typename Kd_tree<TreeTraits,Splitter,Tag_false,EnablePointsCache>::D D;
private:

View File

@ -24,6 +24,8 @@
#include <CGAL/internal/K_neighbor_search.h>
#include <CGAL/Has_member.h>
#include <boost/mpl/has_xxx.hpp>
namespace CGAL {
template <class SearchTraits,
@ -47,6 +49,7 @@ private:
CGAL_GENERATE_MEMBER_DETECTOR(transformed_distance_from_coordinates);
CGAL_GENERATE_MEMBER_DETECTOR(interruptable_transformed_distance);
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false)
// If transformed_distance_from_coordinates does not exist in `Distance`
template <bool has_transformed_distance_from_coordinates = has_transformed_distance_from_coordinates<Distance>::value>
@ -71,6 +74,7 @@ private:
return this->distance_instance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end);
}
// *** Version with cache ***
// If interruptable_transformed_distance does not exist in `Distance`
template <bool has_interruptable_distance_computation = has_interruptable_transformed_distance<Distance>::value>
FT
@ -97,6 +101,30 @@ private:
q, it_coord_begin, it_coord_end, stop_if_geq_to_this);
}
// *** Version without cache ***
// If interruptable_transformed_distance does not exist in `Distance`
template <bool has_interruptable_distance_computation = has_interruptable_transformed_distance<Distance>::value>
FT
interruptable_transformed_distance(
const typename Base::Query_item& q,
Point const& p,
FT)
{
return this->distance_instance.transformed_distance(q, p);
}
// ... or if it exists
template <>
FT
interruptable_transformed_distance<true>(
const typename Base::Query_item& q,
Point const& p,
FT stop_if_geq_to_this)
{
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object();
return this->distance_instance.interruptable_transformed_distance(
q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this);
}
public:
Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q,
@ -124,14 +152,76 @@ public:
compute_furthest_neighbors_orthogonally(tree.root(), distance_to_root);
}
if (sorted) this->queue.sort();
}
private:
template<bool use_cache = (has_Enable_points_cache<Tree>::value && Tree::Enable_points_cache::value)>
void search_in_leaf(typename Tree::Leaf_node_const_handle node);
// With cache
template<>
void 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 (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point)
{
this->number_of_items_visited++;
FT distance_to_query_object =
transformed_distance_from_coordinates(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim);
this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object));
cache_point_begin += m_dim;
}
FT worst_dist = this->queue.top().second;
for (; it_node_point != it_node_point_end; ++it_node_point)
{
this->number_of_items_visited++;
FT distance_to_query_object =
interruptable_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist);
if (distance_to_query_object < worst_dist)
{
this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object));
worst_dist = this->queue.top().second;
}
cache_point_begin += m_dim;
}
}
// Without cache
template<>
void 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 (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point)
{
this->number_of_items_visited++;
FT distance_to_query_object =
this->distance_instance.transformed_distance(this->query_object, *it_node_point);
this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object));
}
FT worst_dist = this->queue.top().second;
for (; it_node_point != it_node_point_end; ++it_node_point)
{
this->number_of_items_visited++;
FT distance_to_query_object =
interruptable_transformed_distance(this->query_object, *it_node_point, worst_dist);
if (distance_to_query_object < worst_dist)
{
this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object));
worst_dist = this->queue.top().second;
}
}
}
void compute_nearest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd)
{
if (N->is_leaf())
@ -141,36 +231,7 @@ private:
static_cast<typename Tree::Leaf_node_const_handle>(N);
this->number_of_leaf_nodes_visited++;
if (node->size() > 0)
{
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 (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point)
{
this->number_of_items_visited++;
FT distance_to_query_object =
transformed_distance_from_coordinates(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim);
this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object));
cache_point_begin += m_dim;
}
FT worst_dist = this->queue.top().second;
for (; it_node_point != it_node_point_end; ++it_node_point)
{
this->number_of_items_visited++;
FT distance_to_query_object =
interruptable_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist);
if (distance_to_query_object < worst_dist)
{
this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object));
worst_dist = this->queue.top().second;
}
cache_point_begin += m_dim;
}
}
search_in_leaf(node);
}
else
{