diff --git a/drawing.cpp b/drawing.cpp index 67cdaa2d..ad63a0da 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -1983,6 +1983,8 @@ EX void draw_main() { if(ray::in_use && !ray::comparison_mode) { ray::cast(); reset_projection(); + /* currently incompatible with primitive-based renderer */ + /* also not implemented in stretch */ return; } @@ -2023,6 +2025,7 @@ EX void draw_main() { if(ray::in_use && !ray::comparison_mode) { ray::cast(); reset_projection(); + if(stretch::in()) return; /*primitive not implemented */ } DEBB(DF_GRAPH, ("outcircle")); diff --git a/geom-exp.cpp b/geom-exp.cpp index b7aa9b85..a4439263 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -826,6 +826,20 @@ EX void showEuclideanMenu() { }); } + if(stretch::applicable()) { + dialog::addSelItem(XLAT("stretched geometry"), fts(stretch::factor), 'S'); + dialog::add_action([] { + dialog::editNumber(stretch::factor, -1, 9, 0.1, 0, XLAT("stretched geometry"), + XLAT( + "Stretch the metric along the fibers. This can currently be done in rotation spaces and in 8-cell, 24-cell and 120-cell. " + "Value of 0 means not stretched, -1 means S2xE or H2xE (works only in the limit). " + "Only the raycaster is implemented for stretched geometry, so you will see only walls." + ) + ); + dialog::reaction = ray::reset_raycaster; + }); + } + dialog::addBreak(100); dialog::addSelItem(XLAT("land"), XLAT1(linf[specialland].name), 'l'); dialog::add_action_push(ge_land_selection); diff --git a/hypgraph.cpp b/hypgraph.cpp index 97b12ddc..ccc5449e 100644 --- a/hypgraph.cpp +++ b/hypgraph.cpp @@ -2149,7 +2149,7 @@ EX void rotate_view(transmatrix T) { /** shift the view according to the given tangent vector */ EX transmatrix get_shift_view_of(const hyperpoint H, const transmatrix V) { - if(!nonisotropic && !rots_twist::in()) { + if(!nonisotropic && !stretch::in()) { return rgpushxto0(direct_exp(lp_iapply(H))) * V; } else if(!nisot::geodesic_movement) { @@ -2169,7 +2169,7 @@ EX void shift_view(hyperpoint H) { auto oView = View; View = get_shift_view_of(H, View); auto& wc = current_display->which_copy; - if(nonisotropic || rots_twist::in()) { + if(nonisotropic || stretch::in()) { transmatrix ioldv = eupush(tC0(inverse(oView))); transmatrix newv = inverse(eupush(tC0(inverse(View)))); wc = newv * ioldv * wc; diff --git a/nonisotropic.cpp b/nonisotropic.cpp index 020d0536..23feedad 100644 --- a/nonisotropic.cpp +++ b/nonisotropic.cpp @@ -1839,8 +1839,6 @@ EX } EX namespace rots { - EX ld stretch_factor; - EX transmatrix uxpush(ld x) { if(sl2) return xpush(x); return cspin(1, 3, x) * cspin(0, 2, x); @@ -2034,16 +2032,21 @@ EX namespace rots { EX } -/** twisted S2xE */ -EX namespace rots_twist { +/** stretched rotation space (S3 or SLR) */ +EX namespace stretch { + + EX ld factor; EX bool applicable() { - return among(geometry, gCell120, gECell120, gCell24, gECell24, gCell8, gECell8); + return rotspace || among(geometry, gCell120, gECell120, gCell24, gECell24, gCell8, gECell8); } - EX bool in() { return rots::stretch_factor && sphere && (rotspace || applicable()); } + EX bool in() { + return factor && applicable(); + } EX transmatrix translate(hyperpoint h) { + if(!sphere) return slr::translate(h); return matrix4( h[3], -h[2], h[1], h[0], h[2], h[3], -h[0], h[1], @@ -2056,6 +2059,7 @@ EX namespace rots_twist { h[0] = -h[0]; h[1] = -h[1]; h[2] = -h[2]; + if(!sphere) return slr::translate(h); return translate(h); } @@ -2066,11 +2070,11 @@ EX namespace rots_twist { } hyperpoint isometric_to_actual(const hyperpoint at, const hyperpoint velocity) { - return mulz(at, velocity, 1/sqrt(1+rots::stretch_factor)); + return mulz(at, velocity, 1/sqrt(1+factor)); } hyperpoint actual_to_isometric(const hyperpoint at, const hyperpoint velocity) { - return mulz(at, velocity, sqrt(1+rots::stretch_factor)); + return mulz(at, velocity, sqrt(1+factor)); } hyperpoint christoffel(const hyperpoint at, const hyperpoint velocity, const hyperpoint transported) { @@ -2080,7 +2084,9 @@ EX namespace rots_twist { hyperpoint c; - auto K = rots::stretch_factor; + auto K = factor; + + if(!sphere) K = -2 - K; c[0] = -K * (vel[1] * tra[2] + vel[2] * tra[1]); c[1] = K * (vel[0] * tra[2] + vel[2] * tra[0]); @@ -2089,7 +2095,13 @@ EX namespace rots_twist { return translate(at) * c; } - + + EX ld sqnorm(hyperpoint at, hyperpoint h) { + if(sphere) + return sqhypot_d(4, h); + h = itranslate(at) * h; + return h[0] * h[0] + h[1] * h[1] + h[2] * h[2]; + } EX } EX namespace nisot { @@ -2099,8 +2111,8 @@ EX namespace nisot { #if CAP_SOLV else if(sn::in()) return sn::christoffel(at, velocity, transported); #endif + else if(stretch::in()) return stretch::christoffel(at, velocity, transported); else if(sl2) return slr::christoffel(at, velocity, transported); - else if(rots_twist::in()) return rots_twist::christoffel(at, velocity, transported); else return point3(0, 0, 0); } @@ -2138,15 +2150,15 @@ EX namespace nisot { EX transmatrix parallel_transport_bare(transmatrix Pos, hyperpoint h) { - bool stretch = rots_twist::in(); - - if(!stretch) h[3] = 0; + bool stretch = stretch::in(); + + h[3] = 0; auto tPos = transpose(Pos); const ld eps = 1e-4; - if(sl2) { + if(sl2 && !stretch) { hyperpoint p = slr::to_phigans(tPos[3]); for(int i=0; i<3; i++) tPos[i] = (slr::to_phigans(tPos[3] + tPos[i] * eps) - p) / eps; @@ -2162,15 +2174,15 @@ EX namespace nisot { auto& vel = h; array ms; - + if(stretch) { for(int i=0; i<3; i++) { - ms[i] = sqhypot_d(4, tPos[i]); - tPos[i] = rots_twist::isometric_to_actual(at, tPos[i]); + ms[i] = stretch::sqnorm(at, tPos[i]); + tPos[i] = stretch::isometric_to_actual(at, tPos[i]); } - ms[3] = sqhypot_d(4, vel); + ms[3] = stretch::sqnorm(at, vel); if(!ms[3]) return Pos; - vel = rots_twist::isometric_to_actual(at, vel); + vel = stretch::isometric_to_actual(at, vel); } for(int i=0; i cm(currentmap, binary_map); binary_map->virtualRebase(alt, T); } - + fixmatrix(T); auto hT = tC0(T); - bool hopf = rots_twist::applicable(); + bool hopf = stretch::applicable(); if(hopf) - T = rots_twist::translate(hT); + T = stretch::translate(hT); if(DEB) println(hlog, "searching at ", alt, ":", hT);