#ifndef geo_hash_h_
#define geo_hash_h_

#include <list>
#include <vector>

//  A point location in 2d
class point {
public:
  point( float in_x, float in_y ) : m_x(in_x), m_y(in_y) {}
  point() : m_x(0), m_y(0) {}
  float x() const { return m_x; }
  float y() const { return m_y; }
private:
  float m_x, m_y;
};


//  The index for a bin in a 2d grid
class bin_index {
public:
  bin_index( int in_i, int in_j ) : m_i(in_i), m_j(in_j) {}
  bin_index() : m_i(0), m_j(0) {}
  int i() const { return m_i; }
  int j() const { return m_j; }
private:
  int m_i, m_j;
};

class geo_hash {
public:
  //  Construct a geometric hash with square bins having the specified
  //  bin width.
  geo_hash( float bin_width=10.0 );

  //  Add a point to the geometric hash
  void add_point( point loc );

  //  Add a vector of points to the geometric hash
  void add_points( std::vector<point> const& locs );

  //  Find all points in the geometric hash that fall within the given
  //  circle.  Order them by increasing x and for ties, by increasing
  //  y
  std::vector<point> points_in_circle( point center, float radius ) const;

  //  Find all points in the geometric hash that fall within the given
  //  rectangle defined by the min_point (smallest x and y) and the
  //  max_point (greatest x and y).  Order the points found by
  //  increasing x and for ties, by increasing y
  std::vector<point> points_in_rectangle( point min_point, point max_point ) const;

  //  Erase the points that fall within the given circle
  int erase_points( point center, float radius=1e-6 );

  //  Find the bin index associated with a given point location
  bin_index point_to_bin( point loc ) const;

  //  Find the hash value of the given point location
  unsigned int hash_value( point loc ) const;

  //  What points are in the bin associated with the given point
  //  location.
  std::vector<point> points_in_bin( point loc ) const;

  //  How many non-empty bins are there?
  int num_non_empty() const;

  //  How many points are in the geometric hash?
  int num_points() const;

  //  What is the size of the hash table?
  int table_size() const;  

};

#endif

