00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "hex.h"
00025
00026 #include <cassert>
00027 #include <sstream>
00028
00029 namespace hex {
00030
00031
00032 Boundary
00033 Area::boundary(void) const
00034 {
00035
00036 Hex* h =*_hexes.begin();
00037 const Grid& grid =h->grid();
00038 const int i0 =h->i;
00039 const int j0 =h->j;
00040
00041 int i=0;
00042 while(i<=i0 && !contains(grid.hex(i,j0)))
00043 ++i;
00044 std::list<Edge*> result;
00045 result.push_back( grid.hex(i,j0)->edge(D) );
00046
00047 while(true)
00048 {
00049 Edge* e =result.back()->next_out();
00050 if( !e || !contains(e->hex()) )
00051 e = result.back()->next_in();
00052 if(e == result.front())
00053 break;
00054 result.push_back(e);
00055 }
00056 return result;
00057 }
00058
00059
00060 std::list<Area>
00061 Area::enclosed_areas(void) const
00062 {
00063 Area a =boundary().area();
00064 return areas( set_difference( a._hexes, _hexes ) );
00065 }
00066
00067
00068 std::list<Boundary>
00069 Area::skeleton(bool include_boundary) const
00070 {
00071 std::list<Boundary> result;
00072 for(std::set<Hex*>::const_iterator h=_hexes.begin(); h!=_hexes.end(); ++h)
00073 {
00074 std::list<Edge*> edges;
00075 edges.push_back( (**h).edge(A) );
00076 edges.push_back( (**h).edge(B) );
00077 edges.push_back( (**h).edge(C) );
00078 result.push_back(edges);
00079 }
00080 if(include_boundary)
00081 result.push_back(boundary());
00082 return result;
00083 }
00084
00085
00086 std::list<hex::Path>
00087 Area::fillpaths(Hex* origin) const
00088 {
00089
00090 std::set<Hex*> queue =_hexes;
00091 std::set<Hex*> seen;
00092 std::list<Path> result;
00093 std::list<Hex*> path;
00094 Hex* hex = origin? origin: *queue.begin();
00095 Direction dir =F;
00096 while(!queue.empty())
00097 {
00098 path.push_back( hex );
00099 queue.erase( hex );
00100 seen.insert( hex );
00101 Direction d=dir+1;
00102 while(true)
00103 {
00104 if(d==dir)
00105 {
00106 result.push_back( path );
00107 path.clear();
00108 hex = *queue.begin();
00109 break;
00110 }
00111 Hex* hd =hex->go(d);
00112 if(queue.count(hd) && !seen.count(hd))
00113 {
00114 hex = hd;
00115 dir = d+3;
00116 break;
00117 }
00118 ++d;
00119 }
00120 }
00121 return result;
00122 }
00123
00124
00125 std::string
00126 Area::str(Hex* origin) const
00127 {
00128 if(!origin)
00129 origin=*_hexes.begin();
00130 std::ostringstream result;
00131 std::list<Path> paths =this->fillpaths(origin);
00132 result << origin->str();
00133 for(std::list<Path>::const_iterator p =paths.begin(); p!=paths.end(); ++p)
00134 {
00135 if(p->hexes().front()!=origin)
00136 result << ">" << hex::steps(origin,p->hexes().front());
00137 result << ":" << p->steps();
00138 }
00139 return result.str();
00140 }
00141
00142
00143 Area
00144 Area::go(const Direction& d, int distance) const throw(hex::out_of_range)
00145 {
00146 Area result;
00147 for(std::set<Hex*>::const_iterator h=_hexes.begin(); h!=_hexes.end(); ++h)
00148 {
00149 Hex* hex =(**h).go(d,distance);
00150 if(!hex)
00151 throw hex::out_of_range("Area::go");
00152 result._hexes.insert(hex);
00153 }
00154 return result;
00155 }
00156
00157
00158 Area
00159 Area::go(const std::string& steps) const throw(hex::out_of_range)
00160 {
00161 Area result;
00162 for(std::set<Hex*>::const_iterator h=_hexes.begin(); h!=_hexes.end(); ++h)
00163 {
00164 Hex* hex =(**h).go(steps);
00165 if(!hex)
00166 throw hex::out_of_range("Area::go");
00167 result._hexes.insert(hex);
00168 }
00169 return result;
00170 }
00171
00172
00173 Area::Area(const std::set<Hex*>& hexes): _hexes(hexes)
00174 {
00175 #ifdef HEX_PARANOID_CHECKS
00176 assert(is_connected(hexes));
00177 #endif
00178 }
00179
00180
00181 Area::Area(Hex* h, int distance): _hexes()
00182 {
00183 for(int i=0; i<=distance; ++i)
00184 {
00185 std::set<Hex*> s =range(h,i);
00186 std::copy(s.begin(),s.end(),inserter(_hexes,_hexes.end()));
00187 }
00188 }
00189
00190
00191 }