aperiodic hat tiling

This commit is contained in:
Zeno Rogue 2023-03-23 01:34:58 +01:00
parent acfa454114
commit b854f68a88
8 changed files with 624 additions and 0 deletions

599
aperiodic-hat.cpp Normal file
View File

@ -0,0 +1,599 @@
// Hyperbolic Rogue -- Kite-and-dart tiling
// Copyright (C) 2011-2019 Zeno Rogue, see 'hyper.cpp' for details
/** \file apeirodic-hat.cpp
* \brief Apeirodic Hat tiling, based on https://arxiv.org/pdf/2303.10798.pdf
*/
#include "hyper.h"
namespace hr {
EX namespace hat {
EX bool in() { return cgflags & qHAT; }
struct rule_base {
int id0, edge0, id1, edge1, master_connection;
};
struct rule_recursive {
int id0, id1, child, parent, rev_child;
};
vector<rule_base> rules_base = {
rule_base{0, 0, 4, 6, -1},
{0, 10, 2, 6, -1},
{0, 11, 2, 5, -1},
{0, 12, 4, 8, -1},
{0, 13, 4, 7, -1},
{0, 1, 4, 5, -1},
{0, 2, 5, 6, -1},
{0, 3, 5, 5, -1},
{0, 4, 1, 0, -1},
{0, 5, 1, 13, -1},
{0, 6, 1, 12, -1},
{0, 7, 1, 11, -1},
{0, 8, 2, 8, -1},
{0, 9, 2, 7, -1},
{1, 0, 0, 4, -1},
{1, 10, 2, 9, -1},
{1, 11, 0, 7, -1},
{1, 12, 0, 6, -1},
{1, 13, 0, 5, -1},
{1, 1, 6, 6, -1},
{1, 2, 6, 5, -1},
{1, 3, 6, 4, -1},
{1, 4, 2, 13, 24},
{1, 4, 3, 13, 33},
{1, 4, 4, 13, 8},
{1, 4, 5, 13, 13},
{1, 4, 6, 13, 18},
{1, 4, 7, 13, 10},
{1, 5, 2, 12, 24},
{1, 5, 3, 12, 33},
{1, 5, 4, 12, 8},
{1, 5, 5, 12, 13},
{1, 5, 6, 12, 18},
{1, 5, 7, 12, 10},
{1, 6, 2, 11, 24},
{1, 6, 3, 11, 33},
{1, 6, 4, 11, 8},
{1, 6, 5, 11, 13},
{1, 6, 6, 11, 18},
{1, 6, 7, 11, 10},
{1, 7, 3, 0, 28},
{1, 7, 3, 4, 8},
{1, 7, 6, 0, 17},
{1, 7, 7, 0, 32},
{1, 8, 3, 13, 28},
{1, 8, 3, 3, 8},
{1, 8, 6, 13, 17},
{1, 8, 7, 13, 32},
{1, 9, 3, 12, 28},
{1, 9, 3, 2, 8},
{1, 9, 6, 12, 17},
{1, 9, 7, 12, 32},
{2, 0, 2, 13, 21},
{2, 0, 3, 13, 23},
{2, 0, 5, 13, 31},
{2, 0, 6, 3, 22},
{2, 10, 3, 11, 28},
{2, 10, 3, 1, 8},
{2, 10, 6, 11, 17},
{2, 10, 7, 11, 32},
{2, 11, 1, 6, 22},
{2, 11, 3, 10, 28},
{2, 11, 6, 10, 17},
{2, 11, 7, 10, 32},
{2, 1, 2, 12, 21},
{2, 12, 1, 5, 22},
{2, 12, 2, 1, 28},
{2, 12, 3, 1, 32},
{2, 12, 5, 1, 17},
{2, 1, 3, 12, 23},
{2, 13, 1, 4, 22},
{2, 13, 2, 0, 28},
{2, 13, 3, 0, 32},
{2, 13, 5, 0, 17},
{2, 1, 5, 12, 31},
{2, 1, 6, 2, 22},
{2, 2, 3, 9, -1},
{2, 3, 3, 8, -1},
{2, 4, 3, 7, -1},
{2, 5, 0, 11, -1},
{2, 6, 0, 10, -1},
{2, 7, 0, 9, -1},
{2, 8, 0, 8, -1},
{2, 9, 1, 10, -1},
{3, 0, 1, 7, 21},
{3, 0, 2, 13, 15},
{3, 0, 5, 13, 27},
{3, 0, 6, 3, 16},
{3, 0, 7, 3, 31},
{3, 10, 2, 11, 21},
{3, 10, 3, 11, 23},
{3, 10, 5, 11, 31},
{3, 10, 6, 1, 22},
{3, 11, 1, 6, 16},
{3, 11, 2, 10, 21},
{3, 11, 3, 10, 23},
{3, 11, 5, 10, 31},
{3, 1, 2, 10, 11},
{3, 1, 2, 12, 15},
{3, 12, 1, 5, 16},
{3, 12, 1, 9, 21},
{3, 12, 2, 1, 23},
{3, 12, 4, 1, 31},
{3, 13, 1, 4, 16},
{3, 13, 1, 8, 21},
{3, 13, 2, 0, 23},
{3, 13, 4, 0, 31},
{3, 1, 5, 12, 27},
{3, 1, 6, 2, 16},
{3, 1, 7, 2, 31},
{3, 2, 1, 9, 11},
{3, 2, 7, 9, -1},
{3, 3, 1, 8, 11},
{3, 3, 7, 8, -1},
{3, 4, 1, 7, 11},
{3, 4, 7, 7, -1},
{3, 5, 4, 10, -1},
{3, 6, 4, 9, -1},
{3, 7, 2, 4, -1},
{3, 8, 2, 3, -1},
{3, 9, 2, 2, -1},
{4, 0, 3, 13, 14},
{4, 0, 6, 13, 26},
{4, 0, 6, 3, 11},
{4, 0, 7, 13, 20},
{4, 10, 3, 5, -1},
{4, 11, 1, 6, 11},
{4, 11, 7, 6, -1},
{4, 12, 1, 5, 11},
{4, 12, 7, 5, -1},
{4, 1, 3, 12, 14},
{4, 13, 1, 4, 11},
{4, 13, 7, 4, -1},
{4, 1, 6, 12, 26},
{4, 1, 6, 2, 11},
{4, 1, 7, 12, 20},
{4, 2, 5, 9, -1},
{4, 3, 5, 8, -1},
{4, 4, 5, 7, -1},
{4, 5, 0, 1, -1},
{4, 6, 0, 0, -1},
{4, 7, 0, 13, -1},
{4, 8, 0, 12, -1},
{4, 9, 3, 6, -1},
{5, 0, 2, 13, 29},
{5, 0, 5, 13, 19},
{5, 0, 6, 3, 30},
{5, 10, 3, 11, 14},
{5, 10, 6, 1, 11},
{5, 10, 6, 11, 26},
{5, 10, 7, 11, 20},
{5, 11, 1, 6, 30},
{5, 11, 3, 10, 14},
{5, 11, 6, 10, 26},
{5, 11, 7, 10, 20},
{5, 1, 2, 12, 29},
{5, 12, 1, 5, 30},
{5, 12, 2, 1, 14},
{5, 12, 3, 1, 20},
{5, 12, 5, 1, 26},
{5, 13, 1, 4, 30},
{5, 13, 2, 0, 14},
{5, 13, 3, 0, 20},
{5, 13, 5, 0, 26},
{5, 1, 5, 12, 19},
{5, 1, 6, 2, 30},
{5, 2, 6, 9, -1},
{5, 3, 6, 8, -1},
{5, 4, 6, 7, -1},
{5, 5, 0, 3, -1},
{5, 6, 0, 2, -1},
{5, 7, 4, 4, -1},
{5, 8, 4, 3, -1},
{5, 9, 4, 2, -1},
{6, 0, 1, 7, 29},
{6, 0, 6, 3, 25},
{6, 0, 7, 3, 19},
{6, 10, 2, 11, 29},
{6, 10, 5, 11, 19},
{6, 10, 6, 1, 30},
{6, 11, 1, 6, 25},
{6, 11, 2, 10, 29},
{6, 11, 5, 10, 19},
{6, 12, 1, 5, 25},
{6, 12, 1, 9, 29},
{6, 12, 4, 1, 19},
{6, 1, 3, 10, 24},
{6, 13, 1, 4, 25},
{6, 13, 1, 8, 29},
{6, 13, 4, 0, 19},
{6, 1, 5, 10, 8},
{6, 1, 6, 10, 13},
{6, 1, 6, 2, 25},
{6, 1, 7, 10, 33},
{6, 1, 7, 2, 19},
{6, 2, 2, 1, 24},
{6, 2, 3, 1, 33},
{6, 2, 4, 1, 8},
{6, 2, 5, 1, 13},
{6, 2, 6, 1, 18},
{6, 2, 7, 1, 10},
{6, 3, 2, 0, 24},
{6, 3, 3, 0, 33},
{6, 3, 4, 0, 8},
{6, 3, 5, 0, 13},
{6, 3, 6, 0, 18},
{6, 3, 7, 0, 10},
{6, 4, 1, 3, -1},
{6, 5, 1, 2, -1},
{6, 6, 1, 1, -1},
{6, 7, 5, 4, -1},
{6, 8, 5, 3, -1},
{6, 9, 5, 2, -1},
{7, 0, 1, 7, 15},
{7, 0, 6, 3, 12},
{7, 0, 7, 3, 27},
{7, 10, 2, 11, 15},
{7, 10, 5, 11, 27},
{7, 10, 6, 1, 16},
{7, 10, 7, 1, 31},
{7, 11, 1, 6, 12},
{7, 11, 2, 10, 15},
{7, 11, 5, 10, 27},
{7, 12, 1, 5, 12},
{7, 12, 1, 9, 15},
{7, 12, 4, 1, 27},
{7, 13, 1, 4, 12},
{7, 13, 1, 8, 15},
{7, 13, 4, 0, 27},
{7, 1, 6, 2, 12},
{7, 1, 7, 10, 14},
{7, 1, 7, 2, 27},
{7, 2, 3, 1, 14},
{7, 2, 6, 1, 26},
{7, 2, 7, 1, 20},
{7, 3, 3, 0, 14},
{7, 3, 6, 0, 26},
{7, 3, 7, 0, 20},
{7, 4, 4, 13, -1},
{7, 5, 4, 12, -1},
{7, 6, 4, 11, -1},
{7, 7, 3, 4, -1},
{7, 8, 3, 3, -1},
{7, 9, 3, 2, -1},
};
vector<rule_recursive> rules_recursive = {
rule_recursive{0, 0, -1, -1, -1},
{0, 1, 10, 18, 12},
{0, 1, 25, -1, 18},
{0, 1, 32, 17, 15},
{0, 2, 10, 13, 12},
{0, 2, 30, -1, 13},
{0, 3, 10, 8, 12},
{0, 3, 11, -1, 8},
{0, 4, 10, 24, 12},
{0, 4, 21, -1, 28},
{0, 5, 10, 33, 12},
{0, 5, 17, 8, 29},
{0, 5, 32, 28, 15},
{0, 6, 10, 10, 12},
{0, 6, 32, 32, 15},
{1, 0, 12, 25, 10},
{1, 0, 15, 29, 32},
{1, 0, 18, -1, 25},
{1, 1, -1, -1, -1},
{1, 1, 14, 13, 31},
{1, 1, 19, 18, 26},
{1, 1, 26, 25, 19},
{1, 1, 31, 30, 14},
{1, 2, 14, 8, 31},
{1, 2, 17, -1, 29},
{1, 2, 19, 13, 26},
{1, 2, 23, 19, 23},
{1, 3, 19, 8, 26},
{1, 3, 27, 19, 20},
{1, 4, 19, 24, 26},
{1, 4, 23, 29, 23},
{1, 5, 14, 24, 31},
{1, 5, 19, 33, 26},
{1, 6, 14, 33, 31},
{1, 6, 19, 10, 26},
{1, 6, 26, 19, 19},
{2, 0, 12, 30, 10},
{2, 0, 13, -1, 30},
{2, 1, 23, 26, 23},
{2, 1, 26, 30, 19},
{2, 1, 29, -1, 17},
{2, 1, 31, 11, 14},
{2, 2, -1, -1, -1},
{2, 2, 20, 19, 27},
{2, 2, 27, 26, 20},
{2, 3, 17, -1, 29},
{2, 4, 20, 29, 27},
{2, 4, 27, 14, 20},
{2, 5, 23, 14, 23},
{2, 5, 27, 20, 20},
{2, 6, 23, 20, 23},
{3, 0, 12, 11, 10},
{3, 0, 8, -1, 11},
{3, 1, 20, 26, 27},
{3, 1, 26, 11, 19},
{3, 2, 29, -1, 17},
{3, 3, -1, -1, -1},
{3, 4, 22, -1, 24},
{3, 5, 16, -1, 33},
{3, 5, 20, 14, 27},
{3, 6, 12, -1, 10},
{3, 6, 20, 20, 27},
{4, 0, 12, 22, 10},
{4, 0, 28, -1, 21},
{4, 1, 23, 17, 23},
{4, 1, 26, 22, 19},
{4, 2, 20, 31, 27},
{4, 2, 27, 17, 20},
{4, 3, 24, -1, 22},
{4, 4, -1, -1, -1},
{4, 4, 20, 21, 27},
{4, 4, 27, 28, 20},
{4, 5, 20, 23, 27},
{4, 5, 23, 28, 23},
{4, 5, 27, 32, 20},
{4, 5, 29, -1, 17},
{4, 5, 31, 8, 14},
{4, 6, 23, 32, 23},
{5, 0, 12, 16, 10},
{5, 0, 15, 21, 32},
{5, 0, 29, 11, 17},
{5, 1, 26, 16, 19},
{5, 1, 31, 22, 14},
{5, 2, 20, 27, 27},
{5, 2, 23, 31, 23},
{5, 3, 27, 31, 20},
{5, 3, 33, -1, 16},
{5, 4, 14, 11, 31},
{5, 4, 17, -1, 29},
{5, 4, 20, 15, 27},
{5, 4, 23, 21, 23},
{5, 4, 27, 23, 20},
{5, 5, -1, -1, -1},
{5, 5, 23, 23, 23},
{5, 6, 26, 31, 19},
{5, 6, 29, -1, 17},
{6, 0, 12, 12, 10},
{6, 0, 15, 15, 32},
{6, 1, 19, 26, 26},
{6, 1, 26, 12, 19},
{6, 1, 31, 16, 14},
{6, 2, 23, 27, 23},
{6, 3, 10, -1, 12},
{6, 3, 27, 27, 20},
{6, 4, 23, 15, 23},
{6, 5, 17, -1, 29},
{6, 5, 19, 14, 26},
{6, 6, -1, -1, -1},
{6, 6, 14, 14, 31},
{6, 6, 19, 20, 26},
{6, 6, 26, 27, 19},
{6, 6, 31, 31, 14},
};
struct hrmap_hat : hrmap {
// always generate the same way
std::mt19937 hatrng;
int hatrand(int i) {
return hatrng() % i;
}
// cluster centers are of type 1, all the rest are of type 0 (they are mirror images)
int shvid(cell *c) override {
return c->master->c7 == c ? 1 : 0;
}
// vertices of each type of hat
vector<hyperpoint> hatcorners[2];
void init() {
auto pt = hpxy;
hatcorners[0] = {
pt(-1.1160254038,1.4330127019),
pt(-0.0915063509,2.0245190528),
pt(0.2500000000,1.4330127019),
pt(-0.0915063509,0.8415063509),
pt(0.9330127019,0.2500000000),
pt(0.9330127019,-0.9330127019),
pt(0.2500000000,-0.9330127019),
pt(-0.0915063509,-1.5245190528),
pt(-1.1160254038,-0.9330127019),
pt(-2.1405444566,-1.5245190528),
pt(-2.4820508076,-0.9330127019),
pt(0,0),
pt(-1.7990381057,0.2500000000),
pt(-1.1160254038,0.2500000000),
};
hatcorners[0][11] = mid(hatcorners[0][10], hatcorners[0][12]);
hatcorners[1] = hatcorners[0];
for(auto& h: hatcorners[1]) h = MirrorX * h;
reverse(hatcorners[0].begin(), hatcorners[0].end());
}
constexpr static int relations = 34;
// heptagons represent clusters
// heptagon->distance is 0 for clusters of hats, d+1 for supercluster of heptagon d
// heptagon->zebraval is 1 for central, 0 for non-central
// 0 is supercluster, 1..(7-zebraval) are child clusters, 8..(relations-1) are nearby clusters on the same level
/** for 0-level, the list of hats*/
map<heptagon*, vector<cell*>> hats;
heptagon *origin;
heptagon *getOrigin() override { return origin; }
hyperpoint get_corner(cell *c, int cid, ld cf) override {
int t = c->master->c7 == c;
auto& h = hatcorners[t][cid];
return C0 * (1-3./cf) + h * (3./cf);
}
heptagon *create_step(heptagon *h, int dir) override {
auto h1 = get_step(h, dir);
if(!h1) throw hr_exception("create_step");
return h1;
}
heptagon *get_step(heptagon *h, int dir) {
if(dir == -1) return h;
if(h->move(dir)) return h->move(dir);
if(dir == 0) {
// create parent
auto h1 = init_heptagon(relations);
h1->distance = h->distance + 1;
if(h->distance >= 1000) throw hr_exception("too much recursion");
h1->zebraval = hatrand(2);
if(h->zebraval == 1) {
h->c.connect(dir, h1, 1, false);
}
else {
h->c.connect(dir, h1, 2 + hatrand(5-h->zebraval), false);
}
return h1;
}
if(dir <= 7 - h->zebraval) {
// create child
auto h1 = init_heptagon(relations);
h1->distance = h->distance - 1;
h1->zebraval = dir == 1;
h->c.connect(dir, h1, 0, false);
return h1;
}
// create side connection
createStep(h, 0);
int id = h->c.spin(0)-1;
// println(hlog, "solving recursion for ", tie(id, dir));
indenter ind(2);
for(auto& ru: rules_recursive) {
if(ru.id0 == id && ru.child == dir) {
heptagon *h1 = get_step(h->move(0), ru.parent);
if(!h1) continue;
heptagon *h2 = get_step(h1, ru.id1+1);
if(!h2) continue;
h->c.connect(dir, h2, ru.rev_child, false);
return h2;
}
}
return nullptr;
}
int fix(int d) {
int n = isize(hatcorners[0]);
return gmod(n-2-d, n);
}
int hat_id(cell *c) {
auto& gha = hats[c->master];
for(int i=0; i<isize(gha); i++) if(gha[i] == c) return i;
throw hr_exception("not in hats");
}
void find_cell_connection(cell *c, int d) {
int id = hat_id(c);
// println(hlog, "solving base for ", tie(id, d));
indenter ind(2);
for(auto& ru: rules_base) {
if(ru.id0 == id && ru.edge0 == fix(d)) {
// println(hlog, "matching rule found: ", tie(ru.id1, ru.edge1, ru.master_connection));
heptagon *h = get_step(c->master, ru.master_connection);
if(!h) continue;
build_cells(h);
auto& ha = hats[h];
// println(hlog, "h valid, with ", isize(ha), " hats");
if(ru.id1 >= isize(ha)) continue;
auto& c1 = ha[ru.id1];
c->c.connect(d, c1, fix(ru.edge1), false);
return;
}
}
throw hr_exception("cell connection not found");
}
transmatrix adj(cell *c0, int d0) override {
cell *c1 = c0->cmove(d0);
int t0 = c0 == c0->master->c7;
int t1 = c1 == c1->master->c7;
int n = isize(hatcorners[0]);
int d1 = c0->c.spin(d0);
hyperpoint vl = hatcorners[t0][d0];
hyperpoint vr = hatcorners[t0][(d0+1)%n];
hyperpoint vm = mid(vl, vr);
transmatrix rm = gpushxto0(vm);
hyperpoint xvl = hatcorners[t1][d1];
hyperpoint xvr = hatcorners[t1][(d1+1)%n];
hyperpoint xvm = mid(xvl, xvr);
transmatrix xrm = gpushxto0(xvm);
if(abs(hdist(vl, vr) - hdist(xvl, xvr)) > 1e-3) throw hr_exception("wrong length connection");
transmatrix T = rgpushxto0(vm) * rspintox(rm*vr) * spintox(xrm*xvl) * xrm;
// println(hlog, vl, " == ", T * xvr, " AND ", vr, " == ", T * xvl);
return T;
}
void build_cells(heptagon *h) {
if(h->c7) return;
auto& ha = hats[h];
ha.resize(8 - h->zebraval);
for(auto& hac: ha) hac = newCell(isize(hatcorners[0]), h);
h->c7 = ha[0];
}
hrmap_hat() {
hatrng.seed(37);
init();
origin = init_heptagon(relations);
origin->distance = 0;
origin->zebraval = 1;
build_cells(origin);
}
~hrmap_hat() {
clearfrom(origin);
}
};
EX hrmap *new_map() { return new hrmap_hat; }
EX color_t hatcolor(cell *c, int mode) {
vector<int> cols;
auto *m = (hrmap_hat*) (currentmap);
cols.push_back(m->hat_id(c));
heptagon *h = c->master;
for(int i=0; i<6; i++) { h->cmove(0); cols.push_back(h->c.spin(0)-1); h = h->cmove(0); }
color_t col = 0xFFFFFF;
if(cols[0] == 0) col |= 0x1000000;
vector<int> ads = {0, 0x1, 0x100, 0x101, 0x10000, 0x10001, 0x10100, 0x10101 };
for(int a=0; a<7; a++) {
col -= ads[cols[a]] << (mode - a) % 7;
}
return col;
}
}}

