base.hpp

Go to the documentation of this file.
00001 
00028 #ifndef MSMAZES_CORE_PATTERN_BASE_HPP
00029 #define MSMAZES_CORE_PATTERN_BASE_HPP
00030 
00031 #include <vector>  // std::vector
00032 #include <boost/utility.hpp>  // boost::tie
00033 #include <boost/property_map.hpp>  // boost::property_map and boost::get
00034 #include <boost/graph/graph_traits.hpp>  // boost::graph_traits
00035 #include <boost/graph/graph_selectors.hpp>  // boost::vecS and boost::listS
00036 #include <boost/graph/adjacency_list.hpp>  // boost::adjacency_list and friends
00037 
00609 namespace msmazes {
00610 
00612 
00632 struct BasicCellEqualityPolicy
00633 {
00661     template <typename Cell>
00662     bool operator()(const Cell& c1, const Cell& c2) const
00663     {
00664         return c1 == c2;
00665     }
00666 };
00667 
00669 
00756 template <
00757 #ifndef MSMAZES_DOX
00758     typename EdgeDirectedSelector
00759   , typename CellType
00760   , typename CellEqualityPolicyType
00761   , typename DirectionType
00762   , typename CellContainer = std::vector<CellType>
00763 #endif  /* MSMAZES_DOX */
00764 >
00765 class BasePattern
00766 {
00767  public:
00772 #ifdef MSMAZES_DOX
00773     typedef implementation_defined Cell;
00774 #else
00775     typedef CellType
00776             Cell;
00777 #endif  /* MSMAZES_DOX */
00778 
00784 #ifdef MSMAZES_DOX
00785     typedef implementation_defined CellEqualityPolicy;
00786 #else
00787     typedef CellEqualityPolicyType
00788             CellEqualityPolicy;
00789 #endif  /* MSMAZES_DOX */
00790 
00796 #ifdef MSMAZES_DOX
00797     typedef implementation_defined Graph;
00798 #else
00799     typedef boost::adjacency_list<boost::listS,boost::vecS,EdgeDirectedSelector>
00800             Graph;
00801 #endif  /* MSMAZES_DOX */
00802 
00808 #ifdef MSMAZES_DOX
00809     typedef implementation_defined CellIndex;
00810 #else
00811     typedef typename boost::graph_traits<Graph>::vertices_size_type
00812             CellIndex;
00813 #endif  /* MSMAZES_DOX */
00814 
00820 #ifdef MSMAZES_DOX
00821     typedef implementation_defined EdgeDirectedCategory;
00822 #else
00823     typedef typename boost::graph_traits<Graph>::directed_category
00824             EdgeDirectedCategory;
00825 #endif  /* MSMAZES_DOX */
00826 
00832 #ifdef MSMAZES_DOX
00833     typedef implementation_defined Direction;
00834 #else
00835     typedef DirectionType
00836             Direction;
00837 #endif  /* MSMAZES_DOX */
00838 
00839  private:
00840     Graph         _graph;
00841     CellContainer _cell;
00842 
00843     BasePattern(const BasePattern& copy)
00844     {
00845     }
00846 
00847  protected:
00849 
00855     BasePattern() : _graph(), _cell()
00856     {
00857     }
00858 
00859  public:
00861 
00864     virtual ~BasePattern()
00865     {
00866     }
00867 
00868  private:
00869     template <
00870         typename PatternFormer
00871       , typename ArgumentPack
00872     >
00873     void
00874         _initializeEdges(
00875             const PatternFormer& pattern_former
00876           , const ArgumentPack& p
00877           , boost::undirected_tag
00878         )
00879     {
00880         typename boost::graph_traits<Graph>::vertex_descriptor u;
00881         CellIndex i = boost::num_vertices(_graph);
00882         CellIndex j;
00883 
00884         while (i > 0)
00885         {
00886             u = boost::vertex(--i, _graph);
00887             boost::clear_vertex(u, _graph);
00888             Cell& u_loc = _cell[i];
00889             j = boost::num_vertices(_graph);
00890 
00891             while (--j > i)
00892             {
00893                 Cell& v_loc = _cell[j];
00894 
00895                 if (
00896                     PatternFormer::isLegalEdge(u_loc, v_loc, p)
00897                  || PatternFormer::isLegalEdge(v_loc, u_loc, p)
00898                 )
00899                 {
00900                     boost::add_edge(u, boost::vertex(j, _graph), _graph);
00901                 }
00902             }
00903         }
00904     }
00905 
00906     template <
00907         typename PatternFormer
00908       , typename ArgumentPack
00909     >
00910     void
00911         _initializeEdges(
00912             const PatternFormer& pattern_former
00913           , const ArgumentPack& p
00914           , boost::directed_tag
00915         )
00916     {
00917         typename boost::graph_traits<Graph>::vertex_descriptor u, v;
00918         CellIndex i = boost::num_vertices(_graph);
00919         CellIndex j;
00920 
00921         while (i > 0)
00922         {
00923             u = boost::vertex(--i, _graph);
00924             boost::clear_vertex(u, _graph);
00925             Cell& u_loc = _cell[i];
00926             j = boost::num_vertices(_graph);
00927 
00928             while (--j > i)
00929             {
00930                 v = boost::vertex(j, _graph);
00931                 Cell& v_loc = _cell[j];
00932 
00933                 if (PatternFormer::isLegalEdge(u_loc, v_loc, p))
00934                 {
00935                     boost::add_edge(u, v, _graph);
00936                 }
00937 
00938                 if (PatternFormer::isLegalEdge(v_loc, u_loc, p))
00939                 {
00940                     boost::add_edge(v, u, _graph);
00941                 }
00942             }
00943         }
00944     }
00945 
00946  protected:
00975     template <
00976         typename PatternFormer
00977       , typename ArgumentPack
00978     >
00979     void
00980         initializeWithPatternFormer(
00981             const PatternFormer& pattern_former
00982           , const ArgumentPack& p
00983         )
00984     {
00985         const CellIndex volume = PatternFormer::countCells(p);
00986 
00987         while (boost::num_vertices(_graph) < volume)
00988         {
00989             boost::add_vertex(_graph);
00990         }
00991 
00992         typename boost::graph_traits<Graph>::vertex_descriptor vertex;
00993         CellIndex vertex_count = boost::num_vertices(_graph);
00994 
00995         while (vertex_count > volume)
00996         {
00997             vertex = boost::vertex(--vertex_count, _graph);
00998             boost::clear_vertex(vertex, _graph);
00999             boost::remove_vertex(vertex, _graph);
01000         }
01001 
01002         _cell.resize(volume);
01003         PatternFormer::makeCells(_cell.begin(), p);
01004         _initializeEdges(pattern_former, p, EdgeDirectedCategory());
01005     }
01006 
01007  public:
01014     inline const Graph& getGraph() const
01015     {
01016         return _graph;
01017     }
01018 
01024     inline CellIndex getCellCount() const
01025     {
01026         return boost::num_vertices(_graph);
01027     }
01028 
01034     inline const Cell& getCell(const CellIndex index) const
01035     {
01036         return _cell[index];
01037     }
01038 
01044     virtual const Cell& getEntranceCell() const = 0;
01045 
01052     virtual const Cell& getSourceCell() const = 0;
01053 
01060     virtual const Cell& getTargetCell() const = 0;
01061 
01067     virtual const Cell& getExitCell() const = 0;
01068 
01069  protected:
01075     virtual Direction
01076         getEdgeDirectionDerived(
01077             const Cell& source
01078           , const Cell& target
01079         ) const
01080     {
01081         return Direction();
01082     }
01083 
01084  public:
01091     Direction
01092         getEdgeDirection(
01093             const CellIndex source_index
01094           , const CellIndex target_index
01095         ) const
01096     {
01097         return
01098             (source_index == target_index)
01099           ? getEdgeDirectionDerived(
01100                 getEntranceCell()
01101               , getCell(target_index)
01102             )
01103           : (target_index == getCellCount())
01104           ? getEdgeDirectionDerived(
01105                 getCell(source_index)
01106               , getExitCell()
01107             )
01108           : getEdgeDirectionDerived(
01109                 getCell(source_index)
01110               , getCell(target_index)
01111             );
01112     }
01113 };
01114 }  // namespace msmazes
01115 
01116 #endif  /* MSMAZES_CORE_PATTERN_BASE_HPP */

Multi-State Mazes in C++ is hosted by SourceForge.net. Use the Table of Contents for navigation.