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