mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-29 19:40:35 +00:00
rogueviz:: a plugin to draw fundamental domains
This commit is contained in:
parent
542e80081f
commit
077c7657b8
4
hyper.h
4
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);
|
||||
|
||||
}
|
||||
|
||||
|
229
rogueviz-fundamental.cpp
Normal file
229
rogueviz-fundamental.cpp
Normal file
@ -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<cell*, int> same;
|
||||
map<cell*, transmatrix> gm;
|
||||
|
||||
bool is_connected(cellwalker cw) {
|
||||
return same[cw.at] & (1<<cw.spin);
|
||||
}
|
||||
|
||||
void be_connected(cellwalker cw) {
|
||||
// transmatrix T = gm[cw.at];
|
||||
same[cw.at] |= (1<<cw.spin);
|
||||
cw += wstep;
|
||||
same[cw.at] |= (1<<cw.spin);
|
||||
/* printf("%s", display(T * C0));
|
||||
printf(" %s\n", display(gm[cw.at] * C0)); */
|
||||
// queueline(T * C0, gm[cw.at] * C0, 0xFF0000FF, 3);
|
||||
}
|
||||
|
||||
int funmode = 0;
|
||||
|
||||
hyperpoint corner(cellwalker cw) {
|
||||
transmatrix T = gm[cw.at];
|
||||
if(funmode == 2) {
|
||||
while(cw.at->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<cell*> cells;
|
||||
cells.push_back(cwt.at);
|
||||
|
||||
int tree_edges = 0;
|
||||
int face_edges = 0;
|
||||
|
||||
for(int k=0; k<isize(cells); k++) {
|
||||
cell *c = cells[k];
|
||||
for(int i=0; i<c->type; 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; k<isize(cells); k++) {
|
||||
cell *c = cells[k];
|
||||
for(int i=0; i<c->type; 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; k<isize(cells); k++) {
|
||||
cell *c = cells[k];
|
||||
for(int i=0; i<c->type; 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<cellwalker, cellwalker> next_corner;
|
||||
map<cellwalker, cellwalker> prev_corner;
|
||||
|
||||
for(int ci=0; ci<corners; ci++) {
|
||||
cellwalker cw0 = cw;
|
||||
|
||||
while(true) {
|
||||
cw++;
|
||||
if(is_connected(cw)) {
|
||||
cw += wstep;
|
||||
cw++;
|
||||
}
|
||||
if(!is_connected(cw+1) && !is_connected(cw+wstep-1))
|
||||
break;
|
||||
}
|
||||
|
||||
next_corner[cw0] = cw;
|
||||
prev_corner[cw] = cw0;
|
||||
}
|
||||
|
||||
vector<transmatrix> nearm;
|
||||
|
||||
for(int ci=0; ci<corners; ci++) {
|
||||
for(int u=0; u<1; u++) {
|
||||
cellwalker cw1 = cw+u+wstep+(u-1);
|
||||
/* printf("%p/%d %p/%d ", cw.at, cw.spin, cw1.at, cw1.spin);
|
||||
printf("[%d %d %d] ", is_connected(cw), is_connected(cw+1), is_connected(cw+wstep-1));
|
||||
printf("[%d %d %d] ", is_connected(cw1), is_connected(cw1+1), is_connected(cw1+wstep-1));
|
||||
printf("%d %d;\n", !!next_corner.count(cw1), !!next_corner.count(cw1+wmirror-1)); */
|
||||
transmatrix T_here = gm[cw.at] * rel(cw+u);
|
||||
transmatrix T_there = gm[cw1.at];
|
||||
nearm.push_back(T_here * inverse(T_there));
|
||||
}
|
||||
cw = next_corner[cw];
|
||||
}
|
||||
|
||||
vid.linewidth *= 5;
|
||||
|
||||
for(int ci=0; ci<corners; ci++) {
|
||||
|
||||
hyperpoint h = corner(cw);
|
||||
cw = next_corner[cw];
|
||||
hyperpoint h2 = corner(cw);
|
||||
|
||||
for(auto& T: nearm) queueline(T * h, T * h2, color1, 3);
|
||||
}
|
||||
|
||||
for(int ci=0; ci<corners; ci++) {
|
||||
|
||||
hyperpoint h = corner(cw);
|
||||
cw = next_corner[cw];
|
||||
hyperpoint h2 = corner(cw);
|
||||
|
||||
queueline(h, h2, color2, 3);
|
||||
}
|
||||
|
||||
if(0) for(int k=0; k<isize(cells); k++) {
|
||||
cell *c = cells[k];
|
||||
for(int i=0; i<c->type; 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<cellwalker> visited;
|
||||
|
||||
int id = 0;
|
||||
|
||||
for(int ci=0; ci<corners; ci++) {
|
||||
|
||||
cellwalker cw1 = (cw+1+wstep);
|
||||
bool mirrored = false;
|
||||
if(!next_corner.count(cw1)) cw1 = cw1 + wmirror - 1, mirrored = true;
|
||||
|
||||
// visited.insert(next_corner[cw]);
|
||||
// cellwalker cw2 = next_corner[cw];
|
||||
if(next_corner[cw] < (mirrored ? next_corner[cw1] : cw1)) {
|
||||
|
||||
int mc = (mirrored ? color1 : color2) >> 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);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -2277,3 +2277,4 @@ auto hooks =
|
||||
#include "rogueviz-video.cpp"
|
||||
#include "rogueviz-pentagonal.cpp"
|
||||
#include "rogueviz-graph.cpp"
|
||||
#include "rogueviz-fundamental.cpp"
|
||||
|
Loading…
Reference in New Issue
Block a user