From 829850a701c10d8d313c388f2f26cc83bb22bcc5 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Thu, 30 Aug 2018 02:11:43 +0200 Subject: [PATCH] dual tilings --- archimedean.cpp | 80 +++++++++++++++++++++++++++++++++---------------- cell.cpp | 17 +++++++++-- complex.cpp | 2 +- floorshapes.cpp | 2 ++ geom-exp.cpp | 6 ++-- geometry2.cpp | 16 ++++++++-- goldberg.cpp | 2 ++ graph.cpp | 4 +++ hyper.h | 5 +++- hypgraph.cpp | 5 ++-- pattern2.cpp | 23 ++++++++++---- system.cpp | 2 ++ 12 files changed, 119 insertions(+), 45 deletions(-) diff --git a/archimedean.cpp b/archimedean.cpp index 347aeb30..60824754 100644 --- a/archimedean.cpp +++ b/archimedean.cpp @@ -423,7 +423,8 @@ struct hrmap_archimedean : hrmap { heptagon *getOrigin() { return origin; } hrmap_archimedean() { - int N0 = isize(current.adjacent[0]); + int id = DUAL ? current.N * 2 : 0;; + int N0 = isize(current.adjacent[id]); origin = tailored_alloc (N0); origin->s = hsOrigin; origin->emeraldval = 0; @@ -435,9 +436,9 @@ struct hrmap_archimedean : hrmap { origin->alt = NULL; origin->distance = 0; - parent_index_of(origin) = 0; - id_of(origin) = 0; - origin->c7 = newCell(N0, origin); + parent_index_of(origin) = DUAL ? 1 : 0; + id_of(origin) = id; + origin->c7 = newCell(DUAL ? N0/2 : N0, origin); heptagon *alt = NULL; @@ -458,20 +459,28 @@ struct hrmap_archimedean : hrmap { archimedean_gmatrix[origin] = make_pair(alt, T); altmap[alt].emplace_back(origin, T); - if(current.real_faces == 0) { - create_adjacent(origin, 0); + if(current.real_faces == 0 && DUAL) { + heptspin hs(origin, 0); + heptagon *hnew = build_child(hs, current.get_adj(hs)); + for(int s=1; s<2*current.N; s++) + origin->c.connect(s, hnew, s, false); + } + else if(current.real_faces == 0) { + create_adjacent(origin, 0); + heptagon *o0 = origin->move(0); create_adjacent(origin, 1); + heptagon *o1 = origin->move(1); for(int s=1; s<2*current.N; s+=2) - origin->move(0)->c.connect(s, origin->move(1), 2*current.N-s, false); + o0->c.connect(s, o1, 2*current.N-s, false); for(int s=2; s<2*current.N; s+=2) { - heptspin hs(origin->move(0), s); + heptspin hs(o0, s); heptagon *hnew = build_child(hs, current.get_adj(hs)); // no need to specify archimedean_gmatrix and altmap - hnew->c.connect(1, heptspin(origin->move(1), 2*current.N-s)); + hnew->c.connect(1, heptspin(o1, 2*current.N-s)); } - origin->move(1)->c.connect(1, origin->move(0), 2*current.N-1, false); + o1->c.connect(1, o0, 2*current.N-1, false); } - else if(origin->c7->type == 2) { + else if(origin->degree() == 2) { create_adjacent(origin, 0); create_adjacent(origin, 1); origin->move(0)->c.connect(1, origin->move(1), 2*current.N-1, false); @@ -508,9 +517,9 @@ heptagon *build_child(heptspin p, pair adj) { id_of(h) = adj.first; parent_index_of(h) = adj.second; int nei = neighbors_of(h); - h->c7 = newCell(nei, h); + h->c7 = newCell(DUAL ? nei/2 : nei, h); h->distance = p.at->distance + 1; - if(adj.first < 2*current.N) { + if(adj.first < 2*current.N && !DUAL) { int s = 0; heptspin hs(p); while(id_of(hs.at->move(0)) >= 2 * current.N) { @@ -607,7 +616,7 @@ void create_adjacent(heptagon *h, int d) { for(auto& p: altmap[alt]) if(intval(p.second * C0, T * C0) < 1e-4) { SDEBUG( printf("cell found: %p\n", p.first); ) - for(int d2=0; d2c7->type; d2++) { + for(int d2=0; d2degree(); d2++) { heptspin hs(p.first, d2); auto& t2 = current.get_triangle(p.first, d2); transmatrix T1 = T * spin(M_PI + t2.first); @@ -682,12 +691,13 @@ void draw() { int id = id_of(h); int S = isize(current.triangles[id]); - if(BITRUNCATED || id < 2*current.N) { + if(id < 2*current.N ? !DUAL : !PURE) { if(!dodrawcell(h->c7)) continue; drawcell(h->c7, V, 0, false); } for(int i=0; icmove(i); if(PURE && id >= 2*current.N && h->move(i) && id_of(h->move(i)) >= 2*current.N) continue; enqueue(h->move(i), V * adjcell_matrix(h, i)); @@ -701,10 +711,12 @@ transmatrix relative_matrix(heptagon *h2, heptagon *h1) { return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; transmatrix gm = Id, where = Id; while(h1 != h2) { - for(int i=0; imove(i) == h2) { - return gm * adjcell_matrix(h1, i) * where; + for(int i=0; imove(i) == h2) { + return gm * adjcell_matrix(h1, i) * where; + } } - else if(h1->distance > h2->distance) { + if(h1->distance > h2->distance) { gm = gm * adjcell_matrix(h1, 0); h1 = h1->move(0); } @@ -789,6 +801,7 @@ int readArgs() { if(0) ; else if(argis("-symbol")) { + PHASE(2); archimedean_tiling at; shift(); at.parse(args()); if(at.errors) { @@ -801,6 +814,7 @@ int readArgs() { } } else if(argis("-dgeom")) debug_geometry = true; + else if(argis("-dual")) { PHASE(2); set_variation(eVariation::dual); } else return 1; return 0; } @@ -819,7 +833,8 @@ int archimedean_tiling::support_threecolor() { } int archimedean_tiling::support_threecolor_bitruncated() { - return N % 2 == 0 ? 2 : 0; + for(int i: current.faces) if(i % 2) return 0; + return 2; } int archimedean_tiling::support_football() { @@ -842,6 +857,8 @@ bool pseudohept(int id) { } bool chessvalue(cell *c) { + if(DUAL) + return c->master->rval1 - 1; return c->master->fieldval & 1; } @@ -971,10 +988,19 @@ archimedean_tiling edited; bool symbol_editing; +void next_variation() { + set_variation( + PURE ? eVariation::dual : + DUAL ? eVariation::bitruncated : + eVariation::pure); + need_reset_geometry = true; + start_game(); + } + void enable(archimedean_tiling& arct) { stop_game(); + if(!archimedean) set_variation(eVariation::pure); set_geometry(gArchimedean); - set_variation(eVariation::pure); patterns::whichPattern = patterns::PAT_NONE; #if CAP_TEXTURE if(texture::config.tstate == texture::tsActive && texture::cgroup == cpThree) @@ -985,6 +1011,7 @@ void enable(archimedean_tiling& arct) { patterns::whichPattern = patterns::PAT_CHESS; #endif current = arct; + need_reset_geometry = true; start_game(); } @@ -1108,10 +1135,7 @@ void show() { if(archimedean) { dialog::addSelItem(XLAT("variations"), gp::operation_name(), 'v'); - dialog::add_action([] () { - set_variation(PURE ? eVariation::bitruncated : eVariation::pure); - start_game(); - }); + dialog::add_action(next_variation); } } @@ -1151,8 +1175,8 @@ string archimedean_tiling::world_size() { denom = denom / g * f; } int anom = 0, adenom = 1; - if(BITRUNCATED) anom = 1, adenom = 1; - for(int f: faces) { + if(BITRUNCATED || DUAL) anom = 1, adenom = 1; + if(!DUAL) for(int f: faces) { int g = gcd(adenom, f); anom = (anom * f + adenom) / g; adenom = adenom / g * f; @@ -1172,6 +1196,10 @@ string archimedean_tiling::world_size() { return s; } +int degree(heptagon *h) { + return isize(current.adjacent[id_of(h)]); + } + } } diff --git a/cell.cpp b/cell.cpp index 89ce5a6a..b1ff475a 100644 --- a/cell.cpp +++ b/cell.cpp @@ -796,14 +796,25 @@ cell *createMov(cell *c, int d) { exit(1); } } - else if(PURE && archimedean) { - if(arcm::id_of(c->master) <= arcm::current.N * 2) { + else if(archimedean && PURE) { + if(arcm::id_of(c->master) < arcm::current.N * 2) { heptspin hs = heptspin(c->master, d) + wstep + 2 + wstep + 1; c->c.connect(d, hs.at->c7, hs.spin, hs.mirrored); } else c->c.connect(d, c, d, false); } - else if(PURE || archimedean) { + else if(archimedean && DUAL) { + if(arcm::id_of(c->master) >= arcm::current.N * 2) { + heptagon *h2 = createStep(c->master, d*2); + int d1 = c->master->c.spin(d*2); + c->c.connect(d, h2->c7, d1/2, false); + } + else { + printf("bad connection\n"); + c->c.connect(d,c,d,false); + } + } + else if(archimedean || PURE) { heptagon *h2 = createStep(c->master, d); c->c.connect(d, h2->c7,c->master->c.spin(d),false); } diff --git a/complex.cpp b/complex.cpp index b0b812aa..5445cea6 100644 --- a/complex.cpp +++ b/complex.cpp @@ -3199,7 +3199,7 @@ namespace windmap { // cw.spin = 0; neighbors.emplace_back(); auto &v = neighbors.back(); - if(NONSTDVAR && !sphere) + if(NONSTDVAR && !sphere && !archimedean) for(int l=0; lmaster, cw.spin); hs = hs + l + wstep; diff --git a/floorshapes.cpp b/floorshapes.cpp index f35bbf6b..e2a7e832 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -500,6 +500,8 @@ void generate_floorshapes() { for(int i=0; i<2*ac.N + 2; i++) { arcm::id_of(&master) = i; model.type = isize(ac.triangles[i]); + if(DUAL) model.type /= 2, arcm::parent_index_of(&master) = !(i&1); + if(BITRUNCATED) generate_floorshapes_for(i, &model, !arcm::pseudohept(i), arcm::pseudohept(i) ? 0 : 1^(i&1)); else if(geosupport_football() == 2) diff --git a/geom-exp.cpp b/geom-exp.cpp index a5d2d27e..80474a4b 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -288,8 +288,6 @@ void showEuclideanMenu() { dialog::addSelItem(XLAT("variations"), XLAT("does not matter"), 'v'); else if(binarytiling) dialog::addSelItem(XLAT("width"), fts(vid.binary_width), 'v'); - else if(archimedean) - dialog::addSelItem(XLAT("variations"), XLAT("Not implemented."), 'v'); else dialog::addSelItem(XLAT("variations"), gp::operation_name(), 'v'); @@ -343,6 +341,7 @@ void showEuclideanMenu() { spf += its(i); } if(BITRUNCATED) spf = "[" + spf + "]," + its(arcm::current.N * 2) + "," + its(arcm::current.N * 2); + if(DUAL) spf = its(arcm::current.N) + "^[" + spf + "]"; } else if(binarytiling) spf = "6,[6,7],7"; @@ -434,7 +433,8 @@ void showEuclideanMenu() { else if(uni == 'z') showquotients = !showquotients; else if(uni == 'v') { - if(euclid6 || archimedean) ; + if(euclid6) ; + else if(archimedean) arcm::next_variation(); else if(binarytiling) { dialog::editNumber(vid.binary_width, 0, 2, 0.1, 1, XLAT("binary tiling width"), ""); dialog::reaction = [] () { diff --git a/geometry2.cpp b/geometry2.cpp index b914634a..aa63d6b8 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -408,6 +408,10 @@ hyperpoint get_corner_position(cell *c, int cid, ld cf) { hyperpoint h1 = xspinpush0(-t1.first, t1.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1)); return mid3(C0, h0, h1); } + if(DUAL) { + auto& t0 = ac.get_triangle(c->master, 2*cid-1); + return xspinpush0(-t0.first, t0.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1)); + } } if(PURE) { return ddspin(c,cid,M_PI/S7) * xpush0(hcrossf * 3 / cf); @@ -447,6 +451,11 @@ hyperpoint nearcorner(cell *c, int i) { auto& t = ac.get_triangle(c->master, i); return xspinpush0(-t.first, t.second); } + if(DUAL) { + auto &ac = arcm::current; + auto& t = ac.get_triangle(c->master, i * 2); + return xspinpush0(-t.first, t.second); + } } if(binarytiling) { ld yx = log(2) / 2; @@ -505,9 +514,10 @@ hyperpoint farcorner(cell *c, int i, int which) { int n1 = isize(ac.adjacent[id1]); return spin(-t.first - M_PI / c->type) * xpush(ac.inradius[id/2] + ac.inradius[id1/2]) * xspinpush0(M_PI + M_PI/n1*(which?3:-3), ac.circumradius[id1/2]); } - if(BITRUNCATED) { + if(BITRUNCATED || DUAL) { + int mul = DUAL ? 2 : 1; auto &ac = arcm::current; - auto adj = ac.get_adj(c->master, i); + auto adj = ac.get_adj(c->master, i * mul); heptagon h; cell cx; cx.master = &h; arcm::id_of(&h) = adj.first; arcm::parent_index_of(&h) = adj.second; @@ -516,7 +526,7 @@ hyperpoint farcorner(cell *c, int i, int which) { auto& t2 = arcm::current.get_triangle(adj); - return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -1 : 2); + return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -mul : 2*mul); } } diff --git a/goldberg.cpp b/goldberg.cpp index 57272dde..a34c611e 100644 --- a/goldberg.cpp +++ b/goldberg.cpp @@ -627,6 +627,8 @@ namespace hr { namespace gp { string operation_name() { if(IRREGULAR) return XLAT("irregular"); + else if(DUAL) + return XLAT("dual"); else if(PURE) return XLAT("OFF"); else if(BITRUNCATED) diff --git a/graph.cpp b/graph.cpp index ecc0c3bf..cf7035db 100644 --- a/graph.cpp +++ b/graph.cpp @@ -240,6 +240,10 @@ ld displayspin(cell *c, int d) { auto& t1 = arcm::current.get_triangle(c->master, d-1); return -(t1.first + M_PI / c->type); } + else if(DUAL) { + auto& t1 = arcm::current.get_triangle(c->master, 2*d); + return -t1.first; + } else { /* BITRUNCATED */ auto& t1 = arcm::current.get_triangle(c->master, d); return -t1.first; diff --git a/hyper.h b/hyper.h index 52a2255c..96f16443 100644 --- a/hyper.h +++ b/hyper.h @@ -137,6 +137,7 @@ void addMessage(string s, char spamtype = 0); #define IRREGULAR (variation == eVariation::irregular) #define PURE (variation == eVariation::pure) #define BITRUNCATED (variation == eVariation::bitruncated) +#define DUAL (variation == eVariation::dual) #define CHANGED_VARIATION (variation != ginf[geometry].default_variation) @@ -530,7 +531,9 @@ struct cell : gcell { // do not add any fields after connection_table (see tailored_alloc) }; -int heptagon::degree() { if(archimedean) return c7->type; else return S7; } +namespace arcm { int degree(heptagon *h); } + +int heptagon::degree() { if(archimedean) return arcm::degree(this); else return S7; } typedef walker heptspin; typedef walker cellwalker; diff --git a/hypgraph.cpp b/hypgraph.cpp index 9a6f5875..40707764 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -807,11 +807,12 @@ void optimizeview() { if(binarytiling || archimedean) { turn = -1, best = View[2][2]; for(int i=0; ic7->type; i++) { - heptagon *h2 = createStep(viewctr.at, i); + int i1 = i * (DUAL ? 2 : 1); + heptagon *h2 = createStep(viewctr.at, i1); transmatrix T = (binarytiling) ? binary::relative_matrix(h2, viewctr.at) : arcm::relative_matrix(h2, viewctr.at); hyperpoint H = View * tC0(T); ld quality = euclid ? hdist0(H) : H[2]; - if(quality < best) best = quality, turn = i, TB = T; + if(quality < best) best = quality, turn = i1, TB = T; } if(turn >= 0) { View = View * TB; diff --git a/pattern2.cpp b/pattern2.cpp index 7d059165..49cff50f 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -1065,13 +1065,17 @@ namespace patterns { } bool geosupport_chessboard() { - return (archimedean && PURE) ? arcm::current.support_chessboard() : (VALENCE % 2 == 0); + return + (archimedean && PURE) ? arcm::current.support_chessboard() : + (archimedean && DUAL) ? arcm::current.support_threecolor_bitruncated() : + (VALENCE % 2 == 0); } int geosupport_threecolor() { if(IRREGULAR) return 0; if(archimedean && PURE) return arcm::current.support_threecolor(); if(archimedean && BITRUNCATED) return arcm::current.support_threecolor_bitruncated(); + if(archimedean && DUAL) return 0; // it sometimes does support threecolor, but it can be obtained in other ways then if(BITRUNCATED && S3 == 3) { if(S7 % 2) return 1; return 2; @@ -1086,8 +1090,11 @@ int geosupport_threecolor() { int geosupport_football() { // always works in bitrunc geometries if(BITRUNCATED) return 2; + + if(archimedean && DUAL) return false; + // it sometimes does support football, but it can be obtained in other ways then - if(archimedean) return arcm::current.support_football(); + if(archimedean /* PURE */) return arcm::current.support_football(); if(IRREGULAR) return irr::bitruncations_performed ? 2 : 1; @@ -1225,8 +1232,12 @@ bool kraken_pseudohept(cell *c) { return ishept(c); else if(IRREGULAR) return c->type != 6; - else if(archimedean) + else if(archimedean && PURE) return c->type == isize(arcm::current.triangles[0]); + else if(archimedean && BITRUNCATED) + return pseudohept(c); + else if(archimedean && DUAL) + return true; else if(!euclid && S3 == 3 && !(S7&1) && gp_threecolor() == 1) return ishept(c); else @@ -1868,12 +1879,12 @@ namespace patterns { return; } if(archimedean) { - if(whichPattern == PAT_COLORING) { + if(whichPattern == PAT_COLORING && geosupport_threecolor()) { if(subpattern_flags & SPF_FOOTBALL) cgroup = cpFootball; else cgroup = cpThree; } - else if(whichPattern == PAT_CHESS && arcm::current.support_chessboard()) cgroup = cpChess; - else if(whichPattern == 0 && (subpattern_flags & SPF_FOOTBALL) && arcm::current.support_football()) cgroup = cpFootball; + else if(whichPattern == PAT_CHESS && geosupport_chessboard()) cgroup = cpChess; + else if(whichPattern == PAT_TYPES && (subpattern_flags & SPF_FOOTBALL) && geosupport_football()) cgroup = cpFootball; return; } for(int i=0; i