/** * \file IMP/multifit/GeometricHash.h \brief Geometric Hashing class. * * Copyright 2007-2013 IMP Inventors. All rights reserved. * */ #ifndef IMPMULTIFIT_GEOMETRIC_HASH_H #define IMPMULTIFIT_GEOMETRIC_HASH_H #include #include #include #include #include #include #include "IMP/algebra/VectorD.h" IMPMULTIFIT_BEGIN_NAMESPACE /* This is the definition of Geometric Hash table. * GeometricHash stores values of type T with D-dimensional * points whose coordinates are of type double inside D-dimensional * buckets (cubes) */ template < typename T, size_t D > class GeometricHash { public: enum Distance { INF, EUCLIDEAN }; typedef algebra::VectorD Point; typedef boost::array Bucket; typedef std::pair< Point, T > ValueType; typedef std::vector< ValueType > PointList; typedef std::map GeomMap; typedef typename GeomMap::iterator iterator; typedef typename GeomMap::const_iterator const_iterator; typedef std::vector< const ValueType *> HashResult; typedef IMP::base::Vector HashResultT; typedef std::vector BucketList; /* Default constructor - all cubes/buckets have the same edge length */ GeometricHash(double radius = 1) { for ( size_t i=0; i GeometricHash(const X &radii) { for ( size_t i=0; i &radii) { for ( size_t i=0; i void add(const X &coordinates, const T &data) { Point pt; for ( size_t i=0; isecond); return tr; } template < typename X > HashResult neighbors(Distance dt, const X ¢er_coordinates, double radius) const { Point center; for ( size_t i=0; isecond); } /* Find all points inside a cube centered in center with edges * radii*2 long */ template < typename X > HashResult neighbors(const Point ¢er, const X &radii) const { return points_in_sphere(inside_cube(center, radii)); } /* Find all points inside a cube centered in center with edges * 2 times bigger than the grid */ HashResult neighbors(const Point ¢er) { return neighbors(center, radii_); } template < typename X > HashResult neighbors(const X ¢er_coordinates) { Point center; for ( size_t i=0; ifirst); return result; } /* Remove all data from the hash map */ void clear() { gmap_.clear(); } PointList const *bucket(const Point &pt) const { typename GeomMap::const_iterator p = gmap_.find(to_bucket(pt)); if ( p != gmap_.end() ) return &p->second; return 0; } double resolution(int axis = 0) const { return radii_[axis]; } private: struct inside_sphere { inside_sphere(const Point ¢er, double radius) : center_(center) , radius_(radius) , sq_radius_(radius*radius) {} bool operator()(const Point &pt) const { return get_squared_distance(center_, pt) <= sq_radius_; } double radius(int) const { return radius_; } const Point ¢er_; double radius_; double sq_radius_; }; struct inside_sphere_inf { inside_sphere_inf(const Point ¢er, double radius) : center_(center) , radius_(radius) {} bool operator()(const Point &pt) const { return inf_distance(center_, pt) <= radius_; } double radius(int) const { return radius_; } const Point ¢er_; double radius_; }; struct inside_cube { template < typename X > inside_cube(const Point ¢er, const X &radii) : center_(center) { for ( size_t i=0; i radii_[i] ) return false; return true; } double radius(size_t i) const { return radii_[i]; } const Point ¢er_; double radii_[D]; }; template < typename Dist > HashResult points_in_sphere(Dist const &dist) const { Point C; for ( size_t i=0; i bool cube_inside_sphere(const Dist &ins, const Bucket &l) const { Point p = from_bucket(l); return cube_inside_sphere_rec(ins, p, 0); } template < typename Dist > bool cube_inside_sphere_rec(const Dist &ins, Point &p, size_t idx) const { if ( idx >= D ) return ins(p); if (! cube_inside_sphere_rec(ins, p, idx + 1) ) return false; double old = p[idx]; p[idx] += radii_[idx]; bool r = cube_inside_sphere_rec(ins, p, idx + 1); p[idx] = old; return r; } template < typename Dist > void points_in_sphere_rec(size_t idx, const Bucket &l, const Bucket &u, const Dist &ins, Bucket &tmp, HashResult &result) const { if ( idx >= D ) { typename GeomMap::const_iterator p = gmap_.find(tmp); if ( p != gmap_.end() ) { const PointList &v = p->second; if ( v.size() > (1<first) ) result.push_back(&(*q)); } } return; } for ( int i=l[idx]; i<=u[idx]; ++i ) { tmp[idx] = i; points_in_sphere_rec(idx + 1, l, u, ins, tmp, result); } } /* Create bucket containing the given point p */ Bucket to_bucket(const Point &p) const { Bucket r; for ( size_t i=0; i