Add new variants of transformed_distance

- Variant taking iterators on coordinates of P instead of P itself
- Variant with an additional param `stop_if_geq_to_this`: 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.
This commit is contained in:
Clement Jamin 2017-04-24 16:52:55 +02:00
parent cfd4e92153
commit 6a5dbdc333
1 changed files with 125 additions and 41 deletions

View File

@ -57,61 +57,145 @@ namespace CGAL {
// default constructor // default constructor
Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {} Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {}
// During the computation, if the partially-computed distance `pcd` gets greater or equal
inline FT transformed_distance(const Query_item& q, const Point_d& p) const { // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned
return transformed_distance(q,p, D()); inline FT transformed_distance(const Query_item& q, const Point_d& p,
FT stop_if_geq_to_this = std::numeric_limits<FT>::max()) 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(q, p_begin, p_end, stop_if_geq_to_this);
} }
//Dynamic version for runtime dimension // During the computation, if the partially-computed distance `pcd` gets greater or equal
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dynamic_dimension_tag) const { // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned
FT distance = FT(0); template <typename Coord_iterator>
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); inline FT transformed_distance(const Query_item& q,
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), Coord_iterator it_coord_begin, Coord_iterator it_coord_end,
qe = construct_it(q,1), pit = construct_it(p); FT stop_if_geq_to_this = std::numeric_limits<FT>::max()) const
for(; qit != qe; qit++, pit++){ {
distance += ((*qit)-(*pit))*((*qit)-(*pit)); return transformed_distance(q, it_coord_begin, it_coord_end, stop_if_geq_to_this, D());
}
return distance;
} }
//Generic version for DIM > 3 // Dynamic version for runtime dimension, taking iterators on coordinates as parameters
template < int DIM > // During the computation, if the partially-computed distance `pcd` gets greater or equal
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<DIM>) const { // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned
FT distance = FT(0); template <typename Coord_iterator>
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); inline FT transformed_distance(const Query_item& q,
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), Coord_iterator it_coord_begin, Coord_iterator it_coord_end,
qe = construct_it(q,1), pit = construct_it(p); FT stop_if_geq_to_this, Dynamic_dimension_tag) const
for(; qit != qe; qit++, pit++){ {
distance += ((*qit)-(*pit))*((*qit)-(*pit)); 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 >= 4)
{
// 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_3 = qe - 3;
for (; qit < qe_minus_3; ++qit, ++it_coord_begin) {
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;
if (distance >= stop_if_geq_to_this)
return distance;
++qit; ++it_coord_begin;
diff = (*qit) - (*it_coord_begin);
distance += diff*diff;
} }
return distance; }
for (; qit != qe; ++qit, ++it_coord_begin)
{
FT diff = (*qit) - (*it_coord_begin);
distance += diff*diff;
}
return distance;
}
// Generic version for DIM > 3 taking iterators on coordinates as parameters
// 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 <int DIM, typename Coord_iterator>
inline FT transformed_distance(const Query_item& q,
Coord_iterator it_coord_begin, Coord_iterator it_coord_end,
FT stop_if_geq_to_this, 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);
if (qe - qit >= 4)
{
// 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_3 = qe - 3;
for (; qit < qe_minus_3; ++qit, ++it_coord_begin) {
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;
if (distance >= stop_if_geq_to_this)
return distance;
++qit; ++it_coord_begin;
diff = (*qit) - (*it_coord_begin);
distance += diff*diff;
}
}
for (; qit != qe; ++qit, ++it_coord_begin)
{
FT diff = (*qit) - (*it_coord_begin);
distance += diff*diff;
}
return distance;
} }
//DIM = 2 loop unrolled //DIM = 2 loop unrolled
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<2> ) const { template <typename Coord_iterator>
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); inline FT transformed_distance(const Query_item& q,
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),pit = construct_it(p); Coord_iterator it_coord_begin, Coord_iterator /*unused*/,
FT distance = square(*qit - *pit); FT /*unused*/, Dimension_tag<2>) const {
qit++;pit++; typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
distance += square(*qit - *pit); typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q);
return distance; FT distance = square(*qit - *it_coord_begin);
qit++; it_coord_begin++;
distance += square(*qit - *it_coord_begin);
return distance;
} }
//DIM = 3 loop unrolled //DIM = 3 loop unrolled
inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<3> ) const { template <typename Coord_iterator>
typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); inline FT transformed_distance(const Query_item& q,
typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),pit = construct_it(p); Coord_iterator it_coord_begin, Coord_iterator /*unused*/,
FT distance = square(*qit - *pit); FT /*unused*/, Dimension_tag<3>) const {
qit++;pit++; typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object();
distance += square(*qit - *pit); typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q);
qit++;pit++; FT distance = square(*qit - *it_coord_begin);
distance += square(*qit - *pit); qit++; it_coord_begin++;
return distance; distance += square(*qit - *it_coord_begin);
qit++; it_coord_begin++;
distance += square(*qit - *it_coord_begin);
return distance;
} }
inline FT min_distance_to_rectangle(const Query_item& q, inline FT min_distance_to_rectangle(const Query_item& q,
const Kd_tree_rectangle<FT,D>& r) const { const Kd_tree_rectangle<FT,D>& r) const {
FT distance = FT(0); FT distance = FT(0);