/** * \file internal/cgal_knn.h * \brief manipulation of text, and Interconversion between text and numbers * Copyright 2007-2010 IMP Inventors. All rights reserved. */ #include #include #include #include #include #include #include #include #include IMPCGAL_BEGIN_INTERNAL_NAMESPACE RCTree::~RCTree(){} template struct Construct_coord_iterator { const double* operator()(const algebra::VectorD& p) const { return p.get_data(); } const double* operator()(const algebra::VectorD& p, int) const { return p.get_data()+D; } }; template struct Distance { typedef algebra::VectorD Query_item; double transformed_distance(const algebra::VectorD& p1, const algebra::VectorD& p2) const { return (p1-p2).get_squared_magnitude(); } template double min_distance_to_rectangle(const algebra::VectorD& p, const CGAL::Kd_tree_rectangle& b) const { double distance(0.0); for (unsigned int i=0; i< D; ++i) { double h = p[i]; if (h < b.min_coord(i)) distance += square(b.min_coord(i)-h); if (h > b.max_coord(i)) distance += square(h-b.max_coord(i)); } return distance; } template double max_distance_to_rectangle(const algebra::VectorD& p, const CGAL::Kd_tree_rectangle& b) const { double d=0.0; for (unsigned int i=0; i< D; ++i) { double h = p[i]; double di = (h >= (b.min_coord(i)+b.max_coord(i))/2.0) ? square(h-b.min_coord(i)) : square(b.max_coord(i)-h); d+=di; } return d; } double new_distance(double dist, double old_off, double new_off, int /* cutting_dimension */) const { return dist + new_off*new_off - old_off*old_off; } double transformed_distance(double d) const { return d*d; } double inverse_of_transformed_distance(double d) { return std::sqrt(d); } }; // end of struct Distance template struct RealRCTree: public RCTree { typedef typename CGAL::Search_traits, const double*, Construct_coord_iterator > Traits; typedef typename CGAL::Fuzzy_sphere Sphere; typedef typename CGAL::K_neighbor_search > K_neighbor_search; typedef typename K_neighbor_search::Tree Tree; Tree tree; template RealRCTree(It b, It e): tree(b,e){} }; #define IMP_CGAL_KNN_D_DEF(D) \ KNNData##D::KNNData##D(const std::vector > &v): \ vsi_(v) { \ tree_= new RealRCTree(v.begin(), v.end()); \ } \ void KNNData##D::fill_nearest_neighbors_v(const algebra::VectorD &g, \ unsigned int k, \ double eps, \ Ints &ret) const { \ VectorWithIndex d(-1, g); \ RealRCTree:: \ K_neighbor_search search(dynamic_cast*>(tree_.get()) \ ->tree, \ d, k, eps); \ IMP_INTERNAL_CHECK(std::distance(search.begin(), search.end()) \ == static_cast(k), \ "Got the wrong number of points out from CGAL neighbor" \ << " search. Expected " << k \ << " got " \ << std::distance(search.begin(), search.end())); \ Ints::iterator rit = ret.begin(); \ for ( RealRCTree::K_neighbor_search::iterator it = search.begin(); \ it != search.end(); ++it) { \ *rit= it->first; \ ++rit; \ } \ } \ void KNNData##D::fill_nearest_neighbors_v(const algebra::VectorD &g, \ double dist, \ double eps, \ Ints &ret) const { \ VectorWithIndex d(-1, g); \ dynamic_cast*>(tree_.get()) \ ->tree.search(std::back_inserter(ret), \ RealRCTree::Sphere(d, dist, eps)); \ } \ IMP_CGAL_KNN_D_DEF(2) IMP_CGAL_KNN_D_DEF(3) IMP_CGAL_KNN_D_DEF(4) IMPCGAL_END_INTERNAL_NAMESPACE