From d5294499993caa8d1462cdac4eed96795a022abe Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Sat, 14 Dec 2019 11:29:53 +0100 Subject: [PATCH] arbitrary tilings --- arbitrile.cpp | 315 ++++++++++++++++++++++++++++++++++++++++++++++++ cell.cpp | 1 + classes.cpp | 1 + classes.h | 2 +- floorshapes.cpp | 24 ++++ geom-exp.cpp | 1 + geometry2.cpp | 4 + hyper.cpp | 1 + pattern2.cpp | 2 + 9 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 arbitrile.cpp diff --git a/arbitrile.cpp b/arbitrile.cpp new file mode 100644 index 00000000..f0693e66 --- /dev/null +++ b/arbitrile.cpp @@ -0,0 +1,315 @@ +// Hyperbolic Rogue -- Arbitrary Tilings +// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details + +/** \file arbitrile.cpp + * \brief Arbitrary tilings + * + * Arbitrary tilings, defined in .tes files. + */ + +#include "hyper.h" +namespace hr { + +EX namespace arb { + +#if HDR + +struct shape { + int id; + vector vertices; + vector angles; + vector edges; + vector> connections; + int size() { return isize(vertices); } + void build_from_angles_edges(); + }; + +struct arbi_tiling { + + vector shapes; + + geometryinfo1& get_geometry(); + eGeometryClass get_class() { return get_geometry().kind; } + + ld scale(); + }; +#endif + +EX arbi_tiling current; + + +/** id of vertex in the arbitrary tiling */ + +EX short& id_of(heptagon *h) { return h->zebraval; } + +void shape::build_from_angles_edges() { + hyperpoint at(0, 0, 1, 0); + hyperpoint direction(1, 0, 0, 0); + vertices.clear(); + int n = isize(angles); + hyperpoint ctr = Hypc; + for(int i=0; i(f); + println(hlog, "type = ", s); + auto& c = current; + c.shapes.clear(); + int N = scan(f); + int tc = 0; + for(int i=0; i(f); + for(int s=0; s(f)); + cc.angles.push_back(scan(f)); + } + println(hlog, cc.edges); + println(hlog, cc.angles); + cc.build_from_angles_edges(); + cc.connections.resize(cc.size()); + tc += siz; + } + while(true) { + int ai = scan(f); + if(ai < 0) break; + int as = scan(f); + int bi = scan(f); + int bs = scan(f); + int m = scan(f); + c.shapes[ai].connections[as] = {bi, bs, m}; + c.shapes[bi].connections[bs] = {ai, as, m}; + } + println(hlog, "loaded"); + } + +geometryinfo1& arbi_tiling::get_geometry() { + return ginf[gEuclid].g; + } + +map > > altmap; + +EX map> arbi_matrix; + +EX hrmap *current_altmap; + +heptagon *build_child(heptspin p, pair adj); + +struct hrmap_arbi : hrmap { + heptagon *origin; + heptagon *getOrigin() override { return origin; } + + hrmap_arbi() { + dynamicval curmap(currentmap, this); + origin = tailored_alloc (current.shapes[0].size()); + origin->s = hsOrigin; + origin->emeraldval = 0; + origin->zebraval = 0; + origin->fiftyval = 0; + origin->fieldval = 0; + origin->rval0 = origin->rval1 = 0; + origin->cdata = NULL; + origin->alt = NULL; + origin->c7 = newCell(origin->type, origin); + origin->distance = 0; + + heptagon *alt = NULL; + + /* + if(hyperbolic) { + dynamicval g(geometry, gNormal); + alt = tailored_alloc (S7); + alt->s = hsOrigin; + alt->emeraldval = 0; + alt->zebraval = 0; + alt->distance = 0; + alt->c7 = NULL; + alt->alt = alt; + alt->cdata = NULL; + current_altmap = newAltMap(alt); + } + */ + + transmatrix T = xpush(.01241) * spin(1.4117) * xpush(0.1241) * Id; + arbi_matrix[origin] = make_pair(alt, T); + altmap[alt].emplace_back(origin, T); + + cgi.base_distlimit = 0; + celllister cl(origin->c7, 1000, 200, NULL); + ginf[geometry].distlimit[0] = cgi.base_distlimit = cl.dists.back(); + if(sphere) cgi.base_distlimit = SEE_ALL; + } + + ~hrmap_arbi() { + /* + if(hyperbolic) for(auto& p: arbi_matrix) if(p.second.first->cdata) { + delete p.second.first->cdata; + p.second.first->cdata = NULL; + } + */ + clearfrom(origin); + altmap.clear(); + arbi_matrix.clear(); + if(current_altmap) { + dynamicval g(geometry, gNormal); + delete current_altmap; + current_altmap = NULL; + } + } + void verify() override { } + + transmatrix adj(heptagon *h, int dl) override { + auto& c = current; + int t = id_of(h); + auto& sh = c.shapes[t]; + + int dr = gmod(dl+1, sh.size()); + + auto& co = sh.connections[dl]; + int xt = get<0>(co); + int xdl = get<1>(co); + // int m = get<2>(co); + auto& xsh = c.shapes[xt]; + int xdr = gmod(xdl+1, xsh.size()); + + hyperpoint vl = sh.vertices[dl]; + hyperpoint vr = sh.vertices[dr]; + hyperpoint vm = mid(vl, vr); + + transmatrix rm = gpushxto0(vm); + + hyperpoint xvl = xsh.vertices[xdl]; + hyperpoint xvr = xsh.vertices[xdr]; + hyperpoint xvm = mid(xvl, xvr); + + transmatrix xrm = gpushxto0(xvm); + + transmatrix Res = rgpushxto0(vm) * rspintox(rm*vr) * spintox(xrm*xvl) * xrm; + + if(hdist(vl, Res*xvr) + hdist(vr, Res*xvl) > .1) { + println(hlog, "s1 = ", kz(spintox(rm*vr)), " s2 = ", kz(rspintox(xrm*xvr))); + println(hlog, tie(t, dl), " = ", kz(Res)); + println(hlog, hdist(vl, Res * xvr), " # ", hdist(vr, Res * xvl)); + exit(3); + } + + return Res; + } + + heptagon *create_step(heptagon *h, int d) override { + + int t = id_of(h); + + const auto& p = arbi_matrix[h]; + + heptagon *alt = p.first; + + auto& sh = current.shapes[t]; + + auto& co = sh.connections[d]; + + int xt = get<0>(co); + int e = get<1>(co); + int m = get<2>(co); + + println(hlog, h, "@", p.second, " dir ", d, ":"); + + println(hlog, "adj = ", adj(h, d)); + + transmatrix T = p.second * adj(h, d); + + if(hyperbolic) { + dynamicval g(geometry, gNormal); + dynamicval cm(currentmap, current_altmap); + // transmatrix U = T; + current_altmap->virtualRebase(alt, T); + // U = U * inverse(T); + } + + if(euclid) { + /* hash the rough coordinates as heptagon* alt */ + size_t s = size_t(T[0][LDIM]+.261) * 124101 + size_t(T[1][LDIM]+.261) * 82143; + alt = (heptagon*) s; + } + + for(auto& p2: altmap[alt]) if(eqmatrix(p2.second, T)) { + println(hlog, "reuse ", p2.first, " at ", T); + h->c.connect(d, p2.first, e, m); + return p2.first; + } + + auto h1 = tailored_alloc (current.shapes[xt].size()); + println(hlog, "create ", h1, " at ", T); + h1->distance = h->distance + 1; + h1->zebraval = xt; + h1->c7 = newCell(h1->type, h1); + h1->alt = nullptr; + h->c.connect(d, h1, e, m); + + arbi_matrix[h1] = make_pair(alt, T); + altmap[alt].emplace_back(h1, T); + return h1; + } + + void draw() override { + dq::visited.clear(); + dq::enqueue(centerover->master, cview()); + + while(!dq::drawqueue.empty()) { + auto& p = dq::drawqueue.front(); + heptagon *h = get<0>(p); + transmatrix V = get<1>(p); + dynamicval b(band_shift, get<2>(p)); + dq::drawqueue.pop(); + + if(do_draw(h->c7, V)) drawcell(h->c7, V); + + for(int i=0; itype; i++) { + transmatrix V1 = V * adj(h, i); + bandfixer bf(V1); + dq::enqueue(h->move(i), V1); + } + } + } + + transmatrix adj(cell *c, int dir) override { return adj(c->master, dir); } + + ld spin_angle(cell *c, int d) override { return SPIN_NOT_AVAILABLE; } + }; + +EX hrmap *new_map() { return new hrmap_arbi; } + +#if CAP_COMMANDLINE +int readArgs() { + using namespace arg; + + if(0) ; + else if(argis("-arbi")) { + PHASEFROM(2); + stop_game(); + shift(); + set_geometry(gArbitrary); + load(args()); + } + else return 1; + return 0; + } + +auto hook = addHook(hooks_args, 100, readArgs); +#endif + +EX bool in() { return geometry == gArbitrary; } + +EX } +} \ No newline at end of file diff --git a/cell.cpp b/cell.cpp index aaf22eaf..b218675f 100644 --- a/cell.cpp +++ b/cell.cpp @@ -273,6 +273,7 @@ EX void initcells() { #if CAP_CRYSTAL else if(cryst) currentmap = crystal::new_map(); #endif + else if(arb::in()) currentmap = arb::new_map(); #if CAP_ARCM else if(archimedean) currentmap = arcm::new_map(); #endif diff --git a/classes.cpp b/classes.cpp index aad0a736..9680fd23 100644 --- a/classes.cpp +++ b/classes.cpp @@ -595,6 +595,7 @@ vector ginf = { {"{3,4,4}","none", "{3,4,4} hyperbolic honeycomb", "344", 8, 4, qIDEAL, giHyperb3, 0x50000, {{7, 2}}, eVariation::pure}, {"{3,4,4}","Crystal", "4D crystal in H3", "Cryst3" , 8, 4, qIDEAL | qANYQ | qCRYSTAL, giHyperb3, 0x52000, {{7, 3}}, eVariation::pure}, {"cat", "cat", "Arnold's cat mapping torus", "cat", 12, 3, qBINARY | qSOL | qsBQ | qOPTQ, giSolNIH, 0x52200, {{6, 4}}, eVariation::pure}, + {"arb", "arb", "arbitrary", "arb", 7, 3, qEXPERIMENTAL, giEuclid2, 0, {{7, 5}}, eVariation::pure}, }; // bits: 9, 10, 15, 16, (reserved for later) 17, 18 diff --git a/classes.h b/classes.h index e3a3ba44..8e69e060 100644 --- a/classes.h +++ b/classes.h @@ -216,7 +216,7 @@ enum eGeometry { gBinary4, gSol, gKiteDart2, gKiteDart3, gNil, gProduct, gRotSpace, gTernary, gNIH, gSolN, gInfOrder, gSpace336, gSpace344, gCrystal344, - gArnoldCat, + gArnoldCat, gArbitrary, gGUARD}; enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProduct, gcSL2 }; diff --git a/floorshapes.cpp b/floorshapes.cpp index a5d27750..508479d7 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -680,6 +680,28 @@ void geometry_information::generate_floorshapes() { } #endif + else if(arb::in()) { + auto& c = arb::current; + int n = isize(c.shapes); + vector models(n); + vector modelh(n); + for(int i=0; i(co)], get<1>(co), get<2>(co)); + ms.c.connect(j, &models[get<0>(co)], get<1>(co), get<2>(co)); + } + } + for(int i=0; imaster); + else if(arb::in()) + return arb::id_of(c->master); else if(geosupport_football() == 2) return pseudohept(c); else if(geometry == gBinaryTiling) diff --git a/geom-exp.cpp b/geom-exp.cpp index 8dc92864..5fe44a2f 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -348,6 +348,7 @@ void ge_select_tiling() { bool on = geometry == g; bool in_2d = WDIM == 2; dynamicval cg(geometry, g); + if(g == gArbitrary) continue; if(g == gTorus) continue; if(archimedean && !CAP_ARCM) continue; if(cryst && !CAP_CRYSTAL) continue; diff --git a/geometry2.cpp b/geometry2.cpp index 3c2f4492..a6521bc9 100644 --- a/geometry2.cpp +++ b/geometry2.cpp @@ -424,6 +424,10 @@ EX hyperpoint get_corner_position(cell *c, int cid, ld cf IS(3)) { } } #endif + if(arb::in()) { + auto& sh = arb::current.shapes[arb::id_of(c->master)]; + return normalize(C0 + (sh.vertices[cid % c->type] - C0) * 3 / cf); + } if(PURE) { return ddspin(c,cid,M_PI/S7) * xpush0(cgi.hcrossf * 3 / cf); } diff --git a/hyper.cpp b/hyper.cpp index b19e470d..f8854c65 100644 --- a/hyper.cpp +++ b/hyper.cpp @@ -37,6 +37,7 @@ #include "asonov.cpp" #include "penrose.cpp" #include "archimedean.cpp" +#include "arbitrile.cpp" #include "euclid.cpp" #include "sphere.cpp" #include "quotient.cpp" diff --git a/pattern2.cpp b/pattern2.cpp index 8ef8758e..1f8e4d1d 100644 --- a/pattern2.cpp +++ b/pattern2.cpp @@ -1263,6 +1263,7 @@ EX int pattern_threecolor(cell *c) { return c->master->rval1; } #endif + if(arb::in()) return 0; if(IRREGULAR || binarytiling) return !pseudohept(c); #if CAP_GP if(S3 == 3 && !(S7&1) && gp_threecolor() == 1 && c->master->c7 != c) { @@ -1597,6 +1598,7 @@ EX namespace patterns { #if CAP_ARCM if(archimedean) return colortables['A'][arcm::current.tilegroup[arcm::id_of(c->master)]]; #endif + if(arb::in()) return colortables['A'][c->master->zebraval]; case 'B': return colortables['B'][c->type & 15]; #if CAP_FIELD