From db4f622588a8359b02c47b9cd26981223bfb139d Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sun, 19 Aug 2018 22:53:34 +0200 Subject: [PATCH] Archimedean tilings available from the menu --- classes.cpp | 2 +- geom-exp.cpp | 21 ++-- syntetic.cpp | 263 ++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 255 insertions(+), 31 deletions(-) diff --git a/classes.cpp b/classes.cpp index 6f435b6b..b01f2017 100644 --- a/classes.cpp +++ b/classes.cpp @@ -1681,7 +1681,7 @@ geometryinfo ginf[gGUARD] = { {"Bolza Surface x2", "Bolza2", 8, 3, qSMALL | qDOCKS, gcHyperbolic, 0x18400, {{6, 4}}}, {"minimal quotient", "minimal", 7, 3, qSMALL | qNONOR, gcHyperbolic, 0x18600, {{7, 5}}}, {"binary tiling", "binary", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}}, - {"syntetic tiling", "syntetic", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}} + {"Archimedean", "A", 7, 3, 0, gcHyperbolic, 0, {{7, 5}}} }; } diff --git a/geom-exp.cpp b/geom-exp.cpp index c029ae1c..da44bc25 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -281,7 +281,7 @@ void showEuclideanMenu() { } dialog::addBreak(50); - dialog::addBoolItem(XLAT("show quotient spaces"), showquotients, 'u'); + dialog::addBoolItem(XLAT("show quotient spaces"), showquotients, 'z'); dialog::addBreak(50); if(ts == 6 && tv == 3) @@ -336,8 +336,8 @@ void showEuclideanMenu() { break; } - dialog::addSelItem(XLAT("sides per face"), its(ts), 0); - dialog::addSelItem(XLAT("faces per vertex"), its(tv), 0); + dialog::addSelItem(XLAT("sides per face"), syntetic ? "?" : its(ts), 0); + dialog::addSelItem(XLAT("faces per vertex"), syntetic ? "?" : its(tv), 0); string qstring = "none"; if(tq & qZEBRA) qstring = "zebra"; @@ -353,6 +353,9 @@ void showEuclideanMenu() { dialog::addSelItem(XLAT("quotient space"), XLAT(qstring), 0); dialog::addSelItem(XLAT("size of the world"), + (syntetic && euclid) ? "∞" : + (syntetic && sphere) ? its(isize(currentmap->allcells())) : + (syntetic && hyperbolic) ? "exp(∞)*?" : worldsize < 0 ? "exp(∞)*" + (nom%denom ? its(nom)+"/"+its(-denom) : its(-worldsize)): worldsize == 0 ? "∞" : its(worldsize), @@ -386,10 +389,14 @@ void showEuclideanMenu() { dialog::handleNavigation(sym, uni); if(uni >= 'a' && uni < 'a'+gGUARD) { targetgeometry = eGeometry(uni - 'a'); - stop_game_and_switch_mode(geometry == targetgeometry ? rg::nothing : rg::geometry); - start_game(); + if(targetgeometry == gSyntetic) + pushScreen(synt::show); + else { + stop_game_and_switch_mode(geometry == targetgeometry ? rg::nothing : rg::geometry); + start_game(); + } } - else if(uni == 'u') + else if(uni == 'z') showquotients = !showquotients; else if(uni == 'v') { if(euclid6) ; @@ -431,7 +438,7 @@ void showEuclideanMenu() { torusconfig::newmode = torusconfig::torus_mode, torus_bitrunc = nonbitrunc, pushScreen(showTorusConfig); - if(geometry == gFieldQuotient) + else if(geometry == gFieldQuotient) pushScreen(showQuotientConfig); } else if(doexiton(sym, uni)) diff --git a/syntetic.cpp b/syntetic.cpp index 3a3fca0d..02c8d152 100644 --- a/syntetic.cpp +++ b/syntetic.cpp @@ -20,6 +20,8 @@ bool have_ph, have_line, have_symmetry, have_chessboard; int repetition = 1; int N; +ld euclidean_angle_sum; + vector flags; vector>> adjacent; @@ -55,9 +57,10 @@ int matches[30][30]; int periods[30]; int tilegroup[30], groupoffset[30], tilegroups; -int gcd(int x, int y) { return x ? gcd(y%x, x) : y; } +int gcd(int x, int y) { return x ? gcd(y%x, x) : y < 0 ? -y : y; } int errors; +string errormsg; pair& get_adj(heptagon *h, int cid); pair& get_triangle(heptagon *h, int cid); @@ -65,8 +68,11 @@ pair& get_triangle(const pair& p, int delta = 0); pair& get_adj(const pair& p, int delta = 0); void make_match(int a, int i, int b, int j) { - if(periods[a] != periods[b]) + if(isize(adjacent[a]) != isize(adjacent[b])) { + SDEBUG(printf("(error here)")); + errormsg = XLAT("polygons match incorrectly"); errors++; + } if(matches[a][b] == -1) matches[a][b] = j - i, matches[b][a] = i - j; else @@ -75,6 +81,27 @@ void make_match(int a, int i, int b, int j) { void prepare() { + for(int i: faces) if(i >= MAX_EDGE) { + errormsg = XLAT("currently no more than %1 edges", its(MAX_EDGE)); + errors++; + return; + } + if(isize(faces) > MAX_EDGE/2) { + errormsg = XLAT("currently no more than %1 faces in vertex", its(MAX_EDGE)); + errors++; + return; + } + if(isize(faces) < 3) { + errormsg = XLAT("not enough faces"); + errors++; + return; + } + for(int i: faces) if(i < 3) { + errormsg = XLAT("not enough edges"); + errors++; + return; + } + errors = 0; /* build the 'adjacent' table */ @@ -95,16 +122,16 @@ void prepare() { for(int oi=0; oi<1; oi++) { int at = (i+oi)%N; int inv = oi; - printf("vertex "); + SDEBUG(printf("vertex ");) for(int z=0; z [%d %d]\n", at, inv); + SDEBUG(printf("-> [%d %d]\n", at, inv);) } } for(int i=0; i= isize(adjacent[ai])) aj = 0; } - printf("-> [%d %d]\n", ai, aj); + SDEBUG( printf("-> [%d %d]\n", ai, aj); ) make_match(i, j, ai, aj); } } @@ -191,19 +219,36 @@ void prepare() { for(int z=2*N; z<2*N+2; z++) flags[z] |= sfPH; } } - - for(int i=0; i 2.000001) ginf[gSyntetic].cclass = gcHyperbolic; + SDEBUG( for(int i=0; i 2.000001) ginf[gSyntetic].cclass = gcHyperbolic; else ginf[gSyntetic].cclass = gcEuclid; - printf("sum = %lf\n", double(sum)); + SDEBUG( printf("euclidean_angle_sum = %lf\n", double(euclidean_angle_sum)); ) dynamicval dv(geometry, gSyntetic); @@ -239,7 +284,7 @@ void prepare() { if(euclid) break; } - printf("computed edgelength = %lf\n", double(edgelength)); + SDEBUG( printf("computed edgelength = %lf\n", double(edgelength)); ) triangles.clear(); triangles.resize(M); @@ -260,11 +305,11 @@ void prepare() { // printf("total = %lf\n", double(total)); } - for(auto& ts: triangles) { + SDEBUG( for(auto& ts: triangles) { printf("T"); for(auto& t: ts) printf(" %lf@%lf", double(t.first), double(t.second)); printf("\n"); - } + } ) } @@ -616,6 +661,178 @@ int threecolor(int id) { } } -} +vector samples = { + /* Euclidean */ + "(3,3,3,3,3,3)", + "(4,4,4,4)", + "(6,6,6)", + "(8,8,4)", + "(4,6,12)", + "(6,4,3,4)", + "(3,6,3,6)", + "(3,12,12)", + "(4,4,3L,3L,3L)[3,4]", + "(3,3,3,3,6)(1,2)(0,4)(3)", + "(3,3,4,3,4)(0,4)(1)(2,3)", + + /* Platonic */ + "(3,3,3)", + "(3,3,3,3)", + "(3,3,3,3,3)", + "(4,4,4)", + "(5,5,5)", + + /* Archimedean solids */ + "(3,6,6)", + "(3,4,3,4)", + "(3,8,8)", + "(4,6,6)", + "(3,4,4,4)", + "(4,6,8)", + "(3,3,3,3,4)(1,2)(0,4)(3)", + "(3,5,3,5)", + "(3,10,10)", + "(5,6,6)", + "(3,4,5,4)", + "(4,6,10)", + "(3,3,3,3,5)(1,2)(0,4)(3)", + + /* prisms */ + "(4,4,3)", + "(4,4,5)", + "(4,4,6)", + "(4,4,7)", + + /* sample antiprisms */ + "(3,3,3,4)(1)(2)", + "(3,3,3,5)(1)(2)", + "(3,3,3,6)(1)(2)", + "(3,3,3,7)(1)(2)", + + /* hyperbolic ones */ + "(4,4,4,4,4)", + "(5,5,5,5)", + "(3,3,3,3,7)(1,2)(0,4)(3)", + "(3HL,6,6,6)(1,0)[2](3)", + "(3,4,4,4,4)", + "(3,4,4,4,4) (0 1)[2 3](4)", + "(3,4,4,4,4) (0 1)(2)(3)(4)", + "(6,6,3,3,3) (0 2)(1)(3)(4)", + "(5,3,5,3,3) (0 1)(2 3)(4)", + "(4,3,3,3,3,3) (0 1)(2 3)(4 5)", + "(3,5,5,5,5,5) (0 1)[2 3](4)(5)", + "(3,5,5,5,5,5) (0 1)(2 4)(3 5)", + "(3,5,5,5,5,5) (0 1)(2 4)[3 5]", + "(3,5,5,5,5,5) (0 1)[2 4](3)(5)", + "(3,5,5,5,5,5) (0 1)(2)(3)(4)(5)", + }; -} \ No newline at end of file +int lastsample = 0; + +struct prepared_sample { + string s; + ld angle_sum; + int flags; + }; + + +vector prepsamples; + +int spos = 0; + +string current_symbol; +string active_symbol; + +bool manual_edit; + +void show() { + if(lastsample < isize(samples) && geometry != gSyntetic) { + string s = samples[lastsample++]; + parse_symbol(s); + if(errors) { + printf("WARNING: %d errors on %s\n", errors, s.c_str()); + } + else { + prepared_sample ps; + ps.s = s; + ps.flags = 0; + ps.angle_sum = euclidean_angle_sum * 180; + if(support_graveyard()) ps.flags |= sfPH; + if(support_threecolor()) ps.flags |= sfTHREE; + if(support_chessboard()) ps.flags |= sfCHESS; + prepsamples.push_back(ps); + } + } + sort(prepsamples.begin(), prepsamples.end(), [] (prepared_sample& s1, prepared_sample& s2) { + if(s1.angle_sum < s2.angle_sum - 1e-6) return true; + if(s2.angle_sum < s1.angle_sum - 1e-6) return false; + return s1.s < s2.s; + }); + cmode = sm::SIDE | sm::MAYDARK; + gamescreen(0); + dialog::init(XLAT("Archimedean tilings")); + if(current_symbol == "") + dialog::addBreak(100); + else + dialog::addSelItem("edit", current_symbol, '/'); + dialog::add_action([] () { + manual_edit = !manual_edit; + if(manual_edit) active_symbol = current_symbol; + if(!manual_edit) { + parse_symbol(current_symbol); + if(errors) parse_symbol(current_symbol = active_symbol); + else { + stop_game(); + need_reset_geometry = true; + if(geometry != gSyntetic) targetgeometry = gSyntetic, stop_game_and_switch_mode(rg::geometry); + nonbitrunc = true; need_reset_geometry = true; + start_game(); + } + } + }); + dialog::addBreak(100); + if(!manual_edit) { + for(int i=0; i<10; i++) { + int j = i + spos; + if(j >= isize(prepsamples)) continue; + auto &ps = prepsamples[j]; + dialog::addSelItem(ps.s, fts(ps.angle_sum) + "°", 'a' + i); + dialog::add_action([&] () { + stop_game(); + current_symbol = ps.s; + if(geometry != gSyntetic) targetgeometry = gSyntetic, stop_game_and_switch_mode(rg::geometry); + nonbitrunc = true; need_reset_geometry = true; + parse_symbol(current_symbol); + start_game(); + }); + } + dialog::addItem(XLAT("next page"), '-'); + dialog::add_action([] () { + if(spos + 10 >= isize(prepsamples)) + spos = 0; + else spos += 10; + }); + } + + dialog::addHelp(); + dialog::addBack(); + dialog::display(); + + keyhandler = [] (int sym, int uni) { + if(manual_edit && sym == SDLK_RETURN) sym = uni = '/'; + dialog::handleNavigation(sym, uni); + if(manual_edit && uni == 8 && current_symbol != "") { + current_symbol = current_symbol.substr(0, isize(current_symbol) - 1); + return; + } + if(manual_edit && uni >= 32 && uni < 128) { + current_symbol += uni; + return; + } + if(doexiton(sym, uni)) popScreen(); + }; + } + + } + +}