fake:: support Archimedean pure

This commit is contained in:
Zeno Rogue 2020-05-31 16:18:44 +02:00
parent b17c75ccec
commit 5238959cbd
7 changed files with 92 additions and 30 deletions

View File

@ -76,10 +76,12 @@ struct archimedean_tiling {
string world_size();
void get_nom_denom(int& anom, int& adenom);
geometryinfo1& get_geometry();
geometryinfo1& get_geometry(ld mul = 1);
eGeometryClass get_class() { return get_geometry().kind; }
bool get_step_values(int& steps, int& single_step);
transmatrix adjcell_matrix(heptagon *h, int d);
ld scale();
};
@ -96,6 +98,12 @@ static const int sfSEMILINE = 16;
#endif
EX archimedean_tiling current;
EX archimedean_tiling fake_current;
EX archimedean_tiling& current_or_fake() {
if(fake::in()) return fake_current;
return current;
}
/** id of vertex in the archimedean tiling
* odd numbers = reflected tiles
@ -354,9 +362,9 @@ void archimedean_tiling::regroup() {
}
}
geometryinfo1& archimedean_tiling::get_geometry() {
if(euclidean_angle_sum < 1.999999) return ginf[gSphere].g;
else if(euclidean_angle_sum > 2.000001) return ginf[gNormal].g;
geometryinfo1& archimedean_tiling::get_geometry(ld mul) {
if(euclidean_angle_sum * mul < 1.999999) return ginf[gSphere].g;
else if(euclidean_angle_sum * mul > 2.000001) return ginf[gNormal].g;
else return ginf[gEuclid].g;
}
@ -366,6 +374,8 @@ void archimedean_tiling::compute_geometry() {
DEBB(DF_GEOM, (format("euclidean_angle_sum = %f\n", float(euclidean_angle_sum))));
bool infake = fake::in();
dynamicval<eGeometry> dv(geometry, gArchimedean);
/* compute the geometry */
@ -374,6 +384,15 @@ void archimedean_tiling::compute_geometry() {
alphas.resize(N);
ld elmin = 0, elmax = hyperbolic ? 10 : sphere ? M_PI : 1;
ld total = M_PI;
dynamicval<geometryinfo1> dgi(ginf[geometry].g, ginf[geometry].g);
if(infake) {
total *= N / fake::around;
ginf[geometry].g = get_geometry(fake::around / N);
}
/* inradius[N] is used in farcorner and nearcorner. Probably a bug */
if(real_faces == 2) {
@ -422,7 +441,7 @@ void archimedean_tiling::compute_geometry() {
println(hlog, "edgelength = ", edgelength, " angles = ", alphas, " inradius = ", inradius, " circumradius = ", circumradius);
if(isnan(alpha_total)) elmax = edgelength;
else if(sphere ^ (alpha_total > M_PI)) elmin = edgelength;
else if(sphere ^ (alpha_total > total)) elmin = edgelength;
else elmax = edgelength;
if(euclid) break;
}
@ -474,7 +493,13 @@ bool skip_digons(heptspin hs, int step);
void connect_digons_too(heptspin h1, heptspin h2);
void fixup_matrix(transmatrix& T, const transmatrix& X, ld step);
void connectHeptagons(heptspin hi, heptspin hs);
transmatrix adjcell_matrix(heptagon *h, int d);
/** @brief should we use gmatrix to compute relative_matrix faster? (not while in fake Archimedean) */
EX bool use_gmatrix = true;
/** @brief like adj, but in pure
* not used by arcm itself, but used in fake arcm
*/
struct hrmap_archimedean : hrmap {
map<gp::loc, struct cdata> eucdata;
@ -573,7 +598,9 @@ struct hrmap_archimedean : hrmap {
heptagon *create_step(heptagon *h, int d) override {
DEBB(DF_GEOM, (format("%p.%d ~ ?\n", hr::voidp(h), d)));
dynamicval<geometryinfo1> gi(ginf[geometry].g, ginf[gArchimedean].g);
heptspin hi(h, d);
while(skip_digons(hi, 1)) hi++;
@ -668,7 +695,7 @@ struct hrmap_archimedean : hrmap {
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;
transmatrix V1 = V * adjcell_matrix(h, i);
transmatrix V1 = V * current.adjcell_matrix(h, i);
bandfixer bf(V1);
dq::enqueue(h->move(i), V1);
}
@ -680,21 +707,22 @@ struct hrmap_archimedean : hrmap {
}
transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
if(gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7))
if(use_gmatrix && gmatrix0.count(h2->c7) && gmatrix0.count(h1->c7))
return inverse(gmatrix0[h1->c7]) * gmatrix0[h2->c7];
transmatrix gm = Id, where = Id;
auto& cof = current_or_fake();
while(h1 != h2) {
for(int i=0; i<neighbors_of(h1); i++) {
if(h1->move(i) == h2) {
return gm * adjcell_matrix(h1, i) * where;
return gm * cof.adjcell_matrix(h1, i) * where;
}
}
if(h1->distance > h2->distance) {
gm = gm * adjcell_matrix(h1, 0);
gm = gm * cof.adjcell_matrix(h1, 0);
h1 = h1->move(0);
}
else {
where = inverse(adjcell_matrix(h2, 0)) * where;
where = inverse(cof.adjcell_matrix(h2, 0)) * where;
h2 = h2->move(0);
}
}
@ -702,16 +730,17 @@ struct hrmap_archimedean : hrmap {
}
ld spin_angle(cell *c, int d) override {
auto &cof = current_or_fake();
if(PURE) {
auto& t1 = arcm::current.get_triangle(c->master, d-1);
auto& t1 = cof.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);
auto& t1 = cof.get_triangle(c->master, 2*d);
return -t1.first;
}
else { /* BITRUNCATED */
auto& t1 = arcm::current.get_triangle(c->master, d);
auto& t1 = cof.get_triangle(c->master, d);
return -t1.first;
}
}
@ -826,13 +855,13 @@ pair<ld, ld>& archimedean_tiling::get_triangle(const pair<int, int>& p, int delt
return triangles[p.first][gmod(p.second + delta, isize(adjacent[p.first]))];
}
transmatrix adjcell_matrix(heptagon *h, int d) {
auto& t1 = current.get_triangle(h, d);
transmatrix archimedean_tiling::adjcell_matrix(heptagon *h, int d) {
auto& t1 = get_triangle(h, d);
heptagon *h2 = h->move(d);
int d2 = h->c.spin(d);
auto& t2 = current.get_triangle(h2, d2);
auto& t2 = get_triangle(h2, d2);
return spin(-t1.first) * xpush(t1.second) * spin(M_PI + t2.first);
}

View File

@ -917,6 +917,7 @@ EX cdata *arcmCdata(cell *c) {
}
EX int getCdata(cell *c, int j) {
if(fake::in()) return FPIU(getCdata(c, j));
if(hybri) { c = hybrid::get_where(c).first; return PIU(getBits(c)); }
else if(euc::in()) return getEuclidCdata(euc2_coordinates(c))->val[j];
else if(arcm::in() && euclid)
@ -935,6 +936,7 @@ EX int getCdata(cell *c, int j) {
}
EX int getBits(cell *c) {
if(fake::in()) return FPIU(getBits(c));
if(hybri) { c = hybrid::get_where(c).first; return PIU(getBits(c)); }
else if(euc::in()) return getEuclidCdata(euc2_coordinates(c))->bits;
else if(arcm::in() && euclid)

View File

@ -54,7 +54,11 @@ EX namespace fake {
for(hrmap*& m: allmaps) if(m == underlying_map) m = NULL;
}
~hrmap_fake() { delete underlying_map; }
~hrmap_fake() {
in_underlying([this] {
delete underlying_map;
});
}
heptagon *create_step(heptagon *parent, int d) override {
parent->c.connect(d, parent, d, false);
@ -65,6 +69,7 @@ EX namespace fake {
transmatrix S1, S2;
ld dist;
in_underlying([c, d, &S1, &S2, &dist] {
dynamicval<bool> u(arcm::use_gmatrix, false);
transmatrix T = currentmap->adj(c, d);
S1 = rspintox(tC0(T));
transmatrix T1 = spintox(tC0(T)) * T;
@ -72,7 +77,14 @@ EX namespace fake {
S2 = xpush(-dist) * T1;
});
if(WDIM == 2) {
if(arcm::in()) {
int t = arcm::id_of(c->master);
int t2 = arcm::id_of(c->move(d)->master);
auto& cof = arcm::current_or_fake();
cgi.adjcheck = cof.inradius[t/2] + cof.inradius[t2/2];
}
else if(WDIM == 2) {
ld dist;
in_underlying([c, d, &dist] {
@ -139,6 +151,7 @@ EX namespace fake {
}
transmatrix relative_matrix(cell *h2, cell *h1, const hyperpoint& hint) override {
if(arcm::in()) return underlying_map->relative_matrix(h2, h1, hint);
if(h1 == h2) return Id;
for(int a=0; a<h1->type; a++) if(h1->move(a) == h2)
@ -148,6 +161,7 @@ EX namespace fake {
}
transmatrix relative_matrix(heptagon *h2, heptagon *h1, const hyperpoint& hint) override {
if(arcm::in()) return underlying_map->relative_matrix(h2, h1, hint);
return relative_matrix(h2->c7, h1->c7, hint);
}
@ -191,6 +205,10 @@ EX namespace fake {
}
}
}
ld spin_angle(cell *c, int d) override {
return underlying_map->spin_angle(c,d);
}
};
EX hrmap* new_map() { return new hrmap_fake; }
@ -295,6 +313,7 @@ EX ld around;
/** @brief the value of 'around' which makes the tiling Euclidean */
EX ld compute_euclidean() {
if(arcm::in()) return arcm::current.N * 2 / arcm::current.euclidean_angle_sum;
if(WDIM == 2) return 4 / (S7-2.) + 2;
int middle = get_middle();
@ -302,6 +321,15 @@ EX ld compute_euclidean() {
return M_PI / asin(cos(M_PI/middle) / sin(M_PI/underlying_cgip->face));
}
EX int around_orig() {
if(arcm::in())
return arcm::current.N;
if(WDIM == 2)
return S3;
return
underlying_cgip->loop;
}
EX void compute_scale() {
ld good = compute_euclidean();
@ -310,7 +338,7 @@ EX void compute_scale() {
if(abs(good - around) < 1e-6) good = around;
int s3 = WDIM == 2 ? S3 : underlying_cgip->loop;
int s3 = around_orig();
multiple = false;
int mcount = int(around / s3 + .5);
@ -381,6 +409,7 @@ void set_gfake(ld _around) {
compute_scale();
check_cgi();
cgi.require_basics();
ginf[gFake].xcode = no_code;
@ -397,7 +426,7 @@ EX void change_around() {
ld range = sightranges[geometry];
if(!fake::in()) {
if(around == (WDIM == 2 ? S3 : cgi.loop)) return; /* do nothing */
if(around == around_orig()) return; /* do nothing */
set_gfake(around);
}

View File

@ -511,7 +511,7 @@ void geometry_information::prepare_basics() {
}
s3 = S3;
if(fake::in()) s3 = fake::around;
if(fake::in() && !arcm::in()) s3 = fake::around;
beta = (S3 >= OINF && !fake::in()) ? 0 : 2*M_PI/s3;
@ -589,10 +589,12 @@ void geometry_information::prepare_basics() {
#endif
#if CAP_ARCM
if(arcm::in()) {
arcm::current.compute_geometry();
crossf = hcrossf7 * arcm::current.scale();
hexvdist = arcm::current.scale() * .5;
rhexf = arcm::current.scale() * .5;
auto& ac = arcm::current_or_fake();
if(fake::in()) ac = arcm::current;
ac.compute_geometry();
crossf = hcrossf7 * ac.scale();
hexvdist = ac.scale() * .5;
rhexf = ac.scale() * .5;
}
#endif
#if CAP_BT

View File

@ -512,7 +512,7 @@ EX hyperpoint get_corner_position(cell *c, int cid, ld cf IS(3)) {
#endif
#if CAP_ARCM
if(arcm::in()) {
auto &ac = arcm::current;
auto &ac = arcm::current_or_fake();
if(PURE) {
if(arcm::id_of(c->master) >= ac.N*2) return C0;
auto& t = ac.get_triangle(c->master, cid-1);

View File

@ -997,7 +997,7 @@ EX ld spherity(const transmatrix& V) {
}
EX bool confusingGeometry() {
return quotient || elliptic || reg3::ultra_mirror_in();
return quotient || elliptic || reg3::ultra_mirror_in() || (fake::in() && fake::multiple);
}
EX ld master_to_c7_angle() {

View File

@ -1083,7 +1083,7 @@ void geometry_information::configure_floorshapes() {
if(0);
#if CAP_ARCM
else if(arcm::in())
shFullFloor.configure(arcm::current.scale()/2, arcm::current.scale()/2);
shFullFloor.configure(arcm::current_or_fake().scale()/2, arcm::current_or_fake().scale()/2);
#endif
else
shFullFloor.configure(hexvdist, rhexf);