boundary.cc

Go to the documentation of this file.
00001 /*                            Package   : libhex
00002  * boundary.cc                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 
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       // If is_closed AND there is no complement, then the boundary must
00057       // be at the very edge of the grid... it MUST be a container.
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   // Boundaries usually go round in a positive (anti-clockwise) direction.
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() ) ); // NULL is OK.
00171   }
00172   return fill(beyond,queue);
00173 }
00174 
00175 
00176 } // end namespace hex

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