mirror of https://github.com/CGAL/cgal
Merge pull request #4187 from sgiraudot/Spatial_searching-Search_traits_adapter_without_lvalue_pmap-GF
Spatial Searching: Search Traits Adapter without lvalue point map
This commit is contained in:
commit
ce82120d61
|
|
@ -11,7 +11,7 @@ in a nearest neighbor search algorithm, this class must be used as distance.
|
|||
|
||||
\tparam Key is a type that is associated to a point of type `Base_distance::Point_d`.
|
||||
|
||||
\tparam PointPropertyMap is a model of `LvaluePropertyMap`
|
||||
\tparam PointPropertyMap is a model of `ReadablePropertyMap`
|
||||
with `Key` as key type and `Base_distance::Point_d` as value type.
|
||||
|
||||
\tparam Base_distance is a model of either `GeneralDistance` or `OrthogonalDistance`.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
namespace CGAL{
|
||||
|
||||
|
|
@ -78,9 +79,6 @@ template <class Point_with_info,class PointPropertyMap,class Base_traits>
|
|||
class Search_traits_adapter : public Base_traits{
|
||||
PointPropertyMap ppmap;
|
||||
|
||||
CGAL_static_assertion( ( boost::is_same< boost::lvalue_property_map_tag,
|
||||
typename boost::property_traits<PointPropertyMap>::category
|
||||
>::value ) );
|
||||
public:
|
||||
typedef Base_traits Base;
|
||||
typedef typename internal::Get_iso_box_d<Base>::type Iso_box_d;
|
||||
|
|
@ -89,17 +87,19 @@ public:
|
|||
const Base_traits& base=Base_traits()
|
||||
):Base_traits(base),ppmap(ppmap_){}
|
||||
|
||||
typedef typename Base_traits::Cartesian_const_iterator_d Cartesian_const_iterator_d;
|
||||
|
||||
typedef Point_with_info Point_d;
|
||||
typedef typename Base_traits::FT FT;
|
||||
typedef typename Base_traits::Dimension Dimension;
|
||||
|
||||
|
||||
struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{
|
||||
// Default if point map is lvalue: use Construct_cartesian_const_iterator_d
|
||||
struct Construct_cartesian_const_iterator_d_lvalue: public Base_traits::Construct_cartesian_const_iterator_d{
|
||||
PointPropertyMap ppmap;
|
||||
typedef typename Base_traits::Construct_cartesian_const_iterator_d Base;
|
||||
|
||||
Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_)
|
||||
Construct_cartesian_const_iterator_d_lvalue
|
||||
(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_)
|
||||
:Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){}
|
||||
|
||||
typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p) const
|
||||
|
|
@ -132,6 +132,125 @@ public:
|
|||
{ return Base::operator() (p,0); }
|
||||
};
|
||||
|
||||
// If point map is not lvalue, use this work-around that stores a
|
||||
// Point object in a shared pointer to avoid iterating on a temp
|
||||
// object
|
||||
class No_lvalue_iterator
|
||||
: public boost::iterator_facade<No_lvalue_iterator,
|
||||
typename std::iterator_traits<typename Base::Cartesian_const_iterator_d>::value_type,
|
||||
std::random_access_iterator_tag
|
||||
>
|
||||
{
|
||||
typedef boost::iterator_facade<No_lvalue_iterator,
|
||||
typename std::iterator_traits<typename Base::Cartesian_const_iterator_d>::value_type,
|
||||
std::random_access_iterator_tag
|
||||
> Facade;
|
||||
|
||||
typedef typename std::iterator_traits<typename Base::Cartesian_const_iterator_d>::value_type
|
||||
Dereference_type;
|
||||
typedef typename boost::property_traits<PointPropertyMap>::value_type
|
||||
Point;
|
||||
|
||||
boost::shared_ptr<Point> point;
|
||||
std::size_t idx;
|
||||
|
||||
public:
|
||||
|
||||
No_lvalue_iterator() : point(NULL), idx(0) { }
|
||||
No_lvalue_iterator(const Point& point, std::size_t idx = 0) : point(new Point(point)), idx(idx) { }
|
||||
|
||||
private:
|
||||
|
||||
friend class boost::iterator_core_access;
|
||||
void increment()
|
||||
{
|
||||
++idx;
|
||||
CGAL_assertion(point != boost::shared_ptr<Point>());
|
||||
}
|
||||
void decrement()
|
||||
{
|
||||
--idx;
|
||||
CGAL_assertion(point != boost::shared_ptr<Point>());
|
||||
}
|
||||
|
||||
void advance(std::ptrdiff_t n)
|
||||
{
|
||||
idx += n;
|
||||
CGAL_assertion(point != boost::shared_ptr<Point>());
|
||||
}
|
||||
|
||||
std::ptrdiff_t distance_to(const No_lvalue_iterator& other) const
|
||||
{
|
||||
return other.idx - this->idx;
|
||||
|
||||
}
|
||||
bool equal(const No_lvalue_iterator& other) const
|
||||
{
|
||||
return this->idx == other.idx;
|
||||
}
|
||||
|
||||
Dereference_type&
|
||||
dereference() const { return const_cast<Dereference_type&>((*point)[idx]); }
|
||||
|
||||
};
|
||||
|
||||
// Alternative Construct_cartesian_const_iterator_d if the point map
|
||||
// is not lvalue (generates No_lvalue_iterator objects)
|
||||
struct Construct_cartesian_const_iterator_d_no_lvalue {
|
||||
typedef No_lvalue_iterator result_type;
|
||||
PointPropertyMap ppmap;
|
||||
|
||||
Construct_cartesian_const_iterator_d_no_lvalue
|
||||
(const typename Base_traits::Construct_cartesian_const_iterator_d&, const PointPropertyMap& ppmap_)
|
||||
: ppmap(ppmap_) { }
|
||||
|
||||
No_lvalue_iterator operator()(const Point_with_info& p) const
|
||||
{ return No_lvalue_iterator(get(ppmap, p)); }
|
||||
|
||||
No_lvalue_iterator operator()(const Point_with_info& p, int) const
|
||||
{ return No_lvalue_iterator(get(ppmap, p),0); }
|
||||
|
||||
// These 2 additional operators forward the call to Base_traits.
|
||||
// This is needed because of an undocumented requirement of
|
||||
// Orthogonal_k_neighbor_search and Orthogonal_incremental_neighbor_search:
|
||||
// Traits::Construct_cartesian_const_iterator should be callable
|
||||
// on the query point type. If the query point type is the same as
|
||||
// Point_with_info, we disable it.
|
||||
|
||||
template <typename Point> // boost::disable_if requires a template argument to work
|
||||
No_lvalue_iterator operator()(const Point& p,
|
||||
typename boost::disable_if<
|
||||
boost::is_same<Point_with_info,
|
||||
Point> >::type* = 0
|
||||
) const
|
||||
{ return No_lvalue_iterator(p); }
|
||||
|
||||
template <typename Point> // boost::disable_if requires a template argument to work
|
||||
No_lvalue_iterator operator()(const Point& p, int,
|
||||
typename boost::disable_if<
|
||||
boost::is_same<Point_with_info,
|
||||
Point> >::type* = 0
|
||||
) const
|
||||
{ return No_lvalue_iterator(p,0); }
|
||||
};
|
||||
|
||||
// Select type of iterator + construct class depending on whether
|
||||
// point map is lvalue or not
|
||||
typedef typename boost::mpl::if_
|
||||
<boost::is_same
|
||||
<boost::lvalue_property_map_tag,
|
||||
typename boost::property_traits<PointPropertyMap>::category >,
|
||||
typename Base::Cartesian_const_iterator_d,
|
||||
No_lvalue_iterator>::type
|
||||
Cartesian_const_iterator_d;
|
||||
typedef typename boost::mpl::if_
|
||||
<boost::is_same
|
||||
<boost::lvalue_property_map_tag,
|
||||
typename boost::property_traits<PointPropertyMap>::category >,
|
||||
Construct_cartesian_const_iterator_d_lvalue,
|
||||
Construct_cartesian_const_iterator_d_no_lvalue>::type
|
||||
Construct_cartesian_const_iterator_d;
|
||||
|
||||
struct Construct_iso_box_d: public Base::Construct_iso_box_d{
|
||||
PointPropertyMap ppmap;
|
||||
typedef typename Base_traits::FT FT; // needed for VC++, because otherwise it is taken from the private typedef of the base class
|
||||
|
|
|
|||
Loading…
Reference in New Issue