inverse tessellation operators

This commit is contained in:
Zeno Rogue 2020-07-12 20:52:32 +02:00
parent db96f3499c
commit 1f1e7d9bbf
13 changed files with 478 additions and 76 deletions

View File

@ -219,6 +219,9 @@ EX cell *createMov(cell *c, int d) {
}
hybrid::link();
}
else if(INVERSE) {
return gp::inverse_move(c, d);
}
#endif
#if CAP_ARCM
else if(arcm::in() && PURE) {
@ -289,7 +292,8 @@ EX void initcells() {
DEBB(DF_INIT, ("initcells"));
hrmap* res = callhandlers((hrmap*)nullptr, hooks_newmap);
if(res) currentmap = res;
if(res) currentmap = res;
else if(INVERSE) currentmap = gp::new_inverse();
else if(fake::in()) currentmap = fake::new_map();
else if(asonov::in()) currentmap = asonov::new_map();
else if(nonisotropic || hybri) currentmap = nisot::new_map();
@ -475,6 +479,11 @@ EX int celldist(cell *c) {
#endif
if(arcm::in() || ctof(c)) return c->master->distance;
#if CAP_GP
if(INVERSE) {
cell *c1 = gp::get_mapped(c);
return UIU(gp::compute_dist(c1, celldist)) / 2;
/* TODO */
}
if(GOLDBERG) return gp::compute_dist(c, celldist);
#endif
int dx[MAX_S3];

View File

@ -737,7 +737,7 @@ enum eGeometry {
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, untruncated, warped, unrectified };
typedef flagtype modecode_t;

View File

@ -3558,7 +3558,7 @@ EX namespace windmap {
// cw.spin = 0;
neighbors.emplace_back();
auto &v = neighbors.back();
if(NONSTDVAR && !sphere && !arcm::in() && !hybri)
if(NONSTDVAR && !sphere && !arcm::in() && !hybri && !INVERSE)
for(int l=0; l<S7; l++) {
v.push_back(getId(cw + cth + l + wstep + cth));
}

View File

@ -675,7 +675,7 @@ void geometry_information::generate_floorshapes() {
}
#endif
else if(GOLDBERG) { /* will be generated on the fly */ }
else if(GOLDBERG_INV) { /* will be generated on the fly */ }
else if(inforder::mixed()) { /* will be generated on the fly */ }
@ -800,22 +800,38 @@ EX namespace gp {
int get_plainshape_id(cell *c) {
int siid, sidir;
if(geosupport_threecolor() == 2) {
auto si = patterns::getpatterninfo(c, patterns::PAT_COLORING, patterns::SPF_NO_SUBCODES);
siid = si.id>>2;
// if(siid == 2) si.dir++;
// if(siid != pattern_threecolor(c)) printf("threecolor mismatch\n");
// if(pattern_threecolor(createMov(c, c->fixd(si.dir))) != (siid+1)%3) printf("threecolor mismatch direction\n");
sidir = c->c.fix(si.dir);
cell *c1 = c;
auto f = [&] {
if(geosupport_threecolor() == 2) {
auto si = patterns::getpatterninfo(c1, patterns::PAT_COLORING, patterns::SPF_NO_SUBCODES);
siid = si.id>>2;
// if(siid == 2) si.dir++;
// if(siid != pattern_threecolor(c)) printf("threecolor mismatch\n");
// if(pattern_threecolor(createMov(c, c->fixd(si.dir))) != (siid+1)%3) printf("threecolor mismatch direction\n");
sidir = c1->c.fix(si.dir);
}
else if(geosupport_football() == 2) {
siid = !pseudohept(c1);
sidir = !ishex1(c1);
}
else if(geosupport_chessboard()) {
siid = !chessvalue(c1);
sidir = 0;
}
else {
siid = 0;
sidir = 0;
}
};
if(INVERSE && gp::variation_for(gp::param) == eVariation::goldberg) {
c1 = gp::get_mapped(c);
UIU(f());
}
else if(geosupport_football() == 2) {
siid = !pseudohept(c);
sidir = !ishex1(c);
}
else {
else if(INVERSE) {
siid = 0;
sidir = 0;
}
else f();
auto& id = cgi.gpdata->pshid[siid][sidir][draw_li.relative.first&31][draw_li.relative.second&31][gmod(draw_li.total_dir, S6)];
if(id == -1 && sphere && isize(cgi.shFloor.b) > 0) {
forCellEx(c1, c) if(!gmatrix0.count(c1)) return 0;
@ -862,7 +878,7 @@ EX int shvid(cell *c) {
cell *c1 = hybrid::get_where(c).first;
return PIU( shvid(c1) );
}
else if(GOLDBERG)
else if(GOLDBERG_INV)
return gp::get_plainshape_id(c);
else if(IRREGULAR)
return irr::cellindex[c];

View File

@ -1081,6 +1081,18 @@ int read_geom_args() {
shift(); gp::param.second = argi();
set_variation(eVariation::goldberg);
}
else if(argis("-unrectified")) {
PHASEFROM(2);
set_variation(eVariation::unrectified);
}
else if(argis("-untruncated")) {
PHASEFROM(2);
set_variation(eVariation::untruncated);
}
else if(argis("-warped")) {
PHASEFROM(2);
set_variation(eVariation::warped);
}
#endif
#if CAP_FIELD
else if(argis("-fi")) {

View File

@ -487,6 +487,13 @@ void geometry_information::prepare_basics() {
if(arcm::in() && !prod)
ginf[gArchimedean].cclass = gcHyperbolic;
dynamicval<eVariation> gv(variation, variation);
bool inv = INVERSE;
if(INVERSE) {
variation = gp::variation_for(gp::param);
println(hlog, "bitruncated = ", BITRUNCATED);
}
if(hybri) {
auto t = this;
@ -582,7 +589,7 @@ void geometry_information::prepare_basics() {
base_distlimit = ginf[geometry].distlimit[!BITRUNCATED];
#if CAP_GP
gp::compute_geometry();
gp::compute_geometry(inv);
#endif
#if CAP_IRR
irr::compute_geometry();
@ -1014,7 +1021,7 @@ EX string cgi_string() {
return s;
}
if(GOLDBERG) V("GP", its(gp::param.first) + "," + its(gp::param.second));
if(GOLDBERG_INV) V("GP", its(gp::param.first) + "," + its(gp::param.second));
if(IRREGULAR) V("IRR", its(irr::irrid));
if(arcm::in()) V("ARCM", arcm::current.symbol);

View File

@ -501,6 +501,37 @@ EX hyperpoint randomPointIn(int t) {
EX hyperpoint get_corner_position(cell *c, int cid, ld cf IS(3)) {
#if CAP_GP
if(GOLDBERG) return gp::get_corner_position(c, cid, cf);
if(UNTRUNCATED) {
cell *c1 = gp::get_mapped(c);
cellwalker cw(c1, cid*2);
if(!gp::untruncated_shift(c)) cw--;
hyperpoint h = UIU(nearcorner(c1, cw.spin));
return mid_at_actual(h, 3/cf);
}
if(UNRECTIFIED) {
cell *c1 = gp::get_mapped(c);
hyperpoint h = UIU(nearcorner(c1, cid));
return mid_at_actual(h, 3/cf);
}
if(WARPED) {
int sh = gp::untruncated_shift(c);
cell *c1 = gp::get_mapped(c);
if(sh == 2) {
cellwalker cw(c, cid);
hyperpoint h1 = UIU(tC0(currentmap->adj(c1, cid)));
cw--;
hyperpoint h2 = UIU(tC0(currentmap->adj(c1, cw.spin)));
hyperpoint h = mid(h1, h2);
return mid_at_actual(h, 3/cf);
}
else {
cellwalker cw(c1, cid*2);
if(!gp::untruncated_shift(c)) cw--;
hyperpoint h = UIU(nearcorner(c1, cw.spin));
h = mid(h, C0);
return mid_at_actual(h, 3/cf);
}
}
#endif
#if CAP_IRR
if(IRREGULAR) {
@ -560,7 +591,7 @@ EX bool approx_nearcorner = false;
/** /brief get the coordinates of the center of c->move(i) */
EX hyperpoint nearcorner(cell *c, int i) {
if(GOLDBERG) {
if(GOLDBERG_INV) {
cellwalker cw(c, i);
cw += wstep;
transmatrix cwm = currentmap->adj(c, i);
@ -657,14 +688,19 @@ EX hyperpoint nearcorner(cell *c, int i) {
EX hyperpoint farcorner(cell *c, int i, int which) {
#if CAP_GP
if(GOLDBERG) {
if(GOLDBERG_INV) {
cellwalker cw(c, i);
cw += wstep;
if(!cw.mirrored) cw += (which?-1:2);
else cw += (which?2:-1);
transmatrix cwm = currentmap->adj(c, i);
auto li1 = gp::get_local_info(cw.at);
return cwm * get_corner_position(li1, cw.spin);
if(gp::variation_for(gp::param) == eVariation::goldberg) {
auto li1 = gp::get_local_info(cw.at);
return cwm * get_corner_position(li1, cw.spin);
}
else {
return cwm * get_corner_position(cw.at, cw.spin, 3);
}
}
#endif
#if CAP_IRR

View File

@ -10,6 +10,11 @@
#include "hyper.h"
namespace hr {
#if HDR
struct hrmap;
extern hrmap *currentmap;
#endif
EX namespace gp {
#if HDR
@ -34,6 +39,15 @@ EX namespace gp {
loc operator*(int i) {
return loc(first*i, second*i);
}
int operator %(int i) {
return gmod(first, i) + gmod(second, i);
}
loc operator /(int i) {
return loc(first/i, second/i);
}
};
struct local_info {
@ -96,6 +110,10 @@ EX namespace gp {
}
EX local_info get_local_info(cell *c) {
if(INVERSE) {
c = get_mapped(c);
return UIU(get_local_info(c));
}
local_info li;
if(c == c->master->c7) {
li.relative = loc(0,0);
@ -609,9 +627,9 @@ EX namespace gp {
map<pair<int, int>, loc> center_locs;
EX void compute_geometry() {
EX void compute_geometry(bool inv) {
center_locs.clear();
if(GOLDBERG) {
if(GOLDBERG_INV || inv) {
if(!cgi.gpdata) cgi.gpdata = make_shared<geometry_information::gpdata_t>();
gp::clear_plainshapes();
int x = param.first;
@ -622,6 +640,7 @@ EX namespace gp {
cgi.gpdata->area = x * x + y * y;
next = point3(x+y/2., -y * sqrt(3) / 2, 0);
ld scale = 1 / hypot_d(2, next);
if(!GOLDBERG) scale = 1;
cgi.crossf *= scale;
cgi.hepvdist *= scale;
cgi.hexhexdist *= scale;
@ -662,6 +681,14 @@ EX namespace gp {
return v;
}
EX eVariation variation_for(loc xy) {
if(xy.first == 1 && xy.second == 0)
return eVariation::pure;
if(xy.first == 1 && xy.second == 1 && S3 == 3)
return eVariation::bitruncated;
return eVariation::goldberg;
}
void whirl_set(loc xy) {
xy = internal_representation(xy);
if(xy.second && xy.second != xy.first && nonorientable) {
@ -713,31 +740,56 @@ EX namespace gp {
}
#endif
if(min_quality == 0 && min_quality_chess == 0) {
dialog::addBoolItem(XLAT("pure"), univ_param() == loc(1,0) && !IRREGULAR, 'a');
dialog::addBoolItem(XLAT("pure"), PURE || (GOLDBERG && univ_param() == loc(1,0)), 'a');
dialog::lastItem().value = "GP(1,0)";
dialog::add_action_confirmed([] { whirl_set(loc(1, 0)); });
}
if(min_quality_chess == 0)
if(min_quality_chess == 0) {
dialog::addBoolItem(XLAT("bitruncated"), BITRUNCATED, 'b');
dialog::add_action_confirmed([] {
if(S3 == 4) {
if(!BITRUNCATED) {
stop_game();
set_variation(eVariation::bitruncated);
start_game();
}
}
else
whirl_set(loc(1, 1));
});
}
dialog::lastItem().value = S3 == 3 ? "GP(1,1)" : XLAT(BITRUNCATED ? "ON" : "OFF");
if(min_quality == 0 || min_quality_chess) {
dialog::addBoolItem(XLAT(S3 == 3 ? "chamfered" : "expanded"), univ_param() == loc(2,0), 'c');
dialog::addBoolItem(XLAT(S3 == 3 ? "chamfered" : "expanded"), univ_param() == loc(2,0) && GOLDBERG, 'c');
dialog::lastItem().value = "GP(2,0)";
dialog::add_action_confirmed([] {
whirl_set(loc(2, 0));
});
}
if(S3 == 3) {
dialog::addBoolItem(XLAT("2x bitruncated"), univ_param() == loc(3,0), 'd');
dialog::addBoolItem(XLAT("2x bitruncated"), GOLDBERG && univ_param() == loc(3,0), 'd');
dialog::lastItem().value = "GP(3,0)";
dialog::add_action_confirmed([] {
whirl_set(loc(3, 0));
});
}
else {
dialog::addBoolItem(XLAT("rectified"), param == loc(1,1) && GOLDBERG, 'd');
dialog::lastItem().value = "GP(1,1)";
dialog::add_action_confirmed([] {
whirl_set(loc(1, 1));
});
}
dialog::addBreak(100);
dialog::addSelItem("x", its(config.first), 'x');
dialog::add_action([] { dialog::editNumber(config.first, 0, 8, 1, 1, "x", helptext()); });
dialog::addSelItem("y", its(config.second), 'y');
dialog::add_action([] { dialog::editNumber(config.second, 0, 8, 1, 1, "y", helptext()); });
if(config.second && config.second != config.first && nonorientable) {
dialog::addInfo(XLAT("This does not work in non-orientable geometries"));
@ -748,6 +800,9 @@ EX namespace gp {
dialog::addInfo(XLAT("This pattern needs x-y divisible by 2"));
else
dialog::addBoolItem(XLAT("select"), param == internal_representation(config) && !IRREGULAR, 'f');
dialog::add_action_confirmed([] { whirl_set(config); });
dialog::addBreak(100);
if(irr::supports(geometry)) {
dialog::addBoolItem(XLAT("irregular"), IRREGULAR, 'i');
@ -760,52 +815,81 @@ EX namespace gp {
if(!IRREGULAR) irr::visual_creator();
}));
}
dialog::addBreak(100);
int style = 0;
auto v0 = variation_for(param);
bool bad_bi = BITRUNCATED && a4;
if(!bad_bi) {
dynamicval<eVariation> v(variation, v0);
if(geosupport_football() == 2) style = 3;
if(geosupport_chessboard()) style = 2;
}
if(style == 2) {
dialog::addBoolItem(XLAT("inverse rectify"), UNRECTIFIED, 'r');
dialog::add_action_confirmed([v0] {
if(UNRECTIFIED) set_variation(v0);
else set_variation(eVariation::unrectified);
start_game();
});
}
else if(style == 3) {
dialog::addBoolItem(XLAT("inverse truncate"), UNTRUNCATED, 't');
dialog::add_action_confirmed([v0] {
if(UNTRUNCATED) set_variation(v0);
else set_variation(eVariation::untruncated);
start_game();
});
dialog::addBoolItem(XLAT("warped version"), WARPED, 'w');
dialog::add_action_confirmed([v0] {
if(WARPED) set_variation(v0);
else set_variation(eVariation::warped);
start_game();
});
}
dialog::addBreak(100);
dialog::addItem(XLAT("swap x and y"), 'z');
dialog::add_action([] { swap(config.first, config.second); });
bool have_dual = !bad_bi && !IRREGULAR && !WARPED;
if(S3 == 3 && UNTRUNCATED && (univ_param()*loc(1,1)) % 3) have_dual = false;
if(S3 == 4 && UNRECTIFIED && (univ_param()*loc(1,1)) % 2) have_dual = false;
if(have_dual) {
dialog::addItem(XLAT("dual of current"), 'D');
dialog::add_action([] {
auto p = univ_param();
if(S3 == 3 && !UNTRUNCATED) {
println(hlog, "set param to ", p * loc(1,1));
whirl_set(p * loc(1, 1));
set_variation(eVariation::untruncated);
start_game();
}
else if(S3 == 4 && !UNRECTIFIED) {
whirl_set(p * loc(1, 1));
set_variation(eVariation::unrectified);
start_game();
}
else if(S3 == 3 && UNTRUNCATED) {
println(hlog, "whirl_set to ", (p * loc(1,1)) / 3);
whirl_set((p * loc(1,1)) / 3);
}
else if(S3 == 4 && UNRECTIFIED) {
whirl_set((p * loc(1,1)) / 2);
}
});
}
dialog::addBreak(100);
dialog::addHelp();
dialog::add_action([] { gotoHelp(helptext()); });
dialog::addBack();
dialog::display();
keyhandler = [] (int sym, int uni) {
dialog::handleNavigation(sym, uni);
if(uni == 'a') dialog::do_if_confirmed([] {
whirl_set(loc(1, 0));
});
else if(uni == 'b') dialog::do_if_confirmed([] {
if(S3 == 4) {
if(!BITRUNCATED) {
stop_game();
set_variation(eVariation::bitruncated);
start_game();
}
}
else
whirl_set(loc(1, 1));
});
else if(uni == 'c') dialog::do_if_confirmed([] {
whirl_set(loc(2, 0));
});
else if(uni == 'd') dialog::do_if_confirmed([] {
whirl_set(S3 == 3 ? loc(3, 0) : loc(1,1));
});
else if(uni == 'f') dialog::do_if_confirmed([] {
whirl_set(config);
});
else if(uni == 'x')
dialog::editNumber(config.first, 0, 8, 1, 1, "x", helptext());
else if(uni == 'y')
dialog::editNumber(config.second, 0, 8, 1, 1, "y", helptext());
else if(uni == 'z')
swap(config.first, config.second);
else if(uni == '?' || sym == SDLK_F1 || uni == 'h' || uni == '2')
gotoHelp(helptext());
else if(doexiton(sym, uni))
popScreen();
};
}
EX loc univ_param() {
if(GOLDBERG) return param;
if(GOLDBERG_INV) return param;
else if(PURE) return loc(1,0);
else return loc(1,1);
}
@ -892,6 +976,7 @@ EX namespace gp {
}
EX int compute_dist(cell *c, int master_function(cell*)) {
if(!GOLDBERG) return master_function(c);
auto li = get_local_info(c);
be_in_triangle(li);
@ -934,6 +1019,10 @@ EX namespace gp {
EX array<heptagon*, 3> get_masters(cell *c) {
if(0);
#if CAP_GP
else if(INVERSE) {
c = get_mapped(c);
return UIU(get_masters(c));
}
else if(GOLDBERG) {
auto li = get_local_info(c);
be_in_triangle(li);
@ -963,23 +1052,232 @@ EX namespace gp {
else if(BITRUNCATED)
return XLAT("bitruncated");
#if CAP_GP
else if(param == loc(1, 0))
else if(GOLDBERG && param == loc(1, 0))
return XLAT("pure");
else if(param == loc(1, 1) && S3 == 3)
else if(GOLDBERG && param == loc(1, 1) && S3 == 3)
return XLAT("bitruncated");
else if(param == loc(1, 1) && S3 == 4)
else if(GOLDBERG && param == loc(1, 1) && S3 == 4)
return XLAT("rectified");
else if(param == loc(2, 0))
else if(UNRECTIFIED && param == loc(1, 1) && S3 == 4)
return XLAT("dual");
else if(UNTRUNCATED && param == loc(1, 1) && S3 == 3)
return XLAT("dual");
else if(GOLDBERG && param == loc(2, 0))
return S3 == 3 ? XLAT("chamfered") : XLAT("expanded");
else if(param == loc(3, 0) && S3 == 3)
else if(GOLDBERG && param == loc(3, 0) && S3 == 3)
return XLAT("2x bitruncated");
else {
auto p = human_representation(param);
return "GP(" + its(p.first) + "," + its(p.second) + ")";
string s = "GP(" + its(p.first) + "," + its(p.second) + ")";
if(UNRECTIFIED) return XLAT("unrectified") + " " + s;
if(WARPED) return XLAT("warped") + " " + s;
if(UNTRUNCATED) return XLAT("untruncated") + " " + s;
return s;
}
#else
else return "UNSUPPORTED";
#endif
}
/* inverse map */
EX hrmap *pmap;
// EX geometry_information *underlying_cgip;
struct hrmap_inverse : hrmap {
hrmap *underlying_map;
map<cell*, cell*> mapping;
map<cell*, int> shift;
template<class T> auto in_underlying(const T& t) -> decltype(t()) {
dynamicval<hrmap*> gpm(pmap, this);
dynamicval<eVariation> gva(variation, variation_for(param));
dynamicval<hrmap*> gu(currentmap, underlying_map);
// dynamicval<geometry_information*> gc(cgip, underlying_cgip);
return t();
}
cell* get_mapped(cell *underlying_cell, int set_shift) {
if(mapping.count(underlying_cell))
return mapping[underlying_cell];
int d = underlying_cell->type;
if(UNTRUNCATED) d /= 2;
if(WARPED && set_shift < 2) d /= 2;
cell *c = newCell(d, underlying_cell->master);
mapping[underlying_cell] = c;
if(!UNRECTIFIED) shift[c] = set_shift;
mapping[c] = underlying_cell;
return c;
}
~hrmap_inverse() {
in_underlying([this] { delete underlying_map; });
}
heptagon *getOrigin() override { return in_underlying([this] { return underlying_map->getOrigin(); }); }
cell *gs;
cell* gamestart() override {
return gs;
}
hrmap_inverse() {
if(0) {
println(hlog, "making ucgi");
dynamicval<eVariation> gva(variation, variation_for(param));
check_cgi();
cgi.require_basics();
// underlying_cgip = cgip;
println(hlog, "done ucgi");
}
bool warped = WARPED;
in_underlying([&,this] {
initcells();
underlying_map = currentmap;
gs = currentmap->gamestart();
if(!warped) gs = gs->cmove(0);
});
if(UNTRUNCATED) gs = get_mapped(gs, 1);
else gs = get_mapped(gs, 2);
for(hrmap*& m: allmaps) if(m == underlying_map) m = NULL;
}
cell *create_move(cell *parent, int d) {
if(UNRECTIFIED) {
cellwalker cw(mapping[parent], d);
in_underlying([&] {
cw += wstep;
cw --;
cw += wstep;
cw --;
});
cw.at = get_mapped(cw.at, 0);
parent->c.connect(d, cw.at, cw.spin, cw.mirrored);
return cw.at;
}
if(UNTRUNCATED) {
cellwalker cw(mapping[parent], 2*d+shift[parent]);
in_underlying([&] {
cw += wstep;
});
cw.at = get_mapped(cw.at, cw.spin & 1);
parent->c.connect(d, cw.at, cw.spin / 2, cw.mirrored);
return cw.at;
}
if(WARPED) {
int sh = shift[parent];
if(sh == 2) {
cellwalker cw(mapping[parent], d);
in_underlying([&] { cw += wstep; });
cw.at = get_mapped(cw.at, cw.spin & 1);
parent->c.connect(d, cw.at, cw.spin / 2, cw.mirrored);
return cw.at;
}
else {
cellwalker cw(mapping[parent], 2*d+sh);
in_underlying([&] {
cw += wstep;
});
cw.at = get_mapped(cw.at, 2);
parent->c.connect(d, cw.at, cw.spin, cw.mirrored);
return cw.at;
}
}
throw "unimplemented";
}
transmatrix adj(cell *c, int d) override {
transmatrix T;
if(UNRECTIFIED) {
cellwalker cw(mapping[c], d);
in_underlying([&] {
T = currentmap->adj(cw.at, cw.spin);
cw += wstep;
cw --;
T = T * currentmap->adj(cw.at, cw.spin);
});
}
if(UNTRUNCATED) {
cellwalker cw(mapping[c], 2*d+shift[c]);
in_underlying([&] { T = currentmap->adj(cw.at, cw.spin); });
}
if(WARPED) {
int sh = shift[c];
if(sh == 2) {
auto c1 = mapping[c];
in_underlying([&] { T = currentmap->adj(c1, d); });
}
else {
cellwalker cw(mapping[c], 2*d+shift[c]);
in_underlying([&] { T = currentmap->adj(cw.at, cw.spin); });
}
}
return T;
}
void draw() override {
dq::clear_all();
auto enqueue = (quotient ? dq::enqueue_by_matrix_c : dq::enqueue_c);
enqueue(centerover, cview());
while(!dq::drawqueue_c.empty()) {
auto& p = dq::drawqueue_c.front();
cell *c = get<0>(p);
transmatrix V = get<1>(p);
dynamicval<ld> b(band_shift, get<2>(p));
bandfixer bf(V);
auto c1 = get_mapped(c, 0);
in_underlying([&] {
if(GOLDBERG) {
gp::draw_li = gp::get_local_info(c1);
}
else {
gp::draw_li.relative.first = shvid(c1);
gp::draw_li.relative.second = shift[c];
}
});
dq::drawqueue_c.pop();
if(!do_draw(c, V)) continue;
drawcell(c, V);
for(int i=0; i<c->type; i++) if(c->cmove(i))
enqueue(c->move(i), V * adj(c, i));
}
}
};
EX hrmap* new_inverse() { return new hrmap_inverse; }
hrmap_inverse* inv_map() { return (hrmap_inverse*)currentmap; }
EX hrmap* get_underlying_map() { return inv_map()->underlying_map; }
EX cell* get_mapped(cell *c) { return inv_map()->get_mapped(c, 0); }
EX int untruncated_shift(cell *c) { return inv_map()->shift[c]; }
EX cell *inverse_move(cell *c, int d) { return inv_map()->create_move(c, d); }
#if HDR
template<class T> auto in_underlying_geometry(const T& f) -> decltype(f()) {
if(!INVERSE) return f();
dynamicval<hrmap*> gpm(pmap, currentmap);
dynamicval<eVariation> gva(variation, variation_for(param));
dynamicval<hrmap*> gu(currentmap, get_underlying_map());
// dynamicval<geometry_information*> gc(cgip, underlying_cgip);
return f();
}
#define UIU(x) hr::gp::in_underlying_geometry([&] { return (x); })
#endif
}}

View File

@ -176,6 +176,14 @@ void addMessage(string s, char spamtype = 0);
#define SG3 (S3==3?3:2)
#define SG2 (S3==3?2:1)
#define GOLDBERG_INV (GOLDBERG || INVERSE)
#define INVERSE among(variation, eVariation::unrectified, eVariation::warped, eVariation::untruncated )
#define UNRECTIFIED (variation == eVariation::unrectified)
#define WARPED (variation == eVariation::warped)
#define UNTRUNCATED (variation == eVariation::untruncated)
#define GOLDBERG (variation == eVariation::goldberg)
#define IRREGULAR (variation == eVariation::irregular)
#define PURE (variation == eVariation::pure)

View File

@ -278,7 +278,7 @@ EX bool haveOrbPower() {
cell *c = dcal[i];
if(itemclass(c->item) == IC_ORB) return true;
}
else if(sphere_narcm && WDIM == 2) for(int i=0; i<spherecells(); i++) {
else if(sphere_narcm && WDIM == 2 && !INVERSE) for(int i=0; i<spherecells(); i++) {
cell *c = getDodecahedron(i)->c7;
if(itemclass(c->item) == IC_ORB) return true;
forCellEx(c2, c) if(itemclass(c2->item) == IC_ORB) return true;

View File

@ -86,6 +86,11 @@ EX int chessvalue(cell *c) {
if(arcm::in())
return arcm::chessvalue(c);
else
#endif
#if CAP_GP
if(WARPED)
return gp::untruncated_shift(c) == 2;
else
#endif
return celldist(c) & 1;
}
@ -269,7 +274,7 @@ EX int fiftyval200(cell *c) {
// zebraval
int dir_bitrunc457(cell *c) {
if(GOLDBERG) return c->master->zebraval / 10;
if(GOLDBERG_INV) return c->master->zebraval / 10;
int wset = 0;
int has1 = 0;
for(int i=0; i<4; i++) {
@ -291,6 +296,10 @@ int val46(cell *c);
EX int zebra40(cell *c) {
if(euclid) return pattern_threecolor(c);
else if(IRREGULAR) return c->master->zebraval/10;
else if(INVERSE) {
cell *c1 = gp::get_mapped(c);
return UIU(zebra40(c1));
}
else if(a46) {
int v = val46(c);
if(v<4) return v;
@ -384,7 +393,7 @@ EX int fieldval_uniq(cell *c) {
else if(IRREGULAR) return irr::cellindex[c];
#endif
#if CAP_GP
else if(GOLDBERG) return (get_code(gp::get_local_info(c)) << 8) | (c->master->fieldval / S7);
else if(GOLDBERG_INV) return (get_code(gp::get_local_info(c)) << 8) | (c->master->fieldval / S7);
#endif
if(ctof(c)) return c->master->fieldval;
else return createMov(c, 0)->master->fieldval + 256 * createMov(c,2)->master->fieldval + (1<<16) * createMov(c,4)->master->fieldval;
@ -1228,6 +1237,8 @@ EX bool geosupport_chessboard() {
(arcm::in() && PURE) ? arcm::current.support_chessboard() :
(arcm::in() && DUAL) ? arcm::current.support_threecolor_bitruncated() :
#endif
WARPED ? true :
INVERSE ? false :
(bt::in() || kite::in()) ? 0 :
(S3 >= OINF) ? true :
(valence() % 2 == 0);
@ -1241,6 +1252,7 @@ EX int geosupport_threecolor() {
if(arcm::in() && BITRUNCATED) return arcm::current.support_threecolor_bitruncated();
if(arcm::in() && DUAL) return 0; // it sometimes does support threecolor, but it can be obtained in other ways then
#endif
if(INVERSE) return 0;
if(BITRUNCATED && S3 == 3) {
if(S7 % 2) return 1;
return 2;
@ -1256,6 +1268,7 @@ EX int geosupport_threecolor() {
EX int geosupport_football() {
// always works in bitrunc geometries
if(BITRUNCATED) return 2;
if(INVERSE) return 0;
if(bt::in() || kite::in()) return 0;
#if CAP_ARCM
@ -1431,6 +1444,7 @@ EX bool pseudohept(cell *c) {
#endif
if(arb::in()) return arb::pseudohept(c);
#if CAP_GP
if(INVERSE) return false;
if(GOLDBERG && gp_threecolor() == 2)
return gp::pseudohept_val(c) == 0;
if(GOLDBERG && gp_threecolor() == 1 && (S7&1) && (S3 == 3))

View File

@ -167,6 +167,7 @@ struct hrmap_spherical : hrmap_standard {
#endif
swap(gmatrix, gmatrix0);
just_gmatrix = true;
dynamicval<cell*> cco(centerover, gamestart());
draw();
just_gmatrix = false;
swap(gmatrix, gmatrix0);

View File

@ -968,6 +968,7 @@ EX void saveStats(bool emergency IS(false)) {
if(dpgen::in) return;
if(experimental) return;
if(ginf[geometry].xcode == no_code) return;
if(INVERSE) return;
if(!gold()) return;
remove_emergency_save();