refactored map functions: ddspin, iddspin, spacedist, spin_angle, virtualRebase[simple], adj

This commit is contained in:
Zeno Rogue 2019-11-14 16:51:50 +01:00
parent 4e534261f0
commit aeaaf7586a
15 changed files with 279 additions and 365 deletions

View File

@ -555,7 +555,7 @@ struct hrmap_archimedean : hrmap {
dynamicval<eGeometry> g(geometry, gNormal);
dynamicval<hrmap*> cm(currentmap, current_altmap);
U = T;
virtualRebaseSimple(alt, T);
current_altmap->virtualRebase(alt, T);
U = U * inverse(T);
}
@ -655,7 +655,21 @@ struct hrmap_archimedean : hrmap {
}
return gm * where;
}
ld spin_angle(cell *c, int d) {
if(PURE) {
auto& t1 = arcm::current.get_triangle(c->master, d-1);
return -(t1.first + M_PI / c->type);
}
else if(DUAL) {
auto& t1 = arcm::current.get_triangle(c->master, 2*d);
return -t1.first;
}
else { /* BITRUNCATED */
auto& t1 = arcm::current.get_triangle(c->master, d);
return -t1.first;
}
}
};
EX hrmap *new_map() { return new hrmap_archimedean; }

View File

@ -586,7 +586,7 @@ EX void resetGL() {
}
#endif
check_cgi();
cgi.require_shapes();
if(currentmap) cgi.require_shapes();
#if MAXMDIM >= 4
if(GDIM == 3 && !floor_textures) make_floor_textures();
#endif

View File

