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 . Use the Table of Contents for navigation.