mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 14:02:59 +00:00 
			
		
		
		
	rogueviz:: a plugin to draw fundamental domains
This commit is contained in:
		
							
								
								
									
										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" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Zeno Rogue
					Zeno Rogue