@ -192,6 +192,8 @@ EX namespace binary {
int nextdir(int choices) { return directions_generator() % choices; }
heptagon *getOrigin() override { return origin; }
hrmap_binary() {
set_seed();
origin = hyperbolic_origin();
@ -427,58 +429,38 @@ EX namespace binary {
if(!do_draw(c, V)) continue;
drawcell(c, V);
if(geometry == gBinaryTiling) {
dq::enqueue(h->move(bd_up), V * xpush(-log(2)));
dq::enqueue(h->move(bd_right), V * parabolic(1));
dq::enqueue(h->move(bd_left), V * parabolic(-1));
if(c->type == 6)
dq::enqueue(h->move(bd_down), V * xpush(log(2)));
if(c->type == 7) {
dq::enqueue(h->move(bd_down_left), V * parabolic(-1) * xpush(log(2)));
dq::enqueue(h->move(bd_down_right), V * parabolic(1) * xpush(log(2)));
}
}
else {
for(int i=0; i<S7; i++)
dq::enqueue(h->move(i), V * tmatrix(h, i));
}
for(int i=0; i<h->type; i++)
dq::enqueue(h->cmove(i), V * adj(h, i));
}
}
// hrmap_standard overrides hrmap's default, override it back
virtual transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override {
return relative_matrix(c2->master, c1->master);
}
int updir_at(heptagon *h) {
if(geometry != gBinaryTiling) return updir();
else if(type_of(h) == 6) return bd_down;
else if(mapside(h) == 1) return bd_left;
else if(mapside(h) == -1) return bd_right;
else throw "unknown updir";
}
transmatrix relative_matrix(heptagon *h2, heptagon *h1) override {
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7))
return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7];
transmatrix gm = Id, where = Id;
while(h1 != h2) {
int up_step = updir();
if(h1->distance <= h2->distance) {
if(geometry != gBinaryTiling)
where = itmatrix(h2, up_step) * where, h2 = may_create_step(h2, up_step);
else {
if(type_of(h2) == 6)
h2 = may_create_step(h2, bd_down), where = xpush(-log(2)) * where;
else if(mapside(h2) == 1)
h2 = may_create_step(h2, bd_left), where = parabolic(+1) * where;
else if(mapside(h2) == -1)
h2 = may_create_step(h2, bd_right), where = parabolic(-1) * where;
}
int d = updir_at(h2);
where = iadj(h2, d) * where;
h2 = may_create_step(h2, d);
}
else {
if(geometry != gBinaryTiling)
gm = gm * tmatrix(h1, up_step), h1 = may_create_step(h1, up_step);
else {
if(type_of(h1) == 6)
h1 = may_create_step(h1, bd_down), gm = gm * xpush(log(2));
else if(mapside(h1) == 1)
h1 = may_create_step(h1, bd_left), gm = gm * parabolic(-1);
else if(mapside(h1) == -1)
h1 = may_create_step(h1, bd_right), gm = gm * parabolic(+1);
}
int d = updir_at(h1);
gm = gm * adj(h1, d);
h1 = may_create_step(h1, d);
}
}
return gm * where;
@ -525,6 +507,79 @@ EX namespace binary {
}
return res;
}
ld spin_angle(cell *c, int d) {
if(WDIM == 3 || geometry == gBinary4 || geometry == gTernary) {
return hrmap::spin_angle(c, d);
}
if(d == NODIR) return 0;
if(d == c->type-1) d++;
return -(d+2)*M_PI/4;
}
const transmatrix adj(heptagon *h, int dir) {
if(geometry == gBinaryTiling) switch(dir) {
case bd_up: return xpush(-log(2));
case bd_left: return parabolic(-1);
case bd_right: return parabolic(+1);
case bd_down:
if(h->type == 6) return xpush(log(2));
/* case bd_down_left: */
return parabolic(-1) * xpush(log(2));
case bd_down_right:
return parabolic(+1) * xpush(log(2));
case bd_up_left:
return xpush(-log(2)) * parabolic(-1);
case bd_up_right:
return xpush(-log(2)) * parabolic(1);
default:
throw "unknown direction";
}
else if(use_direct_for(dir))
return direct_tmatrix[dir];
else {
h->cmove(dir);
return inverse_tmatrix[h->c.spin(dir)];
}
}
const transmatrix iadj(heptagon *h, int dir) { heptagon *h1 = h->cmove(dir); return adj(h1, h->c.spin(dir)); }
transmatrix adj(cell *c, int dir) { return adj(c->master, dir); }
void virtualRebase(heptagon*& base, transmatrix& at) override {
while(true) {
double currz = at[LDIM][LDIM];
heptagon *h = base;
heptagon *newbase = NULL;
transmatrix bestV;
for(int d=0; d<S7; d++) {
transmatrix V2 = iadj(h, d) * at;
double newz = V2[LDIM][LDIM];
if(newz < currz) {
currz = newz;
bestV = V2;
newbase = h->cmove(d);
}
}
if(newbase) {
base = newbase;
at = bestV;
continue;
}
return;
}
}
~hrmap_binary() { clearfrom(origin); }
};
EX hrmap *new_map() { return new hrmap_binary; }
@ -537,8 +592,8 @@ EX namespace binary {
EX hrmap *new_alt_map(heptagon *o) { return new hrmap_binary(o); }
transmatrix direct_tmatrix[14];
transmatrix inverse_tmatrix[14];
EX transmatrix direct_tmatrix[14];
EX transmatrix inverse_tmatrix[14];
int use_direct;
// directions in the 'use_direct' mask are taken from direct_tmatrix;
@ -663,24 +718,6 @@ EX namespace binary {
inverse_tmatrix[i] = inverse(direct_tmatrix[i]);
}
EX const transmatrix& tmatrix(heptagon *h, int dir) {
if(use_direct_for(dir))
return direct_tmatrix[dir];
else {
h->cmove(dir);
return inverse_tmatrix[h->c.spin(dir)];
}
}
EX const transmatrix& itmatrix(heptagon *h, int dir) {
if(use_direct_for(dir))
return inverse_tmatrix[dir];
else {
h->cmove(dir);
return h->cmove(dir), direct_tmatrix[h->c.spin(dir)];
}
}
#if MAXMDIM == 4
EX void queuecube(const transmatrix& V, ld size, color_t linecolor, color_t facecolor) {
@ -927,38 +964,6 @@ EX int celldistance3(heptagon *c1, heptagon *c2) {
}
EX int celldistance3(cell *c1, cell *c2) { return celldistance3(c1->master, c2->master); }
EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) {
while(true) {
double currz = at[LDIM][LDIM];
heptagon *h = base;
heptagon *newbase = NULL;
transmatrix bestV;
for(int d=0; d<S7; d++) {
transmatrix V2 = itmatrix(h, d) * at;
double newz = V2[LDIM][LDIM];
if(newz < currz) {
currz = newz;
bestV = V2;
newbase = h->cmove(d);
}
}
if(newbase) {
base = newbase;
at = bestV;
continue;
}
return;
}
}
#endif
EX hyperpoint get_horopoint(ld y, ld x) {

View File

@ -35,11 +35,37 @@ struct hrmap {
return relative_matrix(c2->master, c1->master);
}
virtual struct transmatrix adj(cell *c, int i);
virtual struct transmatrix iadj(cell *c, int i) { return adj(c->cmove(i), c->c.spin(i)); }
struct transmatrix iadj(cell *c, int i) { cell *c1 = c->cmove(i); return adj(c1, c->c.spin(i)); }
virtual void draw() {
printf("undrawable\n");
}
virtual vector<hyperpoint> get_vertices(cell*);
virtual void virtualRebase(heptagon*& base, transmatrix& at) {
printf("virtualRebase called unexpectedly\n");
return;
}
static constexpr ld SPIN_NOT_AVAILABLE = 1e5;
virtual ld spin_angle(cell *c, int d) { return SPIN_NOT_AVAILABLE; }
virtual transmatrix spin_to(cell *c, int d, ld bonus=0) {
ld sa = spin_angle(c, d);
if(sa != SPIN_NOT_AVAILABLE) { return spin(bonus + sa); }
transmatrix T = rspintox(tC0(adj(c, d)));
if(WDIM == 3) return T * cspin(2, 0, bonus);
return T * spin(bonus);
}
virtual transmatrix spin_from(cell *c, int d, ld bonus=0) {
ld sa = spin_angle(c, d);
if(sa != SPIN_NOT_AVAILABLE) { return spin(bonus - sa); }
transmatrix T = spintox(tC0(iadj(c, d)));
if(WDIM == 3) return T * cspin(2, 0, bonus);
return T * spin(bonus);
}
virtual double spacedist(cell *c, int i) { return hdist0(tC0(adj(c, i))); }
};
/** hrmaps which are based on regular non-Euclidean 2D tilings, possibly quotient */
@ -47,6 +73,11 @@ struct hrmap_standard : hrmap {
void draw() override;
transmatrix relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) override;
heptagon *create_step(heptagon *h, int direction) override;
transmatrix adj(cell *c, int d);
transmatrix adj(heptagon *h, int d);
transmatrix iadj(heptagon *h, int d) { return adj(h->cmove(d), h->c.spin(d)); }
ld spin_angle(cell *c, int d);
double spacedist(cell *c, int i) override;
};
void clearfrom(heptagon*);
@ -54,20 +85,21 @@ void verifycells(heptagon*);
struct hrmap_hyperbolic : hrmap_standard {
heptagon *origin;
eVariation mvar;
hrmap_hyperbolic();
hrmap_hyperbolic(heptagon *origin);
heptagon *getOrigin() override { return origin; }
~hrmap_hyperbolic() {
// verifycells(origin);
// printf("Deleting hyperbolic map: %p\n", this);
dynamicval<eVariation> ph(variation, mvar);
clearfrom(origin);
}
void verify() override { verifycells(origin); }
void virtualRebase(heptagon*& base, transmatrix& at) override;
};
#endif
transmatrix hrmap::adj(cell *c, int i) { return calc_relative_matrix(c->cmove(i), c, C0); }
vector<cell*>& hrmap::allcells() {
static vector<cell*> default_allcells;
if(bounded) {
@ -109,7 +141,8 @@ EX vector<hrmap*> allmaps;
EX hrmap *newAltMap(heptagon *o) { return new hrmap_hyperbolic(o); }
// --- hyperbolic geometry ---
heptagon* hyperbolic_origin() {
EX heptagon* hyperbolic_origin() {
int odegree = geometry == gBinaryTiling ? 6 : S7;
heptagon *origin = tailored_alloc<heptagon> (odegree);
heptagon& h = *origin;
h.s = hsOrigin;
@ -122,7 +155,7 @@ heptagon* hyperbolic_origin() {
h.alt = NULL;
h.distance = 0;
if(IRREGULAR) irr::link_start(origin);
h.c7 = newCell(geometry == gBinaryTiling ? 6 : S7, origin);
h.c7 = newCell(odegree, origin);
return origin;
}

View File

@ -2047,7 +2047,7 @@ void celldrawer::draw_wall_full() {
color_t col = (highwall(c) || c->wall == waTower) ? wcol : fcol;
if(!chasmg) {
#define D(v) darkena(gradient(0, col, 0, v * (sphere ? spherity(V * cellrelmatrix(c,i)) : 1), 1), fd, 0xFF)
#define D(v) darkena(gradient(0, col, 0, v * (sphere ? spherity(V * currentmap->adj(c,i)) : 1), 1), fd, 0xFF)
// #define D(v) darkena(col, fd, 0xFF)
if(sha & 1) {
@ -2242,9 +2242,8 @@ void celldrawer::add_map_effects() {
if(tim > 1000) tim = 800;
if(elec::havecharge && tim > 400) tim = 400;
for(int t=0; t<c->type; t++) if(c->move(t) && c->move(t)->ligon) {
ld hdir = displayspin(c, t);
int lcol = darkena(gradient(iinf[itOrbLightning].color, 0, 0, tim, 1100), 0, 0xFF);
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(xspinpush(hdir, cgi.crossf), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
queueline(V*chei(xspinpush(ticks * M_PI / cgi.S42, cgi.hexf/2), rand() % 1000, 1000) * C0, V*chei(currentmap->adj(c, t), rand() % 1000, 1000) * C0, lcol, 2 + vid.linequality);
}
}
@ -2252,8 +2251,9 @@ void celldrawer::add_map_effects() {
whirlwind::calcdirs(c);
for(int i=0; i<whirlwind::qdirs; i++) {
ld hdir0 = displayspin(c, whirlwind::dfrom[i]) + M_PI;
ld hdir1 = displayspin(c, whirlwind::dto[i]);
ld hdir0 = currentmap->spin_angle(c, whirlwind::dfrom[i]) + M_PI;
ld hdir1 = currentmap->spin_angle(c, whirlwind::dto[i]);
/* todo what if no spin_angle */
double ph1 = fractick(PURE ? 150 : 75);

View File

@ -342,7 +342,7 @@ template<class T> void build_euclidean_moves(cell *c, int vec, const T& builder)
}
}
struct hrmap_euclid_any : hrmap {
struct hrmap_euclid_any : hrmap_standard {
void draw() override;
};
@ -396,7 +396,7 @@ struct hrmap_torus : hrmap_euclid_any {
forCellIdEx(cc, i, c1) {
int d1 = celldistance(cc, c2);
if(d1 < d) {
t = t * cellrelmatrix(c1, i);
t = t * adj(c1, i);
c1 = cc;
d = d1;
goto again;

View File

@ -611,6 +611,17 @@ void geometry_information::generate_floorshapes() {
DEBBI(DF_POLY, ("generate_floorshapes"));
heptagon modelh;
cell model;
model.master = &modelh;
model.type = modelh.type = S7;
for(int i=0; i<S7; i++) {
model.move(i) = &model;
modelh.move(i) = &modelh;
model.c.setspin(i, i, false);
modelh.c.setspin(i, i, false);
}
if(WDIM == 3) ;
#if CAP_IRR
@ -639,12 +650,8 @@ void geometry_information::generate_floorshapes() {
#if CAP_BT
else if(penrose) {
dynamicval<bool> ncor(approx_nearcorner, true);
heptagon master;
cell model;
model.master = &master;
model.type = 4;
for(int i=0; i<2; i++) {
master.s = hstate(i); /* kite/dart shape */
modelh.s = hstate(i); /* kite/dart shape */
generate_floorshapes_for(i, &model, 0, 0);
}
}
@ -652,15 +659,12 @@ void geometry_information::generate_floorshapes() {
#if CAP_ARCM
else if(archimedean) {
heptagon master;
cell model;
model.master = &master;
arcm::parent_index_of(&master) = 0;
arcm::parent_index_of(&modelh) = 0;
auto &ac = arcm::current;
for(int i=0; i<2*ac.N + 2; i++) {
arcm::id_of(&master) = i;
arcm::id_of(&modelh) = i;
model.type = isize(ac.triangles[i]);
if(DUAL) model.type /= 2, arcm::parent_index_of(&master) = !(i&1);
if(DUAL) model.type /= 2, arcm::parent_index_of(&modelh) = !(i&1);
if(BITRUNCATED)
generate_floorshapes_for(i, &model, !arcm::pseudohept(&model), arcm::pseudohept(&model) ? 0 : 1^(i&1));
@ -673,10 +677,6 @@ void geometry_information::generate_floorshapes() {
#endif
else if(geometry == gBinary4) {
heptagon modelh;
cell model;
model.master = &modelh;
model.type = S7;
for(int i: {0,1}) {
modelh.zebraval = i;
generate_floorshapes_for(i, &model, 1, 0);
@ -684,10 +684,6 @@ void geometry_information::generate_floorshapes() {
}
else if(geometry == gTernary) {
heptagon modelh;
cell model;
model.master = &modelh;
model.type = S7;
for(int i: {0,1,2}) {
modelh.zebraval = i;
generate_floorshapes_for(i, &model, 1, 0);
@ -695,8 +691,6 @@ void geometry_information::generate_floorshapes() {
}
else if(PURE && geometry != gBinaryTiling && geosupport_football() < 2) {
cell model;
model.type = S7;
generate_floorshapes_for(0, &model, 1, 0);
}

View File

@ -113,7 +113,7 @@ struct geometry_information {
ld rhexf;
transmatrix heptmove[MAX_EDGE], hexmove[MAX_EDGE];
transmatrix invheptmove[MAX_EDGE], invhexmove[MAX_EDGE];
transmatrix invhexmove[MAX_EDGE];
int base_distlimit;
@ -521,7 +521,6 @@ void geometry_information::prepare_basics() {
for(int d=0; d<S7; d++)
hexmove[d] = spin(hexshift-d * ALPHA) * xpush(-crossf)* spin(M_PI);
for(int d=0; d<S7; d++) invheptmove[d] = inverse(heptmove[d]);
for(int d=0; d<S7; d++) invhexmove[d] = inverse(hexmove[d]);
hexhexdist = hdist(xpush0(crossf), xspinpush0(M_PI*2/S7, crossf));

View File

@ -69,6 +69,14 @@ EX transmatrix calc_relative_matrix(cell *c2, cell *c1, const hyperpoint& point_
namespace gp { extern gp::local_info draw_li; }
#endif
transmatrix hrmap_standard::adj(heptagon *h, int d) {
transmatrix T = cgi.heptmove[d];
if(h->c.mirror(d)) T = T * Mirror;
int sp = h->c.spin(d);
if(sp) T = T * spin(2*M_PI*sp/S7);
return T;
}
transmatrix hrmap_standard::relative_matrix(cell *c2, cell *c1, const hyperpoint& point_hint) {
heptagon *h1 = c1->master;
@ -91,64 +99,57 @@ transmatrix hrmap_standard::relative_matrix(cell *c2, cell *c1, const hyperpoint
if(bounded) {
transmatrix T;
ld bestdist = 1e9;
for(int d=0; d<S7; d++) if(h2->move(d)) {
int sp = h2->c.spin(d);
transmatrix S = cgi.heptmove[sp] * spin(2*M_PI*d/S7);
if(h2->c.mirror(d)) S = cgi.heptmove[sp] * Mirror * spin(2*M_PI*d/S7);
if(h2->move(d) == h1) {
for(int d=0; d<S7; d++) {
auto hm = h1->move(d);
if(!hm) continue;
transmatrix S = adj(h1, d);
if(hm == h2) {
transmatrix T1 = gm * S * where;
auto curdist = hdist(tC0(T1), point_hint);
if(curdist < bestdist) T = T1, bestdist = curdist;
}
if(geometry != gMinimal) for(int e=0; e<S7; e++) if(h2->move(d)->move(e) == h1) {
int sp2 = h2->move(d)->c.spin(e);
transmatrix T1 = gm * cgi.heptmove[sp2] * spin(2*M_PI*e/S7) * S * where;
if(geometry != gMinimal) for(int e=0; e<S7; e++) if(hm->move(e) == h2) {
transmatrix T1 = gm * S * adj(hm, e) * where;
auto curdist = hdist(tC0(T1), point_hint);
if(curdist < bestdist) T = T1, bestdist = curdist;
}
}
if(bestdist < 1e8) return T;
}
for(int d=0; d<S7; d++) if(h2->move(d) == h1) {
int sp = h2->c.spin(d);
return gm * cgi.heptmove[sp] * spin(2*M_PI*d/S7) * where;
for(int d=0; d<S7; d++) if(h1->move(d) == h2) {
return gm * adj(h1, d) * where;
}
if(among(geometry, gFieldQuotient, gBring, gMacbeath)) {
int bestdist = 1000000, bestd = 0;
for(int d=0; d<S7; d++) {
int dist = celldistance(h2->cmove(d)->c7, c1);
int dist = celldistance(h1->cmove(d)->c7, h2->c7);
if(dist < bestdist) bestdist = dist, bestd = d;
}
int sp = h2->c.spin(bestd);
where = cgi.heptmove[sp] * spin(2*M_PI*bestd/S7) * where;
h2 = h2->move(bestd);
gm = gm * adj(h1, bestd);
h1 = h1->move(bestd);
}
#if CAP_CRYSTAL
else if(cryst) {
for(int d3=0; d3<S7; d3++) {
auto h3 = h2->cmove(d3);
if(visited.count(h3)) continue;
visited.insert(h3);
int sp3 = h2->c.spin(d3);
transmatrix where3 = cgi.heptmove[sp3] * spin(2*M_PI*d3/S7) * where;
ld dist = crystal::space_distance(h3->c7, c1);
hbdist[dist].emplace_back(h3, where3);
auto hm = h1->cmove(d3);
if(visited.count(hm)) continue;
visited.insert(hm);
ld dist = crystal::space_distance(hm->c7, c2);
hbdist[dist].emplace_back(hm, gm * adj(h1, d3));
}
auto &bestv = hbdist.begin()->second;
tie(h2, where) = bestv.back();
tie(h1, gm) = bestv.back();
bestv.pop_back();
if(bestv.empty()) hbdist.erase(hbdist.begin());
}
#endif
else if(h1->distance < h2->distance) {
int sp = h2->c.spin(0);
where = iadj(h2, 0) * where;
h2 = h2->move(0);
where = cgi.heptmove[sp] * where;
}
else {
int sp = h1->c.spin(0);
gm = gm * adj(h1, 0);
h1 = h1->move(0);
gm = gm * cgi.invheptmove[sp];
}
}
return gm * where;
@ -169,40 +170,6 @@ EX transmatrix &ggmatrix(cell *c) {
return t;
}
EX transmatrix calc_relative_matrix_help(cell *c, heptagon *h1) {
transmatrix gm = Id;
heptagon *h2 = c->master;
transmatrix where = Id;
if(0);
#if CAP_GP
else if(GOLDBERG && c != c->master->c7) {
auto li = gp::get_local_info(c);
where = cgi.gpdata->Tf[li.last_dir][li.relative.first&31][li.relative.second&31][gmod(li.total_dir, S6)];
}
#endif
else if(BITRUNCATED) for(int d=0; d<S7; d++) if(h2->c7->move(d) == c)
where = cgi.hexmove[d];
// always add to last!
while(h1 != h2) {
for(int d=0; d<S7; d++) if(h1->move(d) == h2) printf("(adj) ");
if(h1->distance < h2->distance) {
int sp = h2->c.spin(0);
printf("A%d ", sp);
h2 = h2->move(0);
where = cgi.heptmove[sp] * where;
}
else {
int sp = h1->c.spin(0);
printf("B%d ", sp);
h1 = h1->move(0);
gm = gm * cgi.invheptmove[sp];
}
}
println(hlog, "OK");
println(hlog, gm * where);
return gm * where;
}
#if HDR
struct horo_distance {
ld a, b;
@ -288,10 +255,7 @@ void virtualRebase(cell*& base, T& at, bool tohex, const U& check) {
base = hybrid::get_at(w.first, w.second);
return;
}
if(sl2) {
virtualRebase_cell(base, at, check);
return;
}
if((euclid || sphere) && WDIM == 2) {
again:
if(euwrap) for(int i=0; i<6; i++) {
@ -316,57 +280,7 @@ void virtualRebase(cell*& base, T& at, bool tohex, const U& check) {
return;
}
at = master_relative(base) * at;
base = base->master->c7;
while(true) {
horo_distance currz(check(at));
heptagon *h = base->master;
cell *newbase = NULL;
transmatrix bestV;
if(WDIM == 2 && !binarytiling && !penrose) for(int d=0; d<h->degree(); d++) {
heptspin hs(h, d, false);
heptspin hs2 = hs + wstep;
transmatrix V2 = spin(-hs2.spin*2*M_PI/S7) * cgi.invheptmove[d];
horo_distance newz(check(V2 * at));
if(newz < currz) {
currz = newz;
bestV = V2;
newbase = hs2.at->c7;
}
}
if(newbase) {
base = newbase;
at = bestV * at;
}
else {
if(tohex && BITRUNCATED) for(int d=0; d<base->type; d++) {
cell *c = createMov(base, d);
transmatrix V2 = spin(-base->c.spin(d)*2*M_PI/S6) * cgi.invhexmove[d];
horo_distance newz(check(V2 * at));
if(newz < currz) {
currz = newz;
bestV = V2;
newbase = c;
}
}
if(newbase) {
base = newbase;
at = bestV * at;
}
else at = master_relative(base, true) * at;
if(binarytiling || (tohex && (GOLDBERG || IRREGULAR)) || WDIM == 3 || penrose)
virtualRebase_cell(base, at, check);
break;
}
}
virtualRebase_cell(base, at, check);
}
EX void virtualRebase(cell*& base, transmatrix& at, bool tohex) {
@ -382,8 +296,7 @@ EX void virtualRebase(cell*& base, hyperpoint& h, bool tohex) {
});
}
// works only in geometries similar to the standard one, and only on heptagons
EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) {
void hrmap_hyperbolic::virtualRebase(heptagon*& base, transmatrix& at) {
while(true) {
@ -398,7 +311,7 @@ EX void virtualRebaseSimple(heptagon*& base, transmatrix& at) {
for(int d=0; d<S7; d++) {
heptspin hs(h, d, false);
heptspin hs2 = hs + wstep;
transmatrix V2 = spin(-hs2.spin*2*M_PI/S7) * cgi.invheptmove[d] * at;
transmatrix V2 = iadj(h, d) * at;
double newz = V2[LDIM][LDIM];
if(newz < currz) {
currz = newz;
@ -421,46 +334,37 @@ EX bool no_easy_spin() {
return NONSTDVAR || archimedean || WDIM == 3 || binarytiling || penrose;
}
double hexshiftat(cell *c) {
if(binarytiling) return 0;
if(ctof(c) && S7==6 && S3 == 4 && BITRUNCATED) return cgi.hexshift + 2*M_PI/S7;
if(ctof(c) && (S7==8 || S7 == 4) && S3 == 3 && BITRUNCATED) return cgi.hexshift + 2*M_PI/S7;
if(cgi.hexshift && ctof(c)) return cgi.hexshift;
return 0;
}
EX transmatrix ddspin(cell *c, int d, ld bonus IS(0)) {
if(no_easy_spin()) {
if(hybri) return PIU( ddspin(c, d, bonus) );
transmatrix T = rspintox(tC0(currentmap->adj(c, d)));
if(WDIM == 3) return T * cspin(2, 0, bonus);
return T * spin(bonus);
ld hrmap_standard::spin_angle(cell *c, int d) {
ld hexshift = 0;
if(ctof(c) && S7==6 && S3 == 4 && BITRUNCATED) hexshift = cgi.hexshift + 2*M_PI/S7;
else if(ctof(c) && (S7==8 || S7 == 4) && S3 == 3 && BITRUNCATED) hexshift = cgi.hexshift + 2*M_PI/S7;
else if(cgi.hexshift && ctof(c)) hexshift = cgi.hexshift;
if(IRREGULAR) {
auto id = irr::cellindex[c];
auto& vs = irr::cells[id];
if(d < 0 || d >= c->type) return 0;
auto& p = vs.jpoints[vs.neid[d]];
return -atan2(p[1], p[0]) - hexshift;
}
return spin(displayspin(c, d) + bonus - hexshiftat(c));
else if(masterless)
return - d * 2 * M_PI / c->type - hexshift;
else
return M_PI - d * 2 * M_PI / c->type - hexshift;
}
EX transmatrix iddspin(cell *c, int d, ld bonus IS(0)) {
if(no_easy_spin()) {
if(hybri) return PIU( iddspin(c, d, bonus) );
transmatrix T = spintox(tC0(currentmap->iadj(c, d)));
if(WDIM == 3) return T * cspin(2, 0, bonus);
return T * spin(bonus);
}
return spin(hexshiftat(c) - displayspin(c, d) + bonus);
EX transmatrix ddspin(cell *c, int d, ld bonus IS(0)) { return currentmap->spin_to(c, d, bonus); }
EX transmatrix iddspin(cell *c, int d, ld bonus IS(0)) { return currentmap->spin_from(c, d, bonus); }
EX ld cellgfxdist(cell *c, int d) { return currentmap->spacedist(c, d); }
double hrmap_standard::spacedist(cell *c, int i) {
if(NONSTDVAR) return hrmap::spacedist(c, i);
if(!BITRUNCATED) return cgi.tessf;
if(c->type == S6 && (i&1)) return cgi.hexhexdist;
return cgi.crossf;
}
EX double cellgfxdist(cell *c, int i) {
if(no_easy_spin())
return hdist0(tC0(currentmap->adj(c, i)));
if(euclid) {
if(c->type == 8 && (i&1)) return cgi.crossf * sqrt(2);
return cgi.crossf;
}
return !BITRUNCATED ? cgi.tessf : (c->type == 6 && (i&1)) ? cgi.hexhexdist : cgi.crossf;
}
transmatrix hrmap::adj(cell *c, int i) {
if(no_easy_spin()) return calc_relative_matrix(c->move(i), c, i);
transmatrix hrmap_standard::adj(cell *c, int i) {
if(NONSTDVAR) return calc_relative_matrix(c->cmove(i), c, i);
double d = cellgfxdist(c, i);
transmatrix T = ddspin(c, i) * xpush(d);
if(c->c.mirror(i)) T = T * Mirror;
@ -469,8 +373,6 @@ transmatrix hrmap::adj(cell *c, int i) {
return T;
}
EX transmatrix cellrelmatrix(cell *c, int i) { return currentmap->adj(c, i); }
EX double randd() { return (rand() + .5) / (RAND_MAX + 1.); }
EX hyperpoint randomPointIn(int t) {
@ -695,7 +597,7 @@ EX hyperpoint farcorner(cell *c, int i, int which) {
}
#endif
return cellrelmatrix(c, i) * get_corner_position(c->move(i), (cellwalker(c, i) + wstep + (which?-1:2)).spin);
return currentmap->adj(c, i) * get_corner_position(c->move(i), (cellwalker(c, i) + wstep + (which?-1:2)).spin);
}
EX hyperpoint midcorner(cell *c, int i, ld v) {

View File

@ -305,46 +305,6 @@ void drawLightning(const transmatrix& V) {
#endif
}
EX ld displayspin(cell *c, int d) {
if(0);
#if CAP_ARCM
else if(archimedean) {
if(PURE) {
auto& t1 = arcm::current.get_triangle(c->master, d-1);
return -(t1.first + M_PI / c->type);
}
else if(DUAL) {
auto& t1 = arcm::current.get_triangle(c->master, 2*d);
return -t1.first;
}
else { /* BITRUNCATED */
auto& t1 = arcm::current.get_triangle(c->master, d);
return -t1.first;
}
}
#endif
#if CAP_IRR
else if(IRREGULAR) {
auto id = irr::cellindex[c];
auto& vs = irr::cells[id];
if(d < 0 || d >= c->type) return 0;
auto& p = vs.jpoints[vs.neid[d]];
return -atan2(p[1], p[0]);
}
#endif
#if CAP_BT
else if(binarytiling) {
if(d == NODIR) return 0;
if(d == c->type-1) d++;
return -(d+2)*M_PI/4;
}
#endif
else if(masterless)
return - d * 2 * M_PI / c->type;
else
return M_PI - d * 2 * M_PI / c->type;
}
#define UNTRANS (GDIM == 3 ? 0x000000FF : 0)
EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
@ -386,7 +346,7 @@ EX void drawPlayerEffects(const transmatrix& V, cell *c, bool onplayer) {
ang %= sword::sword_angles;
#if CAP_QUEUE || CAP_SHAPES
transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * ddspin(c,0,M_PI); // (IRREGULAR ? ddspin(c,0,M_PI) : spin(-hexshiftat(c)));
transmatrix Vnow = gmatrix[c] * rgpushxto0(inverse(gmatrix[c]) * tC0(V)) * ddspin(c,0,M_PI);
#endif
int adj = 1 - ((sword_angles/cwt.at->type)&1);
@ -2301,15 +2261,10 @@ double chainAngle(cell *c, transmatrix& V, cell *c2, double dft, const transmatr
}
// equivalent to V = V * spin(-chainAngle(c,V,c2,dft));
bool chainAnimation(cell *c, transmatrix& V, cell *c2, int i, ld bonus, const transmatrix &Vwhere, ld& length) {
if(!gmatrix0.count(c2)) {
V = V * ddspin(c,i,bonus);
length = cellgfxdist(c,i);
return false;
}
bool chainAnimation(cell *c, cell *c2, transmatrix& V, const transmatrix &Vwhere, ld& length) {
hyperpoint h = C0;
if(animations[LAYER_BIG].count(c2)) h = animations[LAYER_BIG][c2].wherenow * h;
h = inverse(V) * Vwhere * calc_relative_matrix(c2, c, C0) * h;
h = inverse(V) * Vwhere * h;
length = hdist0(h);
V = V * rspintox(h);
return true;
@ -2413,15 +2368,17 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo
transmatrix Vb0 = Vb;
if(c->mondir != NODIR && GDIM == 3 && isAnyIvy(c)) {
queueline(tC0(Vparam), Vparam * tC0(calc_relative_matrix(c->move(c->mondir), c, C0)), (col << 8) + 0xFF, 0);
queueline(tC0(Vparam), Vparam * tC0(currentmap->adj(c, c->mondir)), (col << 8) + 0xFF, 0);
}
else if(c->mondir != NODIR) {
if(mmmon) {
ld length;
// cell *c2 = c->move(c->mondir);
if(nospinb)
chainAnimation(c, Vb, c->move(c->mondir), c->mondir, 0, Vparam, length);
cell *c2 = c->move(c->mondir);
if(nospinb) {
chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, c->mondir), length);
}
else {
Vb = Vb * ddspin(c, c->mondir);
length = cellgfxdist(c, c->mondir);
@ -2489,10 +2446,10 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo
}
else {
int hdir = displayspin(c, c->mondir);
transmatrix T = Vparam * ddspin(c, c->mondir);
color_t col = darkena(0x606020, 0, 0xFF);
for(int u=-1; u<=1; u++)
queueline(Vparam*xspinpush0(hdir+M_PI/2, u*cgi.crossf/5), Vparam*xspinpush(hdir, cgi.crossf)*xspinpush0(hdir+M_PI/2, u*cgi.crossf/5), col, 2 + vid.linequality);
queueline(T*xspinpush0(M_PI/2, u*cgi.crossf/5), T*xspinpush(0, cgi.crossf)*xspinpush0(M_PI/2, u*cgi.crossf/5), col, 2 + vid.linequality);
}
}
@ -2550,7 +2507,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo
if(part == 't') {
if(nospinb) {
ld length;
chainAnimation(c, Vb, c2, nd, 0, Vparam, length);
chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, nd), length);
Vb = Vb * pispin;
}
else {
@ -2564,15 +2521,16 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo
else if(true) {
if(nospinb) {
ld length;
chainAnimation(c, Vb, c2, nd, 0, Vparam, length);
chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, nd), length);
Vb = Vb * pispin;
double ang = chainAngle(c, Vb, c->move(c->mondir), displayspin(c, c->mondir) - displayspin(c, nd), Vparam);
double ang = chainAngle(c, Vb, c->move(c->mondir), currentmap->spin_angle(c, c->mondir) - currentmap->spin_angle(c, nd), Vparam);
ang /= 2;
Vb = Vb * spin(M_PI-ang);
}
else {
ld hdir0 = displayspin(c, nd) + M_PI;
ld hdir1 = displayspin(c, c->mondir);
/* todo what if no spin_angle */
ld hdir0 = currentmap->spin_angle(c, nd) + M_PI;
ld hdir1 = currentmap->spin_angle(c, c->mondir);
while(hdir1 > hdir0 + M_PI) hdir1 -= 2*M_PI;
while(hdir1 < hdir0 - M_PI) hdir1 += 2*M_PI;
Vb = Vb0 * spin((hdir0 + hdir1)/2 + M_PI);
@ -2599,7 +2557,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo
int nd = neighborId(c, c2);
if(nospinb) {
ld length;
chainAnimation(c, Vb, c2, nd, 0, Vparam, length);
chainAnimation(c, c2, Vb, Vparam * currentmap->adj(c, nd), length);
Vb = Vb * pispin;
}
else {
@ -2687,7 +2645,7 @@ EX bool drawMonster(const transmatrix& Vparam, int ct, cell *c, color_t col, boo
if(c->hitpoints == 0) col = 0x404040;
if(nospinb) {
ld length;
chainAnimation(c, Vb, c->move(c->mondir), c->mondir, 0, Vparam, length);
chainAnimation(c, c->move(c->mondir), Vb, Vparam * currentmap->adj(c, c->mondir), length);
Vb = Vb * pispin;
Vb = Vb * xpush(cgi.tentacle_length - cellgfxdist(c, c->mondir));
}

View File

@ -84,9 +84,7 @@ EX namespace netgen {
if(c->type == S7) {
for(int i=0; i<c->type; i++) {
int hdir = displayspin(c, i) + M_PI / S7;
transmatrix V2 = V * spin(hdir) * xpush(cgi.hexf);
transmatrix V2 = V * ddspin(c, i, M_PI/S7) * xpush(cgi.hexf);
hcenter[ii][i] = V2 * C0;
}
@ -95,10 +93,8 @@ EX namespace netgen {
if(c->type == S6) {
for(int i=0; i<c->type; i++) {
int hdir = displayspin(c, i);
transmatrix V2 =
V * spin(hdir) * xpush(cgi.crossf) * spin(M_PI+M_PI/S7) * xpush(cgi.hexf);
V * ddspin(c, i, 0) * xpush(cgi.crossf) * spin(M_PI+M_PI/S7) * xpush(cgi.hexf);
hcenter[ii][i] = V2 * C0;
}

View File

@ -372,6 +372,10 @@ EX namespace solnihv {
default: throw "not nihsolv";
}
}
transmatrix adj(cell *c, int d) override {
return adjmatrix(d, c->c.spin(d));
}
virtual transmatrix relative_matrix(heptagon *h2, heptagon *h1) override {
for(int i=0; i<h1->type; i++) if(h1->move(i) == h2) return adjmatrix(i, h1->c.spin(i));
@ -1035,6 +1039,9 @@ EX namespace hybrid {
for(auto& p: at) tailored_delete(p.second);
}
virtual transmatrix spin_to(cell *c, int d, ld bonus) { return PIU( currentmap->spin_to(c, d, bonus) ); }
virtual transmatrix spin_from(cell *c, int d, ld bonus) { return PIU( currentmap->spin_from(c, d, bonus) ); }
};
hrmap_hybrid* hmap() { return (hrmap_hybrid*) currentmap; }
@ -1558,7 +1565,7 @@ EX namespace rots {
transmatrix Spin;
cell *cw = where[c1].first;
in_underlying([&] {
transmatrix T = cellrelmatrix(cw, i);
transmatrix T = adj(cw, i);
hyperpoint h = tC0(T);
Spin = inverse(gpushxto0(h) * T);
d = hr::inverse_exp(h, iTable);

View File

@ -213,6 +213,9 @@ EX namespace reg3 {
struct hrmap_quotient3 : hrmap {
vector<heptagon*> allh;
vector<vector<transmatrix>> tmatrices;
transmatrix adj(heptagon *h, int d) { return tmatrices[h->fieldval][d]; }
transmatrix adj(cell *c, int d) override { return adj(c->master, d); }
};
int encode_coord(const crystal::coord& co) {
@ -570,13 +573,13 @@ EX namespace reg3 {
dq::enqueue_by_matrix(h->move(d), V * tmatrices[h->fieldval][d]);
}
}
transmatrix relative_matrix(heptagon *h2, heptagon *h1) override {
if(h1 == h2) return Id;
int d = hr::celldistance(h2->c7, h1->c7);
for(int a=0; a<S7; a++) if(hr::celldistance(h1->move(a)->c7, h2->c7) < d)
return tmatrices[h1->fieldval][a] * relative_matrix(h2, h1->move(a));
return adj(h1, a) * relative_matrix(h2, h1->move(a));
println(hlog, "error in hrmap_field3:::relative_matrix");
return Id;
@ -723,7 +726,7 @@ EX namespace reg3 {
if(hyperbolic) {
dynamicval<eGeometry> g(geometry, gBinary3);
dynamicval<hrmap*> cm(currentmap, binary_map);
binary::virtualRebaseSimple(alt, T);
binary_map->virtualRebase(alt, T);
}
fixmatrix(T);
@ -861,15 +864,21 @@ EX namespace reg3 {
if(wallopt && isWall3(c) && isize(dq::drawqueue) > 1000) continue;
for(int i=0; i<S7; i++) if(h->move(i)) {
#if CAP_FIELD
if(quotient_map) dq::enqueue(h->move(i), V * quotient_map->tmatrices[h->fieldval][i]);
else
#endif
dq::enqueue(h->move(i), V * relative_matrix(h->move(i), h));
dq::enqueue(h->move(i), V * adj(h, i));
}
}
}
transmatrix adj(heptagon *h, int d) {
#if CAP_FIELD
if(quotient_map) return quotient_map->adj(h, d);
else
#endif
return relative_matrix(h->cmove(d), h);
}
transmatrix adj(cell *c, int d) override { return adj(c->master, d); }
transmatrix relative_matrix(heptagon *h2, heptagon *h1) override {
auto p1 = reg_gmatrix[h1];
auto p2 = reg_gmatrix[h2];
@ -1073,7 +1082,7 @@ int dist_alt(cell *c) {
#if MAXMDIM >= 4
EX cellwalker strafe(cellwalker cw, int j) {
hyperpoint hfront = tC0(adjmoves[cw.spin]);
transmatrix T = currentmap->relative_matrix(cw.at->cmove(j)->master, cw.at->master);
transmatrix T = currentmap->adj(cw.at, j);
for(int i=0; i<S7; i++) if(i != cw.at->c.spin(j))
if(hdist(hfront, T * tC0(adjmoves[i])) < strafedist + .01)
return cellwalker(cw.at->move(j), i);

View File

@ -85,7 +85,7 @@ void dqi_sky::draw() {
transmatrix T1 = Tsh * si.T;
do {
this_poly.emplace_back(T1 * skypoint, colors[cw.at]);
T1 = T1 * cellrelmatrix(cw.at, cw.spin);
T1 = T1 * currentmap->adj(cw.at, cw.spin);
cw += wstep; cw++;
}
while(cw != cw0);

View File

@ -24,10 +24,8 @@ EX vector<int> siblings;
struct hrmap_spherical : hrmap_standard {
heptagon *dodecahedron[12];
eVariation mvar;
hrmap_spherical() {
mvar = variation;
for(int i=0; i<spherecells(); i++) {
heptagon& h = *(dodecahedron[i] = tailored_alloc<heptagon> (S7));
h.s = hsOrigin;
@ -147,7 +145,6 @@ struct hrmap_spherical : hrmap_standard {
heptagon *getOrigin() { return dodecahedron[0]; }
~hrmap_spherical() {
dynamicval<eVariation> ph(variation, mvar);
for(int i=0; i<spherecells(); i++) clearHexes(dodecahedron[i]);
for(int i=0; i<spherecells(); i++) tailored_delete(dodecahedron[i]);
}