From 90468c0daf0051a90548eb0ebe015b73d12e41e8 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 10 Nov 2018 16:56:08 +0100 Subject: [PATCH] Euclidean spiral --- conformal.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--- hypgraph.cpp | 15 ++++++++---- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/conformal.cpp b/conformal.cpp index 97fd875a..310c2f0d 100644 --- a/conformal.cpp +++ b/conformal.cpp @@ -393,7 +393,10 @@ namespace conformal { movetophase(); } - ld spiral_angle, cos_spiral, sin_spiral; + ld spiral_angle, spiral_x = 10, spiral_y = 7; + int spiral_id = 7; + + cld spiral_multiplier; void configure() { ld ball = -vid.ballangle * degree; @@ -403,8 +406,16 @@ namespace conformal { model_straight = (ocos > 1 - 1e-9); if(conformal::on) conformal::apply(); - ld b = spiral_angle * degree; - cos_spiral = cos(b), sin_spiral = sin(b); + if(hyperbolic) { + ld b = spiral_angle * degree; + ld cos_spiral = cos(b); + ld sin_spiral = sin(b); + spiral_multiplier = cld(cos_spiral, sin_spiral) * M_PI * cos_spiral; + } + if(euclid) { + hyperpoint h = tC0(eumove(spiral_x, spiral_y)); + spiral_multiplier = cld(0, 2 * M_PI) / cld(h[0], h[1]); + } band_shift = 0; } @@ -590,6 +601,33 @@ namespace conformal { return "?"; } + vector > torus_zeros; + + void match_torus_period() { + torus_zeros.clear(); + for(int y=0; y<=200; y++) + for(int x=-200; x<=200; x++) { + if(y == 0 && x <= 0) continue; + auto zero = vec_to_cellwalker(euclid_getvec(x, y)); + if(zero.at == currentmap->gamestart() && !zero.mirrored) + torus_zeros.emplace_back(x, y); + } + sort(torus_zeros.begin(), torus_zeros.end(), [] (const pair p1, const pair p2) { + ld d1 = hdist0(tC0(eumove(p1.first, p1.second))); + ld d2 = hdist0(tC0(eumove(p2.first, p2.second))); + if(d1 < d2 - 1e-6) return true; + if(d1 > d2 + 1e-6) return false; + return p1 < p2; + }); + if(spiral_id > isize(torus_zeros)) spiral_id = 0; + dialog::editNumber(spiral_id, 0, isize(torus_zeros)-1, 1, 10, XLAT("match the period of the torus"), ""); + dialog::reaction = [] () { + tie(spiral_x, spiral_y) = torus_zeros[spiral_id]; + }; + dialog::bound_low(0); + dialog::bound_up(isize(torus_zeros)-1); + } + void model_menu() { cmode = sm::SIDE | sm::MAYDARK | sm::CENTER; gamescreen(0); @@ -769,6 +807,28 @@ namespace conformal { dialog::scaleLog(); }); } + + if(pmodel == mdSpiral && hyperbolic) { + dialog::addSelItem(XLAT("spiral angle"), fts(spiral_angle), 'x'); + dialog::add_action([](){ + dialog::editNumber(spiral_angle, 0, 360, 15, 0, XLAT("spiral angle"), ""); + }); + } + + if(pmodel == mdSpiral && euclid) { + dialog::addSelItem(XLAT("spiral period: x"), fts(spiral_x), 'x'); + dialog::add_action([](){ + dialog::editNumber(spiral_x, -20, 20, 1, 10, XLAT("spiral period: x"), ""); + }); + dialog::addSelItem(XLAT("spiral period: y"), fts(spiral_x), 'y'); + dialog::add_action([](){ + dialog::editNumber(spiral_y, -20, 20, 1, 10, XLAT("spiral period: y"), ""); + }); + if(torus) { + dialog::addSelItem(XLAT("match the period of the torus"), its(spiral_id), 'n'); + dialog::add_action(match_torus_period); + } + } dialog::addSelItem(XLAT("vertical stretch"), fts3(vid.stretch), 's'); diff --git a/hypgraph.cpp b/hypgraph.cpp index 9b9decec..339abf98 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -557,10 +557,10 @@ void applymodel(hyperpoint H, hyperpoint& ret) { } case mdSpiral: { - makeband(H, ret, band_conformal); - - cld z(ret[0], ret[1]); - z = z * cld(conformal::cos_spiral, conformal::sin_spiral) * M_PI * conformal::cos_spiral; + cld z; + if(hyperbolic) makeband(H, ret, band_conformal); + else ret = H; + z = cld(ret[0], ret[1]) * conformal::spiral_multiplier; z = exp(z); ret[0] = real(z); ret[1] = imag(z); @@ -1372,6 +1372,13 @@ bool do_draw(cell *c) { bool do_draw(cell *c, const transmatrix& T) { if(!do_draw(c)) return false; + if(euclid && pmodel == mdSpiral) { + hyperpoint h = tC0(T); + cld z(h[0], h[1]); + z = z * conformal::spiral_multiplier; + ld iz = imag(z) + 1.14279e-2; // make it never fall exactly on PI + if(iz < -M_PI || iz >= M_PI) return false; + } if(cells_drawn > vid.cells_drawn_limit) return false; bool usr = vid.use_smart_range || quotient || torus; if(usr && cells_drawn >= 50 && !in_smart_range(T)) return false;