Aperiodic Spectre tiling

This commit is contained in:
Zeno Rogue 2023-05-30 18:35:08 +02:00
parent 3e8dd6f549
commit d587f29a91
3 changed files with 438 additions and 16 deletions

View File

@ -382,6 +382,405 @@ vector<rule_recursive> rules_recursive = {
{6, 6, 31, 31, 14},
};
vector<rule_base> spectre_rules_base = { rule_base
{0, 0, 5, 5, -1},
{0, 10, 7, 7, -1},
{0, 11, 5, 8, -1},
{0, 12, 5, 7, -1},
{0, 13, 5, 6, -1},
{0, 1, 3, 8, -1},
{0, 2, 3, 7, -1},
{0, 3, 3, 6, -1},
{0, 4, 3, 5, -1},
{0, 5, 1, 0, -1},
{0, 6, 1, 13, -1},
{0, 7, 1, 12, -1},
{0, 8, 1, 11, -1},
{0, 9, 7, 8, -1},
{1, 0, 0, 5, -1},
{1, 10, 7, 9, -1},
{1, 11, 0, 8, -1},
{1, 12, 0, 7, -1},
{1, 1, 2, 6, -1},
{1, 13, 0, 6, -1},
{1, 2, 2, 5, -1},
{1, 3, 2, 4, -1},
{1, 4, 2, 13, 20},
{1, 4, 3, 13, 14},
{1, 4, 6, 13, 30},
{1, 4, 7, 13, 26},
{1, 4, 8, 13, 15},
{1, 5, 2, 12, 20},
{1, 5, 3, 12, 14},
{1, 5, 6, 12, 30},
{1, 5, 7, 12, 26},
{1, 5, 8, 12, 15},
{1, 6, 2, 11, 20},
{1, 6, 3, 11, 14},
{1, 6, 6, 11, 30},
{1, 6, 7, 11, 26},
{1, 6, 8, 11, 15},
{1, 7, 2, 0, 13},
{1, 7, 4, 0, 29},
{1, 7, 4, 4, 14},
{1, 7, 6, 0, 25},
{1, 7, 8, 0, 9},
{1, 8, 2, 13, 13},
{1, 8, 4, 13, 29},
{1, 8, 4, 3, 14},
{1, 8, 6, 13, 25},
{1, 8, 8, 13, 9},
{1, 9, 2, 12, 13},
{1, 9, 4, 12, 29},
{1, 9, 4, 2, 14},
{1, 9, 6, 12, 25},
{1, 9, 8, 12, 9},
{2, 0, 1, 7, 31},
{2, 0, 2, 3, 27},
{2, 0, 6, 3, 16},
{2, 0, 8, 3, 22},
{2, 10, 2, 11, 22},
{2, 10, 2, 1, 32},
{2, 10, 4, 11, 16},
{2, 10, 7, 11, 31},
{2, 11, 1, 6, 27},
{2, 11, 2, 10, 22},
{2, 11, 4, 10, 16},
{2, 11, 7, 10, 31},
{2, 1, 2, 10, 14},
{2, 12, 1, 5, 27},
{2, 12, 1, 9, 31},
{2, 1, 2, 2, 27},
{2, 12, 3, 1, 22},
{2, 12, 5, 1, 16},
{2, 13, 1, 4, 27},
{2, 13, 1, 8, 31},
{2, 13, 3, 0, 22},
{2, 13, 5, 0, 16},
{2, 1, 6, 10, 26},
{2, 1, 6, 2, 16},
{2, 1, 8, 2, 22},
{2, 2, 2, 1, 20},
{2, 2, 3, 1, 14},
{2, 2, 6, 1, 30},
{2, 2, 7, 1, 26},
{2, 2, 8, 1, 15},
{2, 3, 2, 0, 20},
{2, 3, 3, 0, 14},
{2, 3, 6, 0, 30},
{2, 3, 7, 0, 26},
{2, 3, 8, 0, 15},
{2, 4, 1, 3, -1},
{2, 5, 1, 2, -1},
{2, 6, 1, 1, -1},
{2, 7, 3, 4, -1},
{2, 8, 3, 3, -1},
{2, 9, 3, 2, -1},
{3, 0, 2, 13, 22},
{3, 0, 2, 3, 32},
{3, 0, 4, 13, 16},
{3, 0, 7, 13, 31},
{3, 10, 4, 5, -1},
{3, 11, 1, 6, 32},
{3, 11, 8, 6, -1},
{3, 1, 2, 12, 22},
{3, 12, 1, 5, 32},
{3, 1, 2, 2, 32},
{3, 12, 8, 5, -1},
{3, 13, 1, 4, 32},
{3, 13, 8, 4, -1},
{3, 1, 4, 12, 16},
{3, 1, 7, 12, 31},
{3, 2, 2, 9, -1},
{3, 3, 2, 8, -1},
{3, 4, 2, 7, -1},
{3, 5, 0, 4, -1},
{3, 6, 0, 3, -1},
{3, 7, 0, 2, -1},
{3, 8, 0, 1, -1},
{3, 9, 4, 6, -1},
{4, 0, 1, 7, 11},
{4, 0, 4, 13, 21},
{4, 0, 7, 13, 10},
{4, 0, 8, 3, 28},
{4, 10, 2, 11, 28},
{4, 10, 6, 11, 19},
{4, 10, 7, 11, 11},
{4, 10, 8, 11, 23},
{4, 11, 2, 10, 28},
{4, 11, 6, 10, 19},
{4, 11, 7, 10, 11},
{4, 11, 8, 10, 23},
{4, 12, 1, 9, 11},
{4, 12, 3, 1, 28},
{4, 12, 4, 1, 23},
{4, 12, 7, 1, 19},
{4, 13, 1, 8, 11},
{4, 13, 3, 0, 28},
{4, 13, 4, 0, 23},
{4, 13, 7, 0, 19},
{4, 1, 4, 12, 21},
{4, 1, 7, 10, 32},
{4, 1, 7, 12, 10},
{4, 1, 8, 2, 28},
{4, 2, 1, 9, 32},
{4, 2, 8, 9, -1},
{4, 3, 1, 8, 32},
{4, 3, 8, 8, -1},
{4, 4, 1, 7, 32},
{4, 4, 8, 7, -1},
{4, 5, 3, 10, -1},
{4, 6, 3, 9, -1},
{4, 7, 5, 4, -1},
{4, 8, 5, 3, -1},
{4, 9, 5, 2, -1},
{5, 0, 2, 13, 28},
{5, 0, 6, 13, 19},
{5, 0, 7, 13, 11},
{5, 0, 8, 13, 23},
{5, 10, 7, 5, -1},
{5, 11, 6, 6, -1},
{5, 1, 2, 12, 28},
{5, 12, 6, 5, -1},
{5, 13, 6, 4, -1},
{5, 1, 6, 12, 19},
{5, 1, 7, 12, 11},
{5, 1, 8, 12, 23},
{5, 2, 4, 9, -1},
{5, 3, 4, 8, -1},
{5, 4, 4, 7, -1},
{5, 5, 0, 0, -1},
{5, 6, 0, 13, -1},
{5, 7, 0, 12, -1},
{5, 8, 0, 11, -1},
{5, 9, 7, 6, -1},
{6, 0, 1, 7, 17},
{6, 0, 2, 3, 12},
{6, 0, 6, 3, 24},
{6, 10, 2, 1, 18},
{6, 10, 4, 11, 24},
{6, 10, 6, 1, 29},
{6, 10, 7, 11, 17},
{6, 10, 8, 1, 13},
{6, 11, 1, 6, 12},
{6, 11, 4, 10, 24},
{6, 11, 7, 10, 17},
{6, 12, 1, 5, 12},
{6, 12, 1, 9, 17},
{6, 1, 2, 2, 12},
{6, 12, 5, 1, 24},
{6, 13, 1, 4, 12},
{6, 13, 1, 8, 17},
{6, 13, 5, 0, 24},
{6, 1, 6, 10, 11},
{6, 1, 6, 2, 24},
{6, 2, 2, 1, 28},
{6, 2, 6, 1, 19},
{6, 2, 7, 1, 11},
{6, 2, 8, 1, 23},
{6, 3, 2, 0, 28},
{6, 3, 6, 0, 19},
{6, 3, 7, 0, 11},
{6, 3, 8, 0, 23},
{6, 4, 5, 13, -1},
{6, 5, 5, 12, -1},
{6, 6, 5, 11, -1},
{6, 7, 7, 4, -1},
{6, 8, 7, 3, -1},
{6, 9, 7, 2, -1},
{7, 0, 2, 3, 18},
{7, 0, 4, 13, 24},
{7, 0, 6, 3, 29},
{7, 0, 7, 13, 17},
{7, 0, 8, 3, 13},
{7, 10, 2, 11, 13},
{7, 10, 4, 11, 29},
{7, 10, 4, 1, 14},
{7, 10, 6, 11, 25},
{7, 10, 8, 11, 9},
{7, 11, 1, 6, 18},
{7, 11, 2, 10, 13},
{7, 11, 4, 10, 29},
{7, 11, 6, 10, 25},
{7, 11, 8, 10, 9},
{7, 12, 1, 5, 18},
{7, 1, 2, 2, 18},
{7, 12, 3, 1, 13},
{7, 12, 4, 1, 9},
{7, 12, 5, 1, 29},
{7, 12, 7, 1, 25},
{7, 13, 1, 4, 18},
{7, 13, 3, 0, 13},
{7, 13, 4, 0, 9},
{7, 13, 5, 0, 29},
{7, 13, 7, 0, 25},
{7, 1, 4, 12, 24},
{7, 1, 6, 2, 29},
{7, 1, 7, 12, 17},
{7, 1, 8, 2, 13},
{7, 2, 6, 9, -1},
{7, 3, 6, 8, -1},
{7, 4, 6, 7, -1},
{7, 5, 5, 10, -1},
{7, 6, 5, 9, -1},
{7, 7, 0, 10, -1},
{7, 8, 0, 9, -1},
{7, 9, 1, 10, -1},
{8, 0, 1, 7, 10},
{8, 0, 2, 3, 33},
{8, 0, 6, 3, 21},
{8, 10, 4, 11, 21},
{8, 10, 7, 11, 10},
{8, 10, 8, 1, 28},
{8, 11, 1, 6, 33},
{8, 11, 4, 10, 21},
{8, 11, 7, 10, 10},
{8, 12, 1, 5, 33},
{8, 12, 1, 9, 10},
{8, 1, 2, 2, 33},
{8, 12, 5, 1, 21},
{8, 13, 1, 4, 33},
{8, 13, 1, 8, 10},
{8, 13, 5, 0, 21},
{8, 1, 6, 10, 31},
{8, 1, 6, 2, 21},
{8, 1, 8, 10, 16},
{8, 2, 2, 1, 22},
{8, 2, 4, 1, 16},
{8, 2, 7, 1, 31},
{8, 3, 2, 0, 22},
{8, 3, 4, 0, 16},
{8, 3, 7, 0, 31},
{8, 4, 3, 13, -1},
{8, 5, 3, 12, -1},
{8, 6, 3, 11, -1},
{8, 7, 4, 4, -1},
{8, 8, 4, 3, -1},
{8, 9, 4, 2, -1},
};
vector<rule_recursive> spectre_rules_recursive = { rule_recursive
{0, 1, 27, -1, 20},
{0, 1, 9, 18, 10},
{0, 2, 32, -1, 14},
{0, 3, 11, -1, 29},
{0, 3, 9, 32, 10},
{0, 4, 15, 31, 33},
{0, 4, 17, -1, 25},
{0, 4, 9, 27, 10},
{0, 5, 15, 17, 33},
{0, 5, 9, 12, 10},
{0, 6, 15, 11, 33},
{0, 6, 30, 32, 12},
{0, 7, 15, 10, 33},
{0, 7, 9, 33, 10},
{1, 0, 10, 26, 9},
{1, 0, 20, -1, 27},
{1, 1, 21, 17, 23},
{1, 1, 23, 25, 21},
{1, 2, 13, -1, 31},
{1, 2, 21, 11, 23},
{1, 3, 21, 31, 23},
{1, 4, 19, 26, 24},
{1, 4, 22, 31, 22},
{1, 5, 12, -1, 30},
{1, 5, 19, 11, 24},
{1, 5, 22, 17, 22},
{1, 6, 16, 32, 28},
{1, 6, 21, 10, 23},
{1, 6, 22, 11, 22},
{1, 6, 23, 19, 21},
{1, 7, 19, 31, 24},
{1, 7, 22, 10, 22},
{2, 0, 14, -1, 32},
{2, 1, 23, 29, 21},
{2, 1, 31, -1, 13},
{2, 3, 18, -1, 26},
{2, 4, 23, 16, 21},
{2, 5, 10, -1, 9},
{2, 5, 23, 24, 21},
{2, 6, 12, -1, 30},
{2, 7, 23, 21, 21},
{3, 0, 10, 14, 9},
{3, 0, 29, -1, 11},
{3, 1, 23, 13, 21},
{3, 2, 26, -1, 18},
{3, 4, 12, -1, 30},
{3, 4, 19, 14, 24},
{3, 4, 23, 22, 21},
{3, 6, 23, 28, 21},
{3, 6, 31, -1, 13},
{3, 7, 10, -1, 9},
{4, 0, 10, 20, 9},
{4, 0, 25, -1, 17},
{4, 0, 33, 13, 15},
{4, 1, 22, 13, 22},
{4, 1, 24, 18, 19},
{4, 2, 21, 28, 23},
{4, 3, 21, 22, 23},
{4, 3, 24, 32, 19},
{4, 3, 30, -1, 12},
{4, 4, 16, 14, 28},
{4, 4, 19, 20, 24},
{4, 4, 22, 22, 22},
{4, 4, 24, 27, 19},
{4, 4, 28, 32, 16},
{4, 5, 19, 28, 24},
{4, 5, 24, 12, 19},
{4, 5, 28, 18, 16},
{4, 6, 22, 28, 22},
{4, 7, 19, 22, 24},
{4, 7, 24, 33, 19},
{5, 0, 10, 30, 9},
{5, 0, 33, 25, 15},
{5, 1, 22, 25, 22},
{5, 1, 24, 29, 19},
{5, 1, 30, -1, 12},
{5, 2, 21, 19, 23},
{5, 2, 9, -1, 10},
{5, 4, 16, 26, 28},
{5, 4, 19, 30, 24},
{5, 4, 24, 16, 19},
{5, 5, 16, 11, 28},
{5, 5, 19, 19, 24},
{5, 5, 24, 24, 19},
{5, 5, 28, 29, 16},
{5, 6, 22, 19, 22},
{5, 7, 16, 31, 28},
{5, 7, 24, 21, 19},
{6, 0, 12, 14, 30},
{6, 0, 33, 29, 15},
{6, 1, 21, 24, 23},
{6, 1, 22, 29, 22},
{6, 1, 23, 9, 21},
{6, 1, 28, 14, 16},
{6, 2, 30, -1, 12},
{6, 3, 13, -1, 31},
{6, 3, 21, 16, 23},
{6, 4, 22, 16, 22},
{6, 5, 22, 24, 22},
{6, 6, 21, 21, 23},
{6, 6, 23, 23, 21},
{6, 7, 12, -1, 30},
{6, 7, 19, 16, 24},
{6, 7, 22, 21, 22},
{7, 0, 10, 15, 9},
{7, 0, 33, 9, 15},
{7, 1, 22, 9, 22},
{7, 1, 24, 13, 19},
{7, 2, 21, 23, 23},
{7, 3, 9, -1, 10},
{7, 4, 19, 15, 24},
{7, 4, 24, 22, 19},
{7, 5, 19, 23, 24},
{7, 5, 28, 13, 16},
{7, 6, 22, 23, 22},
{7, 6, 24, 28, 19},
{7, 6, 30, -1, 12},
{7, 7, 16, 16, 28},
{7, 7, 28, 28, 16},
};
EX ld hat_param = 1;
EX ld hat_param_imag = 0;
@ -390,6 +789,8 @@ struct hrmap_hat : hrmap {
// always generate the same way
std::mt19937 hatrng;
bool is_spectre;
int hatrand(int i) {
return hatrng() % i;
}
@ -412,6 +813,9 @@ struct hrmap_hat : hrmap {
memo_matrix adj_memo[2][2][14][14];
vector<vector<memo_matrix>> long_transformations;
vector<rule_base> get_rules_base() { return is_spectre ? spectre_rules_base : rules_base; }
vector<rule_recursive> get_rules_recursive() { return is_spectre ? spectre_rules_recursive : rules_recursive; }
void fill_transform_levels(int lev) {
int clev = isize(long_transformations);
while(clev <= lev) {
@ -439,11 +843,11 @@ struct hrmap_hat : hrmap {
else unknown++;
};
if(clev == 1) for(auto& b: rules_base) {
if(clev == 1) for(auto& b: get_rules_base()) {
products_equal(lt[0][b.id0+1], adj2(b.id0==0, fix(b.edge0), b.id1==0, fix(b.edge1)), lt[1][b.master_connection+1], lt[0][b.id1+1]);
}
if(clev >= 2) for(auto& b: rules_recursive) {
if(clev >= 2) for(auto& b: get_rules_recursive()) {
products_equal(lt[clev][b.id0+1], lt[clev-1][b.child+1], lt[clev][b.parent+1], lt[clev][b.id1+1]);
}
@ -464,6 +868,8 @@ struct hrmap_hat : hrmap {
void init() {
relations = 34;
transmatrix T = Id;
auto& hc = hatcorners[0];
hc.clear();
@ -535,14 +941,22 @@ struct hrmap_hat : hrmap {
for(auto& h: hc) h = gpushxto0(ctr) * h;
};
if(hat_param_imag) {
if(is_spectre) {
println(hlog, "eshort = ", eshort, " elong = ", elong);
swap(eshort, elong);
swap(eshorti, elongi);
hat(hatcorners[1]);
}
else if(hat_param_imag) {
eshorti *= -1;
elongi *= -1;
hat(hatcorners[1]);
}
else hatcorners[1] = hc;
for(auto& h: hc) h = MirrorX * h;
reverse(hatcorners[1].begin(), hatcorners[1].end());
if(!is_spectre) {
for(auto& h: hc) h = MirrorX * h;
reverse(hatcorners[1].begin(), hatcorners[1].end());
}
if(q == 6) {
ld phi = (1 + sqrt(5)) / 2;
@ -577,7 +991,7 @@ struct hrmap_hat : hrmap {
long_transformations.clear();
}
constexpr static int relations = 34;
int relations;
// heptagons represent clusters
// heptagon->distance is 0 for clusters of hats, d+1 for supercluster of heptagon d
@ -622,7 +1036,7 @@ struct hrmap_hat : hrmap {
}
return h1;
}
if(dir <= 7 - h->zebraval) {
if(dir <= (is_spectre ? 8 : 7) - h->zebraval) {
// create child
auto h1 = init_heptagon(relations);
h1->distance = h->distance - 1;
@ -635,11 +1049,13 @@ struct hrmap_hat : hrmap {
createStep(h, 0);
int id = h->c.spin(0)-1;
indenter ind(2);
for(auto& ru: rules_recursive) {
if(ru.id0 == id && ru.child == dir) {
for(auto& ru: get_rules_recursive()) {
int i0 = ru.id0, i1 = ru.id1;
if((h->distance & 1) && is_spectre) swap(i0, i1);
if(i0 == id && ru.child == dir) {
heptagon *h1 = get_step(h->move(0), ru.parent);
if(!h1) continue;
heptagon *h2 = get_step(h1, ru.id1+1);
heptagon *h2 = get_step(h1, i1+1);
if(!h2) continue;
h->c.connect(dir, h2, ru.rev_child, false);
return h2;
@ -662,7 +1078,7 @@ struct hrmap_hat : hrmap {
void find_cell_connection(cell *c, int d) override {
int id = hat_id(c);
indenter ind(2);
for(auto& ru: rules_base) {
for(auto& ru: get_rules_base()) {
if(ru.id0 == id && ru.edge0 == fix(d)) {
heptagon *h = get_step(c->master, ru.master_connection);
if(!h) continue;
@ -728,12 +1144,13 @@ struct hrmap_hat : hrmap {
void build_cells(heptagon *h) {
if(h->c7) return;
auto& ha = hats[h];
ha.resize(8 - h->zebraval);
ha.resize((is_spectre ? 9 : 8) - h->zebraval);
for(auto& hac: ha) hac = newCell(isize(hatcorners[0]), h);
h->c7 = ha[0];
}
hrmap_hat() {
is_spectre = geometry == gAperiodicSpectre;
hatrng.seed(37);
init();
origin = init_heptagon(relations);

View File

@ -752,6 +752,7 @@ enum eGeometry {
gHalfBring,
gAperiodicHat,
gSierpinski3, gSierpinski4, gSixFlake, gMengerSponge, gSierpinskiTet,
gAperiodicSpectre,
gGUARD};
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSol, gcNIH, gcSolN, gcNil, gcProduct, gcSL2 };
@ -967,6 +968,7 @@ EX vector<geometryinfo> ginf = {
{"6-flake","none", "6-flake fractal", "S6", 6, 3, qFRACTAL, giEuclid2, {{10, 10}}, eVariation::pure},
{"{4,3,4}","none", "Menger sponge", "S8", 6, 4, qFRACTAL, giEuclid3, {{10, 10}}, eVariation::pure},
{"rh{4,3,4}","none", "Sierpiński tetrahedron", "S4b", 12, 3, qFRACTAL, giEuclid3, {{10, 10}}, eVariation::pure},
{"spectre","none", "aperiodic spectre", "spectre", 14, 3, qAPERIODIC | qHAT, giEuclid2, {{7, 7}}, eVariation::pure},
};
// bits: 9, 10, 15, 16, (reserved for later) 17, 18

View File

@ -834,14 +834,18 @@ EX void initConfig() {
param_f(hat::hat_param, "hat_param", "hat_param", 1)
-> editable(0, 2, 0.1, "hat parameter",
"Apeirodic hat tiling based on: https://arxiv.org/pdf/2303.10798.pdf\n\n"
"This controls the parameter discussed in Section 6. Parameter p is Tile(p, (2-p)√3), scaled so that the area is the same for every p.", 'v'
"This controls the parameter discussed in Section 6. Parameter p is Tile(p, (2-p)√3), scaled so that the area is the same for every p."
"Aperiodic spectre tiling based on: https://arxiv.org/abs/2305.17743\n\n"
"Set the parameter to 'spectre' value to make all tiles have the same shape."
,
'v'
)
-> set_extra([] {
dialog::addSelItem(XLAT("chevron (periodic)"), "0", 'C');
dialog::add_action([] { dialog::ne.s = "0"; dialog::apply_edit(); });
dialog::addSelItem(XLAT("hat"), "1", 'H');
dialog::add_action([] { dialog::ne.s = "1"; dialog::apply_edit(); });
dialog::addSelItem(XLAT("all equal (periodic)"), "3-√3", 'T');
dialog::addSelItem(XLAT("spectre"), "3-√3", 'T');
dialog::add_action([] { dialog::ne.s = "3 - sqrt(3)"; dialog::apply_edit(); });
dialog::addSelItem(XLAT("turtle"), "1.5", 'T');
dialog::add_action([] { dialog::ne.s = "1.5"; dialog::apply_edit(); });
@ -852,8 +856,7 @@ EX void initConfig() {
param_f(hat::hat_param_imag, "hat_param_imag", "hat_param_imag", 0)
-> editable(0, 2, 0.1, "hat parameter (imaginary)",
"Apeirodic hat tiling based on: https://arxiv.org/pdf/2303.10798.pdf\n\n"
"This controls the parameter discussed in Section 6. Parameter p is Tile(p, (2-p)√3), scaled so that the area is the same for every p.", 'v'
"Imaginary part of the hat parameter. This corresponds to the usual interpretation of complex numbers in Euclidean planar geometry: rather than shortened or lengthened, the edges are moved in the other dimension.", 'v'
)
-> set_reaction(hat::reshape);