diff --git a/aperiodic-hat.cpp b/aperiodic-hat.cpp index b661c001..e08e7c7f 100644 --- a/aperiodic-hat.cpp +++ b/aperiodic-hat.cpp @@ -383,6 +383,7 @@ vector rules_recursive = { }; EX ld hat_param = 1; +EX ld hat_param_imag = 0; struct hrmap_hat : hrmap { @@ -473,22 +474,20 @@ struct hrmap_hat : hrmap { bool emb = embedded_plane; if(emb) geom3::light_flip(true); - auto move = [&] (ld angle, ld dist) { - hc.push_back(T * C0); - T = T * cspin(0, 1, angle * degree); - T = T * xpush(dist); - }; - ld q = 6; ld eshort = 0.3; ld elong = sqrt(3) * eshort; if(fake::in()) q = fake::around; + ld eshorti = 0, elongi = 0; + if(q != 6) { eshort = edge_of_triangle_with_angles(M_PI / q, 60._deg, 90._deg); elong = edge_of_triangle_with_angles(60._deg, M_PI / q, 90._deg); } else { + eshorti = eshort * hat_param_imag; + elongi = elong * -hat_param_imag; eshort *= hat_param; elong *= 2 - hat_param; // 0-length edges cause problems... @@ -496,34 +495,66 @@ struct hrmap_hat : hrmap { if(abs(elong) < 1e-6) elong = .0001; } - ld i60 = (M_PI - TAU*2/q)/degree; - ld n60 = (M_PI - TAU*4/q)/degree; + auto hat = [&] (vector& hc) { - move(-90, eshort); move( 60, eshort); move( 0, eshort); - move( 60, eshort); move( 90, elong); move(n60, elong); - move( 90, eshort); move(-60, eshort); move( 90, elong); - move(i60, elong); move(-90, eshort); move( 60, eshort); - move( 90, elong); move(i60, elong); + auto move = [&] (ld angle, ld dist, ld disti) { + hc.push_back(T * C0); + T = T * cspin(0, 1, angle * degree); + T = T * xpush(dist); + T = T * ypush(disti); + }; - if(q == 6) { + auto moves = [&] (ld angle) { move(angle, eshort, eshorti); }; + auto movel = [&] (ld angle) { move(angle, elong, elongi); }; + + ld i60 = (M_PI - TAU*2/q)/degree; + ld n60 = (M_PI - TAU*4/q)/degree; + + moves(-90); moves( 60); moves( 0); + moves( 60); movel( 90); movel(n60); + moves( 90); moves(-60); movel( 90); + movel(i60); moves(-90); moves( 60); + movel( 90); movel(i60); + }; + + hat(hc); + +#undef eshort +#undef elong + + auto compute_area = [&] (vector& hc) { ld area = 0; - for(int i=0; i<14; i++) area += (hc[(i+1)%14] ^ hc[i]) [2]; - println(hlog, "area = ", area); - area = abs(area); - ld scale = sqrt(2.5 / area); - for(auto& h: hc) h = h * scale + (C0) * (1-scale); + for(int i=0; i<14; i++) area += (hc[(i+1)%isize(hc)] ^ hc[i]) [2]; + return abs(area); + }; + + auto recenter = [&] (vector& hc) { + hyperpoint ctr = Hypc; + for(auto h: hc) ctr += h; + ctr /= isize(hc); + ctr = normalize(ctr); + for(auto& h: hc) h = gpushxto0(ctr) * h; + }; + + if(hat_param_imag) { + eshorti *= -1; + elongi *= -1; + hat(hatcorners[1]); } - - hyperpoint ctr = Hypc; - for(auto h: hc) ctr += h; - ctr /= isize(hc); - ctr = normalize(ctr); - for(auto& h: hc) h = gpushxto0(ctr) * h; - - hatcorners[1] = hc; + else hatcorners[1] = hc; for(auto& h: hc) h = MirrorX * h; reverse(hatcorners[1].begin(), hatcorners[1].end()); + if(q == 6) { + ld phi = (1 + sqrt(5)) / 2; + ld phi4 = pow(phi, 4); + ld area = (compute_area(hatcorners[0]) * phi4 + compute_area(hatcorners[1]) * 1) / (phi4 + 1); + area = abs(area); + ld scale = sqrt(2.5 / area); + for(auto &hc: hatcorners) for(auto& h: hc) h = h * scale + (C0) * (1-scale); + } + for(auto &hc: hatcorners) recenter(hc); + clear_adj_memo(); if(q == 6) { hyperpoint hfar = diff --git a/config.cpp b/config.cpp index 1f3fa242..cfc30f49 100644 --- a/config.cpp +++ b/config.cpp @@ -842,6 +842,13 @@ EX void initConfig() { }) -> set_reaction(hat::reshape); + param_f(hat::hat_param_imag, "hat_param_imag", "hat_param_imag", 0) + -> editable(0, 2, 0.1, "hat parameter (imaginary)", + "Apeirodic hat tiling based on: https://arxiv.org/pdf/2303.10798.pdf\n\n" + "This controls the parameter discussed in Section 6. Parameter p is Tile(p, (2-p)√3), scaled so that the area is the same for every p.", 'v' + ) + -> set_reaction(hat::reshape); + addsaver(vid.particles, "extra effects", 1); param_i(vid.framelimit, "frame limit", 999); diff --git a/geom-exp.cpp b/geom-exp.cpp index a03ee121..52ca981e 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -1026,6 +1026,7 @@ EX void showEuclideanMenu() { } else if(hat::in()) { add_edit(hat::hat_param); + add_edit(hat::hat_param_imag); } else if(nil) { menuitem_nilwidth('v');