pattern/parallelepiped.hpp

Go to the documentation of this file.
00001 
00028 #ifndef MSMAZES_CORE_PATTERN_PARALLELEPIPED_HPP
00029 #define MSMAZES_CORE_PATTERN_PARALLELEPIPED_HPP
00030 
00031 #define MSMAZES_CORE_PATTERN_ARITY 9
00032 
00033 // BOOST_ASSERT
00034 #include <boost/assert.hpp>
00035 // std::floor
00036 #include <cmath>
00037 // BOOST_STATIC_CONSTANT
00038 #include <boost/config.hpp>
00039 // BOOST_PP_LESS
00040 #include <boost/preprocessor/comparison/less.hpp>
00041 // boost::mpl::true_ and boost::mpl::false_
00042 #include <boost/mpl/bool.hpp>
00043 // boost::is_same
00044 #include <boost/type_traits/is_same.hpp>
00045 // sgdk::Pi
00046 #include <swiss_gd_knife/zref/pi.hpp>
00047 // sgdk::Tangent
00048 #include <swiss_gd_knife/zref/tangent.hpp>
00049 // sgdk::ZeroChecker
00050 #include <swiss_gd_knife/math/zero_checker.hpp>
00051 // sgdk::Compass, sgdk::ZeroDirection and, sgdk::PositiveRotation
00052 #include <swiss_gd_knife/math/geom/compass.hpp>
00053 // Boost.Parameter keyword objects used by the Core Pattern class templates
00054 #include <msmazes/core/pattern/keywords.hpp>
00055 
00056 #if BOOST_PP_LESS(BOOST_PARAMETER_MAX_ARITY, MSMAZES_CORE_PATTERN_ARITY)
00057 #error Set BOOST_PARAMETER_MAX_ARITY to 9 or higher.
00058 #endif
00059 
00060 // msmazes::TesselationFormerGenerator and msmazes::PhysicalPattern
00061 #include <msmazes/core/pattern/physical.hpp>
00062 // MSMAZES_CORE_PATTERN_TESSELATION_FORMER_TYPE
00063 #include <msmazes/core/pattern/tesselation_former_type.hpp>
00064 
00065 namespace msmazes {
00066   namespace _detail {
00067 
00072     struct OrthogonalParallelepipedTag
00073     {
00074     };
00075 
00080     template <
00081         typename PatternType
00082     >
00083     struct OrthogonalParallelepipedTesselationFormer
00084     {
00085         typedef PatternType
00086                 Pattern;
00087         typedef OrthogonalParallelepipedTag
00088                 tag;
00089         typedef OrthogonalParallelepipedTesselationFormer
00090                 type;
00091 
00092      private:
00093         typedef typename Pattern::Cell
00094                 Cell;
00095         typedef typename Pattern::Coordinate
00096                 Coordinate;
00097 
00098      public:
00099         BOOST_STATIC_CONSTANT(bool, MAKES_3D_TESSELATION = true);
00100 
00101         template <
00102             typename ArgumentPack
00103         >
00104         static typename Pattern::CellIndex
00105             countCells(
00106                 const ArgumentPack& p
00107             )
00108         {
00109             const Cell& min = p[init_cell_minimum_arg];
00110             const Cell& max = p[init_cell_maximum_arg];
00111             const Cell& inc = p[init_cell_increment_arg];
00112 
00113             Coordinate                  x, y, z;
00114             typename Pattern::CellIndex cell_count = 0;
00115 
00116             for (
00117                 z = min[2];
00118                 z <= max[2];
00119                 z += inc[2]
00120             )
00121             {
00122                 for (
00123                     y = min[1];
00124                     y <= max[1];
00125                     y += inc[1]
00126                 )
00127                 {
00128                     for (
00129                         x = min[0];
00130                         x <= max[0];
00131                         x += inc[0]
00132                     )
00133                     {
00134                         ++cell_count;
00135                     }
00136                 }
00137             }
00138 
00139             return cell_count;
00140         }
00141 
00142         template <
00143             typename OutputIterator
00144           , typename ArgumentPack
00145         >
00146         static void
00147             makeCells(
00148                 OutputIterator cell_iterator
00149               , const ArgumentPack& p
00150             )
00151         {
00152             const Cell& min = p[init_cell_minimum_arg];
00153             const Cell& max = p[init_cell_maximum_arg];
00154             const Cell& inc = p[init_cell_increment_arg];
00155 
00156             Cell cell(3);
00157 
00158             for (
00159                 cell[2] = min[2];
00160                 cell[2] <= max[2];
00161                 cell[2] += inc[2]
00162             )
00163             {
00164                 for (
00165                     cell[1] = min[1];
00166                     cell[1] <= max[1];
00167                     cell[1] += inc[1]
00168                 )
00169                 {
00170                     for (
00171                         cell[0] = min[0];
00172                         cell[0] <= max[0];
00173                         cell[0] += inc[0]
00174                     )
00175                     {
00176                         *cell_iterator = cell;
00177                         ++cell_iterator;
00178                     }
00179                 }
00180             }
00181         }
00182 
00183         template <
00184             typename ArgumentPack
00185         >
00186         static bool
00187             isLegalEdge(
00188                 const typename Pattern::Cell& source
00189               , const typename Pattern::Cell& target
00190               , const ArgumentPack& p
00191             )
00192         {
00193             const Cell&      inc = p[init_cell_increment_arg];
00194             const Coordinate dx  = target[0] - source[0];
00195             const Coordinate dy  = target[1] - source[1];
00196             const Coordinate dz  = target[2] - source[2];
00197 
00198             sgdk::ZeroChecker<Coordinate>
00199                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
00200 
00201             return
00202                 zero_checker.isZero(dx - inc[0])
00203              && zero_checker.isZero(dy)
00204              && zero_checker.isZero(dz)
00205              || zero_checker.isZero(dy - inc[1])
00206              && zero_checker.isZero(dx)
00207              && zero_checker.isZero(dz)
00208              || zero_checker.isZero(dz - inc[2])
00209              && zero_checker.isZero(dx)
00210              && zero_checker.isZero(dy);
00211         }
00212     };
00213   }  // namespace _detail
00214 
00219 struct OrthogonalTesselationSelector
00220 {
00221 };
00222 
00227 template <>
00228 struct TesselationFormerGenerator<OrthogonalTesselationSelector>
00229 {
00230     template <typename Pattern>
00231     struct apply
00232     {
00233         typedef typename _detail::OrthogonalParallelepipedTesselationFormer<
00234                     Pattern
00235                 >::type
00236                 type;
00237     };
00238 };
00239 
00240   namespace _detail {
00241 
00246     template <typename Coordinate>
00247     class Upsilon2DIncrement
00248     {
00249      private:
00250         Coordinate _distance;
00251         Coordinate _z;
00252 
00253      public:
00254         Upsilon2DIncrement(const Coordinate distance, const Coordinate z_inc)
00255           : _distance(distance), _z(z_inc)
00256         {
00257         }
00258 
00259         Coordinate getOctagonSquareCellCenterDistance() const
00260         {
00261             return _distance;
00262         }
00263 
00264         Coordinate getZIncrement() const
00265         {
00266             return _z;
00267         }
00268     };
00269 
00274     template <typename Coordinate>
00275     class UpsilonOctagonSquareCellCenterDistance
00276     {
00277      private:
00278         Coordinate _distance;
00279 
00280      public:
00281         explicit UpsilonOctagonSquareCellCenterDistance(
00282             const Coordinate distance
00283         ) : _distance(distance)
00284         {
00285         }
00286 
00287         Upsilon2DIncrement<Coordinate>
00288             setZIncrement(
00289                 const Coordinate z_increment
00290             ) const
00291         {
00292             return Upsilon2DIncrement<Coordinate>(_distance, z_increment);
00293         }
00294     };
00295 
00300     template <typename Coordinate>
00301     class UpsilonZIncrement
00302     {
00303      private:
00304         Coordinate _z;
00305 
00306      public:
00307         explicit UpsilonZIncrement(const Coordinate z_increment)
00308           : _z(z_increment)
00309         {
00310         }
00311 
00312         Upsilon2DIncrement<Coordinate>
00313             setOctagonSquareCellCenterDistance(
00314                 const Coordinate distance
00315             ) const
00316         {
00317             return Upsilon2DIncrement<Coordinate>(distance, _z);
00318         }
00319     };
00320   }  // namespace _detail
00321 
00326 template <typename Coordinate>
00327 _detail::UpsilonOctagonSquareCellCenterDistance<Coordinate>
00328     setOctagonSquareCellCenterDistance(
00329         const Coordinate distance
00330     )
00331 {
00332     return _detail::UpsilonOctagonSquareCellCenterDistance<Coordinate>(
00333         distance
00334     );
00335 }
00336 
00341 template <typename Coordinate>
00342 _detail::UpsilonZIncrement<Coordinate>
00343     setZIncrement(
00344         const Coordinate z_increment
00345     )
00346 {
00347     return _detail::UpsilonZIncrement<Coordinate>(
00348         z_increment
00349     );
00350 }
00351 
00352   namespace _detail {
00353 
00358     struct Upsilon2DParallelepipedTag
00359     {
00360     };
00361 
00366     template <
00367         typename PatternType
00368       , typename BooleanConstantHasOctagonMinCorner
00369     >
00370     struct Upsilon2DParallelepipedTesselationFormer
00371     {
00372         typedef PatternType
00373                 Pattern;
00374         typedef Upsilon2DParallelepipedTag
00375                 tag;
00376         typedef Upsilon2DParallelepipedTesselationFormer
00377                 type;
00378 
00379      private:
00380         typedef typename Pattern::Cell
00381                 Cell;
00382         typedef typename Pattern::Coordinate
00383                 Coordinate;
00384         typedef Upsilon2DIncrement<Coordinate>
00385                 Increment;
00386 
00387      public:
00388         BOOST_STATIC_CONSTANT(bool, MAKES_3D_TESSELATION = false);
00389 
00390         template <
00391             typename ArgumentPack
00392         >
00393         static typename Pattern::CellIndex
00394             countCells(
00395                 const ArgumentPack& p
00396             )
00397         {
00398             const Cell&
00399                 min = p[init_cell_minimum_arg];
00400             const Cell&
00401                 max = p[init_cell_maximum_arg];
00402             const Increment&
00403                 inc = p[init_cell_increment_arg];
00404             const Coordinate
00405                 w_inc = inc.getOctagonSquareCellCenterDistance();
00406             const Coordinate
00407                 z_inc = inc.getZIncrement();
00408 
00409             Coordinate                  x, y, z;
00410             typename Pattern::CellIndex cell_count = 0;
00411 
00412             for (
00413                 z = min[2];
00414                 z <= max[2];
00415                 z += z_inc
00416             )
00417             {
00418                 for (
00419                     y = min[1];
00420                     y <= max[1];
00421                     y += w_inc
00422                 )
00423                 {
00424                     for (
00425                         x = min[0];
00426                         x <= max[0];
00427                         x += w_inc
00428                     )
00429                     {
00430                         ++cell_count;
00431                     }
00432                 }
00433             }
00434 
00435             return cell_count;
00436         }
00437 
00438         template <
00439             typename OutputIterator
00440           , typename ArgumentPack
00441         >
00442         static void
00443             makeCells(
00444                 OutputIterator cell_iterator
00445               , const ArgumentPack& p
00446             )
00447         {
00448             const Cell&
00449                 min = p[init_cell_minimum_arg];
00450             const Cell&
00451                 max = p[init_cell_maximum_arg];
00452             const Increment&
00453                 inc = p[init_cell_increment_arg];
00454             const Coordinate
00455                 w_inc = inc.getOctagonSquareCellCenterDistance();
00456             const Coordinate
00457                 z_inc = inc.getZIncrement();
00458 
00459             Cell cell(3);
00460 
00461             for (
00462                 cell[2] = min[2];
00463                 cell[2] <= max[2];
00464                 cell[2] += z_inc
00465             )
00466             {
00467                 for (
00468                     cell[1] = min[1];
00469                     cell[1] <= max[1];
00470                     cell[1] += w_inc
00471                 )
00472                 {
00473                     for (
00474                         cell[0] = min[0];
00475                         cell[0] <= max[0];
00476                         cell[0] += w_inc
00477                     )
00478                     {
00479                         *cell_iterator = cell;
00480                         ++cell_iterator;
00481                     }
00482                 }
00483             }
00484         }
00485 
00486         template <
00487             typename ArgumentPack
00488         >
00489         static bool
00490             isLegalEdge(
00491                 const typename Pattern::Cell& source
00492               , const typename Pattern::Cell& target
00493               , const ArgumentPack& p
00494             )
00495         {
00496             const Cell&
00497                 min = p[init_cell_minimum_arg];
00498             const Increment&
00499                 inc = p[init_cell_increment_arg];
00500             const Coordinate
00501                 w_inc = inc.getOctagonSquareCellCenterDistance();
00502             const Coordinate
00503                 z_inc = inc.getZIncrement();
00504             const Coordinate
00505                 dx = target[0] - source[0];
00506             const Coordinate
00507                 dy = target[1] - source[1];
00508             const Coordinate
00509                 dz = target[2] - source[2];
00510 
00511             sgdk::ZeroChecker<Coordinate>
00512                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
00513 
00514             if (zero_checker.isZero(dx - w_inc))
00515             {
00516                 if (zero_checker.isZero(dy))
00517                 {
00518                     return zero_checker.isZero(dz);
00519                 }
00520                 else if (
00521                     zero_checker.isZero(dz)
00522                  && (
00523                         zero_checker.isZero(dy + w_inc)
00524                      || zero_checker.isZero(dy - w_inc)
00525                     )
00526                 )
00527                 {
00528                     return
00529                         BooleanConstantHasOctagonMinCorner::value
00530                      == (
00531                             (
00532                                 static_cast<int>(
00533                                     std::floor(
00534                                         (
00535                                             (source[0] - min[0])
00536                                           - (source[1] - min[1])
00537                                         )
00538                                       / w_inc
00539                                       + source[1]
00540                                       + 0.5
00541                                     )
00542                                 )
00543                               & 1
00544                             )
00545                          != 0
00546                         );
00547                 }
00548                 else
00549                 {
00550                     return false;
00551                 }
00552             }
00553             else if (zero_checker.isZero(dx))
00554             {
00555                 if (zero_checker.isZero(dy))
00556                 {
00557                     return zero_checker.isZero(dz - z_inc);
00558                 }
00559                 else if (zero_checker.isZero(dy - w_inc))
00560                 {
00561                     return zero_checker.isZero(dz);
00562                 }
00563                 else
00564                 {
00565                     return false;
00566                 }
00567             }
00568             else
00569             {
00570                 return false;
00571             }
00572         }
00573     };
00574   }  // namespace _detail
00575 
00580 struct UpsilonOctagonMinCornerTesselationSelector
00581 {
00582 };
00583 
00588 template <>
00589 struct TesselationFormerGenerator<UpsilonOctagonMinCornerTesselationSelector>
00590 {
00591     template <typename Pattern>
00592     struct apply
00593     {
00594         typedef typename _detail::Upsilon2DParallelepipedTesselationFormer<
00595                     Pattern
00596                   , boost::mpl::true_
00597                 >::type
00598                 type;
00599     };
00600 };
00601 
00606 struct UpsilonSquareMinCornerTesselationSelector
00607 {
00608 };
00609 
00614 template <>
00615 struct TesselationFormerGenerator<UpsilonSquareMinCornerTesselationSelector>
00616 {
00617     template <typename Pattern>
00618     struct apply
00619     {
00620         typedef typename _detail::Upsilon2DParallelepipedTesselationFormer<
00621                     Pattern
00622                   , boost::mpl::false_
00623                 >::type
00624                 type;
00625     };
00626 };
00627 
00628   namespace _detail {
00629 
00634     struct CubicGridParallelepipedTag
00635     {
00636     };
00637 
00642     template <
00643         typename PatternType
00644       , typename BooleanConstantHas26SidedSolidMinCorner
00645     >
00646     struct Upsilon3DParallelepipedTesselationFormer
00647     {
00648         typedef PatternType
00649                 Pattern;
00650         typedef CubicGridParallelepipedTag
00651                 tag;
00652         typedef Upsilon3DParallelepipedTesselationFormer
00653                 type;
00654 
00655      private:
00656         typedef typename Pattern::Cell
00657                 Cell;
00658         typedef typename Pattern::Coordinate
00659                 Coordinate;
00660 
00661      public:
00662         BOOST_STATIC_CONSTANT(bool, MAKES_3D_TESSELATION = true);
00663 
00664         template <
00665             typename ArgumentPack
00666         >
00667         static typename Pattern::CellIndex
00668             countCells(
00669                 const ArgumentPack& p
00670             )
00671         {
00672             const Cell&      min = p[init_cell_minimum_arg];
00673             const Cell&      max = p[init_cell_maximum_arg];
00674             const Coordinate inc = p[init_cell_increment_arg];
00675 
00676             Coordinate                  x, y, z;
00677             typename Pattern::CellIndex cell_count = 0;
00678 
00679             for (
00680                 z = min[2];
00681                 z <= max[2];
00682                 z += inc
00683             )
00684             {
00685                 for (
00686                     y = min[1];
00687                     y <= max[1];
00688                     y += inc
00689                 )
00690                 {
00691                     for (
00692                         x = min[0];
00693                         x <= max[0];
00694                         x += inc
00695                     )
00696                     {
00697                         ++cell_count;
00698                     }
00699                 }
00700             }
00701 
00702             return cell_count;
00703         }
00704 
00705         template <
00706             typename OutputIterator
00707           , typename ArgumentPack
00708         >
00709         static void
00710             makeCells(
00711                 OutputIterator cell_iterator
00712               , const ArgumentPack& p
00713             )
00714         {
00715             const Cell&      min = p[init_cell_minimum_arg];
00716             const Cell&      max = p[init_cell_maximum_arg];
00717             const Coordinate inc = p[init_cell_increment_arg];
00718 
00719             Cell cell(3);
00720 
00721             for (
00722                 cell[2] = min[2];
00723                 cell[2] <= max[2];
00724                 cell[2] += inc
00725             )
00726             {
00727                 for (
00728                     cell[1] = min[1];
00729                     cell[1] <= max[1];
00730                     cell[1] += inc
00731                 )
00732                 {
00733                     for (
00734                         cell[0] = min[0];
00735                         cell[0] <= max[0];
00736                         cell[0] += inc
00737                     )
00738                     {
00739                         *cell_iterator = cell;
00740                         ++cell_iterator;
00741                     }
00742                 }
00743             }
00744         }
00745 
00746         template <
00747             typename ArgumentPack
00748         >
00749         static bool
00750             isLegalEdge(
00751                 const typename Pattern::Cell& source
00752               , const typename Pattern::Cell& target
00753               , const ArgumentPack& p
00754             )
00755         {
00756             const Cell&      min = p[init_cell_minimum_arg];
00757             const Coordinate inc = p[init_cell_increment_arg];
00758             const Coordinate dx  = target[0] - source[0];
00759             const Coordinate dy  = target[1] - source[1];
00760             const Coordinate dz  = target[2] - source[2];
00761 
00762             sgdk::ZeroChecker<Coordinate>
00763                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
00764 
00765             if (zero_checker.isZero(dx - inc))
00766             {
00767                 if (zero_checker.isZero(dy))
00768                 {
00769                     if (zero_checker.isZero(dz))
00770                     {
00771                         return true;
00772                     }
00773                     else if (
00774                         BooleanConstantHas26SidedSolidMinCorner::value
00775                      == (
00776                             (
00777                                 static_cast<int>(
00778                                     std::floor(
00779                                         (
00780                                             (source[0] - min[0])
00781                                           + (source[1] - min[1])
00782                                           + (source[2] - min[2])
00783                                         )
00784                                       / inc
00785                                       + 0.5
00786                                     )
00787                                 )
00788                               & 1
00789                             )
00790                          == 0
00791                         )
00792                     )
00793                     {
00794                         return
00795                             zero_checker.isZero(dz + inc)
00796                          || zero_checker.isZero(dz - inc);
00797                     }
00798                     else
00799                     {
00800                         return false;
00801                     }
00802                 }
00803                 else if (
00804                     zero_checker.isZero(dz)
00805                  && (
00806                         zero_checker.isZero(dy + inc)
00807                      || zero_checker.isZero(dy - inc)
00808                     )
00809                 )
00810                 {
00811                     return
00812                         BooleanConstantHas26SidedSolidMinCorner::value
00813                      == (
00814                             (
00815                                 static_cast<int>(
00816                                     std::floor(
00817                                         (
00818                                             (source[0] - min[0])
00819                                           - (source[1] - min[1])
00820                                           + (source[2] - min[2])
00821                                         )
00822                                       / inc
00823                                       + source[1]
00824                                       + 0.5
00825                                     )
00826                                 )
00827                               & 1
00828                             )
00829                          != 0
00830                         );
00831                 }
00832                 else
00833                 {
00834                     return false;
00835                 }
00836             }
00837             else if (zero_checker.isZero(dx))
00838             {
00839                 if (zero_checker.isZero(dy))
00840                 {
00841                     return zero_checker.isZero(dz - inc);
00842                 }
00843                 else if (zero_checker.isZero(dy - inc))
00844                 {
00845                     if (zero_checker.isZero(dz))
00846                     {
00847                         return true;
00848                     }
00849                     else if (
00850                         BooleanConstantHas26SidedSolidMinCorner::value
00851                      == (
00852                             (
00853                                 static_cast<int>(
00854                                     std::floor(
00855                                         (
00856                                             (source[0] - min[0])
00857                                           + (source[1] - min[1])
00858                                           + (source[2] - min[2])
00859                                         )
00860                                       / inc
00861                                       + 0.5
00862                                     )
00863                                 )
00864                               & 1
00865                             )
00866                          == 0
00867                         )
00868                     )
00869                     {
00870                         return
00871                             zero_checker.isZero(dz + inc)
00872                          || zero_checker.isZero(dz - inc);
00873                     }
00874                     else
00875                     {
00876                         return false;
00877                     }
00878                 }
00879                 else
00880                 {
00881                     return false;
00882                 }
00883             }
00884             else
00885             {
00886                 return false;
00887             }
00888         }
00889     };
00890   }  // namespace _detail
00891 
00896 struct Upsilon26SidedSolidMinCornerTesselationSelector
00897 {
00898 };
00899 
00904 template <>
00905 struct TesselationFormerGenerator<
00906     Upsilon26SidedSolidMinCornerTesselationSelector
00907 >
00908 {
00909     template <typename Pattern>
00910     struct apply
00911     {
00912         typedef typename _detail::Upsilon3DParallelepipedTesselationFormer<
00913                     Pattern
00914                   , boost::mpl::true_
00915                 >::type
00916                 type;
00917     };
00918 };
00919 
00924 struct UpsilonCubeMinCornerTesselationSelector
00925 {
00926 };
00927 
00932 template <>
00933 struct TesselationFormerGenerator<UpsilonCubeMinCornerTesselationSelector>
00934 {
00935     template <typename Pattern>
00936     struct apply
00937     {
00938         typedef typename _detail::Upsilon3DParallelepipedTesselationFormer<
00939                     Pattern
00940                   , boost::mpl::false_
00941                 >::type
00942                 type;
00943     };
00944 };
00945 
00946   namespace _detail {
00947 
00952     template <
00953         typename PatternType
00954     >
00955     struct ZetaTesselationFormer
00956     {
00957         typedef PatternType
00958                 Pattern;
00959         typedef CubicGridParallelepipedTag
00960                 tag;
00961         typedef ZetaTesselationFormer
00962                 type;
00963 
00964      private:
00965         typedef typename Pattern::Cell
00966                 Cell;
00967         typedef typename Pattern::Coordinate
00968                 Coordinate;
00969 
00970      public:
00971         BOOST_STATIC_CONSTANT(bool, MAKES_3D_TESSELATION = true);
00972 
00973         template <
00974             typename ArgumentPack
00975         >
00976         static typename Pattern::CellIndex
00977             countCells(
00978                 const ArgumentPack& p
00979             )
00980         {
00981             const Cell&      min = p[init_cell_minimum_arg];
00982             const Cell&      max = p[init_cell_maximum_arg];
00983             const Coordinate inc = p[init_cell_increment_arg];
00984 
00985             Coordinate                  x, y, z;
00986             typename Pattern::CellIndex cell_count = 0;
00987 
00988             for (
00989                 z = min[2];
00990                 z <= max[2];
00991                 z += inc
00992             )
00993             {
00994                 for (
00995                     y = min[1];
00996                     y <= max[1];
00997                     y += inc
00998                 )
00999                 {
01000                     for (
01001                         x = min[0];
01002                         x <= max[0];
01003                         x += inc
01004                     )
01005                     {
01006                         ++cell_count;
01007                     }
01008                 }
01009             }
01010 
01011             return cell_count;
01012         }
01013 
01014         template <
01015             typename OutputIterator
01016           , typename ArgumentPack
01017         >
01018         static void
01019             makeCells(
01020                 OutputIterator cell_iterator
01021               , const ArgumentPack& p
01022             )
01023         {
01024             const Cell&      min = p[init_cell_minimum_arg];
01025             const Cell&      max = p[init_cell_maximum_arg];
01026             const Coordinate inc = p[init_cell_increment_arg];
01027 
01028             Cell cell(3);
01029 
01030             for (
01031                 cell[2] = min[2];
01032                 cell[2] <= max[2];
01033                 cell[2] += inc
01034             )
01035             {
01036                 for (
01037                     cell[1] = min[1];
01038                     cell[1] <= max[1];
01039                     cell[1] += inc
01040                 )
01041                 {
01042                     for (
01043                         cell[0] = min[0];
01044                         cell[0] <= max[0];
01045                         cell[0] += inc
01046                     )
01047                     {
01048                         *cell_iterator = cell;
01049                         ++cell_iterator;
01050                     }
01051                 }
01052             }
01053         }
01054 
01055         template <
01056             typename ArgumentPack
01057         >
01058         static bool
01059             isLegalEdge(
01060                 const typename Pattern::Cell& source
01061               , const typename Pattern::Cell& target
01062               , const ArgumentPack& p
01063             )
01064         {
01065         
01066 
01067             const Coordinate inc = p[init_cell_increment_arg];
01068             const Coordinate dx  = target[0] - source[0];
01069             const Coordinate dy  = target[1] - source[1];
01070             const Coordinate dz  = target[2] - source[2];
01071 
01072             sgdk::ZeroChecker<Coordinate>
01073                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
01074 
01075             return
01076                 zero_checker.isZero(dz - inc)
01077              && (
01078                     (
01079                         zero_checker.isZero(dx)
01080                      || zero_checker.isZero(dx - inc)
01081                     )
01082                  && (
01083                         zero_checker.isZero(dy)
01084                      || zero_checker.isZero(dy - inc)
01085                     )
01086                  || zero_checker.isZero(dx - inc)
01087                  && zero_checker.isZero(dy + inc)
01088                  || zero_checker.isZero(dx + inc)
01089                  && zero_checker.isZero(dy - inc)
01090                 )
01091              || zero_checker.isZero(dz + inc)
01092              && (
01093                     zero_checker.isZero(dy - inc)
01094                  && (
01095                         zero_checker.isZero(dx - inc)
01096                      || zero_checker.isZero(dx)
01097                     )
01098                  || zero_checker.isZero(dx - inc)
01099                  && zero_checker.isZero(dy)
01100                 )
01101              || zero_checker.isZero(dz)
01102              && (
01103                     zero_checker.isZero(dy - inc)
01104                  && (
01105                         zero_checker.isZero(dx - inc)
01106                      || zero_checker.isZero(dx)
01107                     )
01108                  || zero_checker.isZero(dx - inc)
01109                  && (
01110                         zero_checker.isZero(dy)
01111                      || zero_checker.isZero(dy + inc)
01112                     )
01113                 );
01114         }
01115     };
01116   }  // namespace _detail
01117 
01122 struct ZetaTesselationSelector
01123 {
01124 };
01125 
01130 template <>
01131 struct TesselationFormerGenerator<ZetaTesselationSelector>
01132 {
01133     template <typename Pattern>
01134     struct apply
01135     {
01136         typedef typename _detail::ZetaTesselationFormer<
01137                     Pattern
01138                 >::type
01139                 type;
01140     };
01141 };
01142 
01143   namespace _parallelepiped {
01144 
01149     struct parameters
01150       : boost::parameter::parameters<
01151             boost::parameter::required<
01152                 keyword_tag::init_tesselation_selector_arg
01153             >
01154           , boost::parameter::required<
01155                 keyword_tag::init_cell_minimum_arg
01156             >
01157           , boost::parameter::required<
01158                 keyword_tag::init_cell_maximum_arg
01159             >
01160           , boost::parameter::required<
01161                 keyword_tag::init_cell_increment_arg
01162             >
01163           , boost::parameter::required<
01164                 keyword_tag::init_entrance_cell_arg
01165             >
01166           , boost::parameter::required<
01167                 keyword_tag::init_exit_cell_arg
01168             >
01169           , boost::parameter::optional<
01170                 keyword_tag::init_zero_direction_arg
01171             >
01172           , boost::parameter::optional<
01173                 keyword_tag::init_positive_rotation_arg
01174             >
01175           , boost::parameter::optional<
01176                 keyword_tag::init_zero_tolerance_arg
01177             >
01178         >
01179     {
01180     };
01181   }  // namespace _parallelepiped
01182 
01184 
01362 template <
01363 #ifndef MSMAZES_DOX
01364     typename DirectionType = unsigned int
01365   , typename DirectionChangeType = int
01366   , typename CellContainerSelector = boost::vecS
01367   , typename PiConstant = sgdk::Pi
01368   , typename TangentFunction = sgdk::Tangent
01369 #endif  /* MSMAZES_DOX */
01370 >
01371 class Parallelepiped
01372 #ifndef MSMAZES_DOX
01373   : public PhysicalPattern<
01374                typename TangentFunction::result_type
01375              , DirectionType
01376              , DirectionChangeType
01377              , CellContainerSelector
01378            >
01379 #endif  /* MSMAZES_DOX */
01380 {
01381 #ifndef MSMAZES_DOX
01382  private:
01383     typedef PhysicalPattern<
01384                 typename TangentFunction::result_type
01385               , DirectionType
01386               , DirectionChangeType
01387               , CellContainerSelector
01388             >
01389             ParentPattern;
01390 #endif  /* MSMAZES_DOX */
01391 
01392  public:
01397 #ifdef MSMAZES_DOX
01398     typedef implementation_defined Cell;
01399 #else
01400     typedef typename ParentPattern::Cell
01401             Cell;
01402 #endif  /* MSMAZES_DOX */
01403 
01409 #ifdef MSMAZES_DOX
01410     typedef implementation_defined Coordinate;
01411 #else
01412     typedef typename ParentPattern::Coordinate
01413             Coordinate;
01414 #endif  /* MSMAZES_DOX */
01415 
01421 #ifdef MSMAZES_DOX
01422     typedef implementation_defined CellEqualityPolicy;
01423 #else
01424     typedef typename ParentPattern::CellEqualityPolicy
01425             CellEqualityPolicy;
01426 #endif  /* MSMAZES_DOX */
01427 
01433 #ifdef MSMAZES_DOX
01434     typedef implementation_defined Graph;
01435 #else
01436     typedef typename ParentPattern::Graph
01437             Graph;
01438 #endif  /* MSMAZES_DOX */
01439 
01445 #ifdef MSMAZES_DOX
01446     typedef implementation_defined CellIndex;
01447 #else
01448     typedef typename ParentPattern::CellIndex
01449             CellIndex;
01450 #endif  /* MSMAZES_DOX */
01451 
01457 #ifdef MSMAZES_DOX
01458     typedef implementation_defined EdgeDirectedCategory;
01459 #else
01460     typedef typename ParentPattern::EdgeDirectedCategory
01461             EdgeDirectedCategory;
01462 #endif  /* MSMAZES_DOX */
01463 
01469 #ifdef MSMAZES_DOX
01470     typedef implementation_defined Direction;
01471 #else
01472     typedef typename ParentPattern::Direction
01473             Direction;
01474 #endif  /* MSMAZES_DOX */
01475 
01482 #ifdef MSMAZES_DOX
01483     typedef implementation_defined DirectionChange;
01484 #else
01485     typedef typename ParentPattern::DirectionChange
01486             DirectionChange;
01487 #endif  /* MSMAZES_DOX */
01488 
01494 #ifdef MSMAZES_DOX
01495     typedef implementation_defined OutDegree;
01496 #else
01497     typedef typename ParentPattern::OutDegree
01498             OutDegree;
01499 #endif  /* MSMAZES_DOX */
01500 
01506 #ifdef MSMAZES_DOX
01507     typedef implementation_defined HasIndexableEndpointCells;
01508 #else
01509     typedef typename ParentPattern::HasIndexableEndpointCells
01510             HasIndexableEndpointCells;
01511 #endif  /* MSMAZES_DOX */
01512 
01513  private:
01514     typedef Parallelepiped
01515             type;
01516     typedef sgdk::Compass<Direction,DirectionChange,PiConstant,TangentFunction>
01517             Compass;
01518 
01519     bool                          _is_3d;
01520     bool                          _is_not_3d_tesselation;
01521     bool                          _is_zeta;
01522     OutDegree                     _max_3d_out_degree;
01523     Compass                       _xy_compass;
01524     Compass                       _xz_compass;
01525     Compass                       _yz_compass;
01526     sgdk::ZeroDirection           _zero_direction;
01527     sgdk::PositiveRotation        _positive_rotation;
01528     sgdk::ZeroChecker<Coordinate> _zero_checker;
01529 
01530     Parallelepiped(const type& copy)
01531     {
01532     }
01533 
01534  public:
01536 
01540     Parallelepiped()
01541       : ParentPattern()
01542       , _is_3d(false)
01543       , _is_not_3d_tesselation(false)
01544       , _is_zeta(false)
01545       , _max_3d_out_degree()
01546       , _xy_compass()
01547       , _xz_compass()
01548       , _yz_compass()
01549       , _zero_direction(sgdk::ZeroDirection::POSITIVE_Y_AXIS)
01550       , _positive_rotation(sgdk::PositiveRotation::CLOCKWISE)
01551       , _zero_checker(0.00001)
01552     {
01553     }
01554 
01556 
01559     virtual ~Parallelepiped()
01560     {
01561     }
01562 
01592     static Cell
01593         createCell(
01594             const Coordinate x
01595           , const Coordinate y
01596           , const Coordinate z
01597         )
01598     {
01599         return ParentPattern::createCell(x, y, z);
01600     }
01601 
01631     static Cell
01632         createCellIncrement(
01633             const Coordinate x
01634           , const Coordinate y
01635           , const Coordinate z
01636         )
01637     {
01638         return ParentPattern::createCell(x, y, z);
01639     }
01640 
01641  private:
01642     template <
01643         typename ArgumentPack
01644     >
01645     void
01646         _initializeFromTesselationFormer(
01647             const _detail::OrthogonalParallelepipedTag& tag
01648           , const ArgumentPack& p
01649         )
01650     {
01651         const Cell& min = p[init_cell_minimum_arg];
01652         const Cell& max = p[init_cell_maximum_arg];
01653         const Cell& inc = p[init_cell_increment_arg];
01654 
01655         BOOST_ASSERT(
01656             (
01657                 (min[2] < max[2])
01658              || _zero_checker.isZero(max[2] - min[2])
01659             )
01660          && "The z coordinates of your bounds are out of order."
01661         );
01662         BOOST_ASSERT(
01663             (0.0 < inc[0])
01664          && !_zero_checker.isZero(inc[0])
01665          && "How long is this pattern along the x axis?"
01666         );
01667         BOOST_ASSERT(
01668             (0.0 < inc[1])
01669          && !_zero_checker.isZero(inc[1])
01670          && "How long is this pattern along the y axis?"
01671         );
01672         BOOST_ASSERT(
01673             (0.0 < inc[2])
01674          && !_zero_checker.isZero(inc[2])
01675          && "How long is this pattern along the z axis?"
01676         );
01677 
01678         const Coordinate endpoint_x_maximum = max[0] - inc[0];
01679         const Coordinate endpoint_x_minimum = min[0] + inc[0];
01680         const Coordinate endpoint_y_maximum = max[1] - inc[1];
01681         const Coordinate endpoint_y_minimum = min[1] + inc[1];
01682 
01683         BOOST_ASSERT(
01684             (
01685                 (endpoint_x_minimum < endpoint_x_maximum)
01686              || _zero_checker.isZero(
01687                     endpoint_x_maximum - endpoint_x_minimum
01688                 )
01689             )
01690          && "The x coordinates of your bounds are out of order."
01691         );
01692         BOOST_ASSERT(
01693             (
01694                 (endpoint_y_minimum < endpoint_y_maximum)
01695              || _zero_checker.isZero(
01696                     endpoint_y_maximum - endpoint_y_minimum
01697                 )
01698             )
01699          && "The y coordinates of your bounds are out of order."
01700         );
01701 
01702         _xy_compass.setDirectionCount(4);
01703         _xz_compass.setDirectionCount(4);
01704         _yz_compass.setDirectionCount(4);
01705         _max_3d_out_degree = 6;
01706 
01707         _is_3d
01708           = (min[2] + inc[2] < max[2])
01709          || _zero_checker.isZero(max[2] - min[2] - inc[2]);
01710     }
01711 
01712     template <
01713         typename ArgumentPack
01714     >
01715     void
01716         _initializeFromTesselationFormer(
01717             const _detail::Upsilon2DParallelepipedTag& tag
01718           , const ArgumentPack& p
01719         )
01720     {
01721         const Cell&
01722             min = p[init_cell_minimum_arg];
01723         const Cell&
01724             max = p[init_cell_maximum_arg];
01725         const _detail::Upsilon2DIncrement<Coordinate>&
01726             inc = p[init_cell_increment_arg];
01727         const Coordinate
01728             w_inc = inc.getOctagonSquareCellCenterDistance();
01729         const Coordinate
01730             z_inc = inc.getZIncrement();
01731 
01732         BOOST_ASSERT(
01733             (
01734                 (min[2] < max[2])
01735              || _zero_checker.isZero(max[2] - min[2])
01736             )
01737          && "The z coordinates of your bounds are out of order."
01738         );
01739         BOOST_ASSERT(
01740             (0.0 < w_inc)
01741          && !_zero_checker.isZero(w_inc)
01742          && "How long is this pattern along the x and y axes?"
01743         );
01744         BOOST_ASSERT(
01745             (0.0 < z_inc)
01746          && !_zero_checker.isZero(z_inc)
01747          && "How long is this pattern along the z axis?"
01748         );
01749 
01750         const Coordinate endpoint_x_maximum = max[0] - w_inc;
01751         const Coordinate endpoint_x_minimum = min[0] + w_inc;
01752         const Coordinate endpoint_y_maximum = max[1] - w_inc;
01753         const Coordinate endpoint_y_minimum = min[1] + w_inc;
01754 
01755         BOOST_ASSERT(
01756             (
01757                 (endpoint_x_minimum < endpoint_x_maximum)
01758              || _zero_checker.isZero(
01759                     endpoint_x_maximum - endpoint_x_minimum
01760                 )
01761             )
01762          && "The x coordinates of your bounds are out of order."
01763         );
01764         BOOST_ASSERT(
01765             (
01766                 (endpoint_y_minimum < endpoint_y_maximum)
01767              || _zero_checker.isZero(
01768                     endpoint_y_maximum - endpoint_y_minimum
01769                 )
01770             )
01771          && "The y coordinates of your bounds are out of order."
01772         );
01773 
01774         _xy_compass.setDirectionCount(8);
01775         _xz_compass.setDirectionCount(8);
01776         _yz_compass.setDirectionCount(8);
01777 
01778         _max_3d_out_degree = 10;
01779         _is_3d
01780           = (min[2] + z_inc < max[2])
01781          || _zero_checker.isZero(max[2] - min[2] - z_inc);
01782     }
01783 
01784     template <
01785         typename ArgumentPack
01786     >
01787     void
01788         _initializeFromTesselationFormer(
01789             const _detail::CubicGridParallelepipedTag& tag
01790           , const ArgumentPack& p
01791         )
01792     {
01793         const Cell&      min = p[init_cell_minimum_arg];
01794         const Cell&      max = p[init_cell_maximum_arg];
01795         const Coordinate inc = p[init_cell_increment_arg];
01796 
01797         BOOST_ASSERT(
01798             (
01799                 (min[2] < max[2])
01800              || _zero_checker.isZero(max[2] - min[2])
01801             )
01802          && "The z coordinates of your bounds are out of order."
01803         );
01804         BOOST_ASSERT(
01805             (0.0 < inc)
01806          && !_zero_checker.isZero(inc)
01807          && "How long is this pattern along the x, y, and z axes?"
01808         );
01809 
01810         const Coordinate endpoint_x_maximum = max[0] - inc;
01811         const Coordinate endpoint_x_minimum = min[0] + inc;
01812         const Coordinate endpoint_y_maximum = max[1] - inc;
01813         const Coordinate endpoint_y_minimum = min[1] + inc;
01814 
01815         BOOST_ASSERT(
01816             (
01817                 (endpoint_x_minimum < endpoint_x_maximum)
01818              || _zero_checker.isZero(
01819                     endpoint_x_maximum - endpoint_x_minimum
01820                 )
01821             )
01822          && "The x coordinates of your bounds are out of order."
01823         );
01824         BOOST_ASSERT(
01825             (
01826                 (endpoint_y_minimum < endpoint_y_maximum)
01827              || _zero_checker.isZero(
01828                     endpoint_y_maximum - endpoint_y_minimum
01829                 )
01830             )
01831          && "The y coordinates of your bounds are out of order."
01832         );
01833 
01834         _xy_compass.setDirectionCount(8);
01835         _xz_compass.setDirectionCount(8);
01836         _yz_compass.setDirectionCount(8);
01837         _max_3d_out_degree = _is_zeta ? 26 : 18;
01838         _is_3d
01839           = (min[2] + inc < max[2])
01840          || _zero_checker.isZero(max[2] - min[2] - inc);
01841     }
01842 
01843  public:
01844 #ifdef MSMAZES_DOX
01845 
02011     template <typename TesselationSelector, typename Increment>
02012     void initialize(
02013         const TesselationSelector& init_tesselation_selector_arg
02014       , const Cell& init_cell_minimum_arg
02015       , const Cell& init_cell_maximum_arg
02016       , Increment init_cell_increment_arg
02017       , const Cell& init_entrance_cell_arg
02018       , const Cell& init_exit_cell_arg
02019       , const sgdk::ZeroDirection& init_zero_direction_arg
02020       , const sgdk::PositiveRotation& init_positive_rotation_arg
02021       , const Coordinate init_zero_tolerance_arg
02022     );
02023 
02030     template <typename Params>
02031     void initialize_with_named_params(Params& p)
02032 #else
02033     BOOST_PARAMETER_MEMFUN(
02034         void
02035       , initialize
02036       , 6
02037       , MSMAZES_CORE_PATTERN_ARITY
02038       , _parallelepiped::parameters
02039     )
02040 #endif  /* MSMAZES_DOX */
02041     {
02042         typedef MSMAZES_CORE_PATTERN_TESSELATION_FORMER_TYPE(Params, type)
02043                 TesselationFormer;
02044         typedef typename TesselationFormer::tag
02045                 Tag;
02046 
02047         _is_not_3d_tesselation
02048           = !TesselationFormer::MAKES_3D_TESSELATION;
02049         _is_zeta
02050           = boost::is_same<
02051                 TesselationFormer
02052               , _detail::ZetaTesselationFormer<type>
02053             >::value;
02054         _zero_direction
02055           = p[init_zero_direction_arg | sgdk::ZeroDirection::POSITIVE_Y_AXIS];
02056         _positive_rotation
02057           = p[init_positive_rotation_arg | sgdk::PositiveRotation::CLOCKWISE];
02058         _zero_checker.setZeroTolerance(p[init_zero_tolerance_arg | 0.00001]);
02059 
02060         _xy_compass.setZeroDirection(_zero_direction);
02061         _initializeFromTesselationFormer(Tag(), p);
02062         ParentPattern::initializeWithTesselationFormer(TesselationFormer(), p);
02063 
02064         if (_zero_direction.isParallelToYAxis())
02065         {
02066             _xz_compass.setZeroDirection(sgdk::ZeroDirection::POSITIVE_Y_AXIS);
02067             _xz_compass.setPositiveRotation(_positive_rotation);
02068 
02069             if (_zero_direction.isPositive())
02070             {
02071                 _yz_compass.setZeroDirection(
02072                     sgdk::ZeroDirection::POSITIVE_X_AXIS
02073                 );
02074                 _yz_compass.setPositiveRotation(
02075                     _positive_rotation.isClockwise()
02076                   ? sgdk::PositiveRotation::COUNTERCLOCKWISE
02077                   : sgdk::PositiveRotation::CLOCKWISE
02078                 );
02079             }
02080             else
02081             {
02082                 _yz_compass.setZeroDirection(
02083                     sgdk::ZeroDirection::NEGATIVE_X_AXIS
02084                 );
02085                 _yz_compass.setPositiveRotation(_positive_rotation);
02086             }
02087         }
02088         else// if (_zero_direction.isParallelToXAxis())
02089         {
02090             _yz_compass.setZeroDirection(sgdk::ZeroDirection::POSITIVE_Y_AXIS);
02091             _yz_compass.setPositiveRotation(_positive_rotation);
02092 
02093             if (_zero_direction.isPositive())
02094             {
02095                 _xz_compass.setZeroDirection(
02096                     sgdk::ZeroDirection::POSITIVE_X_AXIS
02097                 );
02098                 _xz_compass.setPositiveRotation(
02099                     _positive_rotation.isClockwise()
02100                   ? sgdk::PositiveRotation::COUNTERCLOCKWISE
02101                   : sgdk::PositiveRotation::CLOCKWISE
02102                 );
02103             }
02104             else
02105             {
02106                 _xz_compass.setZeroDirection(
02107                     sgdk::ZeroDirection::NEGATIVE_X_AXIS
02108                 );
02109                 _xz_compass.setPositiveRotation(_positive_rotation);
02110             }
02111         }
02112     }
02113 
02120     inline const Graph& getGraph() const
02121     {
02122         return ParentPattern::getGraph();
02123     }
02124 
02130     inline CellIndex getCellCount() const
02131     {
02132         return ParentPattern::getCellCount();
02133     }
02134 
02140     inline const Cell& getCell(const CellIndex index) const
02141     {
02142         return ParentPattern::getCell(index);
02143     }
02144 
02150     inline const Cell& getEntranceCell() const
02151     {
02152         return ParentPattern::getEntranceCell();
02153     }
02154 
02161     inline const Cell& getSourceCell() const
02162     {
02163         return ParentPattern::getSourceCell();
02164     }
02165 
02172     inline const Cell& getTargetCell() const
02173     {
02174         return ParentPattern::getTargetCell();
02175     }
02176 
02182     inline const Cell& getExitCell() const
02183     {
02184         return ParentPattern::getExitCell();
02185     }
02186 
02187 #ifndef MSMAZES_DOX
02188  protected:
02189     Direction
02190         getEdgeDirectionDerived(
02191             const Cell& source
02192           , const Cell& target
02193         ) const
02194     {
02195         const Coordinate dx = target[0] - source[0];
02196         const Coordinate dy = target[1] - source[1];
02197         const Coordinate dz = target[2] - source[2];
02198 
02199         if (_zero_checker.isZero(dz))
02200         {
02201             if (_zero_direction.isParallelToYAxis())
02202             {
02203                 return _xy_compass.getDirection(dx, dy);
02204             }
02205             else// if (_zero_direction.isParallelToXAxis())
02206             {
02207                 return _xy_compass.getDirection(dy, dx);
02208             }
02209         }
02210         else if (_is_zeta)
02211         {
02212             if (_zero_checker.isZero(dx) && _zero_checker.isZero(dy))
02213             {
02214                 return (dz < 0.0) ? 25 : 16;
02215             }
02216             else if (_zero_direction.isParallelToYAxis())
02217             {
02218                 return
02219                     _xy_compass.getDirection(dx, dy) + ((dz < 0.0) ? 17 : 8);
02220             }
02221             else// if (_zero_direction.isParallelToXAxis())
02222             {
02223                 return
02224                     _xy_compass.getDirection(dy, dx) + ((dz < 0.0) ? 17 : 8);
02225             }
02226         }
02227         else// if (!_zero_checker.isZero(dz) && !_is_zeta)
02228         {
02229             const Direction
02230                 direction_count = _xy_compass.getDirectionCount();
02231 
02232             if (_zero_direction.isParallelToYAxis())
02233             {
02234                 if (_is_not_3d_tesselation)
02235                 {
02236                     return
02237                         direction_count
02238                       + (
02239                             ((direction_count & 1) == 0)
02240                          && (
02241                                 (
02242                                     _yz_compass.getDirection(dy, dz) 
02243                                   > (direction_count >> 1)
02244                                 )
02245                              == _positive_rotation.isClockwise()
02246                             )
02247                           ? 0
02248                           : 1
02249                         );
02250                 }
02251                 else if (_zero_checker.isZero(dx))
02252                 {
02253                     const Direction
02254                         direction = _yz_compass.getDirection(dy, dz);
02255 
02256                     return
02257                         direction
02258                       + direction_count
02259                       - (
02260                             ((direction_count & 1) == 0)
02261                          && (direction > (direction_count >> 1))
02262                           ? 2
02263                           : 1
02264                         );
02265                 }
02266                 else if ((direction_count & 3) == 0)
02267                 {
02268                     const Direction
02269                         direction = _xz_compass.getDirection(dx, dz);
02270 
02271                     return
02272                         direction
02273                       + (direction_count << 1)
02274                       - (
02275                             (direction > (direction_count >> 1))
02276                           ? ((direction > ((direction_count * 3) >> 2)) ? 6 : 5)
02277                           : ((direction > (direction_count >> 2)) ? 4 : 3)
02278                         );
02279                 }
02280                 else
02281                 {
02282                     return
02283                         _xz_compass.getDirection(dx, dz)
02284                       + (direction_count << 1)
02285                       - ((direction_count & 1) ? 1 : 2);
02286                 }
02287             }
02288             else// if (_zero_direction.isParallelToXAxis())
02289             {
02290                 if (_is_not_3d_tesselation)
02291                 {
02292                     return
02293                         direction_count
02294                       + (
02295                             ((direction_count & 1) == 0)
02296                          && (
02297                                 _xz_compass.getDirection(dx, dz)
02298                               > (direction_count >> 1)
02299                             )
02300                           ? 0
02301                           : 1
02302                         );
02303                 }
02304                 else if (_zero_checker.isZero(dy))
02305                 {
02306                     const Direction
02307                         direction = _xz_compass.getDirection(dx, dz);
02308 
02309                     return
02310                         direction
02311                       + direction_count
02312                       - (
02313                             ((direction_count & 1) == 0)
02314                          && (direction > (direction_count >> 1))
02315                           ? 2
02316                           : 1
02317                         );
02318                 }
02319                 else if ((direction_count & 3) == 0)
02320                 {
02321                     const Direction
02322                         direction = _yz_compass.getDirection(dy, dz);
02323 
02324                     return
02325                         direction
02326                       + (direction_count << 1)
02327                       - (
02328                             (direction > (direction_count >> 1))
02329                           ? ((direction > ((direction_count * 3) >> 2)) ? 6 : 5)
02330                           : ((direction > (direction_count >> 2)) ? 4 : 3)
02331                         );
02332                 }
02333                 else
02334                 {
02335                     return
02336                         _yz_compass.getDirection(dy, dz)
02337                       + (direction_count << 1)
02338                       - ((direction_count & 1) ? 1 : 2);
02339                 }
02340             }
02341         }
02342     }
02343 
02344     DirectionChange
02345         getYawTurnDerived(
02346             const Cell& source
02347           , const Cell& parent
02348           , const Cell& target
02349         ) const
02350     {
02351         const Coordinate dx1 = parent[0] - source[0];
02352         const Coordinate dy1 = parent[1] - source[1];
02353 
02354         if (_zero_checker.isZero(dx1) && _zero_checker.isZero(dy1))
02355         {
02356             return 0;
02357         }
02358 
02359         const Coordinate dx2 = target[0] - parent[0];
02360         const Coordinate dy2 = target[1] - parent[1];
02361 
02362         if (_zero_checker.isZero(dx2) && _zero_checker.isZero(dy2))
02363         {
02364             return 0;
02365         }
02366 
02367         return _xy_compass.getDirectionChange(dx1, dy1, dx2, dy2);
02368     }
02369 
02370     OutDegree getMaxOutDegreeDerived() const
02371     {
02372         if (_is_3d)
02373         {
02374             return _max_3d_out_degree;
02375         }
02376         else
02377         {
02378             return _xy_compass.getDirectionCount();
02379         }
02380     }
02381 
02382  public:
02383 #endif  /* MSMAZES_DOX */
02384 
02390     Direction
02391         getEdgeDirection(
02392             const CellIndex source_index
02393           , const CellIndex target_index
02394         ) const
02395     {
02396         return ParentPattern::getEdgeDirection(source_index, target_index);
02397     }
02398 
02405     DirectionChange
02406         getYawTurn(
02407             const CellIndex source_index
02408           , const CellIndex parent_index
02409           , const CellIndex target_index
02410         ) const
02411     {
02412         return
02413             ParentPattern::getYawTurn(source_index, parent_index, target_index);
02414     }
02415 
02421     OutDegree getMaxOutDegree() const
02422     {
02423         return ParentPattern::getMaxOutDegree();
02424     }
02425 };
02426 }  // namespace msmazes
02427 
02428 #undef MSMAZES_CORE_PATTERN_ARITY
02429 
02430 #endif  /* MSMAZES_CORE_PATTERN_PARALLELEPIPED_HPP */

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