diff --git a/3d-models.cpp b/3d-models.cpp index 9e9eba07..32732114 100644 --- a/3d-models.cpp +++ b/3d-models.cpp @@ -41,10 +41,6 @@ ld zc(ld z) { return cgi.human_height * (z - 0.5); } -transmatrix zpush(ld z) { - return cpush(2, z); - } - void geometry_information::add_cone(ld z0, const vector& vh, ld z1) { last->flags |= POLY_TRIANGLES; for(int i=0; i 1) return; bool deepOcean = deep_ocean_at(c, from); diff --git a/binary-tiling.cpp b/binary-tiling.cpp index 5c163e54..581a9b2e 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -479,7 +479,7 @@ namespace binary { } void build_tmatrix() { - if(geometry == gBinaryTiling) return; // unused + if(among(geometry, gBinaryTiling, gSol)) return; // unused use_direct = (1 << S7) - 1; if(geometry == gBinary4) { use_direct = 3; @@ -865,4 +865,139 @@ auto hooksw = addHook(hooks_swapdim, 100, [] { }); } + +namespace solv { + + struct hrmap_sol : hrmap { + hrmap *binary_map; + unordered_map, heptagon*> at; + unordered_map> coords; + + heptagon *origin; + + heptagon *getOrigin() override { return origin; } + + heptagon *get_at(heptagon *x, heptagon *y) { + auto& h = at[make_pair(x, y)]; + if(h) return h; + h = tailored_alloc (S7); + h->c7 = newCell(S7, h); + coords[h] = make_pair(x, y); + return h; + h->distance = 0; + h->dm4 = 0; + h->zebraval = 0; + h->emeraldval = 0; + h->fieldval = 0; + h->cdata = NULL; + } + + hrmap_sol() { + + heptagon *alt; + + if(true) { + dynamicval g(geometry, gBinary4); + alt = tailored_alloc (S7); + alt->s = hsOrigin; + alt->alt = alt; + alt->cdata = NULL; + alt->c7 = NULL; + alt->zebraval = 0; + binary_map = binary::new_alt_map(alt); + } + + origin = get_at(alt, alt); + } + + heptagon *altstep(heptagon *h, int d) { + dynamicval g(geometry, gBinary4); + dynamicval cm(currentmap, binary_map); + return h->cmove(d); + } + + heptagon *create_step(heptagon *parent, int d) override { + auto p = coords[parent]; + auto pf = p.first, ps = p.second; + auto rule = [&] (heptagon *c1, heptagon *c2, int d1) { + auto g = get_at(c1, c2); + parent->c.connect(d, g, d1, false); + return g; + }; + + switch(d) { + case 0: // right + return rule(altstep(pf, 2), ps, 4); + case 1: // up + return rule(pf, altstep(ps, 2), 5); + case 2: // front left + return rule(altstep(pf, 0), altstep(ps, 3), ps->zebraval ? 7 : 6); + case 3: // front right + return rule(altstep(pf, 1), altstep(ps, 3), ps->zebraval ? 7 : 6); + case 4: // left + return rule(altstep(pf, 4), ps, 0); + case 5: // down + return rule(pf, altstep(ps, 4), 1); + case 6: // back down + return rule(altstep(pf, 3), altstep(ps, 0), pf->zebraval ? 3 : 2); + case 7: // back up + return rule(altstep(pf, 3), altstep(ps, 1), pf->zebraval ? 3 : 2); + default: + return NULL; + } + } + + ~hrmap_sol() { + delete binary_map; + } + + transmatrix adjmatrix(int i, int j) { + ld z = log(2); + ld bw = vid.binary_width * z; + ld bwh = bw / 4; + switch(i) { + case 0: return xpush(+bw); + case 1: return ypush(+bw); + case 2: return xpush(-bwh) * zpush(+z) * ypush(j == 6 ? +bwh : -bwh); + case 3: return xpush(+bwh) * zpush(+z) * ypush(j == 6 ? +bwh : -bwh); + case 4: return xpush(-bw); + case 5: return ypush(-bw); + case 6: return ypush(-bwh) * zpush(-z) * xpush(j == 2 ? +bwh : -bwh); + case 7: return ypush(+bwh) * zpush(-z) * xpush(j == 2 ? +bwh : -bwh); + default:return Id; + } + } + + 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)); + return Id; + } + + void draw() override { + dq::visited.clear(); + dq::enqueue(viewctr.at, cview()); + + while(!dq::drawqueue.empty()) { + auto& p = dq::drawqueue.front(); + heptagon *h = get<0>(p); + transmatrix V = get<1>(p); + dq::drawqueue.pop(); + + cell *c = h->c7; + if(!do_draw(c, V)) continue; + drawcell(c, V, 0, false); + + for(int i=0; icmove(i); + dq::enqueue(h1, V * adjmatrix(i, h->c.spin(i))); + } + } + } + + }; + + hrmap *new_map() { return new hrmap_sol; } + } + } diff --git a/cell.cpp b/cell.cpp index ee515eb0..05c98572 100644 --- a/cell.cpp +++ b/cell.cpp @@ -231,6 +231,7 @@ void initcells() { else if(sphere) currentmap = new hrmap_spherical; else if(quotient) currentmap = new quotientspace::hrmap_quotient; #if CAP_BT + else if(sol) currentmap = solv::new_map(); else if(binarytiling) currentmap = binary::new_map(); #endif else currentmap = new hrmap_hyperbolic; @@ -851,7 +852,7 @@ int celldistance(cell *c1, cell *c2) { if(geometry == gCrystal) return crystal::precise_distance(c1, c2); #endif - if(masterless || archimedean || quotient) { + if(masterless || archimedean || quotient || sol) { if(saved_distances.count(make_pair(c1,c2))) return saved_distances[make_pair(c1,c2)]; diff --git a/classes.cpp b/classes.cpp index 587a1cc9..66934a40 100644 --- a/classes.cpp +++ b/classes.cpp @@ -559,6 +559,7 @@ vector ginf = { {"{4,3,5}","field", "{4,3,5} field quotient space", "f435", 6, 5, qsSMALLBF, gcHyperbolic, 0x40600, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, {"{5,3,4}","field", "{5,3,4} field quotient space", "f435", 12, 4, qsSMALLBF, gcHyperbolic, 0x40800, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, {"binary4","none", "standard binary tiling", "binary4", 5, 4, qBINARY, gcHyperbolic, 0, {{7, 5}}, eVariation::pure}, + {"sol", "none", "Sol", "sol", 8, 4, qBINARY, gcSol, 0, {{7, 5}}, eVariation::pure}, }; // bits: 9, 10, 15, 16, (reserved for later) 17, 18 diff --git a/classes.h b/classes.h index 5b181f77..9732002d 100644 --- a/classes.h +++ b/classes.h @@ -200,10 +200,10 @@ enum eGeometry { gCell600, gECell600, gHoroTris, gHoroRec, gHoroHex, gField435, gField534, - gBinary4, + gBinary4, gSol, gGUARD}; -enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere }; +enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSol }; enum class eVariation { bitruncated, pure, goldberg, irregular, dual }; diff --git a/geom-exp.cpp b/geom-exp.cpp index 5427b964..8573f054 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -796,6 +796,10 @@ void showEuclideanMenu() { case 2: dialog::addSelItem(XLAT("Curvature"), XLAT("spherical"), 0); break; + + case 3: + dialog::addSelItem(XLAT("Curvature"), XLAT("Sol"), 0); + break; } dialog::display(); diff --git a/graph.cpp b/graph.cpp index c5c971c7..568ea345 100644 --- a/graph.cpp +++ b/graph.cpp @@ -4398,6 +4398,7 @@ int get_darkval(int d) { const int darkval_e14[14] = {0,0,0,4,6,4,6,0,0,0,6,4,6,4}; const int darkval_hh[14] = {0,0,0,1,1,1,2,2,2,3,3,3,1,0}; const int darkval_hrec[7] = {0,0,2,4,2,4,0}; + const int darkval_sol[8] = {0,2,4,5,0,2,4,5}; if(sphere) return darkval_s12[d]; if(euclid && S7 == 6) return darkval_e6[d]; if(euclid && S7 == 12) return darkval_e12[d]; @@ -4407,6 +4408,7 @@ int get_darkval(int d) { if(binarytiling) return darkval_hbt[d]; if(hyperbolic && S7 == 6) return darkval_e6[d]; if(hyperbolic && S7 == 12) return darkval_s12[d]; + if(sol) return darkval_sol[d]; return 0; } @@ -4475,7 +4477,7 @@ int noclipped; void make_clipping_planes() { #if MAXMDIM >= 4 clipping_planes.clear(); - if(sphere) return; + if(sphere || sol) return; auto add_clipping_plane = [] (ld x1, ld y1, ld x2, ld y2) { using namespace hyperpoint_vec; ld z1 = 1, z2 = 1; @@ -4537,7 +4539,7 @@ void draw_grid_at(cell *c, const transmatrix& V) { else if(WDIM == 3) { for(int t=0; ttype; t++) { if(!c->move(t)) continue; - if(binarytiling && !among(t, 5, 6, 8)) continue; + if(binarytiling && !sol && !among(t, 5, 6, 8)) continue; if(!binarytiling && c->move(t) < c) continue; dynamicval g(poly_outline, gridcolor(c, c->move(t))); queuepoly(V, cgi.shWireframe3D[t], 0); @@ -5943,7 +5945,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { int d = (wcol & 0xF0F0F0) >> 4; for(int a=0; atype; a++) - if(c->move(a) && !isWall3(c->move(a), dummy)) { + if(c->move(a) && (sol || !isWall3(c->move(a), dummy))) { if(pmodel == mdPerspective && !sphere && !quotient) { if(a < 4 && among(geometry, gHoroTris, gBinary3) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue; else if(a < 2 && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewctr.at->c7)) continue; diff --git a/hyper.h b/hyper.h index 61a6614a..0c9eb5ba 100644 --- a/hyper.h +++ b/hyper.h @@ -110,7 +110,9 @@ void addMessage(string s, char spamtype = 0); #define cgclass (ginf[geometry].cclass) #define euclid (cgclass == gcEuclid) #define sphere (cgclass == gcSphere) +#define sol (cgclass == gcSol) #define hyperbolic (cgclass == gcHyperbolic) +#define eusol (euclid || sol) #define nonorientable (ginf[geometry].flags & qNONORIENTABLE) #define elliptic (ginf[geometry].flags & qELLIPTIC) #define quotient (ginf[geometry].flags & qANYQ) @@ -325,7 +327,7 @@ extern videopar vid; #if MAXMDIM == 3 #define WDIM 2 #else -#define WDIM ((geometry >= gBinary3 && geometry < gBinary4) ? 3 : 2) +#define WDIM ((geometry >= gBinary3 && geometry != gBinary4) ? 3 : 2) #endif #define GDIM (vid.always3 ? 3 : WDIM) #define DIM GDIM diff --git a/hyperpoint.cpp b/hyperpoint.cpp index d94127ec..db52d838 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -342,6 +342,8 @@ hyperpoint orthogonal_move(const hyperpoint& h, ld z) { // push alpha units vertically transmatrix ypush(ld alpha) { return cpush(1, alpha); } +transmatrix zpush(ld z) { return cpush(2, z); } + transmatrix matrix3(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i) { #if MAXMDIM==3 return transmatrix {{{a,b,c},{d,e,f},{g,h,i}}};