dual tilings

This commit is contained in:
Zeno Rogue 2018-08-30 02:11:43 +02:00
parent d95fc4b8d4
commit 829850a701
12 changed files with 119 additions and 45 deletions

View File

@ -423,7 +423,8 @@ struct hrmap_archimedean : hrmap {
heptagon *getOrigin() { return origin; }
hrmap_archimedean() {
int N0 = isize(current.adjacent[0]);
int id = DUAL ? current.N * 2 : 0;;
int N0 = isize(current.adjacent[id]);
origin = tailored_alloc<heptagon> (N0);
origin->s = hsOrigin;
origin->emeraldval = 0;
@ -435,9 +436,9 @@ struct hrmap_archimedean : hrmap {
origin->alt = NULL;
origin->distance = 0;
parent_index_of(origin) = 0;
id_of(origin) = 0;
origin->c7 = newCell(N0, origin);
parent_index_of(origin) = DUAL ? 1 : 0;
id_of(origin) = id;
origin->c7 = newCell(DUAL ? N0/2 : N0, origin);
heptagon *alt = NULL;
@ -458,20 +459,28 @@ struct hrmap_archimedean : hrmap {
archimedean_gmatrix[origin] = make_pair(alt, T);
altmap[alt].emplace_back(origin, T);
if(current.real_faces == 0) {
create_adjacent(origin, 0);
if(current.real_faces == 0 && DUAL) {
heptspin hs(origin, 0);
heptagon *hnew = build_child(hs, current.get_adj(hs));
for(int s=1; s<2*current.N; s++)
origin->c.connect(s, hnew, s, false);
}
else if(current.real_faces == 0) {
create_adjacent(origin, 0);
heptagon *o0 = origin->move(0);
create_adjacent(origin, 1);
heptagon *o1 = origin->move(1);
for(int s=1; s<2*current.N; s+=2)
origin->move(0)->c.connect(s, origin->move(1), 2*current.N-s, false);
o0->c.connect(s, o1, 2*current.N-s, false);
for(int s=2; s<2*current.N; s+=2) {
heptspin hs(origin->move(0), s);
heptspin hs(o0, s);
heptagon *hnew = build_child(hs, current.get_adj(hs));
// no need to specify archimedean_gmatrix and altmap
hnew->c.connect(1, heptspin(origin->move(1), 2*current.N-s));
hnew->c.connect(1, heptspin(o1, 2*current.N-s));
}
origin->move(1)->c.connect(1, origin->move(0), 2*current.N-1, false);
o1->c.connect(1, o0, 2*current.N-1, false);
}
else if(origin->c7->type == 2) {
else if(origin->degree() == 2) {
create_adjacent(origin, 0);
create_adjacent(origin, 1);
origin->move(0)->c.connect(1, origin->move(1), 2*current.N-1, false);
@ -508,9 +517,9 @@ heptagon *build_child(heptspin p, pair<int, int> adj) {
id_of(h) = adj.first;
parent_index_of(h) = adj.second;
int nei = neighbors_of(h);
h->c7 = newCell(nei, h);
h->c7 = newCell(DUAL ? nei/2 : nei, h);
h->distance = p.at->distance + 1;
if(adj.first < 2*current.N) {
if(adj.first < 2*current.N && !DUAL) {
int s = 0;
heptspin hs(p);
while(id_of(hs.at->move(0)) >= 2 * current.N) {
@ -607,7 +616,7 @@ void create_adjacent(heptagon *h, int d) {
for(auto& p: altmap[alt]) if(intval(p.second * C0, T * C0) < 1e-4) {
SDEBUG( printf("cell found: %p\n", p.first); )
for(int d2=0; d2<p.first->c7->type; d2++) {
for(int d2=0; d2<p.first->degree(); d2++) {
heptspin hs(p.first, d2);
auto& t2 = current.get_triangle(p.first, d2);
transmatrix T1 = T * spin(M_PI + t2.first);
@ -682,12 +691,13 @@ void draw() {
int id = id_of(h);
int S = isize(current.triangles[id]);
if(BITRUNCATED || id < 2*current.N) {
if(id < 2*current.N ? !DUAL : !PURE) {
if(!dodrawcell(h->c7)) continue;
drawcell(h->c7, V, 0, false);
}
for(int i=0; i<S; i++) {
if(DUAL && (i&1)) continue;
h->cmove(i);
if(PURE && id >= 2*current.N && h->move(i) && id_of(h->move(i)) >= 2*current.N) continue;
enqueue(h->move(i), V * adjcell_matrix(h, i));
@ -701,10 +711,12 @@ transmatrix relative_matrix(heptagon *h2, heptagon *h1) {
return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7];
transmatrix gm = Id, where = Id;
while(h1 != h2) {
for(int i=0; i<neighbors_of(h1); i++) if(h1->move(i) == h2) {
return gm * adjcell_matrix(h1, i) * where;
for(int i=0; i<neighbors_of(h1); i++) {
if(h1->move(i) == h2) {
return gm * adjcell_matrix(h1, i) * where;
}
}
else if(h1->distance > h2->distance) {
if(h1->distance > h2->distance) {
gm = gm * adjcell_matrix(h1, 0);
h1 = h1->move(0);
}
@ -789,6 +801,7 @@ int readArgs() {
if(0) ;
else if(argis("-symbol")) {
PHASE(2);
archimedean_tiling at;
shift(); at.parse(args());
if(at.errors) {
@ -801,6 +814,7 @@ int readArgs() {
}
}
else if(argis("-dgeom")) debug_geometry = true;
else if(argis("-dual")) { PHASE(2); set_variation(eVariation::dual); }
else return 1;
return 0;
}
@ -819,7 +833,8 @@ int archimedean_tiling::support_threecolor() {
}
int archimedean_tiling::support_threecolor_bitruncated() {
return N % 2 == 0 ? 2 : 0;
for(int i: current.faces) if(i % 2) return 0;
return 2;
}
int archimedean_tiling::support_football() {
@ -842,6 +857,8 @@ bool pseudohept(int id) {
}
bool chessvalue(cell *c) {
if(DUAL)
return c->master->rval1 - 1;
return c->master->fieldval & 1;
}
@ -971,10 +988,19 @@ archimedean_tiling edited;
bool symbol_editing;
void next_variation() {
set_variation(
PURE ? eVariation::dual :
DUAL ? eVariation::bitruncated :
eVariation::pure);
need_reset_geometry = true;
start_game();
}
void enable(archimedean_tiling& arct) {
stop_game();
if(!archimedean) set_variation(eVariation::pure);
set_geometry(gArchimedean);
set_variation(eVariation::pure);
patterns::whichPattern = patterns::PAT_NONE;
#if CAP_TEXTURE
if(texture::config.tstate == texture::tsActive && texture::cgroup == cpThree)
@ -985,6 +1011,7 @@ void enable(archimedean_tiling& arct) {
patterns::whichPattern = patterns::PAT_CHESS;
#endif
current = arct;
need_reset_geometry = true;
start_game();
}
@ -1108,10 +1135,7 @@ void show() {
if(archimedean) {
dialog::addSelItem(XLAT("variations"), gp::operation_name(), 'v');
dialog::add_action([] () {
set_variation(PURE ? eVariation::bitruncated : eVariation::pure);
start_game();
});
dialog::add_action(next_variation);
}
}
@ -1151,8 +1175,8 @@ string archimedean_tiling::world_size() {
denom = denom / g * f;
}
int anom = 0, adenom = 1;
if(BITRUNCATED) anom = 1, adenom = 1;
for(int f: faces) {
if(BITRUNCATED || DUAL) anom = 1, adenom = 1;
if(!DUAL) for(int f: faces) {
int g = gcd(adenom, f);
anom = (anom * f + adenom) / g;
adenom = adenom / g * f;
@ -1172,6 +1196,10 @@ string archimedean_tiling::world_size() {
return s;
}
int degree(heptagon *h) {
return isize(current.adjacent[id_of(h)]);
}
}
}

View File

@ -796,14 +796,25 @@ cell *createMov(cell *c, int d) {
exit(1);
}
}
else if(PURE && archimedean) {
if(arcm::id_of(c->master) <= arcm::current.N * 2) {
else if(archimedean && PURE) {
if(arcm::id_of(c->master) < arcm::current.N * 2) {
heptspin hs = heptspin(c->master, d) + wstep + 2 + wstep + 1;
c->c.connect(d, hs.at->c7, hs.spin, hs.mirrored);
}
else c->c.connect(d, c, d, false);
}
else if(PURE || archimedean) {
else if(archimedean && DUAL) {
if(arcm::id_of(c->master) >= arcm::current.N * 2) {
heptagon *h2 = createStep(c->master, d*2);
int d1 = c->master->c.spin(d*2);
c->c.connect(d, h2->c7, d1/2, false);
}
else {
printf("bad connection\n");
c->c.connect(d,c,d,false);
}
}
else if(archimedean || PURE) {
heptagon *h2 = createStep(c->master, d);
c->c.connect(d, h2->c7,c->master->c.spin(d),false);
}

View File

@ -3199,7 +3199,7 @@ namespace windmap {
// cw.spin = 0;
neighbors.emplace_back();
auto &v = neighbors.back();
if(NONSTDVAR && !sphere)
if(NONSTDVAR && !sphere && !archimedean)
for(int l=0; l<S7; l++) {
heptspin hs(cw.at->master, cw.spin);
hs = hs + l + wstep;

View File

@ -500,6 +500,8 @@ void generate_floorshapes() {
for(int i=0; i<2*ac.N + 2; i++) {
arcm::id_of(&master) = i;
model.type = isize(ac.triangles[i]);
if(DUAL) model.type /= 2, arcm::parent_index_of(&master) = !(i&1);
if(BITRUNCATED)
generate_floorshapes_for(i, &model, !arcm::pseudohept(i), arcm::pseudohept(i) ? 0 : 1^(i&1));
else if(geosupport_football() == 2)

View File

@ -288,8 +288,6 @@ void showEuclideanMenu() {
dialog::addSelItem(XLAT("variations"), XLAT("does not matter"), 'v');
else if(binarytiling)
dialog::addSelItem(XLAT("width"), fts(vid.binary_width), 'v');
else if(archimedean)
dialog::addSelItem(XLAT("variations"), XLAT("Not implemented."), 'v');
else
dialog::addSelItem(XLAT("variations"), gp::operation_name(), 'v');
@ -343,6 +341,7 @@ void showEuclideanMenu() {
spf += its(i);
}
if(BITRUNCATED) spf = "[" + spf + "]," + its(arcm::current.N * 2) + "," + its(arcm::current.N * 2);
if(DUAL) spf = its(arcm::current.N) + "^[" + spf + "]";
}
else if(binarytiling)
spf = "6,[6,7],7";
@ -434,7 +433,8 @@ void showEuclideanMenu() {
else if(uni == 'z')
showquotients = !showquotients;
else if(uni == 'v') {
if(euclid6 || archimedean) ;
if(euclid6) ;
else if(archimedean) arcm::next_variation();
else if(binarytiling) {
dialog::editNumber(vid.binary_width, 0, 2, 0.1, 1, XLAT("binary tiling width"), "");
dialog::reaction = [] () {

View File

@ -408,6 +408,10 @@ hyperpoint get_corner_position(cell *c, int cid, ld cf) {
hyperpoint h1 = xspinpush0(-t1.first, t1.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1));
return mid3(C0, h0, h1);
}
if(DUAL) {
auto& t0 = ac.get_triangle(c->master, 2*cid-1);
return xspinpush0(-t0.first, t0.second * 3 / cf * (ac.real_faces == 0 ? 0.999 : 1));
}
}
if(PURE) {
return ddspin(c,cid,M_PI/S7) * xpush0(hcrossf * 3 / cf);
@ -447,6 +451,11 @@ hyperpoint nearcorner(cell *c, int i) {
auto& t = ac.get_triangle(c->master, i);
return xspinpush0(-t.first, t.second);
}
if(DUAL) {
auto &ac = arcm::current;
auto& t = ac.get_triangle(c->master, i * 2);
return xspinpush0(-t.first, t.second);
}
}
if(binarytiling) {
ld yx = log(2) / 2;
@ -505,9 +514,10 @@ hyperpoint farcorner(cell *c, int i, int which) {
int n1 = isize(ac.adjacent[id1]);
return spin(-t.first - M_PI / c->type) * xpush(ac.inradius[id/2] + ac.inradius[id1/2]) * xspinpush0(M_PI + M_PI/n1*(which?3:-3), ac.circumradius[id1/2]);
}
if(BITRUNCATED) {
if(BITRUNCATED || DUAL) {
int mul = DUAL ? 2 : 1;
auto &ac = arcm::current;
auto adj = ac.get_adj(c->master, i);
auto adj = ac.get_adj(c->master, i * mul);
heptagon h; cell cx; cx.master = &h;
arcm::id_of(&h) = adj.first;
arcm::parent_index_of(&h) = adj.second;
@ -516,7 +526,7 @@ hyperpoint farcorner(cell *c, int i, int which) {
auto& t2 = arcm::current.get_triangle(adj);
return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -1 : 2);
return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first) * get_corner_position(&cx, which ? -mul : 2*mul);
}
}

View File

@ -627,6 +627,8 @@ namespace hr { namespace gp {
string operation_name() {
if(IRREGULAR)
return XLAT("irregular");
else if(DUAL)
return XLAT("dual");
else if(PURE)
return XLAT("OFF");
else if(BITRUNCATED)

View File

@ -240,6 +240,10 @@ ld displayspin(cell *c, int d) {
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;

View File

@ -137,6 +137,7 @@ void addMessage(string s, char spamtype = 0);
#define IRREGULAR (variation == eVariation::irregular)
#define PURE (variation == eVariation::pure)
#define BITRUNCATED (variation == eVariation::bitruncated)
#define DUAL (variation == eVariation::dual)
#define CHANGED_VARIATION (variation != ginf[geometry].default_variation)
@ -530,7 +531,9 @@ struct cell : gcell {
// do not add any fields after connection_table (see tailored_alloc)
};
int heptagon::degree() { if(archimedean) return c7->type; else return S7; }
namespace arcm { int degree(heptagon *h); }
int heptagon::degree() { if(archimedean) return arcm::degree(this); else return S7; }
typedef walker<heptagon> heptspin;
typedef walker<cell> cellwalker;

View File

@ -807,11 +807,12 @@ void optimizeview() {
if(binarytiling || archimedean) {
turn = -1, best = View[2][2];
for(int i=0; i<viewctr.at->c7->type; i++) {
heptagon *h2 = createStep(viewctr.at, i);
int i1 = i * (DUAL ? 2 : 1);
heptagon *h2 = createStep(viewctr.at, i1);
transmatrix T = (binarytiling) ? binary::relative_matrix(h2, viewctr.at) : arcm::relative_matrix(h2, viewctr.at);
hyperpoint H = View * tC0(T);
ld quality = euclid ? hdist0(H) : H[2];
if(quality < best) best = quality, turn = i, TB = T;
if(quality < best) best = quality, turn = i1, TB = T;
}
if(turn >= 0) {
View = View * TB;

View File

@ -1065,13 +1065,17 @@ namespace patterns {
}
bool geosupport_chessboard() {
return (archimedean && PURE) ? arcm::current.support_chessboard() : (VALENCE % 2 == 0);
return
(archimedean && PURE) ? arcm::current.support_chessboard() :
(archimedean && DUAL) ? arcm::current.support_threecolor_bitruncated() :
(VALENCE % 2 == 0);
}
int geosupport_threecolor() {
if(IRREGULAR) return 0;
if(archimedean && PURE) return arcm::current.support_threecolor();
if(archimedean && BITRUNCATED) return arcm::current.support_threecolor_bitruncated();
if(archimedean && DUAL) return 0; // it sometimes does support threecolor, but it can be obtained in other ways then
if(BITRUNCATED && S3 == 3) {
if(S7 % 2) return 1;
return 2;
@ -1086,8 +1090,11 @@ int geosupport_threecolor() {
int geosupport_football() {
// always works in bitrunc geometries
if(BITRUNCATED) return 2;
if(archimedean && DUAL) return false;
// it sometimes does support football, but it can be obtained in other ways then
if(archimedean) return arcm::current.support_football();
if(archimedean /* PURE */) return arcm::current.support_football();
if(IRREGULAR) return irr::bitruncations_performed ? 2 : 1;
@ -1225,8 +1232,12 @@ bool kraken_pseudohept(cell *c) {
return ishept(c);
else if(IRREGULAR)
return c->type != 6;
else if(archimedean)
else if(archimedean && PURE)
return c->type == isize(arcm::current.triangles[0]);
else if(archimedean && BITRUNCATED)
return pseudohept(c);
else if(archimedean && DUAL)
return true;
else if(!euclid && S3 == 3 && !(S7&1) && gp_threecolor() == 1)
return ishept(c);
else
@ -1868,12 +1879,12 @@ namespace patterns {
return;
}
if(archimedean) {
if(whichPattern == PAT_COLORING) {
if(whichPattern == PAT_COLORING && geosupport_threecolor()) {
if(subpattern_flags & SPF_FOOTBALL) cgroup = cpFootball;
else cgroup = cpThree;
}
else if(whichPattern == PAT_CHESS && arcm::current.support_chessboard()) cgroup = cpChess;
else if(whichPattern == 0 && (subpattern_flags & SPF_FOOTBALL) && arcm::current.support_football()) cgroup = cpFootball;
else if(whichPattern == PAT_CHESS && geosupport_chessboard()) cgroup = cpChess;
else if(whichPattern == PAT_TYPES && (subpattern_flags & SPF_FOOTBALL) && geosupport_football()) cgroup = cpFootball;
return;
}
for(int i=0; i<isize(cpatterns); i++)

View File

@ -1148,6 +1148,8 @@ void set_geometry(eGeometry target) {
if(gp::param.second && gp::param.second != gp::param.first)
gp::param.second = 0;
}
if(DUAL && geometry != gArchimedean)
variation = ginf[geometry].default_variation;
if(geometry == gBinaryTiling) variation = eVariation::pure;
need_reset_geometry = true;