mirror of https://github.com/CGAL/cgal
Merge branch 'Faster_dd_spatial_searching-cjamin-old' into Faster_dd_spatial_searching-cjamin
This commit is contained in:
commit
f0a89af33b
|
|
@ -35,6 +35,7 @@
|
|||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/CC_safe_handle.h>
|
||||
#include <CGAL/Time_stamper.h>
|
||||
#include <CGAL/Has_member.h>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
|
|
@ -87,24 +88,6 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
#define CGAL_GENERATE_MEMBER_DETECTOR(X) \
|
||||
template<typename T> class has_##X { \
|
||||
struct Fallback { int X; }; \
|
||||
struct Derived : T, Fallback { }; \
|
||||
\
|
||||
template<typename U, U> struct Check; \
|
||||
\
|
||||
typedef char ArrayOfOne[1]; \
|
||||
typedef char ArrayOfTwo[2]; \
|
||||
\
|
||||
template<typename U> static ArrayOfOne & func( \
|
||||
Check<int Fallback::*, &U::X> *); \
|
||||
template<typename U> static ArrayOfTwo & func(...); \
|
||||
public: \
|
||||
typedef has_##X type; \
|
||||
enum { value = sizeof(func<Derived>(0)) == 2 }; \
|
||||
} // semicolon is after the macro call
|
||||
|
||||
#define CGAL_INIT_COMPACT_CONTAINER_BLOCK_SIZE 14
|
||||
#define CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE 16
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <CGAL/memory.h>
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/CC_safe_handle.h>
|
||||
#include <CGAL/Has_member.h>
|
||||
|
||||
#include <tbb/tbb.h>
|
||||
|
||||
|
|
@ -40,24 +41,6 @@
|
|||
|
||||
namespace CGAL {
|
||||
|
||||
#define CGAL_GENERATE_MEMBER_DETECTOR(X) \
|
||||
template<typename T> class has_##X { \
|
||||
struct Fallback { int X; }; \
|
||||
struct Derived : T, Fallback { }; \
|
||||
\
|
||||
template<typename U, U> struct Check; \
|
||||
\
|
||||
typedef char ArrayOfOne[1]; \
|
||||
typedef char ArrayOfTwo[2]; \
|
||||
\
|
||||
template<typename U> static ArrayOfOne & func( \
|
||||
Check<int Fallback::*, &U::X> *); \
|
||||
template<typename U> static ArrayOfTwo & func(...); \
|
||||
public: \
|
||||
typedef has_##X type; \
|
||||
enum { value = sizeof(func<Derived>(0)) == 2 }; \
|
||||
} // semicolon is after the macro call
|
||||
|
||||
#define CGAL_INIT_CONCURRENT_COMPACT_CONTAINER_BLOCK_SIZE 14
|
||||
#define CGAL_INCREMENT_CONCURRENT_COMPACT_CONTAINER_BLOCK_SIZE 16
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2017 Inria (France)
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 3 of the License,
|
||||
// or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Author(s) : Clement Jamin
|
||||
|
||||
#ifndef CGAL_HAS_MEMBER_H
|
||||
#define CGAL_HAS_MEMBER_H
|
||||
|
||||
// Macro used to check if a type T has a member named `X`
|
||||
// It generates a class has_X<T> where has_X<T>::value is a boolean
|
||||
// See example in Concurrent_compact_container.h
|
||||
// Note: this macro is similar to BOOST_TTI_HAS_MEMBER_FUNCTION
|
||||
// which was introduced in Boost 1.54 (CGAL supports version 1.48 and
|
||||
// later at this time - June 2017)
|
||||
#define CGAL_GENERATE_MEMBER_DETECTOR(X) \
|
||||
template<typename T> class has_##X { \
|
||||
struct Fallback { int X; }; \
|
||||
struct Derived : T, Fallback { }; \
|
||||
\
|
||||
template<typename U, U> struct Check; \
|
||||
\
|
||||
typedef char ArrayOfOne[1]; \
|
||||
typedef char ArrayOfTwo[2]; \
|
||||
\
|
||||
template<typename U> static ArrayOfOne & func( \
|
||||
Check<int Fallback::*, &U::X> *); \
|
||||
template<typename U> static ArrayOfTwo & func(...); \
|
||||
public: \
|
||||
typedef has_##X type; \
|
||||
enum { value = sizeof(func<Derived>(0)) == 2 }; \
|
||||
} // semicolon is after the macro call
|
||||
|
||||
#endif // CGAL_HAS_MEMBER_H
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
//
|
||||
//
|
||||
// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>)
|
||||
// Clement Jamin (clement.jamin.pro@gmail.com)
|
||||
|
||||
|
||||
#ifndef CGAL_EUCLIDEAN_DISTANCE_H
|
||||
|
|
@ -60,61 +61,114 @@ namespace CGAL {
|
|||
// default constructor
|
||||
Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {}
|
||||
|
||||
|
||||
inline FT transformed_distance(const Query_item& q, const Point_d& p) const {
|
||||
return transformed_distance(q,p, D());
|
||||
inline FT transformed_distance(const Query_item& q, const Point_d& p) const
|
||||
{
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d p_begin = construct_it(p), p_end = construct_it(p, 0);
|
||||
return transformed_distance_from_coordinates(q, p_begin, p_end);
|
||||
}
|
||||
|
||||
//Dynamic version for runtime dimension
|
||||
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dynamic_dimension_tag) const {
|
||||
FT distance = FT(0);
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),
|
||||
qe = construct_it(q,1), pit = construct_it(p);
|
||||
for(; qit != qe; qit++, pit++){
|
||||
distance += ((*qit)-(*pit))*((*qit)-(*pit));
|
||||
}
|
||||
return distance;
|
||||
template <typename Coord_iterator>
|
||||
inline FT transformed_distance_from_coordinates(const Query_item& q,
|
||||
Coord_iterator it_coord_begin, Coord_iterator it_coord_end) const
|
||||
{
|
||||
return transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end, D());
|
||||
}
|
||||
|
||||
//Generic version for DIM > 3
|
||||
template < int DIM >
|
||||
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<DIM>) const {
|
||||
FT distance = FT(0);
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),
|
||||
qe = construct_it(q,1), pit = construct_it(p);
|
||||
for(; qit != qe; qit++, pit++){
|
||||
distance += ((*qit)-(*pit))*((*qit)-(*pit));
|
||||
// Static dim = 2 loop unrolled
|
||||
template <typename Coord_iterator>
|
||||
inline FT transformed_distance_from_coordinates(const Query_item& q,
|
||||
Coord_iterator it_coord_begin, Coord_iterator /*unused*/,
|
||||
Dimension_tag<2>) const
|
||||
{
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q);
|
||||
FT distance = square(*qit - *it_coord_begin);
|
||||
qit++; it_coord_begin++;
|
||||
distance += square(*qit - *it_coord_begin);
|
||||
return distance;
|
||||
}
|
||||
|
||||
// Static dim = 3 loop unrolled
|
||||
template <typename Coord_iterator>
|
||||
inline FT transformed_distance_from_coordinates(const Query_item& q,
|
||||
Coord_iterator it_coord_begin, Coord_iterator /*unused*/,
|
||||
Dimension_tag<3>) const
|
||||
{
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q);
|
||||
FT distance = square(*qit - *it_coord_begin);
|
||||
qit++; it_coord_begin++;
|
||||
distance += square(*qit - *it_coord_begin);
|
||||
qit++; it_coord_begin++;
|
||||
distance += square(*qit - *it_coord_begin);
|
||||
return distance;
|
||||
}
|
||||
|
||||
// Other cases: static dim > 3 or dynamic dim
|
||||
template <typename Coord_iterator, typename Dim>
|
||||
inline FT transformed_distance_from_coordinates(const Query_item& q,
|
||||
Coord_iterator it_coord_begin, Coord_iterator /*unused*/,
|
||||
Dim) const
|
||||
{
|
||||
FT distance = FT(0);
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q, 1);
|
||||
for (; qit != qe; ++qit, ++it_coord_begin)
|
||||
{
|
||||
FT diff = (*qit) - (*it_coord_begin);
|
||||
distance += diff*diff;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
// During the computation, if the partially-computed distance `pcd` gets greater or equal
|
||||
// to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned
|
||||
template <typename Coord_iterator>
|
||||
inline FT interruptible_transformed_distance(const Query_item& q,
|
||||
Coord_iterator it_coord_begin, Coord_iterator /*unused*/,
|
||||
FT stop_if_geq_to_this) const
|
||||
{
|
||||
FT distance = FT(0);
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q, 1);
|
||||
if (qe - qit >= 6)
|
||||
{
|
||||
// Every 4 coordinates, the current partially-computed distance
|
||||
// is compared to stop_if_geq_to_this
|
||||
// Note: the concept SearchTraits specifies that Cartesian_const_iterator_d
|
||||
// must be a random-access iterator
|
||||
typename SearchTraits::Cartesian_const_iterator_d qe_minus_5 = qe - 5;
|
||||
for (;;)
|
||||
{
|
||||
FT diff = (*qit) - (*it_coord_begin);
|
||||
distance += diff*diff;
|
||||
++qit; ++it_coord_begin;
|
||||
diff = (*qit) - (*it_coord_begin);
|
||||
distance += diff*diff;
|
||||
++qit; ++it_coord_begin;
|
||||
diff = (*qit) - (*it_coord_begin);
|
||||
distance += diff*diff;
|
||||
++qit; ++it_coord_begin;
|
||||
diff = (*qit) - (*it_coord_begin);
|
||||
distance += diff*diff;
|
||||
++qit, ++it_coord_begin;
|
||||
|
||||
if (distance >= stop_if_geq_to_this)
|
||||
return distance;
|
||||
|
||||
if (qit >= qe_minus_5)
|
||||
break;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
for (; qit != qe; ++qit, ++it_coord_begin)
|
||||
{
|
||||
FT diff = (*qit) - (*it_coord_begin);
|
||||
distance += diff*diff;
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
//DIM = 2 loop unrolled
|
||||
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<2> ) const {
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),pit = construct_it(p);
|
||||
FT distance = square(*qit - *pit);
|
||||
qit++;pit++;
|
||||
distance += square(*qit - *pit);
|
||||
return distance;
|
||||
}
|
||||
|
||||
//DIM = 3 loop unrolled
|
||||
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<3> ) const {
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object();
|
||||
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),pit = construct_it(p);
|
||||
FT distance = square(*qit - *pit);
|
||||
qit++;pit++;
|
||||
distance += square(*qit - *pit);
|
||||
qit++;pit++;
|
||||
distance += square(*qit - *pit);
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline FT min_distance_to_rectangle(const Query_item& q,
|
||||
const Kd_tree_rectangle<FT,D>& r) const {
|
||||
FT distance = FT(0);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
// $Id$
|
||||
//
|
||||
// Author(s) : Hans Tangelder (<hanst@cs.uu.nl>),
|
||||
// : Waqar Khan <wkhan@mpi-inf.mpg.de>
|
||||
// : Waqar Khan <wkhan@mpi-inf.mpg.de>,
|
||||
// Clement Jamin (clement.jamin.pro@gmail.com)
|
||||
|
||||
#ifndef CGAL_KD_TREE_H
|
||||
#define CGAL_KD_TREE_H
|
||||
|
|
@ -44,7 +45,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:
|
||||
|
|
@ -54,11 +59,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;
|
||||
|
|
@ -76,6 +81,8 @@ public:
|
|||
|
||||
typedef typename internal::Get_dimension_tag<SearchTraits>::Dimension D;
|
||||
|
||||
typedef EnablePointsCache Enable_points_cache;
|
||||
|
||||
private:
|
||||
SearchTraits traits_;
|
||||
Splitter split;
|
||||
|
|
@ -95,6 +102,10 @@ private:
|
|||
Kd_tree_rectangle<FT,D>* bbox;
|
||||
std::vector<Point_d> pts;
|
||||
|
||||
// Store a contiguous copy of the point coordinates
|
||||
// for faster queries (reduce the number of cache misses)
|
||||
std::vector<FT> points_cache;
|
||||
|
||||
// Instead of storing the points in arrays in the Kd_tree_node
|
||||
// we put all the data in a vector in the Kd_tree.
|
||||
// and we only store an iterator range in the Kd_tree_node.
|
||||
|
|
@ -282,9 +293,18 @@ public:
|
|||
//Reorder vector for spatial locality
|
||||
std::vector<Point_d> ptstmp;
|
||||
ptstmp.resize(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.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;
|
||||
|
|
@ -546,6 +566,13 @@ public:
|
|||
return *bbox;
|
||||
}
|
||||
|
||||
|
||||
typename std::vector<FT>::const_iterator
|
||||
cache_begin() const
|
||||
{
|
||||
return points_cache.begin();
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,27 +31,29 @@
|
|||
|
||||
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 Kd_tree<TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Kdt;
|
||||
|
||||
typedef typename Kdt::Node_handle Node_handle;
|
||||
typedef typename Kdt::Node_const_handle Node_const_handle;
|
||||
typedef typename Kdt::Internal_node_handle Internal_node_handle;
|
||||
typedef typename Kdt::Internal_node_const_handle Internal_node_const_handle;
|
||||
typedef typename Kdt::Leaf_node_handle Leaf_node_handle;
|
||||
typedef typename Kdt::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 Kdt::Separator Separator;
|
||||
typedef typename Kdt::Point_d_iterator Point_d_iterator;
|
||||
typedef typename Kdt::iterator iterator;
|
||||
typedef typename Kdt::D D;
|
||||
|
||||
bool leaf;
|
||||
|
||||
|
|
@ -267,13 +269,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:
|
||||
|
|
@ -332,18 +334,20 @@ 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<TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Kdt;
|
||||
|
||||
typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base;
|
||||
typedef typename Kdt::Node_handle Node_handle;
|
||||
typedef typename Kdt::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 Kdt::Separator Separator;
|
||||
typedef typename Kdt::D D;
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -480,18 +484,21 @@ 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>;
|
||||
|
||||
typedef Kd_tree<TreeTraits, Splitter, Tag_false, EnablePointsCache> Kdt;
|
||||
|
||||
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 Kdt::Node_handle Node_handle;
|
||||
typedef typename Kdt::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 Kdt::Separator Separator;
|
||||
typedef typename Kdt::D D;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -32,6 +33,8 @@
|
|||
#include <CGAL/Euclidean_distance.h>
|
||||
#include <CGAL/tuple.h>
|
||||
|
||||
#include <CGAL/internal/Search_helpers.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <class SearchTraits,
|
||||
|
|
@ -79,7 +82,8 @@ namespace CGAL {
|
|||
|
||||
Distance_vector dists;
|
||||
|
||||
Distance Orthogonal_distance_instance;
|
||||
Distance orthogonal_distance_instance;
|
||||
internal::Distance_helper<Distance> m_distance_helper;
|
||||
|
||||
FT multiplication_factor;
|
||||
|
||||
|
|
@ -91,6 +95,8 @@ namespace CGAL {
|
|||
|
||||
FT rd;
|
||||
|
||||
int m_dim;
|
||||
Tree const& m_tree;
|
||||
|
||||
class Priority_higher {
|
||||
public:
|
||||
|
|
@ -146,27 +152,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);
|
||||
|
||||
|
|
@ -176,9 +185,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);
|
||||
|
||||
|
|
@ -260,6 +269,87 @@ namespace CGAL {
|
|||
delete The_item_top;
|
||||
}
|
||||
|
||||
|
||||
template<bool use_cache>
|
||||
bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest);
|
||||
|
||||
// With cache
|
||||
template<>
|
||||
bool search_in_leaf<true>(typename Tree::Leaf_node_const_handle node, bool search_furthest)
|
||||
{
|
||||
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 = (search_furthest ?
|
||||
multiplication_factor*rd < Item_PriorityQueue.top()->second
|
||||
: 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, bool search_furthest)
|
||||
{
|
||||
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 = (search_furthest ?
|
||||
multiplication_factor*rd < Item_PriorityQueue.top()->second
|
||||
: 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()
|
||||
{
|
||||
|
|
@ -290,7 +380,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;
|
||||
|
|
@ -302,7 +392,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 =
|
||||
|
|
@ -316,31 +406,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, false);
|
||||
} // next_neighbour_found or priority queue is empty
|
||||
// in the latter case also the item priority quee is empty
|
||||
}
|
||||
|
|
@ -377,7 +445,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);
|
||||
|
|
@ -388,7 +456,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);
|
||||
|
|
@ -401,31 +469,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, true);
|
||||
} // next_neighbour_found or priority queue is empty
|
||||
// in the latter case also the item priority quee is empty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Gael Guennebaud (gael.guennebaud@inria.fr), Hans Tangelder (<hanst@cs.uu.nl>)
|
||||
// Author(s) : Gael Guennebaud (gael.guennebaud@inria.fr),
|
||||
// Hans Tangelder (<hanst@cs.uu.nl>),
|
||||
// Clement Jamin (clement.jamin.pro@gmail.com)
|
||||
|
||||
#ifndef CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H
|
||||
#define CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H
|
||||
|
|
@ -25,6 +27,7 @@
|
|||
|
||||
|
||||
#include <CGAL/internal/K_neighbor_search.h>
|
||||
#include <CGAL/internal/Search_helpers.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
@ -32,29 +35,39 @@ template <class SearchTraits,
|
|||
class Distance= typename internal::Spatial_searching_default_distance<SearchTraits>::type,
|
||||
class Splitter= Sliding_midpoint<SearchTraits> ,
|
||||
class Tree= Kd_tree<SearchTraits, Splitter, Tag_true> >
|
||||
class Orthogonal_k_neighbor_search: public internal::K_neighbor_search<SearchTraits,Distance,Splitter,Tree> {
|
||||
typedef internal::K_neighbor_search<SearchTraits,Distance,Splitter,Tree> Base;
|
||||
class Orthogonal_k_neighbor_search: public internal::K_neighbor_search<SearchTraits,Distance,Splitter,Tree>
|
||||
{
|
||||
typedef internal::K_neighbor_search<SearchTraits,Distance,Splitter,Tree> Base;
|
||||
typedef typename Tree::Point_d Point;
|
||||
|
||||
typename SearchTraits::Cartesian_const_iterator_d query_object_it;
|
||||
|
||||
std::vector<typename Base::FT> dists;
|
||||
public:
|
||||
typedef typename Base::FT FT;
|
||||
|
||||
private:
|
||||
typename SearchTraits::Cartesian_const_iterator_d query_object_it;
|
||||
|
||||
internal::Distance_helper<Distance> m_distance_helper;
|
||||
std::vector<FT> dists;
|
||||
int m_dim;
|
||||
Tree const& m_tree;
|
||||
|
||||
public:
|
||||
|
||||
Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q,
|
||||
unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance(),bool sorted=true)
|
||||
: Base(q,k,Eps,Search_nearest,d)
|
||||
: Base(q,k,Eps,Search_nearest,d),
|
||||
m_distance_helper(this->distance_instance),
|
||||
m_tree(tree)
|
||||
{
|
||||
if (tree.empty()) return;
|
||||
|
||||
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=tree.traits().construct_cartesian_const_iterator_d_object();
|
||||
query_object_it = construct_it(this->query_object);
|
||||
|
||||
int dim = static_cast<int>(std::distance(query_object_it, construct_it(this->query_object,0)));
|
||||
m_dim = static_cast<int>(std::distance(query_object_it, construct_it(this->query_object,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;
|
||||
|
||||
FT distance_to_root;
|
||||
|
|
@ -67,75 +80,182 @@ public:
|
|||
compute_furthest_neighbors_orthogonally(tree.root(), distance_to_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (sorted) this->queue.sort();
|
||||
}
|
||||
private:
|
||||
|
||||
template<bool use_cache>
|
||||
void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node);
|
||||
|
||||
// With cache
|
||||
template<>
|
||||
void search_nearest_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());
|
||||
// As long as the queue is not full, the node is just inserted
|
||||
for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point)
|
||||
{
|
||||
this->number_of_items_visited++;
|
||||
|
||||
FT distance_to_query_object =
|
||||
m_distance_helper.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;
|
||||
}
|
||||
// Now that the queue is full, we can gain time by keeping track
|
||||
// of the current worst distance to interrupt the distance computation earlier
|
||||
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 =
|
||||
m_distance_helper.interruptible_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_nearest_in_leaf<false>(typename Tree::Leaf_node_const_handle node)
|
||||
{
|
||||
typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end();
|
||||
// As long as the queue is not full, the node is just inserted
|
||||
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));
|
||||
}
|
||||
// Now that the queue is full, we can gain time by keeping track
|
||||
// of the current worst distance to interrupt the distance computation earlier
|
||||
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 =
|
||||
m_distance_helper.interruptible_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()))
|
||||
{
|
||||
typename Tree::Internal_node_const_handle node =
|
||||
static_cast<typename Tree::Internal_node_const_handle>(N);
|
||||
this->number_of_internal_nodes_visited++;
|
||||
int new_cut_dim=node->cutting_dimension();
|
||||
typename Base::Node_const_handle bestChild, otherChild;
|
||||
FT new_off;
|
||||
FT val = *(query_object_it + new_cut_dim);
|
||||
FT diff1 = val - node->upper_low_value();
|
||||
FT diff2 = val - node->lower_high_value();
|
||||
if ( (diff1 + diff2 < FT(0.0)) )
|
||||
{
|
||||
new_off = diff1;
|
||||
bestChild = node->lower();
|
||||
otherChild = node->upper();
|
||||
}
|
||||
else // compute new distance
|
||||
{
|
||||
new_off= diff2;
|
||||
bestChild = node->upper();
|
||||
otherChild = node->lower();
|
||||
}
|
||||
compute_nearest_neighbors_orthogonally(bestChild, rd);
|
||||
FT dst=dists[new_cut_dim];
|
||||
FT new_rd = this->distance_instance.new_distance(rd,dst,new_off,new_cut_dim);
|
||||
dists[new_cut_dim]=new_off;
|
||||
if (this->branch_nearest(new_rd))
|
||||
{
|
||||
compute_nearest_neighbors_orthogonally(otherChild, new_rd);
|
||||
}
|
||||
dists[new_cut_dim]=dst;
|
||||
}
|
||||
else
|
||||
if (N->is_leaf())
|
||||
{
|
||||
// n is a leaf
|
||||
typename Tree::Leaf_node_const_handle node =
|
||||
static_cast<typename Tree::Leaf_node_const_handle>(N);
|
||||
this->number_of_leaf_nodes_visited++;
|
||||
bool full = this->queue.full();
|
||||
FT worst_dist = this->queue.top().second;
|
||||
if (node->size() > 0)
|
||||
search_nearest_in_leaf<internal::Has_points_cache<Tree, internal::has_Enable_points_cache<Tree>::type::value>::value>(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
typename Tree::Internal_node_const_handle node =
|
||||
static_cast<typename Tree::Internal_node_const_handle>(N);
|
||||
this->number_of_internal_nodes_visited++;
|
||||
int new_cut_dim = node->cutting_dimension();
|
||||
typename Base::Node_const_handle bestChild, otherChild;
|
||||
FT new_off;
|
||||
FT val = *(query_object_it + new_cut_dim);
|
||||
FT diff1 = val - node->upper_low_value();
|
||||
FT diff2 = val - node->lower_high_value();
|
||||
if ((diff1 + diff2 < FT(0.0)))
|
||||
{
|
||||
for (typename Tree::iterator it=node->begin(); it != node->end(); it++)
|
||||
{
|
||||
this->number_of_items_visited++;
|
||||
FT distance_to_query_object=
|
||||
this->distance_instance.transformed_distance(this->query_object,*it);
|
||||
|
||||
if(!full || distance_to_query_object < worst_dist)
|
||||
this->queue.insert(std::make_pair(&(*it),distance_to_query_object));
|
||||
}
|
||||
new_off = diff1;
|
||||
bestChild = node->lower();
|
||||
otherChild = node->upper();
|
||||
}
|
||||
else // compute new distance
|
||||
{
|
||||
new_off = diff2;
|
||||
bestChild = node->upper();
|
||||
otherChild = node->lower();
|
||||
}
|
||||
compute_nearest_neighbors_orthogonally(bestChild, rd);
|
||||
FT dst = dists[new_cut_dim];
|
||||
FT new_rd = this->distance_instance.new_distance(rd, dst, new_off, new_cut_dim);
|
||||
dists[new_cut_dim] = new_off;
|
||||
if (this->branch_nearest(new_rd))
|
||||
{
|
||||
compute_nearest_neighbors_orthogonally(otherChild, new_rd);
|
||||
}
|
||||
dists[new_cut_dim] = dst;
|
||||
}
|
||||
}
|
||||
|
||||
void compute_furthest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd)
|
||||
template<bool use_cache>
|
||||
void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node);
|
||||
|
||||
// With cache
|
||||
template<>
|
||||
void search_furthest_in_leaf<true>(typename Tree::Leaf_node_const_handle node)
|
||||
{
|
||||
if (!(N->is_leaf()))
|
||||
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());
|
||||
// In furthest search mode, the interruptible distance cannot be used to optimize
|
||||
for (; it_node_point != it_node_point_end; ++it_node_point)
|
||||
{
|
||||
this->number_of_items_visited++;
|
||||
|
||||
FT distance_to_query_object =
|
||||
m_distance_helper.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;
|
||||
}
|
||||
}
|
||||
|
||||
// Without cache
|
||||
template<>
|
||||
void search_furthest_in_leaf<false>(typename Tree::Leaf_node_const_handle node)
|
||||
{
|
||||
typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end();
|
||||
// In furthest search mode, the interruptible distance cannot be used to optimize
|
||||
for (; 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));
|
||||
}
|
||||
}
|
||||
|
||||
void compute_furthest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd)
|
||||
{
|
||||
if (N->is_leaf())
|
||||
{
|
||||
// n is a leaf
|
||||
typename Tree::Leaf_node_const_handle node =
|
||||
static_cast<typename Tree::Leaf_node_const_handle>(N);
|
||||
this->number_of_leaf_nodes_visited++;
|
||||
if (node->size() > 0)
|
||||
search_furthest_in_leaf<internal::Has_points_cache<Tree, internal::has_Enable_points_cache<Tree>::type::value>::value>(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
typename Tree::Internal_node_const_handle node =
|
||||
static_cast<typename Tree::Internal_node_const_handle>(N);
|
||||
|
|
@ -170,24 +290,7 @@ private:
|
|||
compute_furthest_neighbors_orthogonally(otherChild, new_rd);
|
||||
dists[new_cut_dim]=dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
// n is a leaf
|
||||
typename Tree::Leaf_node_const_handle node =
|
||||
static_cast<typename Tree::Leaf_node_const_handle>(N);
|
||||
this->number_of_leaf_nodes_visited++;
|
||||
if (node->size() > 0)
|
||||
{
|
||||
for (typename Tree::iterator it=node->begin(); it != node->end(); it++)
|
||||
{
|
||||
this->number_of_items_visited++;
|
||||
FT distance_to_query_object=
|
||||
this->distance_instance.transformed_distance(this->query_object,*it);
|
||||
this->queue.insert(std::make_pair(&(*it),distance_to_query_object));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}; // class
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ public:
|
|||
template <class Point_with_info,class PointPropertyMap,class Base_distance>
|
||||
class Distance_adapter : public Base_distance {
|
||||
PointPropertyMap ppmap;
|
||||
typedef typename Base_distance::FT FT;
|
||||
|
||||
CGAL_static_assertion( ( boost::is_same< boost::lvalue_property_map_tag,
|
||||
typename boost::property_traits<PointPropertyMap>::category
|
||||
|
|
@ -155,7 +154,8 @@ public:
|
|||
):Base_distance(distance),ppmap(ppmap_){}
|
||||
|
||||
using Base_distance::transformed_distance;
|
||||
|
||||
|
||||
typedef typename Base_distance::FT FT;
|
||||
typedef Point_with_info Point_d;
|
||||
typedef typename Base_distance::Query_item Query_item;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright (c) 2002,2011 Utrecht University (The Netherlands).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
// You can redistribute it and/or modify it under the terms of the GNU
|
||||
// General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Licensees holding a valid commercial license may use this file in
|
||||
// accordance with the commercial license agreement provided with the software.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// Author(s) : Clement Jamin (clement.jamin.pro@gmail.com)
|
||||
|
||||
#ifndef CGAL_INTERNAL_SEARCH_HELPERS_H
|
||||
#define CGAL_INTERNAL_SEARCH_HELPERS_H
|
||||
|
||||
#include <CGAL/Has_member.h>
|
||||
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
namespace internal {
|
||||
|
||||
// Helper struct to know at compile-time if there is a cache of the points
|
||||
// stored in the tree
|
||||
template <typename Tree, bool has_enable_points_cache>
|
||||
struct Has_points_cache;
|
||||
|
||||
template <typename Tree>
|
||||
struct Has_points_cache<Tree, true>
|
||||
{
|
||||
static const bool value = Tree::Enable_points_cache::value;
|
||||
};
|
||||
|
||||
template <typename Tree>
|
||||
struct Has_points_cache<Tree, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
CGAL_GENERATE_MEMBER_DETECTOR(transformed_distance_from_coordinates);
|
||||
CGAL_GENERATE_MEMBER_DETECTOR(interruptible_transformed_distance);
|
||||
BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false)
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
class Distance_helper
|
||||
{
|
||||
typedef typename Distance::FT FT;
|
||||
typedef typename Distance::Point_d Point;
|
||||
typedef typename Distance::Query_item Query_item;
|
||||
|
||||
public:
|
||||
|
||||
Distance_helper(Distance const& distance)
|
||||
: m_distance(distance)
|
||||
{}
|
||||
|
||||
// If transformed_distance_from_coordinates does not exist in `Distance`
|
||||
template <bool has_transformed_distance_from_coordinates = has_transformed_distance_from_coordinates<Distance>::value>
|
||||
FT
|
||||
transformed_distance_from_coordinates(
|
||||
const typename Query_item& q,
|
||||
Point const& p,
|
||||
typename std::vector<FT>::const_iterator it_coord_begin,
|
||||
typename std::vector<FT>::const_iterator it_coord_end)
|
||||
{
|
||||
return m_distance.transformed_distance(q, p);
|
||||
}
|
||||
// ... or if it exists
|
||||
template <>
|
||||
FT
|
||||
transformed_distance_from_coordinates<true>(
|
||||
const typename Query_item& q,
|
||||
Point const& p,
|
||||
typename std::vector<FT>::const_iterator it_coord_begin,
|
||||
typename std::vector<FT>::const_iterator it_coord_end)
|
||||
{
|
||||
return m_distance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end);
|
||||
}
|
||||
|
||||
// *** Version with cache ***
|
||||
// If interruptible_transformed_distance does not exist in `Distance`
|
||||
template <bool has_interruptible_distance_computation = has_interruptible_transformed_distance<Distance>::value>
|
||||
FT
|
||||
interruptible_transformed_distance(
|
||||
const typename Query_item& q,
|
||||
Point const& p,
|
||||
typename std::vector<FT>::const_iterator it_coord_begin,
|
||||
typename std::vector<FT>::const_iterator it_coord_end,
|
||||
FT)
|
||||
{
|
||||
return transformed_distance_from_coordinates(q, p, it_coord_begin, it_coord_end);
|
||||
}
|
||||
// ... or if it exists
|
||||
template <>
|
||||
FT
|
||||
interruptible_transformed_distance<true>(
|
||||
const typename Query_item& q,
|
||||
Point const& p,
|
||||
typename std::vector<FT>::const_iterator it_coord_begin,
|
||||
typename std::vector<FT>::const_iterator it_coord_end,
|
||||
FT stop_if_geq_to_this)
|
||||
{
|
||||
return m_distance.interruptible_transformed_distance(
|
||||
q, it_coord_begin, it_coord_end, stop_if_geq_to_this);
|
||||
}
|
||||
|
||||
// *** Version without cache ***
|
||||
// If interruptible_transformed_distance does not exist in `Distance`
|
||||
template <bool has_interruptible_distance_computation = has_interruptible_transformed_distance<Distance>::value>
|
||||
FT
|
||||
interruptible_transformed_distance(
|
||||
const typename Query_item& q,
|
||||
Point const& p,
|
||||
FT)
|
||||
{
|
||||
return m_distance.transformed_distance(q, p);
|
||||
}
|
||||
// ... or if it exists
|
||||
template <>
|
||||
FT
|
||||
interruptible_transformed_distance<true>(
|
||||
const typename 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 m_distance.interruptible_transformed_distance(
|
||||
q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this);
|
||||
}
|
||||
|
||||
private:
|
||||
Distance const & m_distance;
|
||||
|
||||
}; // Distance_helper
|
||||
|
||||
|
||||
}} // namespace CGAL::internal
|
||||
|
||||
#endif // CGAL_INTERNAL_SEARCH_HELPERSS_H
|
||||
Loading…
Reference in New Issue