From 5c8c822546039e7422a0dcb0841adbcbc9fb4d60 Mon Sep 17 00:00:00 2001 From: Claudius 'keldu' Holeksa Date: Mon, 23 Sep 2024 18:41:23 +0200 Subject: Minor work on orientation and IDs --- c++/ico.hpp | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 7 deletions(-) (limited to 'c++/ico.hpp') diff --git a/c++/ico.hpp b/c++/ico.hpp index 0ac1a91..257f12d 100644 --- a/c++/ico.hpp +++ b/c++/ico.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace kel { @@ -11,7 +12,7 @@ struct ico_surface_helper { * triangle. The orientation of the triangle is determined by the horizontal line * (on the 2D foldout of the icosahedron) which is the down direction. */ - static constexpr std::array, 20u> neighbour_map { + static constexpr std::array, 20u> neighbour_map {{ {1,4,5},//0 {2,0,6},//1 {3,1,7},//2 @@ -32,26 +33,112 @@ struct ico_surface_helper { {16,18,12},//17 {17,19,13},//18 {18,15,14} //19 - }; + }}; }; } template class ico_addr { private: - std::array vals_; + std::array vals_; public: - template - ico_addr
slice() const { - return {}; + uint8_t& at(uint64_t i){ + return vals_[i]; + } + + const uint8_t& at(uint64_t i) const { + return vals_[i]; + } + + constexpr uint64_t size() const { + return SubD; + } + + bool is_equal(const ico_addr& rhs) const { + bool eq = true; + + for(uint64_t i = 0u; i < size(); ++i){ + eq &= (at(i) == rhs.at(i)); + } + + return eq; + } + + bool has_zero() const { + uint64_t z_ctr = 0u; + for(uint64_t i = 1u; i < size(); ++i){ + z_ctr += (at(i) == 0u ? 1u : 0u); + } + return (z_ctr > 0u); + } + + std::array count_groups() const { + std::array grps{0,0,0,0}; + + for(uint64_t i = 1u; i < size(); ++i){ + auto& addr_i = vals_[i]; + assert(addr_i < 4); + + ++grps[addr_i]; + } + + return grps; + } + + uint64_t count_non_zero_groups() const { + auto ctr = count_groups(); + + uint64_t grp_ctr = 0u; + for(uint64_t i = 1u; i < ctr.size(); ++i){ + grp_ctr += (ctr[i] > 0u ? 1u : 0u); + } + return grp_ctr; + } + + bool has_all_non_zero_groups() const { + auto ctr = count_non_zero_groups(); + return (ctr == 3u); + } + + ico_addr go_to(uint8_t dir_i){ + ico_addr cpy_addr; + cpy_addr.vals_ = vals_; + + if(at(size() - 1u) == 0u){ + cpy_addr.at(size() - 1u) = dir_i + 1u; + } + if(at(size() - 1u) == (dir_i + 1u)){ + cpy_addr.at(size() - 1u) = 0u; + } + + return cpy_addr; + } + + bool borders_root() const { + return not (has_all_non_zero_groups() or has_zero()); } }; template class ico_triangle { private: - std::array> subdivs_; + std::array,4u> subdivs_; public: + + ico_triangle& at(uint8_t i){ + return subdivs_[i]; + } + + template + ico_triangle at(const ico_addr& addr, uint64_t next_i){ + auto& addr_i = addr[next_i]; + + auto& sub_triangle = subdivs_[addr_i]; + if constexpr ( D == 1u){ + return sub_triangle; + } + return sub_triangle.at(addr,next_i+1u); + } }; template @@ -61,10 +148,23 @@ private: public: }; +namespace impl { +} + template class icosahedron final { private: std::array,20u> surfaces_; public: + + template + ico_triangle at(const ico_addr& addr){ + static_assert(AddrD <= (SubD+1u), "Addr length to large."); + static_assert(AddrD > 0u, "Addr length to small."); + + auto& root_addr = addr[0u]; + auto& root_triangle = surfaces_[root_addr]; + return root_triangle.at(addr, 1u); + } }; } -- cgit v1.2.3