1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-09-09 22:06:01 +00:00

rewritten the embeddings more nicely

This commit is contained in:
Zeno Rogue
2023-01-27 00:27:10 +01:00
parent 8744420504
commit 85dffdbeff
28 changed files with 1148 additions and 1090 deletions

View File

@@ -391,8 +391,7 @@ EX hyperpoint hpxy(ld x, ld y) {
geom3::light_flip(true);
hyperpoint h = hpxy(x, y);
geom3::light_flip(false);
swapmatrix(h);
return h;
return cgi.emb->base_to_actual(h);
}
if(sl2) return hyperpoint(x, y, 0, sqrt(1+x*x+y*y));
if(rotspace) return hyperpoint(x, y, 0, sqrt(1-x*x-y*y));
@@ -455,7 +454,7 @@ EX ld hypot_d(int d, const hyperpoint& h) {
*/
EX transmatrix to_other_side(hyperpoint h1, hyperpoint h2) {
if(geom3::sph_in_low() && !geom3::flipped) {
if(cgi.emb->is_sph_in_low() && !geom3::flipped) {
geom3::light_flip(true);
h1 = normalize(h1);
h2 = normalize(h2);
@@ -565,92 +564,6 @@ EX hyperpoint ultra_normalize(hyperpoint H) {
return normalize(H);
}
/** used in esl2_ita */
EX transmatrix esl2_zpush(ld z) { return cspin(2, 3, z) * cspin(0, 1, z); }
/** see esl2_ita; equal to esl2_ita * C0 */
EX hyperpoint esl2_ita0(hyperpoint h1) {
return esl2_zpush(h1[2]) * xpush(h1[0]) * ypush0(h1[1]);
}
/** in embedded-in-sl2, convert from intermediate to actual coordinates */
EX transmatrix esl2_ita(hyperpoint h1) {
return esl2_zpush(h1[2]) * xpush(h1[0]) * ypush(h1[1]);
}
/** in embedded-in-sl2, convert from actual to intermediate coordinates */
EX hyperpoint esl2_ati(hyperpoint h) {
ld a1 = (h[0] * h[3] - h[1] * h[2]) / (-h[2] * h[2] - h[1] * h[1] -h[0] * h[0] - h[3] * h[3]);
// a1 is S*sqrt(1+S*S) / (1+2*S*S), where S = sinh(-x) and C = cosh(-x); U is S*S
ld a = a1 * a1;
ld b = 4 * a - 1;
ld U = sqrt(.25 - a/b) - .5;
ld S = sqrt(U) * (a1 > 0 ? 1 : -1);
ld x = -asinh(S);
h = lorentz(0, 3, -x) * lorentz(1, 2, x) * h;
ld y = h[3]*h[3] > h[2]*h[2] ? atanh(h[1] / h[3]) : atanh(h[0] / h[2]);
h = lorentz(0, 2, -y) * lorentz(1, 3, -y) * h;
ld z = atan2(h[2], h[3]);
return hyperpoint(x, y, z, 0);
}
/** normalize, and in product geometry, also flatten */
EX hyperpoint normalize_flat(hyperpoint h) {
if(gproduct) {
if(geom3::euc_in_product()) {
ld bz = zlevel(h);
auto h1 = h / exp(bz);
ld bx = atan_auto(h1[0] / h1[2]);
return zpush(bz) * xpush(bx) * C0;
}
return product_decompose(h).second;
}
if(geom3::euc_in_nil()) h[1] = 0;
if(geom3::euc_in_sl2()) {
hyperpoint h1 = esl2_ati(h);
h1[1] = 0;
return esl2_ita0(h1);
}
else if(sl2) h = slr::translate(h) * zpush0(-atan2(h[2], h[3]));
if(geom3::euc_in_solnih()) h[2] = 0;
if(geom3::hyp_in_solnih()) h[0] = 0;
if(geom3::euc_in_sph()) {
ld tx = hypot(h[0], h[2]);
ld ty = hypot(h[1], h[3]);
h[0] = h[0] / tx * sin(1);
h[1] = h[1] / ty * cos(1);
h[2] = h[2] / tx * sin(1);
h[3] = h[3] / ty * cos(1);
return h;
}
if(geom3::euc_in_hyp()) {
h = normalize(h);
auto h1 = deparabolic13(h);
h1[2] = 0;
return parabolic13(h1);
}
if(geom3::euc_cylinder()) {
h /= h[3];
ld z = h[1] * h[1] + h[2] * h[2];
if(z > 0) h[1] /= z, h[2] /= z;
return h;
}
if(geom3::sph_in_euc()) {
ld z = hypot_d(3, h);
if(z > 0) h[0] /= z, h[1] /= z, h[2] /= z;
h[3] = 1;
return h;
}
if(geom3::sph_in_hyp()) {
ld z = hypot_d(3, h);
z = sinh(1) / z;
if(z > 0) h[0] *= z, h[1] *= z, h[2] *= z;
h[3] = cosh(1);
return h;
}
return normalize(h);
}
/** get the center of the line segment from H1 to H2 */
EX hyperpoint mid(const hyperpoint& H1, const hyperpoint& H2) {
if(gproduct) {
@@ -713,43 +626,6 @@ EX transmatrix cspin180(int a, int b) {
return T;
}
/** rotate by alpha degrees in the XY plane */
EX transmatrix spin(ld alpha) {
if(embedded_plane && geom3::euc_in_product()) return Id;
if(embedded_plane && geom3::euc_in_sl2()) return Id; // just looks weird...
if(embedded_plane && geom3::euc_vertical()) return cspin(0, 2, alpha);
if(embedded_plane && geom3::hyp_in_solnih()) return cspin(1, 2, alpha);
return cspin(0, 1, alpha);
}
EX transmatrix unswap_spin(transmatrix T) {
return cgi.intermediate_to_logical_scaled * T * cgi.logical_scaled_to_intemediate;
}
/** rotate by 90 degrees in the XY plane */
EX transmatrix spin90() {
if(embedded_plane && geom3::euc_in_product()) return Id;
if(embedded_plane && geom3::euc_vertical()) return cspin90(0, 2);
if(embedded_plane && geom3::hyp_in_solnih()) return cspin90(1, 2);
return cspin90(0, 1);
}
/** rotate by 180 degrees in the XY plane */
EX transmatrix spin180() {
if(embedded_plane && geom3::euc_in_product()) return Id;
if(embedded_plane && geom3::euc_vertical()) return cspin180(0, 2);
if(embedded_plane && geom3::hyp_in_solnih()) return cspin180(1, 2);
return cspin180(0, 1);
}
/** rotate by 270 degrees in the XY plane */
EX transmatrix spin270() {
if(embedded_plane && geom3::euc_in_product()) return Id;
if(embedded_plane && geom3::euc_vertical()) return cspin90(2, 0);
if(embedded_plane && geom3::hyp_in_solnih()) return cspin90(2, 1);
return cspin90(1, 0);
}
EX transmatrix random_spin3() {
ld alpha2 = asin(randd() * 2 - 1);
ld alpha = randd() * TAU;
@@ -833,12 +709,6 @@ EX transmatrix cpush(int cid, ld alpha) {
return T;
}
EX transmatrix lzpush(ld z) {
if(geom3::hyp_in_solnih()) return cpush(0, z);
if(geom3::euc_vertical()) return cpush(1, z);
return cpush(2, z);
}
EX transmatrix cmirror(int cid) {
transmatrix T = Id;
T[cid][cid] = -1;
@@ -848,17 +718,6 @@ EX transmatrix cmirror(int cid) {
// push alpha units to the right
EX transmatrix xpush(ld alpha) { return cpush(0, alpha); }
EX transmatrix lxpush(ld alpha) {
if(embedded_plane) {
geom3::light_flip(true);
auto t = cpush(0, alpha);
geom3::light_flip(false);
swapmatrix(t);
return t;
}
return cpush(0, alpha);
}
EX bool eqmatrix(transmatrix A, transmatrix B, ld eps IS(.01)) {
for(int i=0; i<MXDIM; i++)
for(int j=0; j<MXDIM; j++)
@@ -867,108 +726,6 @@ EX bool eqmatrix(transmatrix A, transmatrix B, ld eps IS(.01)) {
return true;
}
#if MAXMDIM >= 4
/** in the 3D space, move the point h orthogonally to the (x,y) plane by z units */
EX hyperpoint orthogonal_move(const hyperpoint& h, ld z) {
if(geom3::euc_in_hyp()) {
hyperpoint hf = deparabolic13(h);
hf[2] += z;
return parabolic13(hf);
}
if(geom3::euc_in_nil()) {
return nisot::translate(h) * cpush0(1, z);
}
if(geom3::euc_in_solnih()) {
return nisot::translate(h) * cpush0(2, z);
}
if(geom3::sph_in_euc()) {
ld z0 = hypot_d(3, h);
ld f = ((z0 + z) / z0);
hyperpoint hf;
for(int i=0; i<3; i++) hf[i] = h[i] * f;
hf[3] = 1;
return hf;
}
if(geom3::euc_cylinder()) {
auto hf = h / h[3];
ld z0 = hypot(h[1], h[2]);
if(!z0) return hf;
ld f = ((z0 + z) / z0);
hf[1] *= f; hf[2] *= f;
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);
hyperpoint hf;
for(int i=0; i<3; i++) hf[i] = h[i] * f;
hf[3] = cosh(z0 + z);
return hf;
}
if(geom3::euc_in_sph()) {
// cspin(0,2,x) * cspin(1,3,y) * cspin0(2, 3, z)
ld tx = hypot(h[0], h[2]);
ld ty = hypot(h[1], h[3]);
ld z0 = atan2(ty, tx);
z0 -= z;
hyperpoint hf;
hf[0] = h[0] / tx * cos(z0);
hf[1] = h[1] / ty * sin(z0);
hf[2] = h[2] / tx * cos(z0);
hf[3] = h[3] / ty * sin(z0);
return hf;
}
if(geom3::euc_in_product()) {
ld bz = zlevel(h);
auto h1 = h / exp(bz);
ld by = asin_auto(h1[1]);
ld bx = atan_auto(h1[0] / h1[2]);
by += z;
return zpush(bz) * xpush(bx) * ypush(by) * C0;
}
if(geom3::euc_in_sl2()) {
hyperpoint h1 = esl2_ati(h);
h1[1] += z;
return esl2_ita0(h1);
}
if(GDIM == 2) return scale_point(h, geom3::scale_at_lev(z));
if(gproduct) return scale_point(h, exp(z));
if(sl2) return slr::translate(h) * cpush0(2, z);
if(!hyperbolic) return rgpushxto0(h) * cpush(2, z) * C0;
if(nil) return nisot::translate(h) * cpush0(2, z);
if(translatable) return hpxy3(h[0], h[1], h[2] + z);
ld u = 1;
if(h[2]) z += asin_auto(h[2]), u /= cos_auto(asin_auto(h[2]));
u *= cos_auto(z);
return hpxy3(h[0] * u, h[1] * u, sinh(z));
}
EX ld get_logical_z(hyperpoint h) {
if(geom3::euc_in_nil())
return h[1];
if(geom3::euc_in_solnih())
return h[2];
if(geom3::hyp_in_solnih())
return h[0];
if(geom3::euc_in_sl2())
return esl2_ati(h)[1];
if(geom3::euc_in_product()) {
ld bz = zlevel(h);
auto h1 = h / exp(bz);
return asin_auto(h1[1]);
}
if(geom3::euc_cylinder()) {
return hypot(h[1], h[2]) - 1;
}
if(gproduct)
return log(h[2]);
return asin_auto(h[2]) - (moved_center() ? 1 : 0);
}
#endif
// push alpha units vertically
EX transmatrix ypush(ld alpha) { return cpush(1, alpha); }
@@ -993,134 +750,10 @@ EX transmatrix matrix4(ld a, ld b, ld c, ld d, ld e, ld f, ld g, ld h, ld i, ld
#endif
}
#if MAXMDIM >= 4
/** Transform a matrix between the 'embedded_plane' and underlying representation. Switches to the current variant. */
EX void swapmatrix(transmatrix& T) {
if(geom3::euc_in_hyp() && !geom3::flipped) {
geom3::light_flip(true);
hyperpoint mov = T * C02;
transmatrix U = gpushxto0(mov) * T;
geom3::light_flip(false);
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;
}
}
else if(geom3::euc_cylinder()) {
if(!geom3::flipped) {
hyperpoint h1 = cgi.logical_to_intermediate * get_column(T, 2);
T = xpush(h1[0]) * cspin(1, 2, h1[1]);
return;
}
}
else if(geom3::euc_in_nil()) {
if(!geom3::flipped) {
hyperpoint h1 = cgi.logical_to_intermediate * get_column(T, 2);
// rotations are illegal anyway...
T = eupush(hyperpoint(h1[0], 0, h1[2], 1));
return;
}
}
else if(geom3::euc_in_solnih()) {
if(!geom3::flipped) {
hyperpoint h1 = cgi.logical_to_intermediate * get_column(T, 2);
// rotations are illegal anyway...
T = eupush(hyperpoint(h1[0], h1[1], 0, 1));
return;
}
}
else if(geom3::euc_in_product()) {
hyperpoint h1 = cgi.logical_to_intermediate * get_column(T, 2);
T = xpush(h1[0]) * zpush(h1[2]);
return;
}
else if(geom3::euc_in_sl2() && !geom3::flipped) {
hyperpoint h1 = cgi.logical_to_intermediate * get_column(T, 2); h1[1] = 0;
T = esl2_ita(h1);
return;
}
else if(geom3::in_product()) {
/* just do nothing */
}
else if(geom3::euc_in_sph()) {
hyperpoint h1 = cgi.logical_to_intermediate * get_column(T, 2);
T = cspin(0, 2, h1[0]) * cspin(1, 3, h1[1]);
}
else {
for(int i=0; i<4; i++) swap(T[i][2], T[i][3]);
for(int i=0; i<4; i++) swap(T[2][i], T[3][i]);
if(GDIM == 3) {
for(int i=0; i<4; i++) T[i][2] = T[2][i] = 0;
T[2][2] = 1;
}
}
fixmatrix(T);
for(int i=0; i<MDIM; i++) for(int j=0; j<MDIM; j++) if(isnan(T[i][j])) T = Id;
}
/** Just like swapmatrix but for hyperpoints. */
EX void swapmatrix(hyperpoint& h) {
if(geom3::euc_in_product()) {
h = cgi.logical_to_intermediate * h;
h = xpush(h[0]) * zpush(h[2]) * C0;
return;
}
if(geom3::in_product()) return;
if(geom3::sph_in_euc()) { h[3] = 1; return; }
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_cylinder()) {
hyperpoint h1 = cgi.logical_to_intermediate * h;
h[0] = h1[0];
h[1] = sin(h1[1]);
h[2] = cos(h1[1]);
h[3] = 1;
return;
}
if(geom3::euc_in_nil()) { h = cgi.logical_to_intermediate * h; h[3] = 1; h[1] = 0; return; }
if(geom3::euc_in_sl2()) {
hyperpoint h1 = cgi.logical_to_intermediate * h; h1[1] = 0;
h = esl2_ita0(h1);
return;
}
if(geom3::euc_in_sph()) {
h = cgi.logical_to_intermediate * h;
h = cspin(0, 2, h[0]) * cspin(1, 3, h[1]) * lzpush(1) * C0;
return;
}
if(geom3::euc_in_solnih()) { h = cgi.logical_to_intermediate * h; h[3] = 1; h[2] = 0; 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;
}
#endif
EX transmatrix parabolic1(ld u) {
if(euclid)
return ypush(u);
else if(geom3::hyp_in_solnih() && !geom3::flipped) {
else if(cgi.emb->is_hyp_in_solnih() && !geom3::flipped) {
return ypush(u);
}
else {
@@ -1136,7 +769,7 @@ EX transmatrix parabolic1(ld u) {
EX transmatrix parabolic13(ld u, ld v) {
if(euclid)
return eupush3(0, u, v);
else if(geom3::euc_in_hyp()) {
else if(cgi.emb->is_euc_in_hyp()) {
ld diag = (u*u+v*v)/2;
return matrix4(
1, 0, -u, u,
@@ -1158,7 +791,7 @@ EX transmatrix parabolic13(ld u, ld v) {
EX hyperpoint deparabolic13(hyperpoint h) {
if(euclid) return h;
if(geom3::euc_in_hyp()) {
if(cgi.emb->is_euc_in_hyp()) {
h /= (1 + h[LDIM]);
h[2] -= 1;
h /= sqhypot_d(LDIM, h);
@@ -1174,7 +807,7 @@ EX hyperpoint deparabolic13(hyperpoint h) {
EX hyperpoint parabolic13(hyperpoint h) {
if(euclid) return h;
else if(geom3::euc_in_hyp()) {
else if(cgi.emb->is_euc_in_hyp()) {
return parabolic13(h[0], h[1]) * cpush0(2, h[2]);
}
else if(LDIM == 3)
@@ -1185,7 +818,7 @@ EX hyperpoint parabolic13(hyperpoint h) {
EX transmatrix parabolic13_at(hyperpoint h) {
if(euclid) return rgpushxto0(h);
else if(geom3::euc_in_hyp()) {
else if(cgi.emb->is_euc_in_hyp()) {
return parabolic13(h[0], h[1]) * cpush(2, h[2]);
}
else if(LDIM == 3)
@@ -1235,26 +868,6 @@ EX transmatrix rspintox(const hyperpoint& H) {
return rspintoc(H, 0, 1) * rspintoc(T1*H, 0, 2);
}
EX transmatrix lspintox(const hyperpoint& H) {
if(geom3::euc_in_product()) return Id;
if(geom3::euc_in_sl2()) return Id;
if(geom3::euc_vertical()) 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;
}
EX transmatrix lrspintox(const hyperpoint& H) {
if(geom3::euc_in_product()) return Id;
if(geom3::euc_in_sl2()) return Id;
if(geom3::euc_vertical()) return rspintoc(H, 0, 2);
if(geom3::hyp_in_solnih()) return rspintoc(H, 2, 1);
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);
}
/** for H on the X axis, this matrix pushes H to C0
* \see gpushxto0
*/
@@ -1688,25 +1301,8 @@ EX hyperpoint scale_point(const hyperpoint& h, ld scale_factor) {
return res;
}
EX bool moved_center() {
if(geom3::sph_in_euc()) return true;
if(geom3::sph_in_hyp()) return true;
if(geom3::euc_in_sph()) return true;
if(geom3::euc_cylinder()) return true;
return false;
}
/** Returns the intended center of the tile, relative to its local matrix. Usually C0 but may be different, e.g. when embedding a sphere in E3 or H3. */
EX hyperpoint tile_center() {
if(geom3::sph_in_euc()) return C02 + C03;
if(geom3::euc_in_sph()) return zpush0(1);
if(geom3::sph_in_hyp()) return zpush0(1);
if(geom3::euc_cylinder()) return zpush0(1);
return C0;
}
EX transmatrix orthogonal_move(const transmatrix& t, double level) {
if(gproduct && !geom3::euc_in_product()) return scale_matrix(t, exp(level));
if(gproduct && !cgi.emb->is_euc_in_product()) return scale_matrix(t, exp(level));
if(GDIM == 3) return t * lzpush(level);
return scale_matrix(t, geom3::lev_to_factor(level));
}
@@ -1821,7 +1417,7 @@ EX bool use_embedded_shift(eShiftMethodApplication sma) {
EX eShiftMethod shift_method(eShiftMethodApplication sma) {
if(gproduct) return smProduct;
if(embedded_plane && sma == smaObject) return geom3::same_in_same() ? smIsotropic : smEmbedded;
if(embedded_plane && sma == smaObject) return cgi.emb->is_same_in_same() ? smIsotropic : smEmbedded;
if(embedded_plane && use_embedded_shift(sma)) return sl2 ? smESL2 : nonisotropic ? smLie : smEmbedded;
if(!nonisotropic && !stretch::in() && !(!nisot::geodesic_movement && hyperbolic && bt::in())) return smIsotropic;
if(!nisot::geodesic_movement && !embedded_plane) return smLie;
@@ -1843,27 +1439,27 @@ EX transmatrix shift_object(transmatrix Position, const transmatrix& ori, const
}
case smEmbedded: {
if(geom3::euc_in_hyp() || geom3::sph_in_low()) {
if(cgi.emb->is_euc_in_hyp() || cgi.emb->is_sph_in_low()) {
geom3::light_flip(true);
transmatrix T = rgpushxto0(direct_exp(direction));
geom3::light_flip(false);
swapmatrix(T);
return Position * T;
return Position * cgi.emb->base_to_actual(T);
}
if(geom3::euc_in_sph()) Position = inverse(View) * Position;
if(cgi.emb->is_euc_in_sph()) Position = inverse(View) * Position;
transmatrix rot = inverse(map_relative_push(Position * tile_center())) * Position;
if(moved_center()) rot = rot * lzpush(1);
transmatrix rot = inverse(cgi.emb->map_relative_push(Position * tile_center())) * Position;
ld z = cgi.emb->center_z();
if(z) rot = rot * lzpush(z);
transmatrix urot = unswap_spin(rot);
geom3::light_flip(true);
transmatrix T = rgpushxto0(direct_exp(urot * direction));
geom3::light_flip(false);
swapmatrix(T);
T = cgi.emb->base_to_actual(T);
auto res = Position * inverse(rot) * T * rot;
if(geom3::euc_in_sph()) res = View * res;
if(cgi.emb->is_euc_in_sph()) res = View * res;
return res;
}
default: throw hr_exception("unknown shift method in shift_object");
@@ -1875,7 +1471,7 @@ EX void apply_shift_object(transmatrix& Position, const transmatrix orientation,
}
EX void rotate_object(transmatrix& Position, transmatrix& orientation, transmatrix R) {
if(geom3::euc_in_product()) orientation = orientation * R;
if(cgi.emb->is_euc_in_product()) orientation = orientation * R;
else if(gproduct && WDIM == 3) orientation = orientation * R;
else Position = Position * R;
}
@@ -1931,16 +1527,6 @@ EX transmatrix transpose(transmatrix T) {
return result;
}
EX hyperpoint lspinpush0(ld alpha, ld x) {
bool f = embedded_plane;
if(f) geom3::light_flip(true);
if(embedded_plane) throw hr_exception("still embedded plane");
hyperpoint h = xspinpush0(alpha, x);
if(f) geom3::light_flip(false);
if(f) swapmatrix(h);
return h;
}
#if HDR
namespace slr {
hyperpoint xyz_point(ld x, ld y, ld z);
@@ -1960,7 +1546,6 @@ inline hyperpoint cpush0(int c, ld x) {
}
inline hyperpoint xpush0(ld x) { return cpush0(0, x); }
inline hyperpoint lxpush0(ld x) { return lxpush(x) * tile_center(); }
inline hyperpoint ypush0(ld x) { return cpush0(1, x); }
inline hyperpoint zpush0(ld x) { return cpush0(2, x); }
@@ -1978,16 +1563,6 @@ inline shiftpoint tC0(const shiftmatrix &T) {
}
#endif
EX hyperpoint xspinpush0(ld alpha, ld x) {
if(embedded_plane) return lspinpush0(alpha, x);
if(sl2) return slr::polar(x, -alpha, 0);
hyperpoint h = Hypc;
h[LDIM] = cos_auto(x);
h[0] = sin_auto(x) * cos(alpha);
h[1] = sin_auto(x) * -sin(alpha);
return h;
}
/** tangent vector in the given direction */
EX hyperpoint ctangent(int c, ld x) { return point3(c==0?x:0, c==1?x:0, c==2?x:0); }
@@ -1997,13 +1572,6 @@ EX hyperpoint xtangent(ld x) { return ctangent(0, x); }
/** tangent vector in direction Z */
EX hyperpoint ztangent(ld z) { return ctangent(2, z); }
/** tangent vector in logical direction Z */
EX hyperpoint lztangent(ld z) {
if(geom3::hyp_in_solnih()) return ctangent(0, z);
if(geom3::euc_vertical()) return ctangent(1, z);
return ctangent(2, z);
}
/** change the length of the targent vector */
EX hyperpoint tangent_length(hyperpoint dir, ld length) {
ld r = hypot_d(GDIM, dir);
@@ -2108,7 +1676,7 @@ EX unsigned bucketer(hyperpoint h) {
auto d = product_decompose(h);
h = d.second;
dx += bucketer(d.first) * 50;
if(geom3::euc_in_product() && in_h2xe()) h /= h[2];
if(cgi.emb->is_euc_in_product() && in_h2xe()) h /= h[2];
}
dx += bucketer(h[0]) + 1000 * bucketer(h[1]) + 1000000 * bucketer(h[2]);
if(MDIM == 4) dx += bucketer(h[3]) * 1000000001;