hex.h

Go to the documentation of this file.
00001 /*                            Package   : libhex
00002  * hex.h                      Created   : 2007/10/11
00003  *                            Author    : Alex Tingle
00004  *
00005  *    Copyright (C) 2007-2008, Alex Tingle.
00006  *
00007  *    This file is part of the libhex application.
00008  *
00009  *    libhex is free software; you can redistribute it and/or
00010  *    modify it under the terms of the GNU Lesser General Public
00011  *    License as published by the Free Software Foundation; either
00012  *    version 2.1 of the License, or (at your option) any later version.
00013  *
00014  *    libhex is distributed in the hope that it will be useful,
00015  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  *    Lesser General Public License for more details.
00018  *
00019  *    You should have received a copy of the GNU Lesser General Public
00020  *    License along with this library; if not, write to the Free Software
00021  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  */
00023 
00057 #ifndef FIRETREE__HEX_H
00058 #define FIRETREE__HEX_H 1
00059 
00060 
00061 #include <list>
00062 #include <set>
00063 #include <map>
00064 #include <stdexcept>
00065 #include <ostream>
00066 #include <string>
00067 
00068 
00069 #define HEX_PARANOID_CHECKS
00070 
00073 namespace hex {
00074 
00075 
00076 //
00077 // Exceptions
00078 
00080 class exception: public std::exception
00081 {
00082 public:
00083   std::string _what;
00084   exception(const std::string& w) throw(): _what(w) {}
00085   virtual ~exception() throw() {}
00086   virtual const char* what() const throw() { return this->_what.c_str(); }
00087 };
00088 
00089 class invalid_argument: public hex::exception
00090 {
00091 public:
00092   invalid_argument(const std::string& w) throw(): hex::exception(w) {}
00093   virtual ~invalid_argument() throw() {}
00094 };
00095 
00096 class out_of_range: public hex::exception
00097 {
00098 public:
00099   out_of_range(const std::string& w) throw(): hex::exception(w) {}
00100   virtual ~out_of_range() throw() {}
00101 };
00102 
00103 
00104 //
00105 // Distance
00106 
00107 typedef double Distance;
00108 
00109 const Distance M_SQRT3 =1.73205080756887729352744634150587236; // sqrt(3)
00110 const Distance I =1.0;         
00111 const Distance J =M_SQRT3/2.0; 
00112 const Distance K =1.0/M_SQRT3; 
00113 
00114 //
00115 // Direction
00116 
00119 enum Direction {  A=0, B=1, C=2,  D=3, E=4, F=5 };
00120 const int DIRECTIONS =6;
00121 
00122 Direction to_direction(char c) throw(hex::invalid_argument);
00123 char to_char(Direction d);
00124 
00125 // Direction arithmetic.
00126 
00127 Direction& operator+= (Direction& d, int i);
00128 Direction  operator+  (const Direction& d, int i);
00129 Direction& operator++ (Direction& d);
00130 Direction  operator++ (const Direction& d,int);
00131 Direction& operator-= (Direction& d, int i);
00132 Direction  operator-  (const Direction& d, int i);
00133 Direction& operator-- (Direction& d);
00134 Direction  operator-- (const Direction& d,int);
00135 
00136 std::ostream& operator<<(std::ostream& os, const Direction& d);
00137 
00140 std::string rotate(const std::string& steps, int i);
00141 
00142 
00143 //
00144 // svg::Identity
00145 
00146 namespace svg {
00149   class Identity
00150   {
00151   public:
00152     std::string  id;
00153     std::string  style;
00154     std::string  className;
00155     virtual ~Identity(void) {}
00157     std::string attributes(void) const;
00158   };
00159 } // end namespace svg
00160 
00161 
00162 //
00163 // Forward declarations
00164 
00165 class Grid;
00166 class Edge;
00167 class Hex;
00168 class Area;
00169 class Path;
00170 class Boundary;
00171 
00172 
00174 struct Point
00175 {
00176   Distance x,y;
00177   Point offset(Distance dx, Distance dy) const { return Point(x+dx,y+dy); }
00178   Point(): x(0.0), y(0.0) {}
00179   Point(Distance x_, Distance y_): x(x_), y(y_) {}
00180   Point(const std::string s) throw (out_of_range,invalid_argument);
00181   Point& operator+=(const Point& p) { x+=p.x; y+=p.y; return *this; }
00182   Point& operator-=(const Point& p) { x-=p.x; y-=p.y; return *this; }
00183   Point operator+(const Point& p) const { return Point(x+p.x,y+p.y); }
00184   Point operator-(const Point& p) const { return Point(x-p.x,y-p.y); }
00185   Point operator*(double v) const { return Point(x*v,y*v); }
00186   Point operator/(double v) const { return Point(x/v,y/v); }
00187   bool operator==(const Point& p) const { return(x==p.x && y==p.y); }
00188   bool operator!=(const Point& p) const { return !operator==(p); }
00189   std::string str(void) const;
00190 };
00191 
00194 class Grid
00195 {
00196   mutable std::map<int,Hex*> _hexes;
00197   int _cols;
00198   int _rows;
00199 public:
00200   int  cols(void) const { return _cols; }
00201   int  rows(void) const { return _rows; }
00202   Distance width(void) const { return I/2.0 + I*cols(); }
00203   Distance height(void) const { return K*2 + J*(rows()-1); }
00204   bool is_in_range(int i, int j) const {return 0<=i&&i<cols()&&0<=j&&j<rows();}
00205   Hex* hex(int i, int j) const throw(hex::out_of_range);
00206   Hex* hex(Distance x, Distance y) const throw(hex::out_of_range);
00207   Hex* hex(const Point& p) const throw(hex::out_of_range);
00208   Area to_area(void) const;
00209 public: // construction
00210   Grid(int cols, int rows) throw(hex::out_of_range);
00211 public: // housekeeping
00212   Grid(const Grid& right);
00213   virtual ~Grid();
00214 private:
00215   Grid& operator=(const Grid&); 
00216 public: // factory methods
00218   Hex* hex(const std::string& s) const
00219     throw(out_of_range,invalid_argument);
00221   std::set<Hex*> hexes(const std::string& s) const
00222     throw(out_of_range,invalid_argument);
00224   Area area(const std::string& s) const
00225     throw(out_of_range,invalid_argument);
00227   Path path(const std::string& s) const
00228     throw(out_of_range,invalid_argument);
00230   Boundary boundary(const std::string& s) const
00231     throw(out_of_range,invalid_argument);
00232 };
00233 
00234 
00238 class Edge
00239 {
00240   Hex* const  _hex;
00241   const Direction  _direction;
00242 public:
00243   Hex*       hex(void) const { return _hex; }
00244   Direction  direction(void) const { return _direction; }
00245   Edge*      complement(void) const;
00246   bool       is_next(const Edge& v) const;
00247   Edge*      next_in(bool clockwise=false) const;
00248   Edge*      next_out(bool clockwise=false) const;
00249   Point      start_point(float bias =0.0, bool clockwise=false) const;
00250   Point      end_point(float bias =0.0, bool clockwise=false) const;
00251   Point      join_point(const Edge* next, float bias =0.0) const;
00252 private:
00253   friend class Hex;
00254   Edge(Hex* h, Direction d): _hex(h), _direction(d) {}
00255   ~Edge() {}
00256 };
00257 
00258 
00260 class Hex
00261 {
00262   Edge  _edgeA,_edgeB,_edgeC,_edgeD,_edgeE,_edgeF;
00263   const Grid& _grid;
00264 public:
00265   const int  i; 
00266   const int  j; 
00267   const Grid&  grid(void) const { return _grid; }
00268   const Edge*  edge(const Direction& d) const;
00269   Edge*        edge(const Direction& d);
00270   Hex*         go(const Direction& d, int distance=1) const;
00271   Hex*         go(const std::string& steps) const;
00272   Point        centre(void) const;
00273   std::string  str(void) const;
00275   static int   _key(int i, int j) { return (i<<14) | j; }
00276 public: // construction
00277   Hex(const Grid& grid, int i_, int j_);
00278 private:
00279   friend class Grid;
00280   Hex(const Hex& right);               
00281   Hex& operator=(const Hex&);          
00282   Hex(const Grid& grid, const Hex& h); 
00283   ~Hex() {}                            
00284 };
00285 
00286 
00288 class Area: public svg::Identity
00289 {
00290   std::set<Hex*>  _hexes;
00291 public:
00292   int                    size(void) const { return int(_hexes.size()); }
00293   bool                   contains(Hex* h) const { return _hexes.count(h)>0; }
00294   Boundary               boundary(void) const;
00295   const std::set<Hex*>&  hexes(void) const { return _hexes; }
00296   std::list<Area>        enclosed_areas(void) const;
00299   std::list<Boundary>    skeleton(bool include_boundary =true) const;
00301   std::list<hex::Path>   fillpaths(Hex* origin =NULL) const;
00302   std::string            str(Hex* origin =NULL) const;
00303 public: // transformations
00304   Area  go(const Direction& d, int distance=1) const throw(hex::out_of_range);
00305   Area  go(const std::string& steps) const throw(hex::out_of_range);
00306 public: // construction
00307   Area(void): _hexes() {} 
00308   Area(const std::set<Hex*>& hexes);
00309   Area(Hex* h): _hexes() { _hexes.insert(h); }
00310   Area(Hex* h, int distance); 
00311 };
00312 
00313 
00315 class Path: public svg::Identity
00316 {
00317   std::list<Hex*>  _hexes;
00318 public:
00319   Area                    to_area(void) const;
00320   const std::list<Hex*>&  hexes(void) const { return _hexes; }
00321   int                     length(void) const; 
00322   std::string             steps(void) const;
00323   std::string             str(void) const;
00324 public: // construction
00325   Path(void): _hexes() {} 
00326   Path(const std::list<Hex*>& hexes): _hexes(hexes) {}
00328   Path(Hex* start, const std::string& steps)
00329     throw(hex::out_of_range,hex::invalid_argument);
00332   Path(Hex* from, const Hex* to) throw();
00333 };
00334 
00335 
00337 class Boundary: public svg::Identity
00338 {
00339   std::list<Edge*>  _edges;
00340 public:
00341   int                      length(void) const; 
00342   bool                     is_closed(void) const; 
00343   bool                     is_container(void) const; 
00344   Boundary                 complement(void) const throw(hex::out_of_range);
00345   const std::list<Edge*>&  edges(void) const { return _edges; }
00346   Path                     to_path(void) const;
00347   bool                     clockwise(void) const; 
00348   std::string              str(void) const;
00350   std::list<Point>         stroke(float bias =0.0) const;
00353   Area                     area(void) const;
00354 public: // construction
00355   Boundary(void): _edges() {} 
00356   Boundary(const std::list<Edge*>& edges): _edges(edges) {}
00357 };
00358 
00359 
00360 //
00361 // Algorithms
00362 
00363 
00365 void
00366 go(int& i, int& j, Direction d, int distance=1);
00367 
00368 
00370 void
00371 go(int& i, int& j, const std::string& steps);
00372 
00373 
00376 std::string
00377 steps(const Hex* from, const Hex* to);
00378 
00379 
00381 int
00382 distance(const Hex* from, const Hex* to);
00383 
00384 
00388 std::set<Hex*>
00389 range(Hex* h, int distance);
00390 
00391 
00393 std::set<Hex*>
00394 set_difference(const std::set<Hex*>& a, const std::set<Hex*>& b);
00395 
00396 
00398 std::set<Hex*>
00399 set_intersection(const std::set<Hex*>& a, const std::set<Hex*>& b);
00400 
00401 
00403 std::set<Hex*>
00404 set_union(const std::set<Hex*>& a, const std::set<Hex*>& b);
00405 
00406 
00408 std::string
00409 set_str(const std::set<Hex*>& a);
00410 
00411 
00413 bool
00414 bounding_box(const std::set<Hex*>& a, int& i0, int& j0, int& i1, int& j1);
00415 
00416 
00418 Area
00419 fill(const std::set<Hex*>& beyond, Hex* h);
00420 
00421 
00423 Area
00424 fill(const std::set<Hex*>& beyond, const Area& a);
00425 
00426 
00428 std::list<Area>
00429 areas(const std::set<Hex*>& s);
00430 
00431 
00433 bool
00434 is_connected(const std::set<Hex*>& s);
00435 
00436 
00438 std::list<Boundary>
00439 skeleton(const std::list<Area>& a, bool include_boundary =true);
00440 
00441 
00442 } // end namespace hex
00443 
00444 #endif

Generated on Thu Feb 21 00:00:54 2008 for libhex by  doxygen 1.5.1