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
00028 namespace hex {
00029
00030
00031 int
00032 Boundary::length(void) const
00033 {
00034 return int( _edges.size() );
00035 }
00036
00037
00038 bool
00039 Boundary::is_closed(void) const
00040 {
00041 return( _edges.size()>2 && _edges.front()->is_next( *_edges.back() ) );
00042 }
00043
00044
00045 bool
00046 Boundary::is_container(void) const
00047 {
00048 if(is_closed())
00049 {
00050 try {
00051 Path p1 =complement().to_path();
00052 Path p0 =to_path();
00053 return( p0.length() < p1.length() );
00054 }
00055 catch(hex::out_of_range) {
00056
00057
00058 return true;
00059 }
00060 }
00061 return false;
00062 }
00063
00064
00065 Boundary
00066 Boundary::complement(void) const throw(hex::out_of_range)
00067 {
00068 std::list<Edge*> result;
00069 for(std::list<Edge*>::const_iterator e=_edges.begin(); e!=_edges.end(); ++e)
00070 {
00071 Edge* c =(**e).complement();
00072 if(c)
00073 result.push_back( c );
00074 else
00075 throw hex::out_of_range("Boundary complement out of range.");
00076 }
00077 return result;
00078 }
00079
00080
00081 Path
00082 Boundary::to_path(void) const
00083 {
00084 std::list<Hex*> result;
00085 for(std::list<Edge*>::const_iterator e=_edges.begin(); e!=_edges.end(); ++e)
00086 if( result.empty() || (**e).hex() != result.back() )
00087 result.push_back( (**e).hex() );
00088 return result;
00089 }
00090
00091
00092 bool
00093 Boundary::clockwise(void) const
00094 {
00095
00096 if(_edges.size() > 1)
00097 {
00098 std::list<Edge*>::const_iterator e =_edges.begin();
00099 Edge* e0 = *e;
00100 Edge* e1 = *(++e);
00101 return( e0==e1->next_in() || e0==e1->next_out() );
00102 }
00103 return false;
00104 }
00105
00106
00107 std::string
00108 Boundary::str(void) const
00109 {
00110 assert(!_edges.empty());
00111 std::string result =_edges.front()->hex()->str() + (clockwise()?"-":"+");
00112 for(std::list<Edge*>::const_iterator e=_edges.begin(); e!=_edges.end(); ++e)
00113 result += to_char( (**e).direction() );
00114 return result;
00115 }
00116
00117
00118 std::list<Point>
00119 Boundary::stroke(float bias) const
00120 {
00121 std::list<Point> result;
00122 bool cw =this->clockwise();
00123 if(bias==0.0)
00124 {
00125 if(!_edges.empty())
00126 {
00127 std::list<Edge*>::const_iterator e =_edges.begin();
00128 result.push_back( (**e).start_point(0.0,cw) );
00129 while(e!=_edges.end())
00130 {
00131 result.push_back( (**e).end_point(0.0,cw) );
00132 ++e;
00133 }
00134 }
00135 }
00136 else
00137 {
00138 Edge* last =NULL;
00139 for(std::list<Edge*>::const_iterator e=_edges.begin(); e!=_edges.end(); ++e)
00140 {
00141 if(last)
00142 result.push_back( last->join_point(*e,bias) );
00143 last = *e;
00144 }
00145 if(is_closed())
00146 {
00147 Point p =last->join_point(_edges.front(),bias);
00148 result.push_front( p );
00149 result.push_back( p );
00150 }
00151 else
00152 {
00153 result.push_front( _edges.front()->start_point(bias,cw) );
00154 result.push_back( last->end_point(bias,cw) );
00155 }
00156 }
00157 return result;
00158 }
00159
00160
00161 Area
00162 Boundary::area(void) const
00163 {
00164 assert(is_closed());
00165 std::set<Hex*> beyond;
00166 std::set<Hex*> queue;
00167 for(std::list<Edge*>::const_iterator e=_edges.begin(); e!=_edges.end(); ++e)
00168 {
00169 queue.insert( (**e).hex() );
00170 beyond.insert( (**e).hex()->go( (**e).direction() ) );
00171 }
00172 return fill(beyond,queue);
00173 }
00174
00175
00176 }