1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2024-12-24 17:10:36 +00:00

SolN manifold

This commit is contained in:
Zeno Rogue 2019-10-03 20:10:48 +02:00
parent 4872ad01f4
commit d69cb4e946
12 changed files with 176 additions and 120 deletions

View File

@ -336,7 +336,7 @@ void display_data::set_projection(int ed) {
#if CAP_SOLV #if CAP_SOLV
if(among(glhr::new_shader_projection, glhr::shader_projection::standardSolv, glhr::shader_projection::standardNIH)) { if(among(glhr::new_shader_projection, glhr::shader_projection::standardSolv, glhr::shader_projection::standardNIH)) {
auto &tab = ((glhr::new_shader_projection == glhr::shader_projection::standardSolv) ? solv::solt : nihv::niht); auto &tab = solnihv::get_tabled();
GLuint invexpid = tab.get_texture_id(); GLuint invexpid = tab.get_texture_id();

View File

@ -914,7 +914,7 @@ EX int heptdistance(heptagon *h1, heptagon *h2) {
if(cryst) return crystal::space_distance(h1->c7, h2->c7); if(cryst) return crystal::space_distance(h1->c7, h2->c7);
#endif #endif
#if CAP_SOLV #if CAP_SOLV
if(solnih) return solv::approx_distance(h1, h2); if(solnih) return solnihv::approx_distance(h1, h2);
#endif #endif
while(true) { while(true) {
if(h1 == h2) return d; if(h1 == h2) return d;

View File

@ -524,13 +524,11 @@ EX geometryinfo1 giEuclid3 = { gcEuclid, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giHyperb3 = { gcHyperbolic, 3, 3, 4, {1,1, 1,-1} }; EX geometryinfo1 giHyperb3 = { gcHyperbolic, 3, 3, 4, {1,1, 1,-1} };
EX geometryinfo1 giSphere3 = { gcSphere, 3, 3, 4, {1,1, 1,+1} }; EX geometryinfo1 giSphere3 = { gcSphere, 3, 3, 4, {1,1, 1,+1} };
EX geometryinfo1 giSol = { gcSol, 3, 3, 4, {1,1, 1,0 } }; EX geometryinfo1 giSolNIH = { gcSolNIH, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giNil = { gcNil, 3, 3, 4, {1,1, 1,0 } }; EX geometryinfo1 giNil = { gcNil, 3, 3, 4, {1,1, 1,0 } };
EX geometryinfo1 giProduct = { gcSL2, 3, 3, 4, {1,1, 1,0 } /* will be filled in product::configure() */ }; EX geometryinfo1 giProduct = { gcSL2, 3, 3, 4, {1,1, 1,0 } /* will be filled in product::configure() */ };
EX geometryinfo1 giSL2 = { gcSL2, 3, 3, 4, {1,1,-1,-1} }; EX geometryinfo1 giSL2 = { gcSL2, 3, 3, 4, {1,1,-1,-1} };
EX geometryinfo1 giH23 = { gcNIH, 3, 3, 4, {1,1, 1,0 } };
/** list of available geometries */ /** list of available geometries */
vector<geometryinfo> ginf = { vector<geometryinfo> ginf = {
{"{7,3}", "none", "{7,3} (standard HyperRogue map)", "HR", 7, 3, 0, giHyperb2, 0, {{7, 5}}, eVariation::bitruncated}, {"{7,3}", "none", "{7,3} (standard HyperRogue map)", "HR", 7, 3, 0, giHyperb2, 0, {{7, 5}}, eVariation::bitruncated},
@ -583,14 +581,15 @@ vector<geometryinfo> ginf = {
{"{4,3,5}","field", "{4,3,5} field quotient space", "f435", 6, 5, qsSMALLBF, giHyperb3, 0x40600, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, {"{4,3,5}","field", "{4,3,5} field quotient space", "f435", 6, 5, qsSMALLBF, giHyperb3, 0x40600, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"{5,3,4}","field", "{5,3,4} field quotient space", "f435", 12, 4, qsSMALLBF, giHyperb3, 0x40800, {{SEE_ALL, SEE_ALL}}, eVariation::pure}, {"{5,3,4}","field", "{5,3,4} field quotient space", "f435", 12, 4, qsSMALLBF, giHyperb3, 0x40800, {{SEE_ALL, SEE_ALL}}, eVariation::pure},
{"binary4","none", "standard binary tiling", "binary4", 5, 3, qBINARY, giHyperb2, 0x41400, {{7, 5}}, eVariation::pure}, {"binary4","none", "standard binary tiling", "binary4", 5, 3, qBINARY, giHyperb2, 0x41400, {{7, 5}}, eVariation::pure},
{"sol", "none", "Solv geometry", "sol", 8, 3, qBINARY, giSol, 0x41600, {{7, 5}}, eVariation::pure}, {"sol", "none", "Solv geometry", "sol", 8, 3, qBINARY|qSOL, giSolNIH, 0x41600, {{7, 5}}, eVariation::pure},
{"kd2", "none", "kite-and-dart", "kd2", 4, 3, qPENROSE, giEuclid2, 0x48000, {{7, 7}}, eVariation::pure}, {"kd2", "none", "kite-and-dart", "kd2", 4, 3, qPENROSE, giEuclid2, 0x48000, {{7, 7}}, eVariation::pure},
{"kd3", "none", "kite-and-dart on horospheres", "kd3", 12, 3, qsBP, giHyperb3, 0x48200, {{7, 3}}, eVariation::pure}, {"kd3", "none", "kite-and-dart on horospheres", "kd3", 12, 3, qsBP, giHyperb3, 0x48200, {{7, 3}}, eVariation::pure},
{"nil", "none", "Nil geometry", "nil", 6, 3, 0, giNil, 0x48600, {{7, 5}}, eVariation::pure}, {"nil", "none", "Nil geometry", "nil", 6, 3, 0, giNil, 0x48600, {{7, 5}}, eVariation::pure},
{"product","none", "product space", "product", 7, 3, qHYBRID, giProduct, 0x00000, {{7, 3}}, eVariation::pure}, {"product","none", "product space", "product", 7, 3, qHYBRID, giProduct, 0x00000, {{7, 3}}, eVariation::pure},
{"twisted","none", "rotation space", "twisted", 7, 3, qHYBRID, giSL2, 0x00000, {{6, 4}}, eVariation::pure}, {"twisted","none", "rotation space", "twisted", 7, 3, qHYBRID, giSL2, 0x00000, {{6, 4}}, eVariation::pure},
{"ternary","none", "standard ternary tiling", "ternary", 6, 3, qBINARY, giHyperb2, 0x48400, {{6, 4}}, eVariation::pure}, {"ternary","none", "standard ternary tiling", "ternary", 6, 3, qBINARY, giHyperb2, 0x48400, {{6, 4}}, eVariation::pure},
{"NIH", "none", "non-isotropic hyperbolic", "NIH", 11, 3, qBINARY, giH23, 0x49000, {{6, 4}}, eVariation::pure}, {"NIH", "none", "non-isotropic hyperbolic", "NIH", 11, 3, qBINARY|qNIH, giSolNIH, 0x49000, {{6, 3}}, eVariation::pure},
{"solN", "none", "Solv geometry NI", "solN", 9, 3, (qBINARY|qSOL|qNIH), giSolNIH, 0x49200, {{7, 3}}, eVariation::pure},
}; };
// bits: 9, 10, 15, 16, (reserved for later) 17, 18 // bits: 9, 10, 15, 16, (reserved for later) 17, 18

View File

@ -215,10 +215,10 @@ enum eGeometry {
gField435, gField534, gField435, gField534,
gBinary4, gSol, gBinary4, gSol,
gKiteDart2, gKiteDart3, gNil, gProduct, gRotSpace, gKiteDart2, gKiteDart3, gNil, gProduct, gRotSpace,
gTernary, gNIH, gTernary, gNIH, gSolN,
gGUARD}; gGUARD};
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSol, gcNil, gcProduct, gcSL2, gcNIH }; enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSolNIH, gcNil, gcProduct, gcSL2 };
enum class eVariation { bitruncated, pure, goldberg, irregular, dual }; enum class eVariation { bitruncated, pure, goldberg, irregular, dual };
@ -270,8 +270,9 @@ static const flagtype qREGULAR = 1024; /* not set! */
static const flagtype qARCHI = 2048; static const flagtype qARCHI = 2048;
static const flagtype qHYBRID = 4096; static const flagtype qHYBRID = 4096;
static const flagtype qCRYSTAL = 8192; static const flagtype qCRYSTAL = 8192;
static const flagtype qSOL = 16384;
static const flagtype qEXPERIMENTAL = 32768; static const flagtype qEXPERIMENTAL = 32768;
static const flagtype qNIH = 65536;
// note: dnext assumes that x&7 equals 7 // note: dnext assumes that x&7 equals 7
static const int SEE_ALL = 50; static const int SEE_ALL = 50;

View File

@ -509,8 +509,8 @@ EX void initConfig() {
addsaver(vid.cells_generated_limit, "limit on cells generated", 25); addsaver(vid.cells_generated_limit, "limit on cells generated", 25);
#if CAP_SOLV #if CAP_SOLV
addsaver(solv::solrange_xy, "solrange-xy"); addsaver(solnihv::solrange_xy, "solrange-xy");
addsaver(solv::solrange_z, "solrange-z"); addsaver(solnihv::solrange_z, "solrange-z");
#endif #endif
addsaver(slr::steps, "slr-steps"); addsaver(slr::steps, "slr-steps");
addsaver(slr::range_xy, "slr-range-xy"); addsaver(slr::range_xy, "slr-range-xy");
@ -869,16 +869,16 @@ EX void edit_sightrange() {
dialog::editNumber(sightranges[geometry], 0, 10, 0.5, M_PI, solhelp(), ""); dialog::editNumber(sightranges[geometry], 0, 10, 0.5, M_PI, solhelp(), "");
dialog::extra_options = xo; popScreen(); dialog::extra_options = xo; popScreen();
}); });
dialog::addSelItem(XLAT("max difference in X/Y coordinates"), fts(solv::solrange_xy), 'X'); dialog::addSelItem(XLAT("max difference in X/Y coordinates"), fts(solnihv::solrange_xy), 'X');
dialog::add_action([] { dialog::add_action([] {
auto xo = dialog::extra_options; auto xo = dialog::extra_options;
dialog::editNumber(solv::solrange_xy, 0.01, 200, 0.1, 50, XLAT("max difference in X/Y coordinates"), solhelp()), dialog::scaleLog(); dialog::editNumber(solnihv::solrange_xy, 0.01, 200, 0.1, 50, XLAT("max difference in X/Y coordinates"), solhelp()), dialog::scaleLog();
dialog::extra_options = xo; popScreen(); dialog::extra_options = xo; popScreen();
}); });
dialog::addSelItem(XLAT("max difference in Z coordinate"), fts(solv::solrange_z), 'Z'); dialog::addSelItem(XLAT("max difference in Z coordinate"), fts(solnihv::solrange_z), 'Z');
dialog::add_action([] { dialog::add_action([] {
auto xo = dialog::extra_options; auto xo = dialog::extra_options;
dialog::editNumber(solv::solrange_z, 0, 20, 0.1, 6, XLAT("max difference in Z coordinates"), solhelp()); dialog::editNumber(solnihv::solrange_z, 0, 20, 0.1, 6, XLAT("max difference in Z coordinates"), solhelp());
dialog::extra_options = xo; popScreen(); dialog::extra_options = xo; popScreen();
}); });
#endif #endif
@ -955,7 +955,7 @@ EX void menuitem_sightrange(char c IS('c')) {
dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(WDIM == 3 ? vid.smart_range_detail_3 : vid.smart_range_detail), c); dialog::addSelItem(XLAT("minimum visible cell in pixels"), fts(WDIM == 3 ? vid.smart_range_detail_3 : vid.smart_range_detail), c);
#if CAP_SOLV #if CAP_SOLV
else if(pmodel == mdGeodesic && sol) else if(pmodel == mdGeodesic && sol)
dialog::addSelItem(XLAT("3D sight range"), fts(solv::solrange_xy) + "x" + fts(solv::solrange_z), c); dialog::addSelItem(XLAT("3D sight range"), fts(solnihv::solrange_xy) + "x" + fts(solnihv::solrange_z), c);
#endif #endif
else if(WDIM == 3) else if(WDIM == 3)
dialog::addSelItem(XLAT("3D sight range"), fts(sightranges[geometry]), c); dialog::addSelItem(XLAT("3D sight range"), fts(sightranges[geometry]), c);

View File

@ -6062,7 +6062,7 @@ EX void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) {
else if(a < 2 && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewcenter())) continue; else if(a < 2 && among(geometry, gHoroRec) && celldistAlt(c) >= celldistAlt(viewcenter())) continue;
else if(c->move(a)->master->distance > c->master->distance && c->master->distance > viewctr.at->distance && !quotient) continue; else if(c->move(a)->master->distance > c->master->distance && c->master->distance > viewctr.at->distance && !quotient) continue;
} }
else if(sol && in_perspective()) { else if(sol && in_perspective() && !nih) {
ld b = vid.binary_width * log(2) / 2; ld b = vid.binary_width * log(2) / 2;
const ld l = log(2) / 2; const ld l = log(2) / 2;
switch(a) { switch(a) {

View File

@ -129,9 +129,9 @@ void addMessage(string s, char spamtype = 0);
#define cgclass (ginf[geometry].cclass) #define cgclass (ginf[geometry].cclass)
#define euclid (cgclass == gcEuclid) #define euclid (cgclass == gcEuclid)
#define sphere (cgclass == gcSphere) #define sphere (cgclass == gcSphere)
#define sol (cgclass == gcSol) #define solnih (cgclass = gcSolNIH)
#define nih (cgclass == gcNIH) #define sol (ginf[geometry].flags & qSOL)
#define solnih (sol || nih) #define nih (ginf[geometry].flags & qNIH)
#define nil (cgclass == gcNil) #define nil (cgclass == gcNil)
#define sl2 (cgclass == gcSL2) #define sl2 (cgclass == gcSL2)
#define prod (cgclass == gcProduct) #define prod (cgclass == gcProduct)

View File

@ -1131,8 +1131,12 @@ enum iePrecision { iLazy, iTable };
/** inverse exponential function \see hr::direct_exp */ /** inverse exponential function \see hr::direct_exp */
EX hyperpoint inverse_exp(const hyperpoint h, iePrecision p, bool just_direction IS(true)) { EX hyperpoint inverse_exp(const hyperpoint h, iePrecision p, bool just_direction IS(true)) {
#if CAP_SOLV #if CAP_SOLV
if(sol) return solv::get_inverse_exp(h, p == iLazy, just_direction); if(solnih) {
if(nih) return nihv::get_inverse_exp(h, p == iLazy, just_direction); if(nih)
return solnihv::get_inverse_exp_nsym(h, p == iLazy, just_direction);
else
return solnihv::get_inverse_exp_symsol(h, p == iLazy, just_direction);
}
#endif #endif
if(nil) return nilv::get_inverse_exp(h, p == iLazy ? 5 : 20); if(nil) return nilv::get_inverse_exp(h, p == iLazy ? 5 : 20);
if(sl2) return slr::get_inverse_exp(h); if(sl2) return slr::get_inverse_exp(h);

View File

@ -969,7 +969,7 @@ EX bool in_smart_range(const transmatrix& T) {
if(invalid_point(h)) return false; if(invalid_point(h)) return false;
if(nil || nih) return true; if(nil || nih) return true;
#if CAP_SOLV #if CAP_SOLV
if(pmodel == mdGeodesic) return solv::in_table_range(h); if(pmodel == mdGeodesic) return solnihv::in_table_range(h);
#endif #endif
hyperpoint h1; hyperpoint h1;
applymodel(h, h1); applymodel(h, h1);

View File

@ -25,11 +25,15 @@ EX namespace nisot {
return slr::translate(h); return slr::translate(h);
transmatrix T = Id; transmatrix T = Id;
for(int i=0; i<GDIM; i++) T[i][LDIM] = h[i]; for(int i=0; i<GDIM; i++) T[i][LDIM] = h[i];
if(sol) { if(sol && nih) {
T[0][0] = pow(2, -h[2]);
T[1][1] = pow(3, h[2]);
}
else if(sol) {
T[0][0] = exp(-h[2]); T[0][0] = exp(-h[2]);
T[1][1] = exp(+h[2]); T[1][1] = exp(+h[2]);
} }
if(nih) { else if(nih) {
T[0][0] = pow(2, h[2]); T[0][0] = pow(2, h[2]);
T[1][1] = pow(3, h[2]); T[1][1] = pow(3, h[2]);
} }
@ -52,6 +56,8 @@ EX namespace solnihv {
void load(); void load();
hyperpoint get(ld ix, ld iy, ld iz, bool lazy); hyperpoint get(ld ix, ld iy, ld iz, bool lazy);
nisot::ptlow& get_int(int ix, int iy, int iz) { return tab[(iz*PRECY+iy)*PRECX+ix]; }
GLuint texture_id; GLuint texture_id;
bool toload; bool toload;
@ -84,7 +90,7 @@ EX namespace solnihv {
hyperpoint res; hyperpoint res;
if(lazy) { if(lazy) {
auto r = tab[(int(iz)*PRECY+int(iy))*PRECX+int(ix)]; auto r = get_int(int(ix), int(iy), int(iz));
for(int i=0; i<3; i++) res[i] = r[i]; for(int i=0; i<3; i++) res[i] = r[i];
} }
@ -98,7 +104,7 @@ EX namespace solnihv {
int ay = iy, by = ay+1; int ay = iy, by = ay+1;
int az = iz, bz = az+1; int az = iz, bz = az+1;
#define S0(x,y,z) tab[(z*PRECY+y)*PRECX+x][t] #define S0(x,y,z) get_int(x, y, z)[t]
#define S1(x,y) (S0(x,y,az) * (bz-iz) + S0(x,y,bz) * (iz-az)) #define S1(x,y) (S0(x,y,az) * (bz-iz) + S0(x,y,bz) * (iz-az))
#define S2(x) (S1(x,ay) * (by-iy) + S1(x,by) * (iy-ay)) #define S2(x) (S1(x,ay) * (by-iy) + S1(x,by) * (iy-ay))
@ -244,8 +250,10 @@ EX namespace solnihv {
parent->c.connect(d, g, d1, false); parent->c.connect(d, g, d1, false);
return g; return g;
}; };
switch(geometry){
if(sol) switch(d) { case gSol: switch(d) {
case 0: // right case 0: // right
return rule(altstep(pf, 2), ps, 4); return rule(altstep(pf, 2), ps, 4);
case 1: // up case 1: // up
@ -266,7 +274,7 @@ EX namespace solnihv {
return NULL; return NULL;
} }
else switch(d) { case gNIH: switch(d) {
case 0: // right case 0: // right
return rule(altstep(pf, 2), ps, 2); return rule(altstep(pf, 2), ps, 2);
case 1: // up case 1: // up
@ -280,6 +288,26 @@ EX namespace solnihv {
default: default:
return rule(altstep(pf, (d-5) % 2), altstep3(ps, (d-5)/2), 4); return rule(altstep(pf, (d-5) % 2), altstep3(ps, (d-5)/2), 4);
} }
case gSolN: switch(d) {
case 0: // right
return rule(altstep(pf, 2), ps, 2);
case 1: // up
return rule(pf, altstep3(ps, 3), 3);
case 2: // left
return rule(altstep(pf, 4), ps, 0);
case 3: // down
return rule(pf, altstep3(ps, 5), 1);
case 4: case 5:
return rule(altstep(pf, d-4), altstep3(ps, 4), ps->zebraval + 6);
case 6: case 7: case 8:
return rule(altstep(pf, 3), altstep3(ps, d-6), pf->zebraval + 4);
default:
return NULL;
}
default: throw "not solnihv";
}
} }
~hrmap_solnih() { ~hrmap_solnih() {
@ -289,23 +317,23 @@ EX namespace solnihv {
} }
transmatrix adjmatrix(int i, int j) { transmatrix adjmatrix(int i, int j) {
if(sol) { switch(geometry) {
case gSol: {
ld z = log(2); ld z = log(2);
ld bw = vid.binary_width * z; ld bw = vid.binary_width * z;
ld bwh = bw / 4;
switch(i) { switch(i) {
case 0: return xpush(+bw); case 0: return xpush(+bw);
case 1: return ypush(+bw); case 1: return ypush(+bw);
case 2: return xpush(-bwh) * zpush(+z) * ypush(j == 6 ? +bwh : -bwh); case 2: case 3:
case 3: return xpush(+bwh) * zpush(+z) * ypush(j == 6 ? +bwh : -bwh); return ypush(bw*(6.5-j)) * zpush(+z) * xpush(bw*(i-2.5));
case 4: return xpush(-bw); case 4: return xpush(-bw);
case 5: return ypush(-bw); case 5: return ypush(-bw);
case 6: return ypush(-bwh) * zpush(-z) * xpush(j == 2 ? +bwh : -bwh); case 6: case 7:
case 7: return ypush(+bwh) * zpush(-z) * xpush(j == 2 ? +bwh : -bwh); return xpush(bw*(2.5-j)) * zpush(-z) * ypush(bw*(i-6.5));
default:return Id; default:return Id;
} }
} }
else { case gNIH: {
ld bw = vid.binary_width; ld bw = vid.binary_width;
switch(i) { switch(i) {
case 0: return xpush(+bw); case 0: return xpush(+bw);
@ -378,31 +406,40 @@ EX namespace solnihv {
" return 0.5 - atan((0.5-x) / y) / 3.1415926535897932384626433832795;" " return 0.5 - atan((0.5-x) / y) / 3.1415926535897932384626433832795;"
" }"; " }";
EX }
EX namespace solv {
EX ld solrange_xy = 15;
EX ld solrange_z = 4;
EX bool in_table_range(hyperpoint h) {
return abs(h[0]) < solrange_xy && abs(h[1]) < solrange_xy && abs(h[2]) < solrange_z;
}
EX solnihv::tabled_inverses solt = solnihv::tabled_inverses("solv-geodesics.dat");
hyperpoint christoffel(const hyperpoint at, const hyperpoint velocity, const hyperpoint transported) { hyperpoint christoffel(const hyperpoint at, const hyperpoint velocity, const hyperpoint transported) {
return hpxyz3( constexpr ld l2 = log(2);
-velocity[2] * transported[0] - velocity[0] * transported[2], constexpr ld l3 = log(3);
velocity[2] * transported[1] + velocity[1] * transported[2], switch(geometry) {
velocity[0] * transported[0] * exp(2*at[2]) - velocity[1] * transported[1] * exp(-2*at[2]), case gSolN:
0 return hpxyz3(
); -(velocity[2] * transported[0] + velocity[0] * transported[2]) * l2,
(velocity[2] * transported[1] + velocity[1] * transported[2]) * l3,
velocity[0] * transported[0] * exp(2*l2*at[2]) * l2 - velocity[1] * transported[1] * exp(-2*l3*at[2]) * l3,
0
);
case gSol:
return hpxyz3(
-velocity[2] * transported[0] - velocity[0] * transported[2],
velocity[2] * transported[1] + velocity[1] * transported[2],
velocity[0] * transported[0] * exp(2*at[2]) - velocity[1] * transported[1] * exp(-2*at[2]),
0
);
case gNIH:
return hpxyz3(
(velocity[2] * transported[0] + velocity[0] * transported[2]) * l2,
(velocity[2] * transported[1] + velocity[1] * transported[2]) * l3,
-(velocity[0] * transported[0] * exp(-2*l2*at[2]) * l2 + velocity[1] * transported[1] * exp(-2*l3*at[2]) * l3),
0
);
default:
throw "christoffel not in solnihv";
}
} }
EX hyperpoint get_inverse_exp(hyperpoint h, bool lazy, bool just_direction) { EX hyperpoint get_inverse_exp_symsol(hyperpoint h, bool lazy, bool just_direction) {
solt.load(); auto& s = get_tabled();
s.load();
ld ix = h[0] >= 0. ? solnihv::x_to_ix(h[0]) : solnihv::x_to_ix(-h[0]); ld ix = h[0] >= 0. ? solnihv::x_to_ix(h[0]) : solnihv::x_to_ix(-h[0]);
ld iy = h[1] >= 0. ? solnihv::x_to_ix(h[1]) : solnihv::x_to_ix(-h[1]); ld iy = h[1] >= 0. ? solnihv::x_to_ix(h[1]) : solnihv::x_to_ix(-h[1]);
@ -410,7 +447,7 @@ EX namespace solv {
if(h[2] < 0.) { iz = -iz; swap(ix, iy); } if(h[2] < 0.) { iz = -iz; swap(ix, iy); }
hyperpoint res = solt.get(ix, iy, iz, lazy); hyperpoint res = s.get(ix, iy, iz, lazy);
if(h[2] < 0.) { swap(res[0], res[1]); res[2] = -res[2]; } if(h[2] < 0.) { swap(res[0], res[1]); res[2] = -res[2]; }
if(h[0] < 0.) res[0] = -res[0]; if(h[0] < 0.) res[0] = -res[0];
@ -425,7 +462,29 @@ EX namespace solv {
return res; return res;
} }
EX string solshader = solnihv::common + EX hyperpoint get_inverse_exp_nsym(hyperpoint h, bool lazy, bool just_direction) {
auto& s = get_tabled();
s.load();
ld ix = h[0] >= 0. ? solnihv::x_to_ix(h[0]) : solnihv::x_to_ix(-h[0]);
ld iy = h[1] >= 0. ? solnihv::x_to_ix(h[1]) : solnihv::x_to_ix(-h[1]);
ld iz = (tanh(h[2]/4)+1)/2;
hyperpoint res = s.get(ix, iy, iz, lazy);
if(h[0] < 0.) res[0] = -res[0];
if(h[1] < 0.) res[1] = -res[1];
if(!just_direction) {
ld r = hypot_d(3, res);
if(r == 0.) return res;
return res * atanh(r) / r;
}
return res;
}
EX string shader_symsol = solnihv::common +
"vec4 inverse_exp(vec4 h) {" "vec4 inverse_exp(vec4 h) {"
@ -456,57 +515,7 @@ EX namespace solv {
"return res;" "return res;"
"}"; "}";
EX int approx_distance(heptagon *h1, heptagon *h2) { EX string shader_nsym = solnihv::common +
auto m = (solnihv::hrmap_solnih*) currentmap;
dynamicval<eGeometry> g(geometry, gBinary4);
dynamicval<hrmap*> cm(currentmap, m->binary_map);
int d1 = binary::celldistance3_approx(m->coords[h1].first, m->coords[h2].first);
int d2 = binary::celldistance3_approx(m->coords[h1].second, m->coords[h2].second);
return d1 + d2 - abs(h1->distance - h2->distance);
}
EX }
EX namespace nihv {
EX solnihv::tabled_inverses niht = solnihv::tabled_inverses("h23-geodesics.dat");
hyperpoint christoffel(const hyperpoint at, const hyperpoint velocity, const hyperpoint transported) {
static const ld l2 = log(2);
static const ld l3 = log(3);
return hpxyz3(
(velocity[2] * transported[0] + velocity[0] * transported[2]) * l2,
(velocity[2] * transported[1] + velocity[1] * transported[2]) * l3,
-(velocity[0] * transported[0] * exp(-2*l2*at[2]) * l2 + velocity[1] * transported[1] * exp(-2*l3*at[2]) * l3),
// (-velocity[2] * transported[0] - velocity[0] * transported[2]) * l2,
// (-velocity[2] * transported[1] - velocity[1] * transported[2]) * l3,
// velocity[0] * transported[0] * exp(2*l2*at[2]) * l2 + velocity[1] * transported[1] * exp(2*l3*at[2]) * l3,
0
);
}
EX hyperpoint get_inverse_exp(hyperpoint h, bool lazy, bool just_direction) {
niht.load();
ld ix = h[0] >= 0. ? solnihv::x_to_ix(h[0]) : solnihv::x_to_ix(-h[0]);
ld iy = h[1] >= 0. ? solnihv::x_to_ix(h[1]) : solnihv::x_to_ix(-h[1]);
ld iz = (tanh(h[2]/4)+1)/2;
hyperpoint res = niht.get(ix, iy, iz, lazy);
if(h[0] < 0.) res[0] = -res[0];
if(h[1] < 0.) res[1] = -res[1];
if(!just_direction) {
ld r = hypot_d(3, res);
if(r == 0.) return res;
return res * atanh(r) / r;
}
return res;
}
EX string nihshader = solnihv::common +
"vec4 inverse_exp(vec4 h) {" "vec4 inverse_exp(vec4 h) {"
@ -527,6 +536,35 @@ EX namespace nihv {
"return res;" "return res;"
"}"; "}";
EX ld solrange_xy = 15;
EX ld solrange_z = 4;
EX bool in_table_range(hyperpoint h) {
return abs(h[0]) < solrange_xy && abs(h[1]) < solrange_xy && abs(h[2]) < solrange_z;
}
EX tabled_inverses solt = solnihv::tabled_inverses("solv-geodesics.dat");
EX tabled_inverses niht = solnihv::tabled_inverses("h23-geodesics.dat");
EX tabled_inverses sont = solnihv::tabled_inverses("sont-geodesics.dat");
EX tabled_inverses& get_tabled() {
switch(geometry) {
case gSol: return solt;
case gNIH: return niht;
case gSolN: return sont;
default: throw "not solnih";
}
}
EX int approx_distance(heptagon *h1, heptagon *h2) {
auto m = (solnihv::hrmap_solnih*) currentmap;
dynamicval<eGeometry> g(geometry, gBinary4);
dynamicval<hrmap*> cm(currentmap, m->binary_map);
int d1 = binary::celldistance3_approx(m->coords[h1].first, m->coords[h2].first);
int d2 = binary::celldistance3_approx(m->coords[h1].second, m->coords[h2].second);
return d1 + d2 - abs(h1->distance - h2->distance);
}
EX } EX }
#endif #endif
@ -1513,8 +1551,7 @@ EX namespace nisot {
EX hyperpoint christoffel(const hyperpoint at, const hyperpoint velocity, const hyperpoint transported) { EX hyperpoint christoffel(const hyperpoint at, const hyperpoint velocity, const hyperpoint transported) {
if(nil) return nilv::christoffel(at, velocity, transported); if(nil) return nilv::christoffel(at, velocity, transported);
#if CAP_SOLV #if CAP_SOLV
else if(sol) return solv::christoffel(at, velocity, transported); else if(solnih) return solnihv::christoffel(at, velocity, transported);
else if(nih) return nihv::christoffel(at, velocity, transported);
#endif #endif
else if(sl2) return slr::christoffel(at, velocity, transported); else if(sl2) return slr::christoffel(at, velocity, transported);
else return point3(0, 0, 0); else return point3(0, 0, 0);
@ -1522,7 +1559,7 @@ EX namespace nisot {
EX bool in_table_range(hyperpoint h) { EX bool in_table_range(hyperpoint h) {
#if CAP_SOLV #if CAP_SOLV
if(solnih) return solv::in_table_range(h); if(sol) return solnihv::in_table_range(h);
#endif #endif
return true; return true;
} }
@ -1625,8 +1662,8 @@ EX namespace nisot {
using namespace arg; using namespace arg;
#if CAP_SOLV #if CAP_SOLV
if(argis("-solrange")) { if(argis("-solrange")) {
shift_arg_formula(solv::solrange_xy); shift_arg_formula(solnihv::solrange_xy);
shift_arg_formula(solv::solrange_z); shift_arg_formula(solnihv::solrange_z);
return 0; return 0;
} }
#endif #endif
@ -1636,11 +1673,11 @@ EX namespace nisot {
} }
#if CAP_SOLV #if CAP_SOLV
else if(argis("-fsol")) { else if(argis("-fsol")) {
shift(); solv::solt.fname = args(); shift(); solnihv::solt.fname = args();
return 0; return 0;
} }
else if(argis("-nihsol")) { else if(argis("-nihsol")) {
shift(); nihv::niht.fname = args(); shift(); solnihv::niht.fname = args();
return 0; return 0;
} }
#endif #endif

View File

@ -1014,6 +1014,21 @@ void geometry_information::create_wall3d() {
} }
} }
if(geometry == gSolN) {
ld zstep = -.5;
ld bwh = vid.binary_width / 6;
auto pt = [&] (int x, int y, int z) { return xpush(bwh*x) * ypush(bwh*y) * zpush(zstep*z) * C0; };
make_wall(0, {pt(+3,-3,-1), pt(+3,-3,+1), pt(+3,-1,+1), pt(+3,+1,+1), pt(+3,+3,+1), pt(+3,+3,-1)});
make_wall(1, {pt(-3,+3,-1), pt(00,+3,-1), pt(+3,+3,-1), pt(+3,+3,+1), pt(-3,+3,+1)});
make_wall(2, {pt(-3,-3,-1), pt(-3,-3,+1), pt(-3,-1,+1), pt(-3,+1,+1), pt(-3,+3,+1), pt(-3,+3,-1)});
make_wall(3, {pt(-3,-3,-1), pt(00,-3,-1), pt(+3,-3,-1), pt(+3,-3,+1), pt(-3,-3,+1)});
make_wall(4, {pt(-3,+3,-1), pt(-3,-3,-1), pt(00,-3,-1), pt(00,+3,-1)});
make_wall(5, {pt(00,+3,-1), pt(00,-3,-1), pt(+3,-3,-1), pt(+3,+3,-1)});
make_wall(6, {pt(-3,-3,+1), pt(+3,-3,+1), pt(+3,-1,+1), pt(-3,-1,+1)});
make_wall(7, {pt(-3,-1,+1), pt(+3,-1,+1), pt(+3,+1,+1), pt(-3,+1,+1)});
make_wall(8, {pt(-3,+1,+1), pt(+3,+1,+1), pt(+3,+3,+1), pt(-3,+3,+1)});
}
if(geometry == gNil) { if(geometry == gNil) {
for(int i=0; i<S7; i++) make_wall(i, nilv::facevertices[i]); for(int i=0; i<S7; i++) make_wall(i, nilv::facevertices[i]);
} }

View File

@ -757,8 +757,8 @@ void init() {
1, " }", 1, " }",
#if CAP_SOLV #if CAP_SOLV
ssol, solv::solshader, ssol, solnihv::shader_symsol,
snih, nihv::nihshader, snih, solnihv::shader_nsym,
#endif #endif
snil, nilv::nilshader, snil, nilv::nilshader,
ssl2, slr::slshader, ssl2, slr::slshader,