diff --git a/hyper.h b/hyper.h index 15d64bb9..bc11d600 100644 --- a/hyper.h +++ b/hyper.h @@ -4317,5 +4317,9 @@ extern int cells_drawn; void menuitem_sightrange(char c = 'r'); bool in_smart_range(const transmatrix& T); + +void curvepoint(const hyperpoint& H1); +dqi_poly& queuecurve(color_t linecol, color_t fillcol, PPR prio); + } diff --git a/rogueviz-fundamental.cpp b/rogueviz-fundamental.cpp new file mode 100644 index 00000000..9d33292c --- /dev/null +++ b/rogueviz-fundamental.cpp @@ -0,0 +1,229 @@ +// show the fundamental domain for quotient spaces +// Copyright (C) 2018 Zeno and Tehora Rogue, see 'hyper.cpp' for details + +namespace hr { + +namespace fundamental { + +color_t color1, color2; + +map same; +map gm; + +bool is_connected(cellwalker cw) { + return same[cw.at] & (1<type != S7) { + cw++; + T = T * calc_relative_matrix(cw.peek(), cw.at, cw.spin); + cw += wstep; + } + return T * C0; + } + return gm[cw.at] * get_corner_position(cw.at, cw.spin+(cw.mirrored?0:1), 3); + } + +transmatrix rel(cellwalker cw) { + return calc_relative_matrix(cw.cpeek(), cw.at, cw.spin); + } + +transmatrix labelpos(hyperpoint h1, hyperpoint h2) { + hyperpoint h = mid(h1, h2); + transmatrix T = rgpushxto0(h); + hyperpoint hx = inverse(T) * h2; + ld alpha = atan2(-hx[1], hx[0]); + return T * xspinpush(alpha + M_PI/2, .3); + } + +void fundamental_marker() { + if(!funmode || !quotient) return; + same.clear(); + gm.clear(); + + same[cwt.at] = 0; + gm[cwt.at] = ggmatrix(cwt.at); + + vector cells; + cells.push_back(cwt.at); + + int tree_edges = 0; + int face_edges = 0; + + for(int k=0; ktype; i++) { + cellwalker cw(c, i); + cell *c2 = cw.cpeek(); + if(gm.count(c2)) continue; + gm[c2] = gm[c] * rel(cw); + // queueline(gm[c2] * C0, gm[c2] * xspinpush0(ticks, 0.2), 0xFFFFFFFF, 3); + be_connected(cw); + tree_edges++; + cells.push_back(c2); + } + } + + while(true) { + int f = face_edges; + for(int k=0; ktype; i++) { + cellwalker cw(c, i); + if(is_connected(cw) && is_connected(cw+1) && !is_connected(cw+wstep-1)) { + face_edges++; + be_connected(cw+wstep-1); + } + } + } + if(f == face_edges) break; + } + + cellwalker cw; + + int corners = 0; + + for(int k=0; ktype; i++) { + cellwalker cw0(c, i); + if(!is_connected(cw0) && !is_connected(cw0+1) && !is_connected(cw0+wstep-1)) + corners++, cw = cw0; + } + } + + // printf("tree edges = %d, face edges = %d, corners = %d\n", tree_edges, face_edges, corners); + + map next_corner; + map prev_corner; + + for(int ci=0; ci nearm; + + for(int ci=0; citype; i++) { + cellwalker cw0(c, i); + if(!is_connected(cw0)) continue; + int v = 0; + for(auto& n: nearm) { + queueline(n * gm[cw0.at] * xspinpush0(v, .05), n * gm[cw0.cpeek()] * xspinpush0(v, .05), 0xFF8000FF, 0); + v++; + } + queueline(gm[cw0.at] * C0, gm[cw0.cpeek()] * C0, 0xFF0000FF, 0); + } + } + + set visited; + + int id = 0; + + for(int ci=0; ci> 8; + if(hdist(corner(cw), corner(next_corner[cw])) > 1e-3) { + queuestr(labelpos(corner(cw), corner(next_corner[cw])), 1/scalefactor, its(id), mc); + if(mirrored) + queuestr(labelpos(corner(cw1), corner(next_corner[cw1])), 1/scalefactor, its(id), mc); + else + queuestr(labelpos(corner(prev_corner[cw1]), corner(cw1)), 1/scalefactor, its(id), mc); + id++; + } + } + cw = next_corner[cw]; + } + + vid.linewidth /= 5; + } + +int readArgs() { + using namespace arg; + + if(0) ; + else if(argis("-fundamental")) { + shift(); funmode = argi(); + shift(); color1 = arghex(); + shift(); color2 = arghex(); + } + else return 1; + return 0; + } + +auto fundamentalhook = addHook(hooks_args, 100, readArgs) + addHook(hooks_frame, 100, fundamental_marker); + +} + +} \ No newline at end of file diff --git a/rogueviz.cpp b/rogueviz.cpp index 3a4298d4..a97a4199 100644 --- a/rogueviz.cpp +++ b/rogueviz.cpp @@ -2277,3 +2277,4 @@ auto hooks = #include "rogueviz-video.cpp" #include "rogueviz-pentagonal.cpp" #include "rogueviz-graph.cpp" +#include "rogueviz-fundamental.cpp"