summaryrefslogtreecommitdiff
path: root/c++
diff options
context:
space:
mode:
Diffstat (limited to 'c++')
-rw-r--r--c++/ico.hpp114
1 files changed, 107 insertions, 7 deletions
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 <array>
+#include <cassert>
#include <cstdint>
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<std::array<uint8_t,3u>, 20u> neighbour_map {
+ static constexpr std::array<std::array<uint8_t,3u>, 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<uint64_t SubD>
class ico_addr {
private:
- std::array<uint8_t, SubD+1u> vals_;
+ std::array<uint8_t, SubD> vals_;
public:
- template<uint64_t Div = 1u>
- ico_addr<Div> 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<SubD>& 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<uint64_t,4u> count_groups() const {
+ std::array<uint64_t,4u> 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<SubD> go_to(uint8_t dir_i){
+ ico_addr<SubD> 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<typename T, uint64_t D>
class ico_triangle {
private:
- std::array<ico_triangle<T,D-1u>> subdivs_;
+ std::array<ico_triangle<T,D-1u>,4u> subdivs_;
public:
+
+ ico_triangle<T,D-1u>& at(uint8_t i){
+ return subdivs_[i];
+ }
+
+ template<uint64_t AddrOrigLen>
+ ico_triangle<T,0u> at(const ico_addr<AddrOrigLen>& 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<typename T>
@@ -61,10 +148,23 @@ private:
public:
};
+namespace impl {
+}
+
template<typename T, uint64_t SubD>
class icosahedron final {
private:
std::array<ico_triangle<T,SubD>,20u> surfaces_;
public:
+
+ template<uint64_t AddrD>
+ ico_triangle<T,SubD+1u-AddrD> at(const ico_addr<AddrD>& 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);
+ }
};
}