diff --git a/arbitrile.cpp b/arbitrile.cpp index b8579e16..996f92cd 100644 --- a/arbitrile.cpp +++ b/arbitrile.cpp @@ -35,6 +35,13 @@ inline void print(hstream& hs, const connection_t& conn) { print(hs, tie(conn.si * note: the tesfile convention is: edge 0, vertex 0, edge 1, vertex 1, ... */ +/** edge with infinite end on the left */ +constexpr ld INFINITE_LEFT = -1; +/** edge with infinite end on the right */ +constexpr ld INFINITE_RIGHT = -2; +/** edge with two infinite ends */ +constexpr ld INFINITE_BOTH = -3; + struct shape { /** index in the arbi_tiling::shapes */ int id; @@ -46,6 +53,12 @@ struct shape { vector angles; /** list of edge lengths */ vector edges; + /** list of input edges */ + vector in_edges; + /** list of input angles */ + vector in_angles; + /** (ultra)ideal markers */ + vector ideal_markers; /** list of edge connections */ vector connections; int size() const { return isize(vertices); } @@ -199,16 +212,14 @@ void start_poly_debugger(hr_polygon_error& err) { void shape::build_from_angles_edges(bool is_comb) { transmatrix at = Id; - vertices.clear(); - int n = isize(angles); + int n = isize(in_angles); hyperpoint ctr = Hypc; vector matrices; for(int i=0; i anglelist; do { if(at.sid == at1.sid && (at.eid-at1.eid) % ac.shapes[at.sid].cycle_length == 0) pqty = 0; + if(qty && pqty == 0 && !total) break; ld a = ac.shapes[at.sid].angles[at.eid]; while(a < 0) a += 360 * degree; while(a > 360 * degree) a -= 360 * degree; @@ -386,6 +454,7 @@ EX void compute_vertex_valence() { at = ac.shapes[at.sid].connections[at.eid]; } while(total < 360*degree - 1e-6); + if(total == 0) qty = OINF; if(total > 360*degree + 1e-6) throw hr_parse_exception("improper total in compute_stats"); if(at.sid != i) throw hr_parse_exception("ended at wrong type determining vertex_valence"); if((at.eid - k) % ac.shapes[i].cycle_length) { @@ -702,6 +771,8 @@ EX void load(const string& fname, bool after_sliding IS(false)) { auto con = sh.connections[j]; auto& xsh = c.shapes[con.sid]; ld d2 = xsh.edges[con.eid]; + if(d1 == INFINITE_LEFT) d1 = INFINITE_RIGHT; + else if(d1 == INFINITE_RIGHT) d1 = INFINITE_LEFT; if(abs(d1 - d2) > 1e-6) throw hr_parse_exception(lalign(0, "connecting ", make_pair(i,j), " to ", con, " of different lengths only possible in a2")); } @@ -815,6 +886,27 @@ EX hrmap *current_altmap; heptagon *build_child(heptspin p, pair adj); +/** the point in distance 1 from 'material' to 'ideal' */ +EX hyperpoint at1(hyperpoint material, hyperpoint ideal) { + transmatrix T = gpushxto0(material); + hyperpoint id = T * ideal; + return rgpushxto0(material) * rspintox(id) * xpush0(1); + } + +/** get the midedge of lr; it takes infinite vertices into account */ +EX hyperpoint get_midedge(ld len, const hyperpoint &l, const hyperpoint &r) { + if(len == INFINITE_BOTH) { + return normalize(kleinize(l) + kleinize(r)); + } + else if(len == INFINITE_LEFT) { + return at1(r, l); + } + else if(len == INFINITE_RIGHT) { + return at1(l, r); + } + else return mid(l, r); + } + EX transmatrix get_adj(arbi_tiling& c, int t, int dl, int t1, int xdl) { auto& sh = c.shapes[t]; @@ -831,13 +923,13 @@ EX transmatrix get_adj(arbi_tiling& c, int t, int dl, int t1, int xdl) { hyperpoint vl = sh.vertices[dl]; hyperpoint vr = sh.vertices[dr]; - hyperpoint vm = mid(vl, vr); + hyperpoint vm = get_midedge(sh.edges[dr], vl, vr); transmatrix rm = gpushxto0(vm); hyperpoint xvl = xsh.vertices[xdl]; hyperpoint xvr = xsh.vertices[xdr]; - hyperpoint xvm = mid(xvl, xvr); + hyperpoint xvm = get_midedge(sh.edges[xdr], xvl, xvr); transmatrix xrm = gpushxto0(xvm); @@ -1017,7 +1109,11 @@ struct hrmap_arbi : hrmap { hyperpoint get_corner(cell *c, int cid, ld cf) override { auto& sh = arb::current_or_slided().shapes[arb::id_of(c->master)]; - return normalize(C0 + (sh.vertices[gmod(cid, c->type)] - C0) * 3 / cf); + int id = gmod(cid, c->type); + if(sh.angles[id] == 0) { + return normalize(C0 + 999 * kleinize(sh.vertices[id])); + } + return normalize(C0 + (sh.vertices[id] - C0) * 3 / cf); } }; @@ -1391,6 +1487,22 @@ EX void choose() { }); } +EX pair rep_ideal(ld e) { + ld alpha = 2 * M_PI / e; + hyperpoint h1 = point3(cos(alpha), -sin(alpha), 1); + hyperpoint h2 = point3(1, 0, 1); + hyperpoint h3 = point3(cos(alpha), sin(alpha), 1); + hyperpoint h12 = mid(h1, h2); + hyperpoint h23 = mid(h2, h3); + ld len = hdist(h12, h23); + transmatrix T = gpushxto0(h12); + auto T0 = T * C0; + auto Th23 = T * h23; + ld beta = atan2(T0); + ld gamma = atan2(Th23); + return {len, 90 * degree - (gamma - beta)}; + } + #if MAXMDIM >= 4 auto hooksw = addHook(hooks_swapdim, 100, [] { for(auto& p: {¤t, &slided}) diff --git a/util.cpp b/util.cpp index 784fd93f..58235a12 100644 --- a/util.cpp +++ b/util.cpp @@ -245,6 +245,16 @@ cld exp_parser::parse(int prio) { res /= *distunit; } #endif + else if(eat("ideal_angle(")) { + ld edges = rparse(0); + force_eat(")"); + return arb::rep_ideal(edges).second; + } + else if(eat("ideal_edge(")) { + ld edges = rparse(0); + force_eat(")"); + return arb::rep_ideal(edges).first; + } else if(eat("regangle(")) { cld edgelen = parse(0); if (auto *distunit = hr::at_or_null(extra_params, "distunit")) {