pattern/sphere.hpp

Go to the documentation of this file.
00001 
00028 #ifndef MSMAZES_CORE_PATTERN_SPHERE_HPP
00029 #define MSMAZES_CORE_PATTERN_SPHERE_HPP
00030 
00031 #define MSMAZES_CORE_PATTERN_ARITY 9
00032 
00033 // BOOST_ASSERT
00034 #include <boost/assert.hpp>
00035 // std::sqrt, std::sin, std::cos, and std::acos
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::numeric::ublas::vector
00044 #include <boost/numeric/ublas/vector.hpp>
00045 // sgdk::ZeroChecker
00046 #include <swiss_gd_knife/math/zero_checker.hpp>
00047 // sgdk::PositiveRotation
00048 #include <swiss_gd_knife/math/geom/compass.hpp>
00049 // Boost.Parameter keyword objects used by the Core Pattern class templates
00050 #include <msmazes/core/pattern/keywords.hpp>
00051 
00052 #if BOOST_PP_LESS(BOOST_PARAMETER_MAX_ARITY, MSMAZES_CORE_PATTERN_ARITY)
00053 #error Set BOOST_PARAMETER_MAX_ARITY to 9 or higher.
00054 #endif
00055 
00056 // msmazes::TesselationFormerGenerator and msmazes::PhysicalPattern
00057 #include <msmazes/core/pattern/physical.hpp>
00058 // MSMAZES_CORE_PATTERN_TESSELATION_FORMER_TYPE
00059 #include <msmazes/core/pattern/tesselation_former_type.hpp>
00060 
00061 namespace msmazes {
00062   namespace _detail {
00063 
00068     struct OctahedronTag
00069     {
00070         BOOST_STATIC_CONSTANT(unsigned int, MAX_OUT_DEGREE = 4);
00071     };
00072 
00077     template <
00078         typename PatternType
00079     >
00080     struct OctahedronTesselationFormer
00081     {
00082      public:
00083         typedef PatternType
00084                 Pattern;
00085 
00086      private:
00087         typedef typename Pattern::Cell
00088                 Cell;
00089         typedef typename Pattern::Coordinate
00090                 Coordinate;
00091 
00092      public:
00093         typedef OctahedronTag
00094                 tag;
00095         typedef OctahedronTesselationFormer
00096                 type;
00097 
00098         template <
00099             typename ArgumentPack
00100         >
00101         static typename Pattern::CellIndex
00102             countCells(
00103                 const ArgumentPack& p
00104             )
00105         {
00106             const Coordinate r_max = p[init_radius_maximum_arg];
00107             const Coordinate r_inc = p[init_radial_increment_arg];
00108 
00109             typename Pattern::CellIndex cell_count = 0;
00110 
00111             for (
00112                 Coordinate r = p[init_radius_minimum_arg];
00113                 r <= r_max;
00114                 r += r_inc
00115             )
00116             {
00117                 cell_count += 6;
00118             }
00119 
00120             return cell_count;
00121         }
00122 
00123         template <
00124             typename OutputIterator
00125           , typename ArgumentPack
00126         >
00127         static void
00128             makeCells(
00129                 OutputIterator cell_iterator
00130               , const ArgumentPack& p
00131             )
00132         {
00133             const Cell&      centroid = p[init_centroid_arg];
00134             const Coordinate cx       = centroid[0];
00135             const Coordinate cy       = centroid[1];
00136             const Coordinate cz       = centroid[2];
00137             const Coordinate r_max    = p[init_radius_maximum_arg];
00138             const Coordinate r_inc    = p[init_radial_increment_arg];
00139 
00140             Cell cell(3);
00141 
00142             for (
00143                 Coordinate r = p[init_radius_minimum_arg];
00144                 r <= r_max;
00145                 r += r_inc
00146             )
00147             {
00148                 cell[0]        = cx + r;
00149                 cell[1]        = cy;
00150                 cell[2]        = cz;
00151                 *cell_iterator = cell;
00152                 ++cell_iterator;
00153 
00154                 cell[0]        = cx - r;
00155                 cell[1]        = cy;
00156                 cell[2]        = cz;
00157                 *cell_iterator = cell;
00158                 ++cell_iterator;
00159 
00160                 cell[0]        = cx;
00161                 cell[1]        = cy + r;
00162                 cell[2]        = cz;
00163                 *cell_iterator = cell;
00164                 ++cell_iterator;
00165 
00166                 cell[0]        = cx;
00167                 cell[1]        = cy - r;
00168                 cell[2]        = cz;
00169                 *cell_iterator = cell;
00170                 ++cell_iterator;
00171 
00172                 cell[0]        = cx;
00173                 cell[1]        = cy;
00174                 cell[2]        = cz + r;
00175                 *cell_iterator = cell;
00176                 ++cell_iterator;
00177 
00178                 cell[0]        = cx;
00179                 cell[1]        = cy;
00180                 cell[2]        = cz - r;
00181                 *cell_iterator = cell;
00182                 ++cell_iterator;
00183             }
00184         }
00185 
00186         template <
00187             typename ArgumentPack
00188         >
00189         static bool
00190             isLegalEdge(
00191                 const typename Pattern::Cell& source
00192               , const typename Pattern::Cell& target
00193               , const ArgumentPack& p
00194             )
00195         {
00196             const Cell&
00197                 centroid = p[init_centroid_arg];
00198             const Coordinate
00199                 src_x = source[0] - centroid[0];
00200             const Coordinate
00201                 src_y = source[1] - centroid[1];
00202             const Coordinate
00203                 src_z = source[2] - centroid[2];
00204             const Coordinate
00205                 src_prod = src_x * src_x + src_y * src_y + src_z * src_z;
00206             const Coordinate
00207                 tgt_x = target[0] - centroid[0];
00208             const Coordinate
00209                 tgt_y = target[1] - centroid[1];
00210             const Coordinate
00211                 tgt_z = target[2] - centroid[2];
00212             const Coordinate
00213                 tgt_prod = tgt_x * tgt_x + tgt_y * tgt_y + tgt_z * tgt_z;
00214             const Coordinate
00215                 dx = target[0] - source[0];
00216             const Coordinate
00217                 dy = target[1] - source[1];
00218             const Coordinate
00219                 dz = target[2] - source[2];
00220             const Coordinate
00221                 edge_len_sq = dx * dx + dy * dy + dz * dz;
00222 
00223             sgdk::ZeroChecker<Coordinate>
00224                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
00225 
00226             if (zero_checker.isZero(src_prod - tgt_prod))
00227             {
00228                 /*
00229                  * The vectors <center,source> and <center,target> have the
00230                  * same length.  Check if <source,target> is a face edge on
00231                  * the surface of the octahedron.
00232                  */
00233                 return zero_checker.isZero(edge_len_sq - src_prod * 2);
00234             }
00235             else
00236             {
00237                 const Coordinate r_inc = p[init_radial_increment_arg];
00238 
00239                 /*
00240                  * The vectors <center,source> and <center,target> have
00241                  * different lengths.  For <source,target> to be a legal
00242                  * edge, the vectors must point in the same direction,
00243                  * and the magnitude difference must equal r_inc.
00244                  */
00245                 return zero_checker.isZero(edge_len_sq - r_inc * r_inc);
00246             }
00247         }
00248     };
00249   }  // namespace _detail
00250 
00255 struct OctahedronTesselationSelector
00256 {
00257 };
00258 
00263 template <>
00264 struct TesselationFormerGenerator<OctahedronTesselationSelector>
00265 {
00266     template <typename Pattern>
00267     struct apply
00268     {
00269         typedef typename _detail::OctahedronTesselationFormer<Pattern>::type
00270                 type;
00271     };
00272 };
00273 
00274   namespace _detail {
00275 
00280     struct IcosahedronTag
00281     {
00282         BOOST_STATIC_CONSTANT(unsigned int, MAX_OUT_DEGREE = 5);
00283     };
00284 
00285     /*
00286      * Constants used by the template class
00287      * IcosahedronTesselationFormer<PatternType>
00288      */
00293     template <typename Coordinate>
00294     struct IcosahedronTesselationConstants
00295     {
00296         static const Coordinate SIN_36;
00297         static const Coordinate COS_36;
00298         static const Coordinate SIN_72;
00299         static const Coordinate COS_72;
00300         static const Coordinate Y_FACTOR;
00301         static const Coordinate Z_FACTOR;
00302         static const Coordinate EDGE_SQUARED_FACTOR;
00303     };
00304 
00305     template <typename Coordinate>
00306     const Coordinate
00307           IcosahedronTesselationConstants<Coordinate>::SIN_36
00308         = static_cast<Coordinate>(std::sin(0.62831853072));
00309 
00310     template <typename Coordinate>
00311     const Coordinate
00312           IcosahedronTesselationConstants<Coordinate>::COS_36
00313         = static_cast<Coordinate>(std::cos(0.62831853072));
00314 
00315     template <typename Coordinate>
00316     const Coordinate
00317           IcosahedronTesselationConstants<Coordinate>::SIN_72
00318         = static_cast<Coordinate>(std::sin(1.25663706144));
00319 
00320     template <typename Coordinate>
00321     const Coordinate
00322           IcosahedronTesselationConstants<Coordinate>::COS_72
00323         = static_cast<Coordinate>(std::cos(1.25663706144));
00324 
00325     template <typename Coordinate>
00326     const Coordinate
00327           IcosahedronTesselationConstants<Coordinate>::Y_FACTOR
00328         = static_cast<Coordinate>(
00329             std::sqrt(
00330               2.0 / (2.0 + std::cos(0.62831853072) - std::cos(1.25663706144))
00331             )
00332           );
00333 
00334     template <typename Coordinate>
00335     const Coordinate
00336           IcosahedronTesselationConstants<Coordinate>::Z_FACTOR
00337         = static_cast<Coordinate>(
00338             std::sqrt(
00339               (std::cos(0.62831853072) - std::cos(1.25663706144))
00340             / (2.0 + std::cos(0.62831853072) - std::cos(1.25663706144))
00341             )
00342           );
00343 
00344     template <typename Coordinate>
00345     const Coordinate
00346           IcosahedronTesselationConstants<Coordinate>::EDGE_SQUARED_FACTOR
00347         = static_cast<Coordinate>(
00348             4.0 * (1.0 - std::cos(1.25663706144))
00349           / (2.0 + std::cos(0.62831853072) - std::cos(1.25663706144))
00350           );
00351 
00356     template <
00357         typename PatternType
00358     >
00359     struct IcosahedronTesselationFormer
00360     {
00361      public:
00362         typedef PatternType
00363                 Pattern;
00364 
00365      private:
00366         typedef typename Pattern::Cell
00367                 Cell;
00368         typedef typename Pattern::Coordinate
00369                 Coordinate;
00370         typedef IcosahedronTesselationConstants<Coordinate>
00371                 _IcosahedronConstants;
00372 
00373      public:
00374         typedef IcosahedronTag
00375                 tag;
00376         typedef IcosahedronTesselationFormer
00377                 type;
00378 
00379         template <
00380             typename ArgumentPack
00381         >
00382         static typename Pattern::CellIndex
00383             countCells(
00384                 const ArgumentPack& p
00385             )
00386         {
00387             const Coordinate r_max = p[init_radius_maximum_arg];
00388             const Coordinate r_inc = p[init_radial_increment_arg];
00389 
00390             typename Pattern::CellIndex cell_count = 0;
00391 
00392             for (
00393                 Coordinate r = p[init_radius_minimum_arg];
00394                 r <= r_max;
00395                 r += r_inc
00396             )
00397             {
00398                 cell_count += 12;
00399             }
00400 
00401             return cell_count;
00402         }
00403 
00404         template <
00405             typename OutputIterator
00406           , typename ArgumentPack
00407         >
00408         static void
00409             makeCells(
00410                 OutputIterator cell_iterator
00411               , const ArgumentPack& p
00412             )
00413         {
00414             const Cell&      centroid = p[init_centroid_arg];
00415             const Coordinate cx       = centroid[0];
00416             const Coordinate cy       = centroid[1];
00417             const Coordinate cz       = centroid[2];
00418             const Coordinate r_max    = p[init_radius_maximum_arg];
00419             const Coordinate r_inc    = p[init_radial_increment_arg];
00420 
00421             Cell cell(3);
00422 
00423             for (
00424                 Coordinate r = p[init_radius_minimum_arg];
00425                 r <= r_max;
00426                 r += r_inc
00427             )
00428             {
00429                 cell[0]        = cx;
00430                 cell[1]        = cy;
00431                 cell[2]        = cz + r;
00432                 *cell_iterator = cell;
00433                 ++cell_iterator;
00434 
00435                 cell[0]        = cx;
00436                 cell[1]        = cy;
00437                 cell[2]        = cz - r;
00438                 *cell_iterator = cell;
00439                 ++cell_iterator;
00440 
00441                 cell[0]        = cx;
00442                 cell[1]        = cy + r * _IcosahedronConstants::Y_FACTOR;
00443                 cell[2]        = cz + r * _IcosahedronConstants::Z_FACTOR;
00444                 *cell_iterator = cell;
00445                 ++cell_iterator;
00446 
00447                 cell[0]        = cx + r * _IcosahedronConstants::Y_FACTOR
00448                                         * _IcosahedronConstants::SIN_72;
00449                 cell[1]        = cy + r * _IcosahedronConstants::Y_FACTOR
00450                                         * _IcosahedronConstants::COS_72;
00451                 *cell_iterator = cell;
00452                 ++cell_iterator;
00453 
00454                 cell[0]        = cx - r * _IcosahedronConstants::Y_FACTOR
00455                                         * _IcosahedronConstants::SIN_72;
00456                 *cell_iterator = cell;
00457                 ++cell_iterator;
00458 
00459                 cell[0]        = cx + r * _IcosahedronConstants::Y_FACTOR
00460                                         * _IcosahedronConstants::SIN_36;
00461                 cell[1]        = cy - r * _IcosahedronConstants::Y_FACTOR
00462                                         * _IcosahedronConstants::COS_36;
00463                 *cell_iterator = cell;
00464                 ++cell_iterator;
00465 
00466                 cell[0]        = cx - r * _IcosahedronConstants::Y_FACTOR
00467                                         * _IcosahedronConstants::SIN_36;
00468                 *cell_iterator = cell;
00469                 ++cell_iterator;
00470 
00471                 cell[0]        = cx;
00472                 cell[1]        = cy - r * _IcosahedronConstants::Y_FACTOR;
00473                 cell[2]        = cz - r * _IcosahedronConstants::Z_FACTOR;
00474                 *cell_iterator = cell;
00475                 ++cell_iterator;
00476 
00477                 cell[0]        = cx + r * _IcosahedronConstants::Y_FACTOR
00478                                         * _IcosahedronConstants::SIN_72;
00479                 cell[1]        = cy - r * _IcosahedronConstants::Y_FACTOR
00480                                         * _IcosahedronConstants::COS_72;
00481                 *cell_iterator = cell;
00482                 ++cell_iterator;
00483 
00484                 cell[0]        = cx - r * _IcosahedronConstants::Y_FACTOR
00485                                         * _IcosahedronConstants::SIN_72;
00486                 *cell_iterator = cell;
00487                 ++cell_iterator;
00488 
00489                 cell[0]        = cx + r * _IcosahedronConstants::Y_FACTOR
00490                                         * _IcosahedronConstants::SIN_36;
00491                 cell[1]        = cy + r * _IcosahedronConstants::Y_FACTOR
00492                                         * _IcosahedronConstants::COS_36;
00493                 *cell_iterator = cell;
00494                 ++cell_iterator;
00495 
00496                 cell[0]        = cx - r * _IcosahedronConstants::Y_FACTOR
00497                                         * _IcosahedronConstants::SIN_36;
00498                 *cell_iterator = cell;
00499                 ++cell_iterator;
00500             }
00501         }
00502 
00503         template <
00504             typename ArgumentPack
00505         >
00506         static bool
00507             isLegalEdge(
00508                 const typename Pattern::Cell& source
00509               , const typename Pattern::Cell& target
00510               , const ArgumentPack& p
00511             )
00512         {
00513             const Cell&
00514                 centroid = p[init_centroid_arg];
00515             const Coordinate
00516                 src_x = source[0] - centroid[0];
00517             const Coordinate
00518                 src_y = source[1] - centroid[1];
00519             const Coordinate
00520                 src_z = source[2] - centroid[2];
00521             const Coordinate
00522                 src_prod = src_x * src_x + src_y * src_y + src_z * src_z;
00523             const Coordinate
00524                 tgt_x = target[0] - centroid[0];
00525             const Coordinate
00526                 tgt_y = target[1] - centroid[1];
00527             const Coordinate
00528                 tgt_z = target[2] - centroid[2];
00529             const Coordinate
00530                 tgt_prod = tgt_x * tgt_x + tgt_y * tgt_y + tgt_z * tgt_z;
00531             const Coordinate
00532                 dx = target[0] - source[0];
00533             const Coordinate
00534                 dy = target[1] - source[1];
00535             const Coordinate
00536                 dz = target[2] - source[2];
00537             const Coordinate
00538                 edge_len_sq = dx * dx + dy * dy + dz * dz;
00539 
00540             sgdk::ZeroChecker<Coordinate>
00541                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
00542 
00543             if (zero_checker.isZero(src_prod - tgt_prod))
00544             {
00545                 /*
00546                  * The vectors <center,source> and <center,target> have the
00547                  * same length.  Check if <source,target> is a face edge on
00548                  * the surface of the octahedron.
00549                  */
00550                 return zero_checker.isZero(
00551                            edge_len_sq
00552                          - src_prod
00553                          * _IcosahedronConstants::EDGE_SQUARED_FACTOR
00554                        );
00555             }
00556             else
00557             {
00558                 const Coordinate r_inc = p[init_radial_increment_arg];
00559 
00560                 /*
00561                  * The vectors <center,source> and <center,target> have
00562                  * different lengths.  For <source,target> to be a legal
00563                  * edge, the vectors must point in the same direction,
00564                  * and the magnitude difference must equal r_inc.
00565                  */
00566                 return zero_checker.isZero(edge_len_sq - r_inc * r_inc);
00567             }
00568         }
00569     };
00570   }  // namespace _detail
00571 
00576 struct IcosahedronTesselationSelector
00577 {
00578 };
00579 
00584 template <>
00585 struct TesselationFormerGenerator<IcosahedronTesselationSelector>
00586 {
00587     template <typename Pattern>
00588     struct apply
00589     {
00590         typedef typename _detail::IcosahedronTesselationFormer<Pattern>::type
00591                 type;
00592     };
00593 };
00594 
00595   namespace _detail {
00596 
00601     struct BuckyballTag
00602     {
00603         BOOST_STATIC_CONSTANT(unsigned int, MAX_OUT_DEGREE = 3);
00604     };
00605 
00606     /*
00607      * Constants used by the template class
00608      * BuckyballTesselationFormer<PatternType>
00609      */
00614     template <typename Coordinate>
00615     struct BuckyballTesselationConstants
00616     {
00617         static const Coordinate GOLDEN_MEAN_2X;
00618         static const Coordinate GOLDEN_MEAN;
00619         static const Coordinate RADIAL_DIVISOR;
00620         static const Coordinate EDGE_SQUARED_FACTOR;
00621     };
00622 
00623     // 1 + sqrt(5)
00624     template <typename Coordinate>
00625     const Coordinate
00626           BuckyballTesselationConstants<Coordinate>::GOLDEN_MEAN_2X
00627         = static_cast<Coordinate>(3.2360679774997896964);
00628 
00629     // (1 + sqrt(5)) / 2
00630     template <typename Coordinate>
00631     const Coordinate
00632           BuckyballTesselationConstants<Coordinate>::GOLDEN_MEAN
00633         = static_cast<Coordinate>(1.6180339887498948482);
00634 
00635     // sqrt((9 * sqrt(5) + 29) / 2)
00636     template <typename Coordinate>
00637     const Coordinate
00638           BuckyballTesselationConstants<Coordinate>::RADIAL_DIVISOR
00639         = static_cast<Coordinate>(4.95603731813523107513);
00640 
00641     // 4 / (9 * sqrt(5) + 29)
00642     template <typename Coordinate>
00643     const Coordinate
00644           BuckyballTesselationConstants<Coordinate>::EDGE_SQUARED_FACTOR
00645         = 4 / static_cast<Coordinate>(24.5623058987490536338);
00646 
00651     template <
00652         typename PatternType
00653     >
00654     struct BuckyballTesselationFormer
00655     {
00656      public:
00657         typedef PatternType
00658                 Pattern;
00659 
00660      private:
00661         typedef typename Pattern::Cell
00662                 Cell;
00663         typedef typename Pattern::Coordinate
00664                 Coordinate;
00665         typedef BuckyballTesselationConstants<Coordinate>
00666                 _BuckyballConstants;
00667 
00668      public:
00669         typedef BuckyballTag
00670                 tag;
00671         typedef BuckyballTesselationFormer
00672                 type;
00673 
00674         template <
00675             typename ArgumentPack
00676         >
00677         static typename Pattern::CellIndex
00678             countCells(
00679                 const ArgumentPack& p
00680             )
00681         {
00682             const Coordinate r_max = p[init_radius_maximum_arg];
00683             const Coordinate r_inc = p[init_radial_increment_arg];
00684 
00685             typename Pattern::CellIndex cell_count = 0;
00686 
00687             for (
00688                 Coordinate r = p[init_radius_minimum_arg];
00689                 r <= r_max;
00690                 r += r_inc
00691             )
00692             {
00693                 cell_count += 60;
00694             }
00695 
00696             return cell_count;
00697         }
00698 
00699         template <
00700             typename OutputIterator
00701           , typename ArgumentPack
00702         >
00703         static void
00704             makeCells(
00705                 OutputIterator cell_iterator
00706               , const ArgumentPack& p
00707             )
00708         {
00709             const Cell&      centroid = p[init_centroid_arg];
00710             const Coordinate cx       = centroid[0];
00711             const Coordinate cy       = centroid[1];
00712             const Coordinate cz       = centroid[2];
00713             const Coordinate r_max    = p[init_radius_maximum_arg]
00714                                       / _BuckyballConstants::RADIAL_DIVISOR;
00715             const Coordinate r_inc    = p[init_radial_increment_arg]
00716                                       / _BuckyballConstants::RADIAL_DIVISOR;
00717 
00718             Cell cell(3);
00719 
00720             for (
00721                 Coordinate r = p[init_radius_minimum_arg]
00722                              / _BuckyballConstants::RADIAL_DIVISOR;
00723                 r <= r_max;
00724                 r += r_inc
00725             )
00726             {
00727                 cell[0]        = cx;
00728                 cell[1]        = cy + r;
00729                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN * 3;
00730                 *cell_iterator = cell;
00731                 ++cell_iterator;
00732 
00733                 cell[0]        = cx;
00734                 cell[1]        = cy + r;
00735                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN * 3;
00736                 *cell_iterator = cell;
00737                 ++cell_iterator;
00738 
00739                 cell[0]        = cx;
00740                 cell[1]        = cy - r;
00741                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN * 3;
00742                 *cell_iterator = cell;
00743                 ++cell_iterator;
00744 
00745                 cell[0]        = cx;
00746                 cell[1]        = cy - r;
00747                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN * 3;
00748                 *cell_iterator = cell;
00749                 ++cell_iterator;
00750 
00751                 cell[0]        = cx + r;
00752                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN * 3;
00753                 cell[2]        = cz;
00754                 *cell_iterator = cell;
00755                 ++cell_iterator;
00756 
00757                 cell[0]        = cx + r;
00758                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN * 3;
00759                 cell[2]        = cz;
00760                 *cell_iterator = cell;
00761                 ++cell_iterator;
00762 
00763                 cell[0]        = cx - r;
00764                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN * 3;
00765                 cell[2]        = cz;
00766                 *cell_iterator = cell;
00767                 ++cell_iterator;
00768 
00769                 cell[0]        = cx - r;
00770                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN * 3;
00771                 cell[2]        = cz;
00772                 *cell_iterator = cell;
00773                 ++cell_iterator;
00774 
00775                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN * 3;
00776                 cell[1]        = cy;
00777                 cell[2]        = cz + r;
00778                 *cell_iterator = cell;
00779                 ++cell_iterator;
00780 
00781                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN * 3;
00782                 cell[1]        = cy;
00783                 cell[2]        = cz - r;
00784                 *cell_iterator = cell;
00785                 ++cell_iterator;
00786 
00787                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN * 3;
00788                 cell[1]        = cy;
00789                 cell[2]        = cz + r;
00790                 *cell_iterator = cell;
00791                 ++cell_iterator;
00792 
00793                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN * 3;
00794                 cell[1]        = cy;
00795                 cell[2]        = cz - r;
00796                 *cell_iterator = cell;
00797                 ++cell_iterator;
00798 
00799                 cell[0]        = cx + r * 2;
00800                 cell[1]        = cy + r
00801                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00802                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN;
00803                 *cell_iterator = cell;
00804                 ++cell_iterator;
00805 
00806                 cell[0]        = cx + r * 2;
00807                 cell[1]        = cy + r
00808                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00809                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN;
00810                 *cell_iterator = cell;
00811                 ++cell_iterator;
00812 
00813                 cell[0]        = cx + r * 2;
00814                 cell[1]        = cy - r
00815                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00816                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN;
00817                 *cell_iterator = cell;
00818                 ++cell_iterator;
00819 
00820                 cell[0]        = cx + r * 2;
00821                 cell[1]        = cy - r
00822                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00823                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN;
00824                 *cell_iterator = cell;
00825                 ++cell_iterator;
00826 
00827                 cell[0]        = cx - r * 2;
00828                 cell[1]        = cy + r
00829                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00830                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN;
00831                 *cell_iterator = cell;
00832                 ++cell_iterator;
00833 
00834                 cell[0]        = cx - r * 2;
00835                 cell[1]        = cy + r
00836                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00837                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN;
00838                 *cell_iterator = cell;
00839                 ++cell_iterator;
00840 
00841                 cell[0]        = cx - r * 2;
00842                 cell[1]        = cy - r
00843                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00844                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN;
00845                 *cell_iterator = cell;
00846                 ++cell_iterator;
00847 
00848                 cell[0]        = cx - r * 2;
00849                 cell[1]        = cy - r
00850                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00851                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN;
00852                 *cell_iterator = cell;
00853                 ++cell_iterator;
00854 
00855                 cell[0]        = cx + r
00856                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00857                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN;
00858                 cell[2]        = cz + r * 2;
00859                 *cell_iterator = cell;
00860                 ++cell_iterator;
00861 
00862                 cell[0]        = cx + r
00863                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00864                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN;
00865                 cell[2]        = cz - r * 2;
00866                 *cell_iterator = cell;
00867                 ++cell_iterator;
00868 
00869                 cell[0]        = cx + r
00870                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00871                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN;
00872                 cell[2]        = cz + r * 2;
00873                 *cell_iterator = cell;
00874                 ++cell_iterator;
00875 
00876                 cell[0]        = cx + r
00877                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00878                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN;
00879                 cell[2]        = cz - r * 2;
00880                 *cell_iterator = cell;
00881                 ++cell_iterator;
00882 
00883                 cell[0]        = cx - r
00884                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00885                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN;
00886                 cell[2]        = cz + r * 2;
00887                 *cell_iterator = cell;
00888                 ++cell_iterator;
00889 
00890                 cell[0]        = cx - r
00891                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00892                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN;
00893                 cell[2]        = cz - r * 2;
00894                 *cell_iterator = cell;
00895                 ++cell_iterator;
00896 
00897                 cell[0]        = cx - r
00898                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00899                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN;
00900                 cell[2]        = cz + r * 2;
00901                 *cell_iterator = cell;
00902                 ++cell_iterator;
00903 
00904                 cell[0]        = cx - r
00905                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00906                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN;
00907                 cell[2]        = cz - r * 2;
00908                 *cell_iterator = cell;
00909                 ++cell_iterator;
00910 
00911                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN;
00912                 cell[1]        = cy + r * 2;
00913                 cell[2]        = cz + r
00914                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00915                 *cell_iterator = cell;
00916                 ++cell_iterator;
00917 
00918                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN;
00919                 cell[1]        = cy + r * 2;
00920                 cell[2]        = cz - r
00921                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00922                 *cell_iterator = cell;
00923                 ++cell_iterator;
00924 
00925                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN;
00926                 cell[1]        = cy - r * 2;
00927                 cell[2]        = cz + r
00928                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00929                 *cell_iterator = cell;
00930                 ++cell_iterator;
00931 
00932                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN;
00933                 cell[1]        = cy - r * 2;
00934                 cell[2]        = cz - r
00935                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00936                 *cell_iterator = cell;
00937                 ++cell_iterator;
00938 
00939                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN;
00940                 cell[1]        = cy + r * 2;
00941                 cell[2]        = cz + r
00942                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00943                 *cell_iterator = cell;
00944                 ++cell_iterator;
00945 
00946                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN;
00947                 cell[1]        = cy + r * 2;
00948                 cell[2]        = cz - r
00949                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00950                 *cell_iterator = cell;
00951                 ++cell_iterator;
00952 
00953                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN;
00954                 cell[1]        = cy - r * 2;
00955                 cell[2]        = cz + r
00956                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00957                 *cell_iterator = cell;
00958                 ++cell_iterator;
00959 
00960                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN;
00961                 cell[1]        = cy - r * 2;
00962                 cell[2]        = cz - r
00963                                     * (_BuckyballConstants::GOLDEN_MEAN_2X + 1);
00964                 *cell_iterator = cell;
00965                 ++cell_iterator;
00966 
00967                 cell[0]        = cx + r;
00968                 cell[1]        = cy + r
00969                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
00970                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN_2X;
00971                 *cell_iterator = cell;
00972                 ++cell_iterator;
00973 
00974                 cell[0]        = cx + r;
00975                 cell[1]        = cy + r
00976                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
00977                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN_2X;
00978                 *cell_iterator = cell;
00979                 ++cell_iterator;
00980 
00981                 cell[0]        = cx + r;
00982                 cell[1]        = cy - r
00983                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
00984                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN_2X;
00985                 *cell_iterator = cell;
00986                 ++cell_iterator;
00987 
00988                 cell[0]        = cx + r;
00989                 cell[1]        = cy - r
00990                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
00991                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN_2X;
00992                 *cell_iterator = cell;
00993                 ++cell_iterator;
00994 
00995                 cell[0]        = cx - r;
00996                 cell[1]        = cy + r
00997                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
00998                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN_2X;
00999                 *cell_iterator = cell;
01000                 ++cell_iterator;
01001 
01002                 cell[0]        = cx - r;
01003                 cell[1]        = cy + r
01004                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01005                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01006                 *cell_iterator = cell;
01007                 ++cell_iterator;
01008 
01009                 cell[0]        = cx - r;
01010                 cell[1]        = cy - r
01011                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01012                 cell[2]        = cz + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01013                 *cell_iterator = cell;
01014                 ++cell_iterator;
01015 
01016                 cell[0]        = cx - r;
01017                 cell[1]        = cy - r
01018                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01019                 cell[2]        = cz - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01020                 *cell_iterator = cell;
01021                 ++cell_iterator;
01022 
01023                 cell[0]        = cx + r
01024                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01025                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01026                 cell[2]        = cz + r;
01027                 *cell_iterator = cell;
01028                 ++cell_iterator;
01029 
01030                 cell[0]        = cx + r
01031                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01032                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01033                 cell[2]        = cz - r;
01034                 *cell_iterator = cell;
01035                 ++cell_iterator;
01036 
01037                 cell[0]        = cx + r
01038                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01039                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01040                 cell[2]        = cz + r;
01041                 *cell_iterator = cell;
01042                 ++cell_iterator;
01043 
01044                 cell[0]        = cx + r
01045                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01046                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01047                 cell[2]        = cz - r;
01048                 *cell_iterator = cell;
01049                 ++cell_iterator;
01050 
01051                 cell[0]        = cx - r
01052                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01053                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01054                 cell[2]        = cz + r;
01055                 *cell_iterator = cell;
01056                 ++cell_iterator;
01057 
01058                 cell[0]        = cx - r
01059                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01060                 cell[1]        = cy + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01061                 cell[2]        = cz - r;
01062                 *cell_iterator = cell;
01063                 ++cell_iterator;
01064 
01065                 cell[0]        = cx - r
01066                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01067                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01068                 cell[2]        = cz + r;
01069                 *cell_iterator = cell;
01070                 ++cell_iterator;
01071 
01072                 cell[0]        = cx - r
01073                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01074                 cell[1]        = cy - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01075                 cell[2]        = cz - r;
01076                 *cell_iterator = cell;
01077                 ++cell_iterator;
01078 
01079                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01080                 cell[1]        = cy + r;
01081                 cell[2]        = cz + r
01082                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01083                 *cell_iterator = cell;
01084                 ++cell_iterator;
01085 
01086                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01087                 cell[1]        = cy + r;
01088                 cell[2]        = cz - r
01089                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01090                 *cell_iterator = cell;
01091                 ++cell_iterator;
01092 
01093                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01094                 cell[1]        = cy - r;
01095                 cell[2]        = cz + r
01096                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01097                 *cell_iterator = cell;
01098                 ++cell_iterator;
01099 
01100                 cell[0]        = cx + r * _BuckyballConstants::GOLDEN_MEAN_2X;
01101                 cell[1]        = cy - r;
01102                 cell[2]        = cz - r
01103                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01104                 *cell_iterator = cell;
01105                 ++cell_iterator;
01106 
01107                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01108                 cell[1]        = cy + r;
01109                 cell[2]        = cz + r
01110                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01111                 *cell_iterator = cell;
01112                 ++cell_iterator;
01113 
01114                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01115                 cell[1]        = cy + r;
01116                 cell[2]        = cz - r
01117                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01118                 *cell_iterator = cell;
01119                 ++cell_iterator;
01120 
01121                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01122                 cell[1]        = cy - r;
01123                 cell[2]        = cz + r
01124                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01125                 *cell_iterator = cell;
01126                 ++cell_iterator;
01127 
01128                 cell[0]        = cx - r * _BuckyballConstants::GOLDEN_MEAN_2X;
01129                 cell[1]        = cy - r;
01130                 cell[2]        = cz - r
01131                                     * (_BuckyballConstants::GOLDEN_MEAN + 2);
01132                 *cell_iterator = cell;
01133                 ++cell_iterator;
01134             }
01135         }
01136 
01137         template <
01138             typename ArgumentPack
01139         >
01140         static bool
01141             isLegalEdge(
01142                 const typename Pattern::Cell& source
01143               , const typename Pattern::Cell& target
01144               , const ArgumentPack& p
01145             )
01146         {
01147             const Cell&
01148                 centroid = p[init_centroid_arg];
01149             const Coordinate
01150                 src_x = source[0] - centroid[0];
01151             const Coordinate
01152                 src_y = source[1] - centroid[1];
01153             const Coordinate
01154                 src_z = source[2] - centroid[2];
01155             const Coordinate
01156                 src_prod = src_x * src_x + src_y * src_y + src_z * src_z;
01157             const Coordinate
01158                 tgt_x = target[0] - centroid[0];
01159             const Coordinate
01160                 tgt_y = target[1] - centroid[1];
01161             const Coordinate
01162                 tgt_z = target[2] - centroid[2];
01163             const Coordinate
01164                 tgt_prod = tgt_x * tgt_x + tgt_y * tgt_y + tgt_z * tgt_z;
01165             const Coordinate
01166                 dx = target[0] - source[0];
01167             const Coordinate
01168                 dy = target[1] - source[1];
01169             const Coordinate
01170                 dz = target[2] - source[2];
01171             const Coordinate
01172                 edge_len_sq = dx * dx + dy * dy + dz * dz;
01173 
01174             sgdk::ZeroChecker<Coordinate>
01175                 zero_checker(p[init_zero_tolerance_arg | 0.00001]);
01176 
01177             if (zero_checker.isZero(src_prod - tgt_prod))
01178             {
01179                 /*
01180                  * The vectors <center,source> and <center,target> have the
01181                  * same length.  Check if <source,target> is a face edge on
01182                  * the surface of the truncated icosahedron.
01183                  */
01184                 return zero_checker.isZero(
01185                            edge_len_sq
01186                          - src_prod
01187                          * _BuckyballConstants::EDGE_SQUARED_FACTOR
01188                        );
01189             }
01190             else
01191             {
01192                 const Coordinate r_inc = p[init_radial_increment_arg];
01193 
01194                 /*
01195                  * The vectors <center,source> and <center,target> have
01196                  * different lengths.  For <source,target> to be a legal
01197                  * edge, the vectors must point in the same direction,
01198                  * and the magnitude difference must equal
01199                  * r_inc * sqrt((9 * sqrt(5) + 29) / 2).
01200                  */
01201                 return zero_checker.isZero(edge_len_sq - r_inc * r_inc);
01202             }
01203         }
01204     };
01205   }  // namespace _detail
01206 
01211 struct BuckyballTesselationSelector
01212 {
01213 };
01214 
01219 template <>
01220 struct TesselationFormerGenerator<BuckyballTesselationSelector>
01221 {
01222     template <typename Pattern>
01223     struct apply
01224     {
01225         typedef typename _detail::BuckyballTesselationFormer<Pattern>::type
01226                 type;
01227     };
01228 };
01229 
01230   namespace _sphere {
01231 
01236     struct parameters
01237       : boost::parameter::parameters<
01238             boost::parameter::required<
01239                 keyword_tag::init_tesselation_selector_arg
01240             >
01241           , boost::parameter::required<
01242                 keyword_tag::init_centroid_arg
01243             >
01244           , boost::parameter::required<
01245                 keyword_tag::init_radius_minimum_arg
01246             >
01247           , boost::parameter::required<
01248                 keyword_tag::init_radius_maximum_arg
01249             >
01250           , boost::parameter::required<
01251                 keyword_tag::init_radial_increment_arg
01252             >
01253           , boost::parameter::required<
01254                 keyword_tag::init_entrance_cell_arg
01255             >
01256           , boost::parameter::required<
01257                 keyword_tag::init_exit_cell_arg
01258             >
01259           , boost::parameter::optional<
01260                 keyword_tag::init_positive_rotation_arg
01261             >
01262           , boost::parameter::optional<
01263                 keyword_tag::init_zero_tolerance_arg
01264             >
01265         >
01266     {
01267     };
01268   }  // namespace _sphere
01269 
01271 
01397 template <
01398 #ifndef MSMAZES_DOX
01399     typename CoordinateType = double
01400   , typename DirectionChangeType = int
01401   , typename CellContainerSelector = boost::vecS
01402 #endif  /* MSMAZES_DOX */
01403 >
01404 class SpherePattern
01405 #ifndef MSMAZES_DOX
01406   : public PhysicalPattern<
01407                CoordinateType
01408              , boost::numeric::ublas::vector<CoordinateType>
01409              , DirectionChangeType
01410              , CellContainerSelector
01411            >
01412 #endif  /* MSMAZES_DOX */
01413 {
01414 #ifndef MSMAZES_DOX
01415  private:
01416     typedef PhysicalPattern<
01417                 CoordinateType
01418               , boost::numeric::ublas::vector<CoordinateType>
01419               , DirectionChangeType
01420               , CellContainerSelector
01421             >
01422             ParentPattern;
01423 #endif  /* MSMAZES_DOX */
01424 
01425  public:
01430 #ifdef MSMAZES_DOX
01431     typedef implementation_defined Cell;
01432 #else
01433     typedef typename ParentPattern::Cell
01434             Cell;
01435 #endif  /* MSMAZES_DOX */
01436 
01442 #ifdef MSMAZES_DOX
01443     typedef implementation_defined Coordinate;
01444 #else
01445     typedef typename ParentPattern::Coordinate
01446             Coordinate;
01447 #endif  /* MSMAZES_DOX */
01448 
01454 #ifdef MSMAZES_DOX
01455     typedef implementation_defined CellEqualityPolicy;
01456 #else
01457     typedef typename ParentPattern::CellEqualityPolicy
01458             CellEqualityPolicy;
01459 #endif  /* MSMAZES_DOX */
01460 
01466 #ifdef MSMAZES_DOX
01467     typedef implementation_defined Graph;
01468 #else
01469     typedef typename ParentPattern::Graph
01470             Graph;
01471 #endif  /* MSMAZES_DOX */
01472 
01478 #ifdef MSMAZES_DOX
01479     typedef implementation_defined CellIndex;
01480 #else
01481     typedef typename ParentPattern::CellIndex
01482             CellIndex;
01483 #endif  /* MSMAZES_DOX */
01484 
01490 #ifdef MSMAZES_DOX
01491     typedef implementation_defined EdgeDirectedCategory;
01492 #else
01493     typedef typename ParentPattern::EdgeDirectedCategory
01494             EdgeDirectedCategory;
01495 #endif  /* MSMAZES_DOX */
01496 
01502 #ifdef MSMAZES_DOX
01503     typedef implementation_defined Direction;
01504 #else
01505     typedef typename ParentPattern::Direction
01506             Direction;
01507 #endif  /* MSMAZES_DOX */
01508 
01515 #ifdef MSMAZES_DOX
01516     typedef implementation_defined DirectionChange;
01517 #else
01518     typedef typename ParentPattern::DirectionChange
01519             DirectionChange;
01520 #endif  /* MSMAZES_DOX */
01521 
01527 #ifdef MSMAZES_DOX
01528     typedef implementation_defined OutDegree;
01529 #else
01530     typedef typename ParentPattern::OutDegree
01531             OutDegree;
01532 #endif  /* MSMAZES_DOX */
01533 
01539 #ifdef MSMAZES_DOX
01540     typedef implementation_defined HasIndexableEndpointCells;
01541 #else
01542     typedef typename ParentPattern::HasIndexableEndpointCells
01543             HasIndexableEndpointCells;
01544 #endif  /* MSMAZES_DOX */
01545 
01546  private:
01547     typedef SpherePattern
01548             type;
01549 
01550     bool                          _has_mult_layers;
01551     OutDegree                     _max_out_degree;
01552     Coordinate                    _center_x;
01553     Coordinate                    _center_y;
01554     Coordinate                    _center_z;
01555     Coordinate                    _r_inc;
01556     Coordinate                    _r_max;
01557     Coordinate                    _r_min;
01558     sgdk::PositiveRotation        _positive_rotation;
01559     sgdk::ZeroChecker<Coordinate> _zero_checker;
01560 
01561     SpherePattern(const type& copy)
01562     {
01563     }
01564 
01565  public:
01567 
01570     SpherePattern()
01571       : ParentPattern()
01572       , _has_mult_layers(false)
01573       , _max_out_degree()
01574       , _center_x()
01575       , _center_y()
01576       , _center_z()
01577       , _r_inc()
01578       , _r_max()
01579       , _r_min()
01580       , _positive_rotation(sgdk::PositiveRotation::CLOCKWISE)
01581       , _zero_checker(0.00001)
01582     {
01583     }
01584 
01586 
01589     virtual ~SpherePattern()
01590     {
01591     }
01592 
01622     static Cell
01623         createCell(
01624             const Coordinate x
01625           , const Coordinate y
01626           , const Coordinate z
01627         )
01628     {
01629         return ParentPattern::createCell(x, y, z);
01630     }
01631 
01632 #ifdef MSMAZES_DOX
01633 
01739     template <typename TesselationSelector>
01740     void initialize(
01741         const TesselationSelector& init_tesselation_selector_arg
01742       , const Cell& init_centroid_arg
01743       , const Coordinate init_radial_increment_arg
01744       , const Coordinate init_radius_maximum_arg
01745       , const Coordinate init_radius_minimum_arg
01746       , const Cell& init_entrance_cell_arg
01747       , const Cell& init_exit_cell_arg
01748       , const sgdk::PositiveRotation& init_positive_rotation_arg
01749       , const Coordinate init_zero_tolerance_arg
01750     );
01751 
01758     template <typename Params>
01759     void initialize_with_named_params(Params& p)
01760 #else
01761     BOOST_PARAMETER_MEMFUN(
01762         void
01763       , initialize
01764       , 7
01765       , MSMAZES_CORE_PATTERN_ARITY
01766       , _sphere::parameters
01767     )
01768 #endif  /* MSMAZES_DOX */
01769     {
01770         typedef MSMAZES_CORE_PATTERN_TESSELATION_FORMER_TYPE(Params, type)
01771                 TesselationFormer;
01772         typedef typename TesselationFormer::tag
01773                 Tag;
01774 
01775         _zero_checker.setZeroTolerance(p[init_zero_tolerance_arg | 0.00001]);
01776         _r_min = p[init_radius_minimum_arg];
01777 
01778         BOOST_ASSERT(
01779             (0.0 < _r_min)
01780          && !_zero_checker.isZero(_r_min)
01781          && "Your minimum radius is negative."
01782         );
01783 
01784         _r_max = p[init_radius_maximum_arg];
01785 
01786         BOOST_ASSERT(
01787             (
01788                 (_r_min < _r_max)
01789              || !_zero_checker.isZero(_r_max - _r_min)
01790             )
01791          && "Your maximum radius is less than your minimum radius."
01792         );
01793 
01794         _r_inc = p[init_radial_increment_arg];
01795 
01796         BOOST_ASSERT(
01797             (0.0 < _r_inc)
01798          && !_zero_checker.isZero(_r_inc)
01799          && "How many concentric layers do you want in this tesselation?"
01800         );
01801 
01802         const Cell& centroid = p[init_centroid_arg];
01803 
01804         ParentPattern::initializeWithTesselationFormer(TesselationFormer(), p);
01805         _center_x        = centroid[0];
01806         _center_y        = centroid[1];
01807         _center_z        = centroid[2];
01808         _max_out_degree  = Tag::MAX_OUT_DEGREE;
01809         _has_mult_layers
01810           = (_r_min + _r_inc < _r_max)
01811          || _zero_checker.isZero(_r_max - _r_min - _r_inc);
01812         _positive_rotation
01813           = p[init_positive_rotation_arg | sgdk::PositiveRotation::CLOCKWISE];
01814     }
01815 
01822     inline const Graph& getGraph() const
01823     {
01824         return ParentPattern::getGraph();
01825     }
01826 
01832     inline CellIndex getCellCount() const
01833     {
01834         return ParentPattern::getCellCount();
01835     }
01836 
01842     inline const Cell& getCell(const CellIndex index) const
01843     {
01844         return ParentPattern::getCell(index);
01845     }
01846 
01852     inline const Cell& getEntranceCell() const
01853     {
01854         return ParentPattern::getEntranceCell();
01855     }
01856 
01863     inline const Cell& getSourceCell() const
01864     {
01865         return ParentPattern::getSourceCell();
01866     }
01867 
01874     inline const Cell& getTargetCell() const
01875     {
01876         return ParentPattern::getTargetCell();
01877     }
01878 
01884     inline const Cell& getExitCell() const
01885     {
01886         return ParentPattern::getExitCell();
01887     }
01888 
01889 #ifndef MSMAZES_DOX
01890  protected:
01891     Direction
01892         getEdgeDirectionDerived(
01893             const Cell& source
01894           , const Cell& target
01895         ) const
01896     {
01897         Direction direction(3);
01898 
01899         direction[0] = target[0] - source[0];
01900         direction[1] = target[1] - source[1];
01901         direction[2] = target[2] - source[2];
01902 
01903         return direction;
01904     }
01905 
01906     DirectionChange
01907         getYawTurnDerived(
01908             const Cell& source
01909           , const Cell& parent
01910           , const Cell& target
01911         ) const
01912     {
01913         const Coordinate
01914             source_x
01915               = source[0] - _center_x;
01916         const Coordinate
01917             source_y
01918               = source[1] - _center_y;
01919         const Coordinate
01920             source_z
01921               = source[2] - _center_z;
01922         const Coordinate
01923             src_dir_x
01924               = parent[0] - source[0];
01925         const Coordinate
01926             src_dir_y
01927               = parent[1] - source[1];
01928         const Coordinate
01929             src_dir_z
01930               = parent[2] - source[2];
01931         const Coordinate
01932             src_prod_1
01933               = source_x * src_dir_y - source_y * src_dir_x;
01934         const Coordinate
01935             src_prod_2
01936               = source_x * src_dir_z - source_z * src_dir_x;
01937         const Coordinate
01938             src_prod_3
01939               = source_y * src_dir_z - source_z * src_dir_y;
01940 
01941         if (
01942             _zero_checker.isZero(src_prod_1)
01943          && _zero_checker.isZero(src_prod_2)
01944          && _zero_checker.isZero(src_prod_3)
01945         )
01946         {
01947             /*
01948              * <source,parent> is a radial edge.
01949              */
01950             return 0;
01951         }
01952 
01953         const Coordinate
01954             parent_x
01955               = parent[0] - _center_x;
01956         const Coordinate
01957             parent_y
01958               = parent[1] - _center_y;
01959         const Coordinate
01960             parent_z
01961               = parent[2] - _center_z;
01962         const Coordinate
01963             tgt_dir_x
01964               = target[0] - parent[0];
01965         const Coordinate
01966             tgt_dir_y
01967               = target[1] - parent[1];
01968         const Coordinate
01969             tgt_dir_z
01970               = target[2] - parent[2];
01971         const Coordinate
01972             tgt_prod_1
01973               = parent_x * tgt_dir_y - parent_y * tgt_dir_x;
01974         const Coordinate
01975             tgt_prod_2
01976               = parent_x * tgt_dir_z - parent_z * tgt_dir_x;
01977         const Coordinate
01978             tgt_prod_3
01979               = parent_y * tgt_dir_z - parent_z * tgt_dir_y;
01980 
01981         if (
01982             _zero_checker.isZero(tgt_prod_1)
01983          && _zero_checker.isZero(tgt_prod_2)
01984          && _zero_checker.isZero(tgt_prod_3)
01985         )
01986         {
01987             /*
01988              * <parent,target> is a radial edge.
01989              */
01990             return 0;
01991         }
01992 
01993         /*
01994          * <source,parent> and <parent,target> are face edges.
01995          */
01996         const Coordinate
01997             x_prod_x
01998               = src_dir_y * tgt_dir_z - src_dir_z * tgt_dir_y;
01999         const Coordinate
02000             x_prod_y
02001               = src_dir_z * tgt_dir_x - src_dir_x * tgt_dir_z;
02002         const Coordinate
02003             x_prod_z
02004               = src_dir_x * tgt_dir_y - src_dir_y * tgt_dir_x;
02005         const Coordinate
02006             d_prod_n
02007               = parent_x * x_prod_x + parent_y * x_prod_y + parent_z * x_prod_z;
02008         const Coordinate
02009             prtdirln
02010               = parent_x * parent_x + parent_y * parent_y + parent_z * parent_z;
02011         const Coordinate
02012             xprdirln
02013               = x_prod_x * x_prod_x + x_prod_y * x_prod_y + x_prod_z * x_prod_z;
02014         const double
02015             normal_angle
02016               = std::acos(d_prod_n / std::sqrt(static_cast<double>(prtdirln))
02017               / std::sqrt(static_cast<double>(xprdirln)));
02018         const Coordinate
02019             d_prod_a
02020               = src_dir_x * tgt_dir_x
02021               + src_dir_y * tgt_dir_y
02022               + src_dir_z * tgt_dir_z;
02023         const Coordinate
02024             edgelnsq
02025               = src_dir_x * src_dir_x
02026               + src_dir_y * src_dir_y
02027               + src_dir_z * src_dir_z;
02028         const double
02029             angle
02030               = std::acos(static_cast<double>(d_prod_a / edgelnsq));
02031 
02032         switch (_max_out_degree)
02033         {
02034             case 3:
02035                 /*
02036                  * Dodecahedron, Truncated Icosahedron
02037                  */
02038                 return
02039                     _zero_checker.isZero(angle - 3.14159265358979323846264)
02040                   ? 1
02041                   : (
02042                         (normal_angle < 1.57079632679489661923132)
02043                      == _positive_rotation.isClockwise()
02044                     )
02045                   ? -1
02046                   : 0;
02047 
02048             case 4:
02049                 /*
02050                  * Octahedron
02051                  */
02052                 return
02053                     _zero_checker.isZero(angle - 3.14159265358979323846264)
02054                   ? 2
02055                   : _zero_checker.isZero(
02056                         normal_angle - 1.57079632679489661923132
02057                     )
02058                   ? 0
02059                   : (
02060                         (normal_angle < 1.57079632679489661923132)
02061                      == _positive_rotation.isClockwise()
02062                     )
02063                   ? -1
02064                   : 1;
02065 
02066             case 5:
02067                 /*
02068                  * Icosahedron
02069                  */
02070                 return
02071                     _zero_checker.isZero(angle - 3.14159265358979323846264)
02072                   ? 2
02073                   : (
02074                         (normal_angle < 1.57079632679489661923132)
02075                      == _positive_rotation.isClockwise()
02076                     )
02077                   ? ((angle < 1.57079632679489661923132) ? -1 : -2)
02078                   : ((angle < 1.57079632679489661923132) ? 0 : 1);
02079 
02080             default:
02081                 /*
02082                  * The solid is neither Archimedean nor Platonic!
02083                  */
02084                 return _max_out_degree;
02085         }
02086     }
02087 
02088     OutDegree getMaxOutDegreeDerived() const
02089     {
02090         return _has_mult_layers ? (_max_out_degree + 2) : _max_out_degree;
02091     }
02092 
02093  public:
02094 #endif  /* MSMAZES_DOX */
02095 
02101     Direction
02102         getEdgeDirection(
02103             const CellIndex source_index
02104           , const CellIndex target_index
02105         ) const
02106     {
02107         return ParentPattern::getEdgeDirection(source_index, target_index);
02108     }
02109 
02116     DirectionChange
02117         getYawTurn(
02118             const CellIndex source_index
02119           , const CellIndex parent_index
02120           , const CellIndex target_index
02121         ) const
02122     {
02123         return
02124             ParentPattern::getYawTurn(source_index, parent_index, target_index);
02125     }
02126 
02132     OutDegree getMaxOutDegree() const
02133     {
02134         return ParentPattern::getMaxOutDegree();
02135     }
02136 };
02137 }  // namespace msmazes
02138 
02139 #undef MSMAZES_CORE_PATTERN_ARITY
02140 
02141 #endif  /* MSMAZES_CORE_PATTERN_SPHERE_HPP */

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