diff --git a/binary-tiling.cpp b/binary-tiling.cpp index f3ac92a4..4e5d82ff 100644 --- a/binary-tiling.cpp +++ b/binary-tiling.cpp @@ -483,19 +483,19 @@ EX namespace bt { transmatrix adj(heptagon *h, int dir) override { if(geometry == gBinaryTiling) switch(dir) { - case bd_up: return xpush(-log(2)); + case bd_up: return lxpush(-log(2)); case bd_left: return parabolic(-2); case bd_right: return parabolic(+2); case bd_down: - if(h->type == 6) return xpush(log(2)); + if(h->type == 6) return lxpush(log(2)); /* case bd_down_left: */ - return parabolic(-2) * xpush(log(2)); + return parabolic(-2) * lxpush(log(2)); case bd_down_right: - return parabolic(+2) * xpush(log(2)); + return parabolic(+2) * lxpush(log(2)); case bd_up_left: - return xpush(-log(2)) * parabolic(-2); + return lxpush(-log(2)) * parabolic(-2); case bd_up_right: - return xpush(-log(2)) * parabolic(2); + return lxpush(-log(2)) * parabolic(2); default: throw hr_exception("unknown direction"); } @@ -634,9 +634,9 @@ EX namespace bt { auto &x = h[0], &y = h[1], &z = h[2]; switch(geometry) { case gBinaryTiling: case gBinary4: - return bt::parabolic(y) * xpush(x*z2*2); + return bt::parabolic(y) * lxpush(x*z2*2); case gTernary: - return bt::parabolic(y) * xpush(x*z3*2); + return bt::parabolic(y) * lxpush(x*z3*2); #if CAP_SOLV case gSol: return xpush(bwh*x) * ypush(bwh*y) * zpush(z2*z); @@ -700,16 +700,16 @@ EX namespace bt { use_direct = (1 << (S7-1)) - 1; if(geometry == gBinary4) { use_direct = 3; - direct_tmatrix[0] = xpush(-log(2)) * parabolic(-1); - direct_tmatrix[1] = xpush(-log(2)) * parabolic(+1); + direct_tmatrix[0] = lxpush(-log(2)) * parabolic(-1); + direct_tmatrix[1] = lxpush(-log(2)) * parabolic(+1); direct_tmatrix[2] = parabolic(2); direct_tmatrix[4] = parabolic(-2); use_direct = 1+2+4+16; } if(geometry == gTernary) { - direct_tmatrix[0] = xpush(-log(3)) * parabolic(-2); - direct_tmatrix[1] = xpush(-log(3)); - direct_tmatrix[2] = xpush(-log(3)) * parabolic(+2); + direct_tmatrix[0] = lxpush(-log(3)) * parabolic(-2); + direct_tmatrix[1] = lxpush(-log(3)); + direct_tmatrix[2] = lxpush(-log(3)) * parabolic(+2); direct_tmatrix[3] = parabolic(2); direct_tmatrix[5] = parabolic(-2); use_direct = 1+2+4+8+32; @@ -1027,7 +1027,7 @@ EX int celldistance3(heptagon *c1, heptagon *c2) { EX int celldistance3(cell *c1, cell *c2) { return celldistance3(c1->master, c2->master); } EX hyperpoint get_horopoint(ld y, ld x) { - return bt::parabolic(x*2) * xpush(-y) * C0; + return bt::parabolic(x*2) * lxpush(-y) * C0; } EX hyperpoint get_horopoint(hyperpoint h) { diff --git a/floorshapes.cpp b/floorshapes.cpp index 7197d76a..44f055a1 100644 --- a/floorshapes.cpp +++ b/floorshapes.cpp @@ -321,8 +321,9 @@ void geometry_information::bshape_regular(floorshape &fsh, int id, int sides, ld hyperpoint h0 = bt::get_corner_horo_coordinates(c, i) * size; hyperpoint h1 = bt::get_corner_horo_coordinates(c, i+1) * size; hyperpoint hd = (h1 - h0) / STEP; + transmatrix T = geom3::hyp_in_solnih() ? Id : iddspin_side(c, i); for(int j=0; j<=STEP; j++) - hpcpush(iddspin_side(c, i) * bt::get_horopoint(h0 + hd * j)); + hpcpush(T * bt::get_horopoint(h0 + hd * j)); chasmifyPoly(dlow_table[k], dhi_table[k], k); } } diff --git a/geometry.cpp b/geometry.cpp index 22ebabf2..94280e7b 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1128,6 +1128,10 @@ EX namespace geom3 { return among(ggclass(), gcSol, gcNIH, gcSolN) && mgclass() == gcEuclid; } + EX bool hyp_in_solnih() { + return among(ggclass(), gcSol, gcNIH, gcSolN) && mgclass() == gcHyperbolic; + } + EX bool euc_in_noniso() { return among(ggclass(), gcNil, gcSol, gcNIH, gcSolN) && nonisotropic; } @@ -1200,27 +1204,31 @@ EX namespace geom3 { g.gameplay_dimension = 2; } - if(spatial_embedding == seNil && euclid) { + bool ieuclid = g.kind == gcEuclid; + + if(spatial_embedding == seNil && ieuclid) { g = ginf[gNil].g; g.gameplay_dimension = 2; } - if(spatial_embedding == seSol && euclid) { + bool ieuc_or_binary = ieuclid || (gi.flags & qBINARY); + + if(spatial_embedding == seSol && ieuc_or_binary) { g = ginf[gSol].g; g.gameplay_dimension = 2; } - if(spatial_embedding == seNIH && euclid) { + if(spatial_embedding == seNIH && ieuc_or_binary) { g = ginf[gNIH].g; g.gameplay_dimension = 2; } - if(spatial_embedding == seNIH_inv && euclid) { + if(spatial_embedding == seNIH_inv && ieuc_or_binary) { g = ginf[gNIH].g; g.gameplay_dimension = 2; } - if(spatial_embedding == seSolN && euclid) { + if(spatial_embedding == seSolN && ieuc_or_binary) { g = ginf[gSolN].g; g.gameplay_dimension = 2; } diff --git a/graph.cpp b/graph.cpp index a9443640..573536bb 100644 --- a/graph.cpp +++ b/graph.cpp @@ -346,12 +346,12 @@ void drawCurse(const shiftmatrix& V, eItem it) { #define UNTRANS (GDIM == 3 ? 0x000000FF : 0) EX transmatrix lpispin() { - if(geom3::euc_in_nil()) return spin180(); - return pispin; + return spin180(); } EX const transmatrix& lmirror() { if(geom3::euc_in_nil()) return MirrorZ; + if(geom3::hyp_in_solnih()) return MirrorZ; return Mirror; } @@ -3749,7 +3749,7 @@ EX bool placeSidewall(cell *c, int i, int sidepar, const shiftmatrix& V, color_t else if(sidepar == SIDE_BSHA) prio = PPR::BSHALLOW; else prio = PPR::REDWALL-2+4*(sidepar-SIDE_SLEV); - if(geom3::euc_in_noniso()) { + if(geom3::euc_in_noniso() || geom3::hyp_in_solnih()) { draw_shapevec(c, V, qfi.fshape->gpside[sidepar][i], col, prio); return false; } diff --git a/hyperpoint.cpp b/hyperpoint.cpp index 823c0ee5..7eee3721 100644 --- a/hyperpoint.cpp +++ b/hyperpoint.cpp @@ -561,6 +561,7 @@ EX hyperpoint normalize_flat(hyperpoint h) { if(sl2) h = slr::translate(h) * zpush0(-atan2(h[2], h[3])); if(geom3::euc_in_nil()) h[1] = 0; if(geom3::euc_in_solnih()) h[2] = 0; + if(geom3::hyp_in_solnih()) h[0] = 0; if(geom3::euc_in_hyp()) { h = normalize(h); auto h1 = deparabolic13(h); @@ -642,6 +643,7 @@ EX transmatrix cspin180(int a, int b) { EX transmatrix spin(ld alpha) { if(embedded_plane && geom3::euc_in_hyp() && !destandarize_eih) return cspin(1, 2, alpha); if(embedded_plane && geom3::euc_in_nil()) return cspin(0, 2, alpha); + if(embedded_plane && geom3::hyp_in_solnih()) return cspin(1, 2, alpha); return cspin(0, 1, alpha); } @@ -649,6 +651,7 @@ EX transmatrix spin(ld alpha) { EX transmatrix spin90() { if(embedded_plane && geom3::euc_in_hyp() && !destandarize_eih) return cspin90(1, 2); if(embedded_plane && geom3::euc_in_nil()) return cspin90(0, 2); + if(embedded_plane && geom3::hyp_in_solnih()) return cspin90(1, 2); return cspin90(0, 1); } @@ -656,6 +659,7 @@ EX transmatrix spin90() { EX transmatrix spin180() { if(embedded_plane && geom3::euc_in_hyp() && !destandarize_eih) return cspin180(1, 2); if(embedded_plane && geom3::euc_in_nil()) return cspin180(0, 2); + if(embedded_plane && geom3::hyp_in_solnih()) return cspin180(1, 2); return cspin180(0, 1); } @@ -663,6 +667,7 @@ EX transmatrix spin180() { EX transmatrix spin270() { if(embedded_plane && geom3::euc_in_hyp() && !destandarize_eih) return cspin90(2, 1); if(embedded_plane && geom3::euc_in_nil()) return cspin90(2, 0); + if(embedded_plane && geom3::hyp_in_solnih()) return cspin90(2, 1); return cspin90(1, 0); } @@ -750,6 +755,7 @@ EX transmatrix cpush(int cid, ld alpha) { EX transmatrix lzpush(ld z) { if(geom3::euc_in_hyp() && !destandarize_eih) return cpush(0, z); + if(geom3::hyp_in_solnih()) return cpush(0, z); if(geom3::euc_in_nil()) return cpush(1, z); return cpush(2, z); } @@ -804,6 +810,9 @@ EX hyperpoint orthogonal_move(const hyperpoint& h, ld z) { hf[3] = 1; return hf; } + if(geom3::hyp_in_solnih()) { + return nisot::translate(h) * cpush0(0, z); + } if(geom3::sph_in_hyp()) { ld z0 = acosh(h[3]); ld f = sinh(z0 + z) / sinh(z0); @@ -860,6 +869,13 @@ EX void swapmatrix(transmatrix& T) { for(int i=0; i<4; i++) U[i][3] = U[3][i] = i == 3; T = parabolic13(mov[0], mov[1]) * U; } + else if(geom3::hyp_in_solnih()) { + // rotations are illegal anyway... + hyperpoint h = get_column(T, 2); + swapmatrix(h); + T = rgpushxto0(h); + return; + } else if(geom3::sph_in_euc() || geom3::sph_in_hyp()) { if(!geom3::flipped) { for(int i=0; i<4; i++) T[i][3] = T[3][i] = i == 3; @@ -901,6 +917,19 @@ EX void swapmatrix(hyperpoint& h) { if(geom3::sph_in_hyp()) { h[0] *= sinh(1); h[1] *= sinh(1); h[2] *= sinh(1); h[3] = cosh(1); return; } if(geom3::euc_in_nil()) { h[3] = 1; h[2] = h[1] * geom3::euclid_embed_scale; h[1] = 0; h[0] *= geom3::euclid_embed_scale; return; } if(geom3::euc_in_solnih()) { h[3] = 1; h[1] = h[1] * geom3::euclid_embed_scale; h[2] = 0; h[0] *= geom3::euclid_embed_scale; return; } + if(geom3::hyp_in_solnih()) { + // copied from deparabolic13 + h /= (1 + h[2]); + h[0] -= 1; + h /= sqhypot_d(2, h); + h[0] += .5; + ld hx = log(2) + log(-h[0]); + if(cgclass == gcNIH) hx /= log(3); + if(cgclass == gcSolN) hx /= log(3); + ld hy = h[1] * 2; + h = point31(0, hy, hx); + return; + } swap(h[2], h[3]); if(GDIM == 3) h[2] = 0; if(geom3::euc_in_hyp()) h = parabolic13(h[0], h[1]) * C0; @@ -910,6 +939,9 @@ EX void swapmatrix(hyperpoint& h) { EX transmatrix parabolic1(ld u) { if(euclid) return ypush(u); + else if(geom3::hyp_in_solnih()) { + return ypush(u); + } else { ld diag = u*u/2; return matrix3( @@ -1026,6 +1058,7 @@ EX transmatrix rspintox(const hyperpoint& H) { EX transmatrix lspintox(const hyperpoint& H) { if(geom3::euc_in_nil()) return spintoc(H, 0, 2); + if(geom3::hyp_in_solnih()) return spintoc(H, 1, 2); if(WDIM == 2 || gproduct) return spintoc(H, 0, 1); transmatrix T1 = spintoc(H, 0, 1); return spintoc(T1*H, 0, 2) * T1; @@ -1033,6 +1066,7 @@ EX transmatrix lspintox(const hyperpoint& H) { EX transmatrix lrspintox(const hyperpoint& H) { if(geom3::euc_in_nil()) return rspintoc(H, 0, 2); + if(geom3::hyp_in_solnih()) return rspintoc(H, 1, 2); if(WDIM == 2 || gproduct) return rspintoc(H, 0, 1); transmatrix T1 = spintoc(H, 0, 1); return rspintoc(H, 0, 1) * rspintoc(T1*H, 0, 2);