View File

@ -429,6 +429,7 @@ EX void initcells() {
else if(arcm::in()) currentmap = arcm::new_map();
#endif
else if(euc::in()) currentmap = euc::new_map();
else if(hat::in()) currentmap = hat::new_map();
#if CAP_BT
else if(kite::in()) currentmap = kite::new_map();
#endif

View File

@ -750,6 +750,7 @@ enum eGeometry {
gInfOrderMixed, gSpace436, gFake,
gSpace345, gSpace353, gSpace354, gSpace355,
gHalfBring,
gAperiodicHat,
gGUARD};
enum eGeometryClass { gcHyperbolic, gcEuclid, gcSphere, gcSol, gcNIH, gcSolN, gcNil, gcProduct, gcSL2 };
@ -827,6 +828,7 @@ static const flagtype qSTRETCHABLE = Flag(27);
static const flagtype qCAT = Flag(28);
static const flagtype qAPERIODIC = Flag(29);
static const flagtype qHAT = Flag(30);
// note: dnext assumes that x&7 equals 7
static const int SEE_ALL = 50;
@ -956,6 +958,7 @@ EX vector<geometryinfo> ginf = {
{"{3,5,4}","none", "{3,5,4} hyperbolic honeycomb", "354", 20, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure},
{"{3,5,5}","none", "{3,5,5} hyperbolic honeycomb", "355", 20, 5, qIDEAL | qULTRA, giHyperb3, {{7, 2}}, eVariation::pure},
{"{5,4}", "pBring", "projective Bring's Surface", "pBring", 5, 4, qsSMALLN, giHyperb2, {{6, 4}}, eVariation::bitruncated},
{"hat", "none", "aperiodic hat", "hat", 14, 3, qAPERIODIC | qHAT, giEuclid2, {{7, 7}}, eVariation::pure},
};
// bits: 9, 10, 15, 16, (reserved for later) 17, 18

View File

@ -3581,6 +3581,7 @@ EX namespace windmap {
EX void create() {
if(disable_bigstuff) return;
if(cgflags & qPORTALSPACE) return;
if(hat::in()) return;
samples.clear();
neighbors.clear();
getid.clear();

View File

@ -825,6 +825,14 @@ void geometry_information::generate_floorshapes() {
else if(inforder::mixed()) { /* will be generated on the fly */ }
else if(hat::in()) {
dynamicval<bool> ncor(approx_nearcorner, true);
for(int i=0; i<2; i++) {
modelh.c7 = i == 1 ? &model : nullptr;
generate_floorshapes_for(i, &model, 0, 0);
}
}
#if CAP_BT
else if(kite::in()) {
dynamicval<bool> ncor(approx_nearcorner, true);

View File

@ -720,6 +720,7 @@ void geometry_information::prepare_basics() {
#if CAP_BT
if(bt::in()) hexvdist = rhexf = 1, tessf = 1, scalefactor = 1, crossf = hcrossf7;
if(geometry == gHoroRec || kite::in() || sol || nil || nih) hexvdist = rhexf = .5, tessf = .5, scalefactor = .5, crossf = hcrossf7/2;
if(hat::in()) scalefactor *= 1.5, crossf *= 1.5, tessf *= 1.5, hexvdist *= 1.5, rhexf *= 1.5;
if(bt::in()) scalefactor *= min<ld>(vid.binary_width, 1), crossf *= min<ld>(vid.binary_width, 1);
#endif
#if MAXMDIM >= 4

View File

@ -37,6 +37,7 @@
#include "nonisotropic.cpp"
#include "asonov.cpp"
#include "kite.cpp"
#include "aperiodic-hat.cpp"
#include "archimedean.cpp"
#include "arbitrile.cpp"
#include "rulegen.cpp"

View File

@ -1477,6 +1477,7 @@ EX bool pseudohept(cell *c) {
if(sol) return (c->master->emeraldval % 3 == 2) && (c->master->zebraval % 3 == 2) && (c->master->distance % 2);
if(nih) return c->master->zebraval % 3 == 2 && c->master->emeraldval % 2 == 1 && (c->master->distance % 2);
if(kite::in()) return kite::getshape(c->master) == kite::pDart;
if(hat::in()) return c == c->master->c7;
if(bt::in()) return bt::pseudohept(c);
#endif
if(S3 >= OINF) return c->master->distance % 3 == 1;
@ -1976,12 +1977,15 @@ EX namespace patterns {
return c->landparam;
}
case 'Z': {
if(hat::in()) return hat::hatcolor(c, 6);
return nearer_map(c);
}
case 'Y': {
if(hat::in()) return hat::hatcolor(c, 7);
return furthest_map(c, 0);
}
case 'X': {
if(hat::in()) return hat::hatcolor(c, 8);
return furthest_map(c, 1);
}
case 'W': {
@ -2060,6 +2064,12 @@ EX namespace patterns {
dialog::addSelItem(XLAT("furthest from start"), "bounded", 'Y');
}
if(hat::in()) {
dialog::addSelItem(XLAT("hat in cluster"), "hat", 'Z');
dialog::addSelItem(XLAT("hat clusters"), "hat", 'Y');
dialog::addSelItem(XLAT("hat superclusters"), "hat", 'X');
}
dialog::addSelItem(XLAT("types"), "types", 'A');
dialog::addSelItem(XLAT("types (mark reverse)"), "types", 'R');
dialog::addSelItem(XLAT("sides"), "sides", 'B');