diff --git a/archimedean.cpp b/archimedean.cpp index 4368cc7b..de06784a 100644 --- a/archimedean.cpp +++ b/archimedean.cpp @@ -555,7 +555,7 @@ struct hrmap_archimedean : hrmap { dynamicval g(geometry, gNormal); dynamicval cm(currentmap, current_altmap); U = T; - virtualRebaseSimple(alt, T); + current_altmap->virtualRebase(alt, T); U = U * inverse(T); } @@ -655,7 +655,21 @@ struct hrmap_archimedean : hrmap { } return gm * where; } - + + ld spin_angle(cell *c, int d) { + if(PURE) { + 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; + } + } }; EX hrmap *new_map() { return new hrmap_archimedean; } diff --git a/basegraph.cpp b/basegraph.cpp index 412e48ee..24332e61 100644 --- a/basegraph.cpp +++ b/basegraph.cpp @@ -586,7 +586,7 @@ EX void resetGL() { } #endif check_cgi(); - cgi.require_shapes(); + if(currentmap) cgi.require_shapes(); #if MAXMDIM >= 4 if(GDIM == 3 && !floor_textures) make_floor_textures(); #endif diff --git a/binary-tiling.cpp b/binary-tiling.cpp index 2ca5ac69..94aa40e3 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -192,6 +192,8 @@ EX namespace binary { int nextdir(int choices) { return directions_generator() % choices; } + heptagon *getOrigin() override { return origin; } + hrmap_binary() { set_seed(); origin = hyperbolic_origin(); @@ -427,58 +429,38 @@ EX namespace binary { if(!do_draw(c, V)) continue; drawcell(c, V); - if(geometry == gBinaryTiling) { - dq::enqueue(h->move(bd_up), V * xpush(-log(2))); - dq::enqueue(h->move(bd_right), V * parabolic(1)); - dq::enqueue(h->move(bd_left), V * parabolic(-1)); - if(c->type == 6) - dq::enqueue(h->move(bd_down), V * xpush(log(2))); - if(c->type == 7) { - dq::enqueue(h->move(bd_down_left), V * parabolic(-1) * xpush(log(2))); - dq::enqueue(h->move(bd_down_right), V * parabolic(1) * xpush(log(2))); - } - } - else { - for(int i=0; imove(i), V * tmatrix(h, i)); - } + for(int i=0; itype; i++) + dq::enqueue(h->cmove(i), V * adj(h, i)); } } - + // hrmap_standard overrides hrmap's default, override it back virtual transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override { return relative_matrix(c2->master, c1->master); } + + int updir_at(heptagon *h) { + if(geometry != gBinaryTiling) return updir(); + else if(type_of(h) == 6) return bd_down; + else if(mapside(h) == 1) return bd_left; + else if(mapside(h) == -1) return bd_right; + else throw "unknown updir"; + } transmatrix relative_matrix(heptagon *h2, heptagon *h1) override { if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7)) return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7]; transmatrix gm = Id, where = Id; while(h1 != h2) { - int up_step = updir(); if(h1->distance <= h2->distance) { - if(geometry != gBinaryTiling) - where = itmatrix(h2, up_step) * where, h2 = may_create_step(h2, up_step); - else { - if(type_of(h2) == 6) - h2 = may_create_step(h2, bd_down), where = xpush(-log(2)) * where; - else if(mapside(h2) == 1) - h2 = may_create_step(h2, bd_left), where = parabolic(+1) * where; - else if(mapside(h2) == -1) - h2 = may_create_step(h2, bd_right), where = parabolic(-1) * where; - } + int d = updir_at(h2); + where = iadj(h2, d) * where; + h2 = may_create_step(h2, d); } else { - if(geometry != gBinaryTiling) - gm = gm * tmatrix(h1, up_step), h1 = may_create_step(h1, up_step); - else { - if(type_of(h1) == 6) - h1 = may_create_step(h1, bd_down), gm = gm * xpush(log(2)); - else if(mapside(h1) == 1) - h1 = may_create_step(h1, bd_left), gm = gm * parabolic(-1); - else if(mapside(h1) == -1) - h1 = may_create_step(h1, bd_right), gm = gm * parabolic(+1); - } + int d = updir_at(h1); + gm = gm * adj(h1, d); + h1 = may_create_step(h1, d); } } return gm * where; @@ -525,6 +507,79 @@ EX namespace binary { } return res; } + + ld spin_angle(cell *c, int d) { + if(WDIM == 3 || geometry == gBinary4 || geometry == gTernary) { + return hrmap::spin_angle(c, d); + } + if(d == NODIR) return 0; + if(d == c->type-1) d++; + return -(d+2)*M_PI/4; + } + + const transmatrix adj(heptagon *h, int dir) { + if(geometry == gBinaryTiling) switch(dir) { + case bd_up: return xpush(-log(2)); + case bd_left: return parabolic(-1); + case bd_right: return parabolic(+1); + case bd_down: + if(h->type == 6) return xpush(log(2)); + /* case bd_down_left: */ + return parabolic(-1) * xpush(log(2)); + case bd_down_right: + return parabolic(+1) * xpush(log(2)); + case bd_up_left: + return xpush(-log(2)) * parabolic(-1); + case bd_up_right: + return xpush(-log(2)) * parabolic(1); + default: + throw "unknown direction"; + } + else if(use_direct_for(dir)) + return direct_tmatrix[dir]; + else { + h->cmove(dir); + return inverse_tmatrix[h->c.spin(dir)]; + } + } + + const transmatrix iadj(heptagon *h, int dir) { heptagon *h1 = h->cmove(dir); return adj(h1, h->c.spin(dir)); } + + transmatrix adj(cell *c, int dir) { return adj(c->master, dir); } + + void virtualRebase(heptagon*& base, transmatrix& at) override { + + while(true) { + + double currz = at[LDIM][LDIM]; + + heptagon *h = base; + + heptagon *newbase = NULL; + + transmatrix bestV; + + for(int d=0; dcmove(d); + } + } + + if(newbase) { + base = newbase; + at = bestV; + continue; + } + + return; + } + } + + ~hrmap_binary() { clearfrom(origin); } }; EX hrmap *new_map() { return new hrmap_binary; } @@ -537,8 +592,8 @@ EX namespace binary { EX hrmap *new_alt_map(heptagon *o) { return new hrmap_binary(o); } - transmatrix direct_tmatrix[14]; - transmatrix inverse_tmatrix[14]; + EX transmatrix direct_tmatrix[14]; + EX transmatrix inverse_tmatrix[14]; int use_direct; // directions in the 'use_direct' mask are taken from direct_tmatrix; @@ -663,24 +718,6 @@ EX namespace binary { inverse_tmatrix[i] = inverse(direct_tmatrix[i]); } - EX const transmatrix& tmatrix(heptagon *h, int dir) { - if(use_direct_for(dir)) - return direct_tmatrix[dir]; - else { - h->cmove(dir); - return inverse_tmatrix[h->c.spin(dir)]; - } - } - - EX const transmatrix& itmatrix(heptagon *h, int dir) { - if(use_direct_for(dir)) - return inverse_tmatrix[dir]; - else { - h->cmove(dir); - return h->cmove(dir), direct_tmatrix[h->c.spin(dir)]; - } - } - #if MAXMDIM == 4 EX void queuecube(const transmatrix& V, ld size, color_t linecolor, color_t facecolor) { @@ -927,38 +964,6 @@ EX int celldistance3(heptagon *c1, heptagon *c2) { } EX int celldistance3(cell *c1, cell *c2) { return celldistance3(c1->master, c2->master); } - -EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) { - - while(true) { - - double currz = at[LDIM][LDIM]; - - heptagon *h = base; - - heptagon *newbase = NULL; - - transmatrix bestV; - - for(int d=0; dcmove(d); - } - } - - if(newbase) { - base = newbase; - at = bestV; - continue; - } - - return; - } - } #endif EX hyperpoint get_horopoint(ld y, ld x) { diff --git a/cell.cpp b/cell.cpp index 868dc8b7..a5450acd 100644 --- a/cell.cpp +++ b/cell.cpp @@ -35,11 +35,37 @@ struct hrmap { return relative_matrix(c2->master, c1->master); } virtual struct transmatrix adj(cell *c, int i); - virtual struct transmatrix iadj(cell *c, int i) { return adj(c->cmove(i), c->c.spin(i)); } + struct transmatrix iadj(cell *c, int i) { cell *c1 = c->cmove(i); return adj(c1, c->c.spin(i)); } virtual void draw() { printf("undrawable\n"); } virtual vector get_vertices(cell*); + + virtual void virtualRebase(heptagon*& base, transmatrix& at) { + printf("virtualRebase called unexpectedly\n"); + return; + } + + static constexpr ld SPIN_NOT_AVAILABLE = 1e5; + virtual ld spin_angle(cell *c, int d) { return SPIN_NOT_AVAILABLE; } + + virtual transmatrix spin_to(cell *c, int d, ld bonus=0) { + ld sa = spin_angle(c, d); + if(sa != SPIN_NOT_AVAILABLE) { return spin(bonus + sa); } + transmatrix T = rspintox(tC0(adj(c, d))); + if(WDIM == 3) return T * cspin(2, 0, bonus); + return T * spin(bonus); + } + + virtual transmatrix spin_from(cell *c, int d, ld bonus=0) { + ld sa = spin_angle(c, d); + if(sa != SPIN_NOT_AVAILABLE) { return spin(bonus - sa); } + transmatrix T = spintox(tC0(iadj(c, d))); + if(WDIM == 3) return T * cspin(2, 0, bonus); + return T * spin(bonus); + } + + virtual double spacedist(cell *c, int i) { return hdist0(tC0(adj(c, i))); } }; /** hrmaps which are based on regular non-Euclidean 2D tilings, possibly quotient */ @@ -47,6 +73,11 @@ struct hrmap_standard : hrmap { void draw() override; transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override; heptagon *create_step(heptagon *h, int direction) override; + transmatrix adj(cell *c, int d); + transmatrix adj(heptagon *h, int d); + transmatrix iadj(heptagon *h, int d) { return adj(h->cmove(d), h->c.spin(d)); } + ld spin_angle(cell *c, int d); + double spacedist(cell *c, int i) override; }; void clearfrom(heptagon*); @@ -54,20 +85,21 @@ void verifycells(heptagon*); struct hrmap_hyperbolic : hrmap_standard { heptagon *origin; - eVariation mvar; hrmap_hyperbolic(); hrmap_hyperbolic(heptagon *origin); heptagon *getOrigin() override { return origin; } ~hrmap_hyperbolic() { // verifycells(origin); // printf("Deleting hyperbolic map: %p\n", this); - dynamicval ph(variation, mvar); clearfrom(origin); } void verify() override { verifycells(origin); } + void virtualRebase(heptagon*& base, transmatrix& at) override; }; #endif +transmatrix hrmap::adj(cell *c, int i) { return calc_relative_matrix(c->cmove(i), c, C0); } + vector& hrmap::allcells() { static vector default_allcells; if(bounded) { @@ -109,7 +141,8 @@ EX vector allmaps; EX hrmap *newAltMap(heptagon *o) { return new hrmap_hyperbolic(o); } // --- hyperbolic geometry --- -heptagon* hyperbolic_origin() { +EX heptagon* hyperbolic_origin() { + int odegree = geometry == gBinaryTiling ? 6 : S7; heptagon *origin = tailored_alloc (odegree); heptagon& h = *origin; h.s = hsOrigin; @@ -122,7 +155,7 @@ heptagon* hyperbolic_origin() { h.alt = NULL; h.distance = 0; if(IRREGULAR) irr::link_start(origin); - h.c7 = newCell(geometry == gBinaryTiling ? 6 : S7, origin); + h.c7 = newCell(odegree, origin); return origin; } diff --git a/celldrawer.cpp b/celldrawer.cpp index 77515030..db4e1d1d 100644 --- a/celldrawer.cpp +++ b/celldrawer.cpp @@ -2047,7 +2047,7 @@ void celldrawer::draw_wall_full() { color_t col = (highwall(c) || c->wall == waTower) ? wcol : fcol; if(!chasmg) { -#define D(v) darkena(gradient(0, col, 0, v * (sphere ? spherity(V * cellrelmatrix(c,i)) : 1), 1), fd, 0xFF) +#define D(v) darkena(gradient(0, col, 0, v * (sphere ? spherity(V * currentmap->adj(c,i)) : 1), 1), fd, 0xFF) // #define D(v) darkena(col, fd, 0xFF) if(sha & 1) { @@ -2242,9 +2242,8 @@ void celldrawer::add_map_effects() { if(tim > 1000) tim = 800; if(elec::havecharge && tim > 400) tim = 400; for(int t=0; ttype; t++) if(c->move(t) && c->move(t)->ligon) { - ld hdir = displayspin(c, t); int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF); - queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(xspinpush(hdir, cgi.crossf), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality); + queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality); } } @@ -2252,8 +2251,9 @@ void celldrawer::add_map_effects() { whirlwind::calcdirs(c); for(int i=0; ispin_angle(c, whirlwind::dfrom[i]) + M_PI; + ld hdir1 = currentmap->spin_angle(c, whirlwind::dto[i]); + /* todo what if no spin_angle */ double ph1 = fractick(PURE ? 150 : 75); diff --git a/euclid.cpp b/euclid.cpp index e9d90d06..c93ac435 100644 --- a/euclid.cpp +++ b/euclid.cpp @@ -342,7 +342,7 @@ template void build_euclidean_moves(cell *c, int vec, const T& builder) } } -struct hrmap_euclid_any : hrmap { +struct hrmap_euclid_any : hrmap_standard { void draw() override; }; @@ -396,7 +396,7 @@ struct hrmap_torus : hrmap_euclid_any { forCellIdEx(cc, i, c1) { int d1 = celldistance(cc, c2); if(d1 < d) { - t = t * cellrelmatrix(c1, i); + t = t * adj(c1, i); c1 = cc; d = d1; goto again; diff --git a/floorshapes.cpp b/floorshapes.cpp index 79c3eed3..261dd76a 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -611,6 +611,17 @@ void geometry_information::generate_floorshapes() { DEBBI(DF_POLY, ("generate_floorshapes")); + heptagon modelh; + cell model; + model.master = &modelh; + model.type = modelh.type = S7; + for(int i=0; i ncor(approx_nearcorner, true); - heptagon master; - cell model; - model.master = &master; - model.type = 4; for(int i=0; i<2; i++) { - master.s = hstate(i); /* kite/dart shape */ + modelh.s = hstate(i); /* kite/dart shape */ generate_floorshapes_for(i, &model, 0, 0); } } @@ -652,15 +659,12 @@ void geometry_information::generate_floorshapes() { #if CAP_ARCM else if(archimedean) { - heptagon master; - cell model; - model.master = &master; - arcm::parent_index_of(&master) = 0; + arcm::parent_index_of(&modelh) = 0; auto &ac = arcm::current; for(int i=0; i<2*ac.N + 2; i++) { - arcm::id_of(&master) = i; + arcm::id_of(&modelh) = i; model.type = isize(ac.triangles[i]); - if(DUAL) model.type /= 2, arcm::parent_index_of(&master) = !(i&1); + if(DUAL) model.type /= 2, arcm::parent_index_of(&modelh) = !(i&1); if(BITRUNCATED) generate_floorshapes_for(i, &model, !arcm::pseudohept(&model), arcm::pseudohept(&model) ? 0 : 1^(i&1)); @@ -673,10 +677,6 @@ void geometry_information::generate_floorshapes() { #endif else if(geometry == gBinary4) { - heptagon modelh; - cell model; - model.master = &modelh; - model.type = S7; for(int i: {0,1}) { modelh.zebraval = i; generate_floorshapes_for(i, &model, 1, 0); @@ -684,10 +684,6 @@ void geometry_information::generate_floorshapes() { } else if(geometry == gTernary) { - heptagon modelh; - cell model; - model.master = &modelh; - model.type = S7; for(int i: {0,1,2}) { modelh.zebraval = i; generate_floorshapes_for(i, &model, 1, 0); @@ -695,8 +691,6 @@ void geometry_information::generate_floorshapes() { } else if(PURE && geometry != gBinaryTiling && geosupport_football() < 2) { - cell model; - model.type = S7; generate_floorshapes_for(0, &model, 1, 0); } diff --git a/geometry.cpp b/geometry.cpp index 70492123..51630585 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -113,7 +113,7 @@ struct geometry_information { ld rhexf; transmatrix heptmove[MAX_EDGE], hexmove[MAX_EDGE]; - transmatrix invheptmove[MAX_EDGE], invhexmove[MAX_EDGE]; + transmatrix invhexmove[MAX_EDGE]; int base_distlimit; @@ -521,7 +521,6 @@ void geometry_information::prepare_basics() { for(int d=0; dc.mirror(d)) T = T * Mirror; + int sp = h->c.spin(d); + if(sp) T = T * spin(2*M_PI*sp/S7); + return T; + } + transmatrix hrmap_standard::relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) { heptagon *h1 = c1->master; @@ -91,64 +99,57 @@ transmatrix hrmap_standard::relative_matrix(cell *c2, cell *c1, const hyperpoint if(bounded) { transmatrix T; ld bestdist = 1e9; - for(int d=0; dmove(d)) { - int sp = h2->c.spin(d); - transmatrix S = cgi.heptmove[sp] * spin(2*M_PI*d/S7); - if(h2->c.mirror(d)) S = cgi.heptmove[sp] * Mirror * spin(2*M_PI*d/S7); - if(h2->move(d) == h1) { + for(int d=0; dmove(d); + if(!hm) continue; + transmatrix S = adj(h1, d); + if(hm == h2) { transmatrix T1 = gm * S * where; auto curdist = hdist(tC0(T1), point_hint); if(curdist < bestdist) T = T1, bestdist = curdist; } - if(geometry != gMinimal) for(int e=0; emove(d)->move(e) == h1) { - int sp2 = h2->move(d)->c.spin(e); - transmatrix T1 = gm * cgi.heptmove[sp2] * spin(2*M_PI*e/S7) * S * where; + if(geometry != gMinimal) for(int e=0; emove(e) == h2) { + transmatrix T1 = gm * S * adj(hm, e) * where; auto curdist = hdist(tC0(T1), point_hint); if(curdist < bestdist) T = T1, bestdist = curdist; } } if(bestdist < 1e8) return T; } - for(int d=0; dmove(d) == h1) { - int sp = h2->c.spin(d); - return gm * cgi.heptmove[sp] * spin(2*M_PI*d/S7) * where; + for(int d=0; dmove(d) == h2) { + return gm * adj(h1, d) * where; } if(among(geometry, gFieldQuotient, gBring, gMacbeath)) { int bestdist = 1000000, bestd = 0; for(int d=0; dcmove(d)->c7, c1); + int dist = celldistance(h1->cmove(d)->c7, h2->c7); if(dist < bestdist) bestdist = dist, bestd = d; } - int sp = h2->c.spin(bestd); - where = cgi.heptmove[sp] * spin(2*M_PI*bestd/S7) * where; - h2 = h2->move(bestd); + gm = gm * adj(h1, bestd); + h1 = h1->move(bestd); } #if CAP_CRYSTAL else if(cryst) { for(int d3=0; d3cmove(d3); - if(visited.count(h3)) continue; - visited.insert(h3); - int sp3 = h2->c.spin(d3); - transmatrix where3 = cgi.heptmove[sp3] * spin(2*M_PI*d3/S7) * where; - ld dist = crystal::space_distance(h3->c7, c1); - hbdist[dist].emplace_back(h3, where3); + auto hm = h1->cmove(d3); + if(visited.count(hm)) continue; + visited.insert(hm); + ld dist = crystal::space_distance(hm->c7, c2); + hbdist[dist].emplace_back(hm, gm * adj(h1, d3)); } auto &bestv = hbdist.begin()->second; - tie(h2, where) = bestv.back(); + tie(h1, gm) = bestv.back(); bestv.pop_back(); if(bestv.empty()) hbdist.erase(hbdist.begin()); } #endif else if(h1->distance < h2->distance) { - int sp = h2->c.spin(0); + where = iadj(h2, 0) * where; h2 = h2->move(0); - where = cgi.heptmove[sp] * where; } else { - int sp = h1->c.spin(0); + gm = gm * adj(h1, 0); h1 = h1->move(0); - gm = gm * cgi.invheptmove[sp]; } } return gm * where; @@ -169,40 +170,6 @@ EX transmatrix &ggmatrix(cell *c) { return t; } -EX transmatrix calc_relative_matrix_help(cell *c, heptagon *h1) { - transmatrix gm = Id; - heptagon *h2 = c->master; - transmatrix where = Id; - if(0); - #if CAP_GP - else if(GOLDBERG && c != c->master->c7) { - auto li = gp::get_local_info(c); - where = cgi.gpdata->Tf[li.last_dir][li.relative.first&31][li.relative.second&31][gmod(li.total_dir, S6)]; - } - #endif - else if(BITRUNCATED) for(int d=0; dc7->move(d) == c) - where = cgi.hexmove[d]; - // always add to last! - while(h1 != h2) { - for(int d=0; dmove(d) == h2) printf("(adj) "); - if(h1->distance < h2->distance) { - int sp = h2->c.spin(0); - printf("A%d ", sp); - h2 = h2->move(0); - where = cgi.heptmove[sp] * where; - } - else { - int sp = h1->c.spin(0); - printf("B%d ", sp); - h1 = h1->move(0); - gm = gm * cgi.invheptmove[sp]; - } - } - println(hlog, "OK"); - println(hlog, gm * where); - return gm * where; - } - #if HDR struct horo_distance { ld a, b; @@ -288,10 +255,7 @@ void virtualRebase(cell*& base, T& at, bool tohex, const U& check) { base = hybrid::get_at(w.first, w.second); return; } - if(sl2) { - virtualRebase_cell(base, at, check); - return; - } + if((euclid || sphere) && WDIM == 2) { again: if(euwrap) for(int i=0; i<6; i++) { @@ -316,57 +280,7 @@ void virtualRebase(cell*& base, T& at, bool tohex, const U& check) { return; } - at = master_relative(base) * at; - base = base->master->c7; - - while(true) { - - horo_distance currz(check(at)); - - heptagon *h = base->master; - - cell *newbase = NULL; - - transmatrix bestV; - - if(WDIM == 2 && !binarytiling && !penrose) for(int d=0; ddegree(); d++) { - heptspin hs(h, d, false); - heptspin hs2 = hs + wstep; - transmatrix V2 = spin(-hs2.spin*2*M_PI/S7) * cgi.invheptmove[d]; - horo_distance newz(check(V2 * at)); - if(newz < currz) { - currz = newz; - bestV = V2; - newbase = hs2.at->c7; - } - } - - if(newbase) { - base = newbase; - at = bestV * at; - } - else { - if(tohex && BITRUNCATED) for(int d=0; dtype; d++) { - cell *c = createMov(base, d); - transmatrix V2 = spin(-base->c.spin(d)*2*M_PI/S6) * cgi.invhexmove[d]; - horo_distance newz(check(V2 * at)); - if(newz < currz) { - currz = newz; - bestV = V2; - newbase = c; - } - } - if(newbase) { - base = newbase; - at = bestV * at; - } - else at = master_relative(base, true) * at; - if(binarytiling || (tohex && (GOLDBERG || IRREGULAR)) || WDIM == 3 || penrose) - virtualRebase_cell(base, at, check); - break; - } - } - + virtualRebase_cell(base, at, check); } EX void virtualRebase(cell*& base, transmatrix& at, bool tohex) { @@ -382,8 +296,7 @@ EX void virtualRebase(cell*& base, hyperpoint& h, bool tohex) { }); } -// works only in geometries similar to the standard one, and only on heptagons -EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) { +void hrmap_hyperbolic::virtualRebase(heptagon*& base, transmatrix& at) { while(true) { @@ -398,7 +311,7 @@ EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) { for(int d=0; dadj(c, d))); - if(WDIM == 3) return T * cspin(2, 0, bonus); - return T * spin(bonus); +ld hrmap_standard::spin_angle(cell *c, int d) { + ld hexshift = 0; + if(ctof(c) && S7==6 && S3 == 4 && BITRUNCATED) hexshift = cgi.hexshift + 2*M_PI/S7; + else if(ctof(c) && (S7==8 || S7 == 4) && S3 == 3 && BITRUNCATED) hexshift = cgi.hexshift + 2*M_PI/S7; + else if(cgi.hexshift && ctof(c)) hexshift = cgi.hexshift; + if(IRREGULAR) { + auto id = irr::cellindex[c]; + auto& vs = irr::cells[id]; + if(d < 0 || d >= c->type) return 0; + auto& p = vs.jpoints[vs.neid[d]]; + return -atan2(p[1], p[0]) - hexshift; } - return spin(displayspin(c, d) + bonus - hexshiftat(c)); + else if(masterless) + return - d * 2 * M_PI / c->type - hexshift; + else + return M_PI - d * 2 * M_PI / c->type - hexshift; } -EX transmatrix iddspin(cell *c, int d, ld bonus IS(0)) { - if(no_easy_spin()) { - if(hybri) return PIU( iddspin(c, d, bonus) ); - transmatrix T = spintox(tC0(currentmap->iadj(c, d))); - if(WDIM == 3) return T * cspin(2, 0, bonus); - return T * spin(bonus); - } - return spin(hexshiftat(c) - displayspin(c, d) + bonus); +EX transmatrix ddspin(cell *c, int d, ld bonus IS(0)) { return currentmap->spin_to(c, d, bonus); } +EX transmatrix iddspin(cell *c, int d, ld bonus IS(0)) { return currentmap->spin_from(c, d, bonus); } +EX ld cellgfxdist(cell *c, int d) { return currentmap->spacedist(c, d); } + +double hrmap_standard::spacedist(cell *c, int i) { + if(NONSTDVAR) return hrmap::spacedist(c, i); + if(!BITRUNCATED) return cgi.tessf; + if(c->type == S6 && (i&1)) return cgi.hexhexdist; + return cgi.crossf; } -EX double cellgfxdist(cell *c, int i) { - if(no_easy_spin()) - return hdist0(tC0(currentmap->adj(c, i))); - if(euclid) { - if(c->type == 8 && (i&1)) return cgi.crossf * sqrt(2); - return cgi.crossf; - } - return !BITRUNCATED ? cgi.tessf : (c->type == 6 && (i&1)) ? cgi.hexhexdist : cgi.crossf; - } - -transmatrix hrmap::adj(cell *c, int i) { - if(no_easy_spin()) return calc_relative_matrix(c->move(i), c, i); +transmatrix hrmap_standard::adj(cell *c, int i) { + if(NONSTDVAR) return calc_relative_matrix(c->cmove(i), c, i); double d = cellgfxdist(c, i); transmatrix T = ddspin(c, i) * xpush(d); if(c->c.mirror(i)) T = T * Mirror; @@ -469,8 +373,6 @@ transmatrix hrmap::adj(cell *c, int i) { return T; } -EX transmatrix cellrelmatrix(cell *c, int i) { return currentmap->adj(c, i); } - EX double randd() { return (rand() + .5) / (RAND_MAX + 1.); } EX hyperpoint randomPointIn(int t) { @@ -695,7 +597,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) { } #endif - return cellrelmatrix(c, i) * get_corner_position(c->move(i), (cellwalker(c, i) + wstep + (which?-1:2)).spin); + return currentmap->adj(c, i) * get_corner_position(c->move(i), (cellwalker(c, i) + wstep + (which?-1:2)).spin); } EX hyperpoint midcorner(cell *c, int i, ld v) { diff --git a/graph.cpp b/graph.cpp index e8e713be..d5f06338 100644 --- a/graph.cpp +++ b/graph.cpp @@ -305,46 +305,6 @@ void drawLightning(const transmatrix& V) { #endif } -EX ld displayspin(cell *c, int d) { - if(0); - #if CAP_ARCM - else if(archimedean) { - if(PURE) { - 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; - } - } - #endif - #if CAP_IRR - else if(IRREGULAR) { - auto id = irr::cellindex[c]; - auto& vs = irr::cells[id]; - if(d < 0 || d >= c->type) return 0; - auto& p = vs.jpoints[vs.neid[d]]; - return -atan2(p[1], p[0]); - } - #endif - #if CAP_BT - else if(binarytiling) { - if(d == NODIR) return 0; - if(d == c->type-1) d++; - return -(d+2)*M_PI/4; - } - #endif - else if(masterless) - return - d * 2 * M_PI / c->type; - else - return M_PI - d * 2 * M_PI / c->type; - } - #define UNTRANS (GDIM == 3 ? 0x000000FF : 0) EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { @@ -386,7 +346,7 @@ EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) { ang %= sword::sword_angles; #if CAP_QUEUE || CAP_SHAPES - transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * ddspin(c,0,M_PI); // (IRREGULAR ? ddspin(c,0,M_PI) : spin(-hexshiftat(c))); + transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * ddspin(c,0,M_PI); #endif int adj = 1 - ((sword_angles/cwt.at->type)&1); @@ -2301,15 +2261,10 @@ double chainAngle(cell *c, transmatrix& V, cell *c2, double dft, const transmatr } // equivalent to V = V * spin(-chainAngle(c,V,c2,dft)); -bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, ld bonus, const transmatrix &Vwhere, ld& length) { - if(!gmatrix0.count(c2)) { - V = V * ddspin(c,i,bonus); - length = cellgfxdist(c,i); - return false; - } +bool chainAnimation(cell *c, cell *c2, transmatrix& V, const transmatrix &Vwhere, ld& length) { hyperpoint h = C0; if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h; - h = inverse(V) * Vwhere * calc_relative_matrix(c2, c, C0) * h; + h = inverse(V) * Vwhere * h; length = hdist0(h); V = V * rspintox(h); return true; @@ -2413,15 +2368,17 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo transmatrix Vb0 = Vb; if(c->mondir != NODIR && GDIM == 3 && isAnyIvy(c)) { - queueline(tC0(Vparam), Vparam * tC0(calc_relative_matrix(c->move(c->mondir), c, C0)), (col << 8) + 0xFF, 0); + queueline(tC0(Vparam), Vparam * tC0(currentmap->adj(c, c->mondir)), (col << 8) + 0xFF, 0); } else if(c->mondir != NODIR) { if(mmmon) { ld length; - // cell *c2 = c->move(c->mondir); - if(nospinb) - chainAnimation(c, Vb, c->move(c->mondir), c->mondir, 0, Vparam, length); + cell *c2 = c->move(c->mondir); + + if(nospinb) { + chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, c->mondir), length); + } else { Vb = Vb * ddspin(c, c->mondir); length = cellgfxdist(c, c->mondir); @@ -2489,10 +2446,10 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo } else { - int hdir = displayspin(c, c->mondir); + transmatrix T = Vparam * ddspin(c, c->mondir); color_t col = darkena(0x606020, 0, 0xFF); for(int u=-1; u<=1; u++) - queueline(Vparam*xspinpush0(hdir+M_PI/2, u*cgi.crossf/5), Vparam*xspinpush(hdir, cgi.crossf)*xspinpush0(hdir+M_PI/2, u*cgi.crossf/5), col, 2 + vid.linequality); + queueline(T*xspinpush0(M_PI/2, u*cgi.crossf/5), T*xspinpush(0, cgi.crossf)*xspinpush0(M_PI/2, u*cgi.crossf/5), col, 2 + vid.linequality); } } @@ -2550,7 +2507,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo if(part == 't') { if(nospinb) { ld length; - chainAnimation(c, Vb, c2, nd, 0, Vparam, length); + chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, nd), length); Vb = Vb * pispin; } else { @@ -2564,15 +2521,16 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo else if(true) { if(nospinb) { ld length; - chainAnimation(c, Vb, c2, nd, 0, Vparam, length); + chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, nd), length); Vb = Vb * pispin; - double ang = chainAngle(c, Vb, c->move(c->mondir), displayspin(c, c->mondir) - displayspin(c, nd), Vparam); + double ang = chainAngle(c, Vb, c->move(c->mondir), currentmap->spin_angle(c, c->mondir) - currentmap->spin_angle(c, nd), Vparam); ang /= 2; Vb = Vb * spin(M_PI-ang); } else { - ld hdir0 = displayspin(c, nd) + M_PI; - ld hdir1 = displayspin(c, c->mondir); + /* todo what if no spin_angle */ + ld hdir0 = currentmap->spin_angle(c, nd) + M_PI; + ld hdir1 = currentmap->spin_angle(c, c->mondir); while(hdir1 > hdir0 + M_PI) hdir1 -= 2*M_PI; while(hdir1 < hdir0 - M_PI) hdir1 += 2*M_PI; Vb = Vb0 * spin((hdir0 + hdir1)/2 + M_PI); @@ -2599,7 +2557,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo int nd = neighborId(c, c2); if(nospinb) { ld length; - chainAnimation(c, Vb, c2, nd, 0, Vparam, length); + chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, nd), length); Vb = Vb * pispin; } else { @@ -2687,7 +2645,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo if(c->hitpoints == 0) col = 0x404040; if(nospinb) { ld length; - chainAnimation(c, Vb, c->move(c->mondir), c->mondir, 0, Vparam, length); + chainAnimation(c, c->move(c->mondir), Vb, Vparam * currentmap->adj(c, c->mondir), length); Vb = Vb * pispin; Vb = Vb * xpush(cgi.tentacle_length - cellgfxdist(c, c->mondir)); } diff --git a/netgen.cpp b/netgen.cpp index 15724bf8..05dc9375 100644 --- a/netgen.cpp +++ b/netgen.cpp @@ -84,9 +84,7 @@ EX namespace netgen { if(c->type == S7) { for(int i=0; itype; i++) { - int hdir = displayspin(c, i) + M_PI / S7; - - transmatrix V2 = V * spin(hdir) * xpush(cgi.hexf); + transmatrix V2 = V * ddspin(c, i, M_PI/S7) * xpush(cgi.hexf); hcenter[ii][i] = V2 * C0; } @@ -95,10 +93,8 @@ EX namespace netgen { if(c->type == S6) { for(int i=0; itype; i++) { - int hdir = displayspin(c, i); - transmatrix V2 = - V * spin(hdir) * xpush(cgi.crossf) * spin(M_PI+M_PI/S7) * xpush(cgi.hexf); + V * ddspin(c, i, 0) * xpush(cgi.crossf) * spin(M_PI+M_PI/S7) * xpush(cgi.hexf); hcenter[ii][i] = V2 * C0; } diff --git a/nonisotropic.cpp b/nonisotropic.cpp index 44a62122..d2813cee 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -372,6 +372,10 @@ EX namespace solnihv { default: throw "not nihsolv"; } } + + transmatrix adj(cell *c, int d) override { + return adjmatrix(d, c->c.spin(d)); + } virtual transmatrix relative_matrix(heptagon *h2, heptagon *h1) override { for(int i=0; itype; i++) if(h1->move(i) == h2) return adjmatrix(i, h1->c.spin(i)); @@ -1035,6 +1039,9 @@ EX namespace hybrid { for(auto& p: at) tailored_delete(p.second); } + virtual transmatrix spin_to(cell *c, int d, ld bonus) { return PIU( currentmap->spin_to(c, d, bonus) ); } + virtual transmatrix spin_from(cell *c, int d, ld bonus) { return PIU( currentmap->spin_from(c, d, bonus) ); } + }; hrmap_hybrid* hmap() { return (hrmap_hybrid*) currentmap; } @@ -1558,7 +1565,7 @@ EX namespace rots { transmatrix Spin; cell *cw = where[c1].first; in_underlying([&] { - transmatrix T = cellrelmatrix(cw, i); + transmatrix T = adj(cw, i); hyperpoint h = tC0(T); Spin = inverse(gpushxto0(h) * T); d = hr::inverse_exp(h, iTable); diff --git a/reg3.cpp b/reg3.cpp index c6dd3c2f..6e593789 100644 --- a/reg3.cpp +++ b/reg3.cpp @@ -213,6 +213,9 @@ EX namespace reg3 { struct hrmap_quotient3 : hrmap { vector allh; vector> tmatrices; + + transmatrix adj(heptagon *h, int d) { return tmatrices[h->fieldval][d]; } + transmatrix adj(cell *c, int d) override { return adj(c->master, d); } }; int encode_coord(const crystal::coord& co) { @@ -570,13 +573,13 @@ EX namespace reg3 { dq::enqueue_by_matrix(h->move(d), V * tmatrices[h->fieldval][d]); } } - + transmatrix relative_matrix(heptagon *h2, heptagon *h1) override { if(h1 == h2) return Id; int d = hr::celldistance(h2->c7, h1->c7); for(int a=0; amove(a)->c7, h2->c7) < d) - return tmatrices[h1->fieldval][a] * relative_matrix(h2, h1->move(a)); + return adj(h1, a) * relative_matrix(h2, h1->move(a)); println(hlog, "error in hrmap_field3:::relative_matrix"); return Id; @@ -723,7 +726,7 @@ EX namespace reg3 { if(hyperbolic) { dynamicval g(geometry, gBinary3); dynamicval cm(currentmap, binary_map); - binary::virtualRebaseSimple(alt, T); + binary_map->virtualRebase(alt, T); } fixmatrix(T); @@ -861,15 +864,21 @@ EX namespace reg3 { if(wallopt && isWall3(c) && isize(dq::drawqueue) > 1000) continue; for(int i=0; imove(i)) { - #if CAP_FIELD - if(quotient_map) dq::enqueue(h->move(i), V * quotient_map->tmatrices[h->fieldval][i]); - else - #endif - dq::enqueue(h->move(i), V * relative_matrix(h->move(i), h)); + dq::enqueue(h->move(i), V * adj(h, i)); } } } + transmatrix adj(heptagon *h, int d) { + #if CAP_FIELD + if(quotient_map) return quotient_map->adj(h, d); + else + #endif + return relative_matrix(h->cmove(d), h); + } + + transmatrix adj(cell *c, int d) override { return adj(c->master, d); } + transmatrix relative_matrix(heptagon *h2, heptagon *h1) override { auto p1 = reg_gmatrix[h1]; auto p2 = reg_gmatrix[h2]; @@ -1073,7 +1082,7 @@ int dist_alt(cell *c) { #if MAXMDIM >= 4 EX cellwalker strafe(cellwalker cw, int j) { hyperpoint hfront = tC0(adjmoves[cw.spin]); - transmatrix T = currentmap->relative_matrix(cw.at->cmove(j)->master, cw.at->master); + transmatrix T = currentmap->adj(cw.at, j); for(int i=0; ic.spin(j)) if(hdist(hfront, T * tC0(adjmoves[i])) < strafedist + .01) return cellwalker(cw.at->move(j), i); diff --git a/sky.cpp b/sky.cpp index 007afb9e..cfaf83e9 100644 --- a/sky.cpp +++ b/sky.cpp @@ -85,7 +85,7 @@ void dqi_sky::draw() { transmatrix T1 = Tsh * si.T; do { this_poly.emplace_back(T1 * skypoint, colors[cw.at]); - T1 = T1 * cellrelmatrix(cw.at, cw.spin); + T1 = T1 * currentmap->adj(cw.at, cw.spin); cw += wstep; cw++; } while(cw != cw0); diff --git a/sphere.cpp b/sphere.cpp index 54222627..2e0e8b1e 100644 --- a/sphere.cpp +++ b/sphere.cpp @@ -24,10 +24,8 @@ EX vector siblings; struct hrmap_spherical : hrmap_standard { heptagon *dodecahedron[12]; - eVariation mvar; hrmap_spherical() { - mvar = variation; for(int i=0; i (S7)); h.s = hsOrigin; @@ -147,7 +145,6 @@ struct hrmap_spherical : hrmap_standard { heptagon *getOrigin() { return dodecahedron[0]; } ~hrmap_spherical() { - dynamicval ph(variation, mvar); for(int i=0; i