Compare commits

3 Commits

Author SHA1 Message Date
Florian Stecker
78769593a7 movie command line arguments 2023-02-05 15:10:16 -05:00
Florian Stecker
a8b4bb7c2c implement rotation group and play around with it a bit 2022-07-29 14:38:48 +09:00
Florian Stecker
35932782e9 new .gitignore 2022-03-02 10:53:19 -06:00
8 changed files with 1040 additions and 526 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.o
limit_set
*.pdf

View File

@@ -1,50 +0,0 @@
# triangle_group_limit_set - visualizer for triangle group limit sets in the projective plane
This program visualizes the fractal limit set of triangle groups in SL(3,R) in the projective plane.
## Installation & Prerequisites ##
This program is written C and exclusively for Linux. It uses [Cairo] for drawing and X11 for input, which means it will only run in the X window system. Besides these, the only required library is the [Gnu Scientific Library (GSL)] including CBLAS.
To build, make sure GCC as well as these libraries are installed, and run
make
Then we can run it for example like this:
./limit_set 5 5 5 1 1 1 1.0 1.0
The arguments are 6 integers (p1, p2, p3, q1, q2, q3) and two floating point numbers (t,s) describing the triangle group under consideration (initially, t and s can be changed with the arrow keys).
The last argument is optional; if it is not given, it defaults to s = 1.
## Key bindings
Drag the mouse to move the image, drag with Shift pressed to rotate.
| Key | function |
|----------|-----------------------------------------------------------------------------------------------------|
| PageUp | increase t by 2% |
| PageDown | decrease t by 2% |
| Right | increase t by 0.2% |
| Left | decreaes t by 0.2% |
| Up | increase t by 0.002% |
| Down | decrease t by 0.002% |
| Space | (reset t to original value) |
| R | cycle through affine charts |
| l | show limit curve |
| L | show limit curve as line or as points |
| f | generate limit curve using attracting / repelling fixed points of conjugates of the Coxeter element |
| d | show dual limit curve |
| r | show fixed points and lines of generating reflections |
| a | show fixed points and lines of Coxeter elements |
| c | show the orbit of an arbitrary point (point can be changed with Shift+Click) |
| b | show certain conics touching the limit curve |
| B | show the "boxes" used to approximate the limit curve |
| p | save a screenshot of the current image (in PDF format) |
| t | toggle info text |
| i | (print some info to terminal?) |
| x | (show rotated reflectors?) |
| M | (make a movie) |
[Cairo]: https://cairographics.org/
[Gnu Scientific Library (GSL)]: https://www.gnu.org/software/gsl/

644
draw.c
View File

@@ -46,21 +46,22 @@ int fixedPoints(DrawingContext *ctx, const char *word, vector_t *out)
{ {
gsl_matrix *tmp = getTempMatrix(ctx->ws); gsl_matrix *tmp = getTempMatrix(ctx->ws);
gsl_matrix *ev = getTempMatrix(ctx->ws); gsl_matrix *ev = getTempMatrix(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(tmp); gsl_matrix_set_identity(tmp);
for(int i = 0; i < strlen(word); i++) { for(int i = 0; i < strlen(word); i++) {
if(word[i] == ' ') if(word[i] >= 'a' && word[i] <= 'c')
continue; multiply_right(tmp, gen[word[i]-'a'], ctx->ws);
multiply_right(tmp, gen[word[i]-'a'], ctx->ws); else if(word[i] >= 'A' && word[i] <= 'C')
multiply_right(tmp, gen[word[i]-'A'+3], ctx->ws);
} }
int count = real_eigenvectors(tmp, ev, ctx->ws); int count = real_eigenvectors(tmp, ev, ctx->ws);
LOOP(i) LOOP(j) out[i].x[j] = gsl_matrix_get(ev, j, i); LOOP(i) LOOP(j) out[i].x[j] = gsl_matrix_get(ev, j, i);
releaseTempMatrices(ctx->ws, 5); releaseTempMatrices(ctx->ws, 8);
return count; return count;
} }
@@ -69,9 +70,9 @@ int wordEigenvalues(DrawingContext *ctx, const char *word, double *out)
{ {
gsl_matrix *tmp = getTempMatrix(ctx->ws); gsl_matrix *tmp = getTempMatrix(ctx->ws);
gsl_vector *ev = getTempVector(ctx->ws); gsl_vector *ev = getTempVector(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(tmp); gsl_matrix_set_identity(tmp);
for(int i = 0; i < strlen(word); i++) { for(int i = 0; i < strlen(word); i++) {
@@ -83,7 +84,7 @@ int wordEigenvalues(DrawingContext *ctx, const char *word, double *out)
LOOP(i) out[i] = gsl_vector_get(ev, i); LOOP(i) out[i] = gsl_vector_get(ev, i);
releaseTempMatrices(ctx->ws, 4); releaseTempMatrices(ctx->ws, 7);
releaseTempVectors(ctx->ws, 1); releaseTempVectors(ctx->ws, 1);
return count; return count;
@@ -96,10 +97,20 @@ void drawPoint(DrawingContext *ctx, point_t p)
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
cairo_save(C); cairo_save(C);
cairo_arc(C, p.x, p.y, 4.0/ctx->dim->scalefactor, 0, 2*M_PI); cairo_arc(C, p.x, p.y, 3.0/ctx->dim->scalefactor, 0, 2*M_PI);
cairo_close_path(C); cairo_close_path(C);
cairo_fill(C); cairo_fill(C);
cairo_restore(C); cairo_restore(C);
/*
cairo_save(C);
cairo_move_to(C, p.x, p.y);
cairo_close_path(C);
cairo_set_line_cap(C, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width(C, 10.0/ctx->dim->scalefactor);
cairo_stroke(C);
cairo_restore(C);
*/
} }
void drawSegment2d(DrawingContext *ctx, point_t a, point_t b) void drawSegment2d(DrawingContext *ctx, point_t a, point_t b)
@@ -183,13 +194,22 @@ void drawSegmentWith(DrawingContext *ctx, vector_t a, vector_t b, vector_t line,
LOOP(i) x[i] = 0.0; LOOP(i) x[i] = 0.0;
LOOP(i) LOOP(j) { LOOP(i) LOOP(j) {
cofactor = gsl_matrix_get(ctx->cob, (i+1)%3, (j+1)%3) * gsl_matrix_get(ctx->cob, (i+2)%3, (j+2)%3) cofactor = gsl_matrix_get(ctx->cob, (i+1)%3, (j+1)%3) * gsl_matrix_get(ctx->cob, (i+2)%3, (j+2)%3)
- gsl_matrix_get(ctx->cob, (i+1)%3, (j+2)%3) * gsl_matrix_get(ctx->cob, (i+2)%3, (j+1)%3); - gsl_matrix_get(ctx->cob, (i+1)%3, (j+2)%3) * gsl_matrix_get(ctx->cob, (i+2)%3, (j+1)%3);
x[i] += cofactor * line.x[j]; x[i] += cofactor * line.x[j];
} }
// t = parameter on segment of intersection with line, s(t) = a + (b-a)*t // t = parameter on segment of intersection with line, s(t) = a + (b-a)*t
tline = -(a_.x*x[0] + a_.y*x[1] + x[2])/((b_.x - a_.x)*x[0] + (b_.y - a_.y)*x[1]); tline = -(a_.x*x[0] + a_.y*x[1] + x[2])/((b_.x - a_.x)*x[0] + (b_.y - a_.y)*x[1]);
/*
printf("tline: %f\n", tline);
point_t s;
s.x = a_.x - (b_.x-a_.x)*tline;
s.y = a_.y - (b_.y-a_.y)*tline;
drawPoint(ctx, s);
*/
if((tline < 0 || tline > 1) != contains) { if((tline < 0 || tline > 1) != contains) {
drawSegment2d(ctx, a_, b_); drawSegment2d(ctx, a_, b_);
} else { // need to draw complementary segment } else { // need to draw complementary segment
@@ -197,7 +217,6 @@ void drawSegmentWith(DrawingContext *ctx, vector_t a, vector_t b, vector_t line,
m.x = ctx->dim->center_x; m.x = ctx->dim->center_x;
m.y = ctx->dim->center_y; m.y = ctx->dim->center_y;
r = ctx->dim->radius; r = ctx->dim->radius;
// equation is coeff2 t^2 + 2 coeff1 t + coeff0 = 0 // equation is coeff2 t^2 + 2 coeff1 t + coeff0 = 0
coeff0 = (a_.x - m.x)*(a_.x - m.x) + (a_.y - m.y)*(a_.y - m.y) - r*r; coeff0 = (a_.x - m.x)*(a_.x - m.x) + (a_.y - m.y)*(a_.y - m.y) - r*r;
coeff1 = (a_.x - m.x)*(b_.x - a_.x) + (a_.y - m.y)*(b_.y - a_.y); coeff1 = (a_.x - m.x)*(b_.x - a_.x) + (a_.y - m.y)*(b_.y - a_.y);
@@ -218,6 +237,7 @@ void drawSegmentWith(DrawingContext *ctx, vector_t a, vector_t b, vector_t line,
} }
// level 3: boxes and polygons // level 3: boxes and polygons
void drawPolygon(DrawingContext *ctx, int segments, int sides, ...) void drawPolygon(DrawingContext *ctx, int segments, int sides, ...)
{ {
va_list args; va_list args;
@@ -308,13 +328,13 @@ void drawRotationOrbitFrame(DrawingContext *ctx, gsl_matrix *frame, vector_t sta
vector_t v[3], w; vector_t v[3], w;
point_t p; point_t p;
double parameter, startangle; double parameter, startangle;
int iterations = 200; int iterations = 2000;
gsl_matrix *inverse = getTempMatrix(ctx->ws); gsl_matrix *inverse = getTempMatrix(ctx->ws);
gsl_vector *start_v = getTempVector(ctx->ws); gsl_vector *start_v = getTempVector(ctx->ws);
gsl_vector *start_in_frame = getTempVector(ctx->ws); gsl_vector *start_in_frame = getTempVector(ctx->ws);
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
// computeRotationMatrix(ctx, frame, word); // computeRotationMatrixFrame(ctx, frame, word);
LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(frame, j, i); LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(frame, j, i);
LOOP(i) gsl_vector_set(start_v, i, start.x[i]); LOOP(i) gsl_vector_set(start_v, i, start.x[i]);
@@ -350,7 +370,7 @@ void drawRotationOrbit(DrawingContext *ctx, const char *word, vector_t start)
{ {
gsl_matrix *frame = getTempMatrix(ctx->ws); gsl_matrix *frame = getTempMatrix(ctx->ws);
computeRotationMatrix(ctx, frame, word); computeRotationMatrixFrame(ctx, frame, word);
drawRotationOrbitFrame(ctx, frame, start); drawRotationOrbitFrame(ctx, frame, start);
releaseTempMatrices(ctx->ws, 1); releaseTempMatrices(ctx->ws, 1);
@@ -368,7 +388,7 @@ void drawDualRotationOrbit(DrawingContext *ctx, const char *word, vector_t start
gsl_vector *start_in_frame = getTempVector(ctx->ws); gsl_vector *start_in_frame = getTempVector(ctx->ws);
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
computeRotationMatrix(ctx, frame, word); computeRotationMatrixFrame(ctx, frame, word);
LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(frame, j, i); LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(frame, j, i);
LOOP(i) gsl_vector_set(start_v, i, start.x[i]); LOOP(i) gsl_vector_set(start_v, i, start.x[i]);
@@ -413,7 +433,7 @@ void drawArcWithOutput(DrawingContext *ctx, const char *word, vector_t start, ve
gsl_vector *vector_in_frame = getTempVector(ctx->ws); gsl_vector *vector_in_frame = getTempVector(ctx->ws);
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
computeRotationMatrix(ctx, frame, word); computeRotationMatrixFrame(ctx, frame, word);
LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(frame, j, i); LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(frame, j, i);
LOOP(i) gsl_vector_set(vector, i, start.x[i]); LOOP(i) gsl_vector_set(vector, i, start.x[i]);
@@ -555,11 +575,10 @@ void drawAttractors(DrawingContext *ctx)
vector_t p[6][3]; vector_t p[6][3];
vector_t l[6][3]; vector_t l[6][3];
fixedPoints(ctx, "abc", p[0]); fixedPoints(ctx, "cba", p[0]);
fixedPoints(ctx, "bca", p[1]); fixedPoints(ctx, "bac", p[1]);
fixedPoints(ctx, "cab", p[2]); fixedPoints(ctx, "acb", p[2]);
// fixedPoints(ctx, "abacacbabc", p[3]); fixedPoints(ctx, "a cab a", p[3]);
// fixedPoints(ctx, "abcabcabcabcab", p[3]);
fixedPoints(ctx, "b abc b", p[4]); fixedPoints(ctx, "b abc b", p[4]);
fixedPoints(ctx, "c bca c", p[5]); fixedPoints(ctx, "c bca c", p[5]);
@@ -633,6 +652,12 @@ void drawCurvedBox(DrawingContext *ctx, int base, const char *conj, int style)
fixedPoints(ctx, word, p[10]); fixedPoints(ctx, word, p[10]);
// conjugate_word("bca b abc b acb", modifier, conj, word);
// fixedPoints(ctx, word, p[6]);
// conjugate_word("bca baca cab acab acb", modifier, conj, word);
// fixedPoints(ctx, word, p[7]);
LOOP(j) l[0][j] = cross(p[0][(3-j)%3], p[0][(4-j)%3]); LOOP(j) l[0][j] = cross(p[0][(3-j)%3], p[0][(4-j)%3]);
LOOP(j) l[1][j] = cross(p[1][(3-j)%3], p[1][(4-j)%3]); LOOP(j) l[1][j] = cross(p[1][(3-j)%3], p[1][(4-j)%3]);
LOOP(j) l[10][j] = cross(p[10][(3-j)%3], p[10][(4-j)%3]); LOOP(j) l[10][j] = cross(p[10][(3-j)%3], p[10][(4-j)%3]);
@@ -679,68 +704,233 @@ void drawCurvedBox(DrawingContext *ctx, int base, const char *conj, int style)
} }
} }
groupelement_t *left(const char *word, groupelement_t *g)
{
int n = strlen(word);
for(int i = n-1; i >= 0; i--) {
if(word[i] == ' ')
continue;
g = g->adj[word[i]-'a'];
if(!g)
break;
}
return g;
}
void drawBoxes(DrawingContext *ctx) void drawBoxes(DrawingContext *ctx)
{ {
gsl_matrix *rot = getTempMatrix(ctx->ws); gsl_matrix *tmp = getTempMatrix(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
gsl_matrix *frame = getTempMatrix(ctx->ws); gsl_matrix *frame = getTempMatrix(ctx->ws);
gsl_matrix *frame2 = getTempMatrix(ctx->ws);
gsl_vector *startpoint_drawbasis = getTempVector(ctx->ws);
gsl_vector *startpoint_globalbasis = getTempVector(ctx->ws);
gsl_matrix **elements = getTempMatrices(ctx->ws, ctx->n_group_elements);
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
cairo_save(C); cairo_save(C);
vector_t p[22][3];
vector_t l[22][3];
vector_t alpha[6];
vector_t ptmp[3];
char word[100], word2[100];
fixedPoints(ctx, "abc", p[0]);
fixedPoints(ctx, "bca", p[1]);
fixedPoints(ctx, "cab", p[2]);
fixedPoints(ctx, "bacabab", p[3]);
fixedPoints(ctx, "bcacabacb", p[4]);
cairo_set_line_width(C, 2.0/ctx->dim->scalefactor); cairo_set_line_width(C, 2.0/ctx->dim->scalefactor);
cairo_set_source_rgb(C, 0.6, 0.6, 0.6); cairo_set_source_rgb(C, 0.6, 0.6, 0.6);
drawRotationOrbit(ctx, "ab", p[0][0]); vector_t p[22][3];
drawRotationOrbit(ctx, "bc", p[0][0]); vector_t fp[3];
drawRotationOrbit(ctx, "ca", p[0][0]); vector_t l[22][3];
vector_t alpha[6];
vector_t ptmp[3];
vector_t start;
vector_t start2;
char word[100], word2[100];
if(ctx->mode >= 2) { fixedPoints(ctx, "cba", p[0]);
drawRotationOrbit(ctx, "bcabcb", p[1][0]); // bcC fixedPoints(ctx, "acb", p[1]);
drawRotationOrbit(ctx, "abcabcba", p[0][0]); // abcC fixedPoints(ctx, "bac", p[2]);
initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(elements[0]);
for(int i = 1; i < ctx->n_group_elements; i++) {
if(ctx->group[i].length % 2)
continue;
int letter = ROTATION_LETTER(ctx->group[i].letter, ctx->group[i].parent->letter);
multiply(gen[letter], elements[ctx->group[i].parent->parent->id], elements[i]);
} }
cairo_set_source_rgb(C, 0, 0, 0); gsl_vector_set(startpoint_drawbasis, 0, ctx->marking.x);
fixedPoints(ctx, "abababcbaba", p[3]); gsl_vector_set(startpoint_drawbasis, 1, ctx->marking.y);
gsl_vector_set(startpoint_drawbasis, 2, 1);
solve(ctx->cob, startpoint_drawbasis, startpoint_globalbasis, ctx->ws);
LOOP(i) start.x[i] = gsl_vector_get(startpoint_globalbasis, i);
cairo_set_source_rgb(C, 0, 0, 1); /*
fixedPoints(ctx, "bc bca cb", p[3]); fixedPoints(ctx, "ABAB", fp);
drawCovector(ctx, cross(fp[0], fp[2]));
drawVector(ctx, fp[1]);
computeRotationMatrixFrame(ctx, frame, "c");
drawRotationOrbit(ctx, "c", start); // ba cb ab ac = C A c B
drawVector(ctx, start);
computeMatrix(ctx, tmp, "ABABc");
start2 = apply(tmp, start);
computeRotationMatrixFrame(ctx, frame, "c");
multiply(tmp, frame, frame2);
drawVector(ctx, start2);
drawRotationOrbitFrame(ctx, frame2, apply(tmp, start));
computeMatrix(ctx, tmp, "ABABcABABC");
start2 = apply(tmp, start);
computeRotationMatrixFrame(ctx, frame, "c");
multiply(tmp, frame, frame2);
drawVector(ctx, start2);
drawRotationOrbitFrame(ctx, frame2, apply(tmp, start));
*/
for(groupelement_t *cur = &ctx->group[180]; cur->parent; cur = cur->parent)
fputc('a'+cur->letter, stdout);
fputc('\n', stdout);
queue_t queue;
queue_init(&queue);
queue_put(&queue, 0);
int current;
groupelement_t *cur, *next;
for(int i = 0; i < ctx->n_group_elements_combinatorial; i++)
ctx->group[i].visited = 0;
cur = &ctx->group[0];
computeRotationMatrixFrame(ctx, frame, "c");
for(int i = 0; i < 1000; i++) {
if(ctx->group[i].length % 2 != 0)
continue;
multiply(elements[i], frame, frame2);
drawRotationOrbitFrame(ctx, frame2, apply(elements[i], start));
}
/*
while((current = queue_get(&queue)) != -1) {
cur = &ctx->group[current];
if(cur->visited > 4)
continue;
if(cur->id < ctx->n_group_elements) {
multiply(elements[cur->id], frame, frame2);
drawRotationOrbitFrame(ctx, frame2, apply(elements[cur->id], start));
}
next = left("ab ab", cur);
if(next && next->visited == 0) {
queue_put(&queue, next->id);
next->visited = cur->visited+1;
}
next = left("cbac cbac", cur);
if(next && next->visited == 0) {
queue_put(&queue, next->id);
next->visited = cur->visited+1;
}
next = left("cacbca cacbca", cur);
if(next && next->visited == 0) {
queue_put(&queue, next->id);
next->visited = cur->visited+1;
}
next = left("cabcacbcac cabcacbcac", cur);
if(next && next->visited == 0) {
queue_put(&queue, next->id);
next->visited = cur->visited+1;
}
next = left("acbcacba acbcacba", cur);
if(next && next->visited == 0) {
queue_put(&queue, next->id);
next->visited = cur->visited+1;
}
next = left("bcacbc bcacbc", cur);
if(next && next->visited == 0) {
queue_put(&queue, next->id);
next->visited = cur->visited+1;
}
}
*/
// drawRotationOrbit(ctx, "a", p[1][0]);
// drawRotationOrbit(ctx, "b", p[2][0]);
cairo_restore(C); cairo_restore(C);
releaseTempMatrices(ctx->ws, 5); releaseTempMatrices(ctx->ws, 9 + ctx->n_group_elements);
releaseTempVectors(ctx->ws, 2);
} }
void drawBoxes2(DrawingContext *ctx) void drawBoxes2(DrawingContext *ctx)
{ {
gsl_matrix *rot = getTempMatrix(ctx->ws); gsl_matrix *rot = getTempMatrix(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
cairo_save(C); cairo_save(C);
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
vector_t p[4][3]; vector_t p[4][3];
fixedPoints(ctx, "abc", p[0]); fixedPoints(ctx, "cba", p[0]);
fixedPoints(ctx, "bca", p[1]); fixedPoints(ctx, "acb", p[1]);
fixedPoints(ctx, "cab", p[2]); fixedPoints(ctx, "bac", p[2]);
cairo_set_line_width(C, 2.5/ctx->dim->scalefactor); cairo_set_line_width(C, 2.5/ctx->dim->scalefactor);
/*
cairo_set_source_rgb(C, 0, 1, 1);
fixedPoints(ctx, "abc", p[0]);
drawRotationOrbit(ctx, "bc", p[0][0]); // (r^{-1}a)^2 C / cbr
fixedPoints(ctx, "bca", p[0]);
drawRotationOrbit(ctx, "abca", p[0][0]); // (r^{-1}a)^2 C / cbr
cairo_set_source_rgb(C, 1, 1, 0);
fixedPoints(ctx, "abc", p[0]);
drawRotationOrbit(ctx, "cbcabc", p[0][0]); // (r^{-1}a)^4 C / cbac r-
fixedPoints(ctx, "bca", p[0]);
drawRotationOrbit(ctx, "acbcabca", p[0][0]); // (r^{-1}a)^4 C / cbac r-
cairo_set_source_rgb(C, 1, 0, 1);
fixedPoints(ctx, "abc", p[0]);
drawRotationOrbit(ctx, "cbacabcabc", p[0][0]); // (r^{-1}a)^6 C / cbacba
fixedPoints(ctx, "bca", p[0]);
drawRotationOrbit(ctx, "acbacabcabca", p[0][0]); // (r^{-1}a)^6 C / cbacba
*/
/*
cairo_set_source_rgb(C, 1, 0, 0);
fixedPoints(ctx, "bca", p[3]);
drawRotationOrbit(ctx, "bcabcb", p[3][0]); // cb c a bc
fixedPoints(ctx, "abc", p[3]);
drawRotationOrbit(ctx, "abcabcba", p[3][0]); // cb c a bc
cairo_set_source_rgb(C, 0, 1, 0);
fixedPoints(ctx, "ababcba", p[3]);
drawRotationOrbit(ctx, "ababcababa", p[3][0]); // cb c a bc
fixedPoints(ctx, "abc", p[3]);
drawRotationOrbit(ctx, "abcabcabacba", p[3][0]); // cb c a bc
*/
// drawRotationOrbit(ctx, "bc", p[3][0]);
cairo_set_source_rgb(C, 0, 0, 0); cairo_set_source_rgb(C, 0, 0, 0);
drawCurvedBox(ctx, 'A', "", 2); drawCurvedBox(ctx, 'A', "", 2);
cairo_set_source_rgb(C, 0, 0, 1);
// drawCurvedBox(ctx, 'C', "ab", 2);
// drawCurvedBox(ctx, 'C', "ab", 2);
// drawCurvedBox(ctx, 'B', "bca", 2);
// drawCurvedBox(ctx, 'B', "ba", 2);
// drawCurvedBox(ctx, 'B', "bca", 2);
// drawCurvedBox(ctx, 'B', "abca", 2);
// drawCurvedBox(ctx, 'C', "abab", 2);
// drawCurvedBox(ctx, 'C', "ababab", 2);
if(ctx->mode >= 3 && ctx->mode != 4) { if(ctx->mode >= 3 && ctx->mode != 4) {
cairo_set_source_rgb(C, 0, 0, 0); cairo_set_source_rgb(C, 0, 0, 0);
drawCurvedBox(ctx, 'B', "", 2); drawCurvedBox(ctx, 'B', "", 2);
@@ -756,11 +946,15 @@ void drawBoxes2(DrawingContext *ctx)
drawCurvedBox(ctx, 'A', "bcbcbcbc", 2); drawCurvedBox(ctx, 'A', "bcbcbcbc", 2);
drawCurvedBox(ctx, 'A', "bcbcbcbcbc", 2); drawCurvedBox(ctx, 'A', "bcbcbcbcbc", 2);
drawCurvedBox(ctx, 'A', "bcbcbcbcbcbc", 2); drawCurvedBox(ctx, 'A', "bcbcbcbcbcbc", 2);
// drawCurvedBox(ctx, 'A', "b", 2);
// drawCurvedBox(ctx, 'A', "bcb", 2);
// drawCurvedBox(ctx, 'A', "bcbcb", 2);
// drawCurvedBox(ctx, 'A', "bcbcbcb", 2);
// drawCurvedBox(ctx, 'A', "bcbcbcbcb", 2);
} }
if(ctx->mode == 6) { if(ctx->mode == 6) {
cairo_set_source_rgb(C, 0, 0.8, 0.5); cairo_set_source_rgb(C, 0, 0.8, 0.5);
drawCurvedBox(ctx, 'C', "ababab", 2);
drawCurvedBox(ctx, 'C', "abababab", 2); drawCurvedBox(ctx, 'C', "abababab", 2);
drawCurvedBox(ctx, 'C', "ababababab", 2); drawCurvedBox(ctx, 'C', "ababababab", 2);
} }
@@ -769,45 +963,291 @@ void drawBoxes2(DrawingContext *ctx)
cairo_set_source_rgb(C, 0, 0.8, 0.5); cairo_set_source_rgb(C, 0, 0.8, 0.5);
drawCurvedBox(ctx, 'C', "ab", 2); drawCurvedBox(ctx, 'C', "ab", 2);
drawCurvedBox(ctx, 'C', "abab", 2); drawCurvedBox(ctx, 'C', "abab", 2);
drawCurvedBox(ctx, 'C', "ababab", 2);
} }
if(ctx->mode >= 8) { if(ctx->mode >= 8) {
cairo_set_source_rgb(C, 0, 0.8, 0.5); cairo_set_source_rgb(C, 0, 0.8, 0.5);
drawCurvedBox(ctx, 'C', "b", 2); drawCurvedBox(ctx, 'C', "b", 2);
drawCurvedBox(ctx, 'C', "bab", 2); drawCurvedBox(ctx, 'C', "bab", 2);
drawCurvedBox(ctx, 'C', "babab", 2);
} }
if(ctx->mode >= 9) { if(ctx->mode >= 9) {
cairo_set_source_rgb(C, 0.8, 0, 0.5); cairo_set_source_rgb(C, 0.8, 0, 0.5);
drawCurvedBox(ctx, 'B', "abca", 2); drawCurvedBox(ctx, 'B', "abca", 2);
drawCurvedBox(ctx, 'B', "abcaca", 2); drawCurvedBox(ctx, 'B', "abcaca", 2);
drawCurvedBox(ctx, 'B', "aba", 2); drawCurvedBox(ctx, 'B', "abcacaca", 2);
drawCurvedBox(ctx, 'B', "abaca", 2); drawCurvedBox(ctx, 'B', "aba", 2);
drawCurvedBox(ctx, 'B', "abaca", 2);
drawCurvedBox(ctx, 'B', "abacaca", 2);
drawCurvedBox(ctx, 'B', "ababca", 2); drawCurvedBox(ctx, 'B', "ababca", 2);
drawCurvedBox(ctx, 'B', "ababcaca", 2); drawCurvedBox(ctx, 'B', "ababcaca", 2);
drawCurvedBox(ctx, 'B', "ababa", 2); drawCurvedBox(ctx, 'B', "ababcacaca", 2);
drawCurvedBox(ctx, 'B', "ababaca", 2); drawCurvedBox(ctx, 'B', "ababa", 2);
drawCurvedBox(ctx, 'B', "ababaca", 2);
drawCurvedBox(ctx, 'B', "ababacaca", 2);
drawCurvedBox(ctx, 'B', "bca", 2); drawCurvedBox(ctx, 'B', "abababca", 2);
drawCurvedBox(ctx, 'B', "bcaca", 2); drawCurvedBox(ctx, 'B', "abababcaca", 2);
drawCurvedBox(ctx, 'B', "ba", 2); drawCurvedBox(ctx, 'B', "abababcacaca", 2);
drawCurvedBox(ctx, 'B', "baca", 2); drawCurvedBox(ctx, 'B', "abababa", 2);
drawCurvedBox(ctx, 'B', "abababaca", 2);
drawCurvedBox(ctx, 'B', "abababacaca", 2);
drawCurvedBox(ctx, 'B', "babca", 2); drawCurvedBox(ctx, 'B', "bca", 2);
drawCurvedBox(ctx, 'B', "babcaca", 2); drawCurvedBox(ctx, 'B', "bcaca", 2);
drawCurvedBox(ctx, 'B', "baba", 2); drawCurvedBox(ctx, 'B', "bcacaca", 2);
drawCurvedBox(ctx, 'B', "babaca", 2); drawCurvedBox(ctx, 'B', "ba", 2);
drawCurvedBox(ctx, 'B', "baca", 2);
drawCurvedBox(ctx, 'B', "bacaca", 2);
cairo_restore(C); drawCurvedBox(ctx, 'B', "babca", 2);
releaseTempMatrices(ctx->ws, 4); drawCurvedBox(ctx, 'B', "babcaca", 2);
drawCurvedBox(ctx, 'B', "babcacaca", 2);
drawCurvedBox(ctx, 'B', "baba", 2);
drawCurvedBox(ctx, 'B', "babaca", 2);
drawCurvedBox(ctx, 'B', "babacaca", 2);
drawCurvedBox(ctx, 'B', "bababca", 2);
drawCurvedBox(ctx, 'B', "bababcaca", 2);
drawCurvedBox(ctx, 'B', "bababcacaca", 2);
drawCurvedBox(ctx, 'B', "bababa", 2);
drawCurvedBox(ctx, 'B', "bababaca", 2);
drawCurvedBox(ctx, 'B', "bababacaca", 2);
} }
// drawCurvedBox(ctx, 'B', "abab", 2);
// drawCurvedBox(ctx, 'B', "ababab", 2);
// drawCurvedBox(ctx, 'C', "b", 1);
// drawCurvedBox(ctx, 'C', "ababab");
// drawCurvedBox(ctx, 'C', "abababab");
// drawCurvedBox(ctx, 'C', "b");
// drawCurvedBox(ctx, 'C', "bab");
// drawCurvedBox(ctx, 'C', "babab");
// drawCurvedBox(ctx, 'C', "abababab");
// drawCurvedBox(ctx, 'C', "ababababab");
// drawCurvedBox(ctx, 'C', "abababababab");
cairo_set_source_rgb(C, 0, 0, 1);
// drawCurvedBox(ctx, 'B', "abca", 1);
// drawCurvedBox(ctx, 'B', "aba", 1);
// drawCurvedBox(ctx, 'B', "bca", 1);
// drawCurvedBox(ctx, 'B', "ba", 1);
// drawCurvedBox(ctx, 'B', "abaca");
// drawCurvedBox(ctx, 'B', "abcaca");
// drawCurvedBox(ctx, 'B', "abaca");
// drawCurvedBox(ctx, 'B', "aba");
// drawCurvedBox(ctx, 'B', "ababca");
// drawCurvedBox(ctx, 'B', "ababa");
// drawCurvedBox(ctx, 'B', "abababca");
// drawCurvedBox(ctx, 'B', "abababa");
// drawCurvedBox(ctx, 'B', "bca");
// drawCurvedBox(ctx, 'B', "ba");
// drawCurvedBox(ctx, 'B', "babca");
// drawCurvedBox(ctx, 'B', "baba");
// drawCurvedBox(ctx, 'B', "bababca");
// drawCurvedBox(ctx, 'B', "bababa");
cairo_set_source_rgb(C, 1, 0, 1);
// drawCurvedBox(ctx, 'A', "abcac");
// drawCurvedBox(ctx, 'A', "bcac");
// drawCurvedBox(ctx, 'A', "abcacbc");
// drawCurvedBox(ctx, 'A', "abcac");
// drawCurvedBox(ctx, 'A', "abcacbc");
// drawCurvedBox(ctx, 'A', "ababc");
// drawCurvedBox(ctx, 'A', "ababcbc");
/* drawCurvedBox(ctx, 'A', "abcac");
drawCurvedBox(ctx, 'A', "ababc");
drawCurvedBox(ctx, 'A', "abac");
drawCurvedBox(ctx, 'A', "ababcabc");
drawCurvedBox(ctx, 'A', "ababcac");
drawCurvedBox(ctx, 'A', "abababc");
drawCurvedBox(ctx, 'A', "ababac");
drawCurvedBox(ctx, 'A', "abababcabc");
drawCurvedBox(ctx, 'A', "abababcac");
drawCurvedBox(ctx, 'A', "ababababc");
drawCurvedBox(ctx, 'A', "abababac");
drawCurvedBox(ctx, 'A', "bcabc");
drawCurvedBox(ctx, 'A', "bcac");
drawCurvedBox(ctx, 'A', "babc");
drawCurvedBox(ctx, 'A', "bac");
drawCurvedBox(ctx, 'A', "babcabc");
drawCurvedBox(ctx, 'A', "babcac");
drawCurvedBox(ctx, 'A', "bababc");
drawCurvedBox(ctx, 'A', "babac");
drawCurvedBox(ctx, 'A', "bababcabc");
drawCurvedBox(ctx, 'A', "bababcac");
drawCurvedBox(ctx, 'A', "babababc");
drawCurvedBox(ctx, 'A', "bababac");
*/
// drawCurvedBox(ctx, 'A', "ababc");
cairo_set_source_rgb(C, 1, 0.5, 0);
// drawCurvedBox(ctx, 'C', "abcabcab");
// drawCurvedBox(ctx, 'B', "bca");
// drawCurvedBox(ctx, 'B', "abcacaca");
// drawCurvedBox(ctx, 'B', "abaca");
// drawCurvedBox(ctx, 'B', "aba");
// drawCurvedBox(ctx, 'B', "aba");
// drawCurvedBox(ctx, 'B', "abcaca");
// drawCurvedBox(ctx, 'B', "aba");
// drawCurvedBox(ctx, 'B', "abaca");
cairo_set_source_rgb(C, 0, 0, 1);
// drawCurvedBox(ctx, 'A', "abcabc");
// drawCurvedBox(ctx, 'A', "abcabcbc");
// drawCurvedBox(ctx, 'A', "abcacbc");
// drawCurvedBox(ctx, 'A', "abcac");
// drawCurvedBox(ctx, 'A', "bcabc");
// drawCurvedBox(ctx, 'A', "bcabcbc");
// drawCurvedBox(ctx, 'A', "bcacbc");
// drawCurvedBox(ctx, 'A', "bcac");
// drawCurvedBox(ctx, 'A', "abcac");
// drawCurvedBox(ctx, 'A', "abcac");
// drawCurvedBox(ctx, 'A', "abcacbc");
// drawCurvedBox(ctx, 'B', "abacaca");
// drawCurvedBox(ctx, 'B', "abacacaca");
cairo_set_source_rgb(C, 0, 1, 1);
fixedPoints(ctx, "ababcba", p[0]);
// drawRotationOrbit(ctx, "abcaba", p[0][0]);
/*
int p = 9;
vector_t fp[3][3],neutral_line[3],reflection_line[p],star[2*p],outer[2];
vector_t rotation_line = {0,0,1};
cairo_set_line_width(C, 1.5/ctx->dim->scalefactor);
cairo_set_source_rgb(C, 1, 0, 0);
multiply(gen[0], gen[1], rot);
fixedPoints(ctx, "abc", fp[0]);
fixedPoints(ctx, "bca", fp[1]);
fixedPoints(ctx, "cab", fp[2]);
LOOP(i) neutral_line[i] = cross(fp[i][0], fp[i][2]);
LOOP(j) reflection_line[0].x[j] = gsl_matrix_get(ctx->cartan, 0, j);
star[0] = cross(neutral_line[0],reflection_line[0]);
star[p] = cross(neutral_line[2],reflection_line[0]);
for(int j = 1; j < p; j++) {
reflection_line[j] = apply_transpose(rot, reflection_line[j-1]);
star[j] = apply(rot, star[j-1]);
star[j+p] = apply(rot, star[j+p-1]);
}
outer[0] = cross(neutral_line[0],reflection_line[5]);
outer[1] = cross(neutral_line[2],reflection_line[5]);
for(int j = 0; j < 8; j++) {
drawVector(ctx, star[j]);
drawVector(ctx, star[p+j]);
}
for(int j = 0; j < 7; j++) {
// if(j == 3)
// continue;
drawSegment(ctx, star[j%p], star[(j+1)%p+p]);
drawSegment(ctx, star[(j+1)%p+p], star[(j+1)%p]);
drawSegment(ctx, star[(j+1)%p], star[j%p+p]);
drawSegment(ctx, star[j%p+p], star[j%p]);
}
cairo_set_source_rgb(C, 0, 0, 1);
drawVector(ctx,outer[0]);
drawVector(ctx,outer[1]);
// drawCovector(ctx, neutral_line[0]);
// drawCovector(ctx, neutral_line[2]);
drawSegment(ctx, star[0], star[p]);
drawSegment(ctx, star[p], outer[1]);
drawSegment(ctx, outer[1], outer[0]);
drawSegment(ctx, outer[0], star[0]);
cairo_set_source_rgb(C, 0, 0, 0);
drawCovector(ctx, rotation_line);
*/
// for(int j = 0; j < 5; j++)
// drawCovector(ctx, reflection_line[j]);
// intersect attracting line with neutral line of the other element
// for(int j = 0; j < 2; j++)
// i[j] = cross(cross(p[j%2][0],p[j%2][1]),cross(p[(j+1)%2][0],p[(j+1)%2][2]));
// drawPolygon(ctx, 1, 4, p[0][0], i[0], p[1][0], i[1]);
// abc, ababcba, abababcbaba, ..., cab
// bca, acaba, abacababa, ..., babcb
/*
vector_t v[4][3];
vector_t i[4];
fixedPoints(ctx, "abc", v[0]);
fixedPoints(ctx, "bca", v[1]);
fixedPoints(ctx, "cab", v[2]);
fixedPoints(ctx, "acaba", v[3]);
i[0] = cross(cross(v[0][1],v[0][2]),cross(v[2][0],v[2][2]));
i[1] = cross(cross(v[1][1],v[1][2]),cross(v[3][0],v[3][2]));
i[2] = cross(cross(v[2][0],v[2][2]),cross(v[3][0],v[3][2]));
i[3] = cross(cross(v[0][0],v[0][2]),cross(v[1][0],v[1][2]));
// cairo_set_source_rgb(C, 0, 0, 1);
// drawPolygon(ctx, 1, 6, v[2][2], v[1][1], v[0][1], v[3][2], v[3][1], v[2][1]);
// drawPolygon(ctx, 1, 6, v[1][2], i[1], i[2], i[0], v[0][2], i[3]);
cairo_set_line_width(C, 1.5/ctx->dim->scalefactor);
cairo_set_source_rgb(C, 1, 0, 0);
// drawBox(ctx, "bca", "abc");
drawCurvedBox(ctx, 'A', "");
*/
/*
cairo_set_source_rgb(C, 1, 0.5, 0);
drawBox(ctx, "ab abc ba", "ab cab ba");
drawBox(ctx, "abab abc baba", "abab cab baba");
drawBox(ctx, "ababab abc bababa", "ababab cab bababa");
drawBox(ctx, "abababab abc babababa", "abababab cab babababa");
// drawBox(ctx, "ababababab abc bababababa", "ababababab cab bababababa");
drawBox(ctx, "b abc b", "b cab b");
drawBox(ctx, "bab abc bab", "bab cab bab");
drawBox(ctx, "babab abc babab", "babab cab babab");
drawBox(ctx, "bababab abc bababab", "bababab cab bababab");
// drawBox(ctx, "babababab abc babababab", "babababab cab babababab");
*/
cairo_restore(C);
releaseTempMatrices(ctx->ws, 7);
} }
void drawRotatedReflectors(DrawingContext *ctx) void drawRotatedReflectors(DrawingContext *ctx)
{ {
gsl_matrix *rot = getTempMatrix(ctx->ws); gsl_matrix *rot = getTempMatrix(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
cairo_t *C = ctx->cairo; cairo_t *C = ctx->cairo;
vector_t fp[3], fp2[3]; vector_t fp[3], fp2[3];
vector_t w; vector_t w;
@@ -815,7 +1255,7 @@ void drawRotatedReflectors(DrawingContext *ctx)
cairo_set_source_rgb(C, 0.7, 0.7, 0.7); cairo_set_source_rgb(C, 0.7, 0.7, 0.7);
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(ctx->cartan, i, j); LOOP(i) LOOP(j) v[i].x[j] = gsl_matrix_get(ctx->cartan, i, j);
multiply(gen[0], gen[1], rot); multiply(gen[0], gen[1], rot);
@@ -836,7 +1276,7 @@ void drawRotatedReflectors(DrawingContext *ctx)
fixedPoints(ctx, "cacabac", fp2); fixedPoints(ctx, "cacabac", fp2);
drawRotationOrbit(ctx, "ac", fp[0]); drawRotationOrbit(ctx, "ac", fp[0]);
releaseTempMatrices(ctx->ws, 4); releaseTempMatrices(ctx->ws, 7);
} }
void drawDualLimitCurve(DrawingContext *ctx) void drawDualLimitCurve(DrawingContext *ctx)
@@ -846,12 +1286,36 @@ void drawDualLimitCurve(DrawingContext *ctx)
cairo_save(C); cairo_save(C);
cairo_set_source_rgb(C, 0.5, 0.5, 1); cairo_set_source_rgb(C, 0.5, 0.5, 1);
int n = 18; gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
vector_t p[n][3]; gsl_matrix **elements = getTempMatrices(ctx->ws, ctx->n_group_elements);
vector_t l[n][3];
vector_t ptmp[3], ltmp[3];
fixedPoints(ctx, "abc", p[0]); // wordEigenvalues(ctx, "abc", ev);
// LOOP(i) LOOP(j) gsl_matrix_set(coxeter_fixedpoints, j, i, cox[0][i].x[j]);
initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(elements[0]);
for(int i = 1; i < ctx->n_group_elements; i++)
multiply(gen[ctx->group[i].letter], elements[ctx->group[i].parent->id], elements[i]);
vector_t p[3], l[3], v;
fixedPoints(ctx, "cba", p);
drawVector(ctx, p[0]);
drawVector(ctx, p[1]);
drawVector(ctx, p[2]);
LOOP(i) l[i] = cross(p[(i+1)%3], p[(i+2)%3]);
for(int i = 0; i < ctx->n_group_elements; i++) {
v = apply_transpose(elements[i], l[0]);
drawCovector(ctx, v);
}
releaseTempMatrices(ctx->ws, 3 + ctx->n_group_elements);
// releaseTempVectors(ctx->ws, 4);
/*
fixedPoints(ctx, "ab abc ba", p[1]); fixedPoints(ctx, "ab abc ba", p[1]);
fixedPoints(ctx, "abab abc baba", p[2]); fixedPoints(ctx, "abab abc baba", p[2]);
fixedPoints(ctx, "ababab abc bababa", p[3]); fixedPoints(ctx, "ababab abc bababa", p[3]);
@@ -870,6 +1334,7 @@ void drawDualLimitCurve(DrawingContext *ctx)
fixedPoints(ctx, "bababa bca ababab", p[15]); fixedPoints(ctx, "bababa bca ababab", p[15]);
fixedPoints(ctx, "baba bca abab", p[16]); fixedPoints(ctx, "baba bca abab", p[16]);
fixedPoints(ctx, "ba bca ab", p[17]); fixedPoints(ctx, "ba bca ab", p[17]);
*/
/* /*
fixedPoints(ctx, "abc", p[0]); fixedPoints(ctx, "abc", p[0]);
@@ -907,6 +1372,7 @@ void drawDualLimitCurve(DrawingContext *ctx)
// drawCovector(ctx, l[i][2]); // drawCovector(ctx, l[i][2]);
}*/ }*/
/*
fixedPoints(ctx, "abc", ptmp); fixedPoints(ctx, "abc", ptmp);
drawCovector(ctx, cross(ptmp[0], ptmp[1])); drawCovector(ctx, cross(ptmp[0], ptmp[1]));
fixedPoints(ctx, "bca", ptmp); fixedPoints(ctx, "bca", ptmp);
@@ -919,6 +1385,7 @@ void drawDualLimitCurve(DrawingContext *ctx)
drawCovector(ctx, cross(ptmp[0], ptmp[1])); drawCovector(ctx, cross(ptmp[0], ptmp[1]));
fixedPoints(ctx, "acaba", ptmp); fixedPoints(ctx, "acaba", ptmp);
drawCovector(ctx, cross(ptmp[0], ptmp[1])); drawCovector(ctx, cross(ptmp[0], ptmp[1]));
*/
cairo_restore(C); cairo_restore(C);
} }
@@ -974,7 +1441,7 @@ void drawLimitCurve(DrawingContext *ctx)
void drawCoxeterOrbit(DrawingContext *ctx) void drawCoxeterOrbit(DrawingContext *ctx)
{ {
gsl_matrix *rot = getTempMatrix(ctx->ws); gsl_matrix *rot = getTempMatrix(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
gsl_vector *eval = getTempVector(ctx->ws); gsl_vector *eval = getTempVector(ctx->ws);
gsl_matrix *coxeter_fixedpoints = getTempMatrix(ctx->ws); gsl_matrix *coxeter_fixedpoints = getTempMatrix(ctx->ws);
gsl_vector *startpoint_coxeterbasis = getTempVector(ctx->ws); gsl_vector *startpoint_coxeterbasis = getTempVector(ctx->ws);
@@ -991,7 +1458,7 @@ void drawCoxeterOrbit(DrawingContext *ctx)
int first = 1; int first = 1;
cairo_save(C); cairo_save(C);
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
cairo_set_source_rgb(C, 0, 0, 1); cairo_set_source_rgb(C, 0, 0, 1);
@@ -1002,7 +1469,7 @@ void drawCoxeterOrbit(DrawingContext *ctx)
wordEigenvalues(ctx, "abc", ev); wordEigenvalues(ctx, "abc", ev);
LOOP(i) LOOP(j) gsl_matrix_set(coxeter_fixedpoints, j, i, cox[0][i].x[j]); LOOP(i) LOOP(j) gsl_matrix_set(coxeter_fixedpoints, j, i, cox[0][i].x[j]);
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(elements[0]); gsl_matrix_set_identity(elements[0]);
for(int i = 1; i < ctx->n_group_elements; i++) for(int i = 1; i < ctx->n_group_elements; i++)
multiply(gen[ctx->group[i].letter], elements[ctx->group[i].parent->id], elements[i]); multiply(gen[ctx->group[i].letter], elements[ctx->group[i].parent->id], elements[i]);
@@ -1016,7 +1483,7 @@ void drawCoxeterOrbit(DrawingContext *ctx)
gsl_vector_set(startpoint_drawbasis, 2, 1); gsl_vector_set(startpoint_drawbasis, 2, 1);
solve(ctx->cob, startpoint_drawbasis, startpoint_globalbasis, ctx->ws); solve(ctx->cob, startpoint_drawbasis, startpoint_globalbasis, ctx->ws);
solve(coxeter_fixedpoints, startpoint_globalbasis, startpoint_coxeterbasis, ctx->ws); // solve(coxeter_fixedpoints, startpoint_globalbasis, startpoint_coxeterbasis, ctx->ws);
// LOOP(i) start.x[i] = gsl_vector_get(startpoint_coxeterbasis, i); // LOOP(i) start.x[i] = gsl_vector_get(startpoint_coxeterbasis, i);
LOOP(i) start.x[i] = gsl_vector_get(startpoint_globalbasis, i); LOOP(i) start.x[i] = gsl_vector_get(startpoint_globalbasis, i);
@@ -1056,7 +1523,7 @@ void drawCoxeterOrbit(DrawingContext *ctx)
// LOOP(i) drawVector(ctx, abcb[i]); // LOOP(i) drawVector(ctx, abcb[i]);
cairo_restore(C); cairo_restore(C);
releaseTempMatrices(ctx->ws, 5 + ctx->n_group_elements); releaseTempMatrices(ctx->ws, 8 + ctx->n_group_elements);
releaseTempVectors(ctx->ws, 4); releaseTempVectors(ctx->ws, 4);
} }
@@ -1065,7 +1532,7 @@ void drawText(DrawingContext *ctx)
cairo_move_to(ctx->cairo, 15, 30); cairo_move_to(ctx->cairo, 15, 30);
cairo_set_source_rgb(ctx->cairo, 0, 0, 0); cairo_set_source_rgb(ctx->cairo, 0, 0, 0);
char buf[100]; char buf[100];
sprintf(buf, "t = exp(%.8f) = %.8f, marking = (%.5f, %.5f)", log(ctx->parameter), ctx->parameter, ctx->marking.x, ctx->marking.y); sprintf(buf, "t = exp(%.8f) = %.8f, s = exp(%.8f) = %.8f, marking = (%.5f, %.5f)", log(ctx->parameter), ctx->parameter, log(ctx->parameter2), ctx->parameter2, ctx->marking.x, ctx->marking.y);
cairo_show_text(ctx->cairo, buf); cairo_show_text(ctx->cairo, buf);
} }
@@ -1111,6 +1578,7 @@ void draw(DrawingContext *ctx)
if(ctx->show_marking) if(ctx->show_marking)
{ {
cairo_set_source_rgb(C, 0, 0, 1); cairo_set_source_rgb(C, 0, 0, 1);
drawPoint(ctx, ctx->marking);
} }
if(ctx->show_coxeter_orbit) if(ctx->show_coxeter_orbit)
@@ -1120,7 +1588,7 @@ void draw(DrawingContext *ctx)
cairo_identity_matrix(C); // text is in screen coordinates cairo_identity_matrix(C); // text is in screen coordinates
if(ctx->show_text) if(ctx->show_text)
drawText(ctx); drawText(ctx);
cairo_surface_flush(cairo_get_target(C)); cairo_surface_flush(cairo_get_target(C));
} }

View File

@@ -5,6 +5,7 @@ static int compareAngle(const void *x, const void *y)
return ((double*)x)[2] > ((double*)y)[2] ? 1 : -1; return ((double*)x)[2] > ((double*)y)[2] ? 1 : -1;
} }
// might need a rewrite
void cartanMatrix(gsl_matrix *cartan, double a1, double a2, double a3, double s) void cartanMatrix(gsl_matrix *cartan, double a1, double a2, double a3, double s)
{ {
gsl_matrix_set(cartan, 0, 0, 2); gsl_matrix_set(cartan, 0, 0, 2);
@@ -20,11 +21,58 @@ void cartanMatrix(gsl_matrix *cartan, double a1, double a2, double a3, double s)
gsl_matrix_set(cartan, 2, 2, 2); gsl_matrix_set(cartan, 2, 2, 2);
} }
void initializeTriangleGenerators(gsl_matrix **gen, gsl_matrix *cartan) void initializeTriangleGenerators(gsl_matrix **gen, double a1, double a2, double a3, double s, double t, workspace_t *ws)
{ {
LOOP(i) gsl_matrix_set_identity(gen[i]); gsl_matrix *reflection_gen[3];
LOOP(i) LOOP(j) *gsl_matrix_ptr(gen[i], j, j) = -1.0;
LOOP(i) LOOP(j) *gsl_matrix_ptr(gen[i], i, j) += gsl_matrix_get(cartan, i, j); LOOP(i) {
reflection_gen[i] = gsl_matrix_alloc(3, 3);
gsl_matrix_set_identity(reflection_gen[i]);
}
double rho[3];
rho[0] = sqrt(s*s + 2*s*cos(a1) + 1);
rho[1] = sqrt(s*s + 2*s*cos(a2) + 1);
rho[2] = sqrt(s*s + 2*s*cos(a3) + 1);
gsl_matrix_set(reflection_gen[0], 0, 0, -1.0);
gsl_matrix_set(reflection_gen[0], 0, 1, rho[2]*t);
gsl_matrix_set(reflection_gen[0], 0, 2, rho[1]/t);
gsl_matrix_set(reflection_gen[1], 1, 0, rho[2]/t);
gsl_matrix_set(reflection_gen[1], 1, 1, -1.0);
gsl_matrix_set(reflection_gen[1], 1, 2, rho[0]*t);
gsl_matrix_set(reflection_gen[2], 2, 0, rho[1]*t);
gsl_matrix_set(reflection_gen[2], 2, 1, rho[0]/t);
gsl_matrix_set(reflection_gen[2], 2, 2, -1.0);
LOOP(i) {
gsl_matrix_set_identity(gen[i]);
gsl_matrix_set(gen[i], (i+1)%3, (i+1)%3, s);
gsl_matrix_set(gen[i], (i+2)%3, (i+2)%3, 1/s);
gsl_matrix_set_identity(gen[i+3]);
gsl_matrix_set(gen[i+3], (i+1)%3, (i+1)%3, 1/s);
gsl_matrix_set(gen[i+3], (i+2)%3, (i+2)%3, s);
}
LOOP(i) {
multiply_left(reflection_gen[i], gen[(i+2)%3], ws);
multiply_right(gen[(i+2)%3], reflection_gen[(i+1)%3], ws);
multiply_left(reflection_gen[(i+1)%3], gen[(i+2)%3+3], ws);
multiply_right(gen[(i+2)%3+3], reflection_gen[i], ws);
}
LOOP(i) gsl_matrix_free(reflection_gen[i]);
}
void initializeTriangleGeneratorsCurrent(gsl_matrix **gen, DrawingContext *ctx)
{
double angle[3];
LOOP(i) angle[i] = 2*M_PI*ctx->k[i]/ctx->p[i];
initializeTriangleGenerators(gen, angle[0], angle[1], angle[2], ctx->parameter2, ctx->parameter, ctx->ws);
} }
int computeLimitCurve(DrawingContext *ctx) int computeLimitCurve(DrawingContext *ctx)
@@ -38,7 +86,7 @@ int computeLimitCurve(DrawingContext *ctx)
gsl_matrix *coxeter = getTempMatrix(ctx->ws); gsl_matrix *coxeter = getTempMatrix(ctx->ws);
gsl_matrix *coxeter_fixedpoints = getTempMatrix(ctx->ws); gsl_matrix *coxeter_fixedpoints = getTempMatrix(ctx->ws);
gsl_matrix *fixedpoints = getTempMatrix(ctx->ws); gsl_matrix *fixedpoints = getTempMatrix(ctx->ws);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
gsl_matrix **elements = getTempMatrices(ctx->ws, ctx->n_group_elements); gsl_matrix **elements = getTempMatrices(ctx->ws, ctx->n_group_elements);
groupelement_t *group = ctx->group; groupelement_t *group = ctx->group;
int success = 0; int success = 0;
@@ -50,31 +98,43 @@ int computeLimitCurve(DrawingContext *ctx)
// do first in the Fuchsian positive case to get the angles // do first in the Fuchsian positive case to get the angles
cartanMatrix(cartan_pos, M_PI/ctx->p[0], M_PI/ctx->p[1], M_PI/ctx->p[2], 1.0); cartanMatrix(cartan_pos, M_PI/ctx->p[0], M_PI/ctx->p[1], M_PI/ctx->p[2], 1.0);
initializeTriangleGenerators(gen, cartan_pos); initializeTriangleGenerators(gen, 2*M_PI/ctx->p[0], 2*M_PI/ctx->p[1], 2*M_PI/ctx->p[2], 1.0, 1.0, ctx->ws);
gsl_matrix_set_identity(elements[0]); gsl_matrix_set_identity(elements[0]);
for(int i = 1; i < ctx->n_group_elements; i++) for(int i = 1; i < ctx->n_group_elements; i++) {
multiply(gen[group[i].letter], elements[group[i].parent->id], elements[i]); if(group[i].length % 2)
continue;
int letter = ROTATION_LETTER(group[i].letter, group[i].parent->letter);
multiply(gen[letter], elements[group[i].parent->parent->id], elements[i]);
}
diagonalize_symmetric_form(cartan_pos, cob_pos, ws); diagonalize_symmetric_form(cartan_pos, cob_pos, ws);
multiply_many(ws, coxeter_pos, 3, gen[0], gen[1], gen[2]); multiply_many(ws, coxeter_pos, 3, gen[2], gen[1], gen[0]);
int ev_count_pos = real_eigenvectors(coxeter_pos, coxeter_fixedpoints_pos, ws); int ev_count_pos = real_eigenvectors(coxeter_pos, coxeter_fixedpoints_pos, ws);
if(ev_count_pos != 3) if(ev_count_pos != 3)
goto error_out; goto error_out;
int n = 0;
for(int i = 0; i < ctx->n_group_elements; i++) { for(int i = 0; i < ctx->n_group_elements; i++) {
if(group[i].length % 2)
continue;
multiply_many(ws, fixedpoints_pos, 3, cob_pos, elements[i], coxeter_fixedpoints_pos); multiply_many(ws, fixedpoints_pos, 3, cob_pos, elements[i], coxeter_fixedpoints_pos);
ctx->limit_curve[3*i+2] = atan2( ctx->limit_curve[3*n+2] = atan2(
gsl_matrix_get(fixedpoints_pos, 2, column)/gsl_matrix_get(fixedpoints_pos, 0, column), gsl_matrix_get(fixedpoints_pos, 2, column)/gsl_matrix_get(fixedpoints_pos, 0, column),
gsl_matrix_get(fixedpoints_pos, 1, column)/gsl_matrix_get(fixedpoints_pos, 0, column)); gsl_matrix_get(fixedpoints_pos, 1, column)/gsl_matrix_get(fixedpoints_pos, 0, column));
n++;
} }
// now do it again to calculate x and y coordinates // now do it again to calculate x and y coordinates
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(elements[0]); gsl_matrix_set_identity(elements[0]);
for(int i = 1; i < ctx->n_group_elements; i++) for(int i = 1; i < ctx->n_group_elements; i++) {
multiply(gen[group[i].letter], elements[group[i].parent->id], elements[i]); if(group[i].length % 2)
continue;
int letter = ROTATION_LETTER(group[i].letter, group[i].parent->letter);
multiply(gen[letter], elements[group[i].parent->parent->id], elements[i]);
}
multiply_many(ws, coxeter, 3, gen[0], gen[1], gen[2]); multiply_many(ws, coxeter, 3, gen[2], gen[1], gen[0]);
int ev_count = real_eigenvectors(coxeter, coxeter_fixedpoints, ws); int ev_count = real_eigenvectors(coxeter, coxeter_fixedpoints, ws);
if(ev_count == 1) if(ev_count == 1)
@@ -82,11 +142,17 @@ int computeLimitCurve(DrawingContext *ctx)
if(ev_count == 0) if(ev_count == 0)
goto error_out; goto error_out;
ctx->limit_curve_count = 0;
for(int i = 0; i < ctx->n_group_elements; i++) { for(int i = 0; i < ctx->n_group_elements; i++) {
if(group[i].length % 2)
continue;
multiply_many(ws, fixedpoints, 3, ctx->cob, elements[i], coxeter_fixedpoints); multiply_many(ws, fixedpoints, 3, ctx->cob, elements[i], coxeter_fixedpoints);
x = ctx->limit_curve[3*i ] = gsl_matrix_get(fixedpoints, 0, column)/gsl_matrix_get(fixedpoints, 2, column); x = ctx->limit_curve[3*ctx->limit_curve_count ] = gsl_matrix_get(fixedpoints, 0, column)/gsl_matrix_get(fixedpoints, 2, column);
y = ctx->limit_curve[3*i+1] = gsl_matrix_get(fixedpoints, 1, column)/gsl_matrix_get(fixedpoints, 2, column); y = ctx->limit_curve[3*ctx->limit_curve_count+1] = gsl_matrix_get(fixedpoints, 1, column)/gsl_matrix_get(fixedpoints, 2, column);
ctx->limit_curve_count++;
if((x - ctx->marking.x)*(x - ctx->marking.x) + (y - ctx->marking.y)*(y - ctx->marking.y) < 25e-10) if((x - ctx->marking.x)*(x - ctx->marking.x) + (y - ctx->marking.y)*(y - ctx->marking.y) < 25e-10)
{ {
@@ -95,19 +161,16 @@ int computeLimitCurve(DrawingContext *ctx)
fputc('a' + cur->letter, stdout); // bcbcbca, bacbcacab, bc bca cb fputc('a' + cur->letter, stdout); // bcbcbca, bacbcacab, bc bca cb
fputc('\n',stdout); fputc('\n',stdout);
} }
// bca abc acb = abc
} }
qsort(ctx->limit_curve, ctx->n_group_elements, 3*sizeof(double), compareAngle); qsort(ctx->limit_curve, ctx->limit_curve_count, 3*sizeof(double), compareAngle);
ctx->limit_curve_count = ctx->n_group_elements; // ctx->limit_curve_count = ctx->n_group_elements;
success = 1; success = 1;
error_out: error_out:
releaseTempMatrices(ctx->ws, 11+ctx->n_group_elements); releaseTempMatrices(ctx->ws, 14+ctx->n_group_elements);
return success; return success;
} }

View File

@@ -13,7 +13,7 @@
#define ERROR(condition, msg, ...) if(condition){fprintf(stderr, msg, ##__VA_ARGS__); exit(1);} #define ERROR(condition, msg, ...) if(condition){fprintf(stderr, msg, ##__VA_ARGS__); exit(1);}
#define FCMP(x, y) gsl_fcmp(x, y, 1e-10) #define FCMP(x, y) gsl_fcmp(x, y, 1e-10)
#define MAX_TEMP_MATRICES 1200000 #define MAX_TEMP_MATRICES 600000
#define MAX_TEMP_VECTORS 100 #define MAX_TEMP_VECTORS 100
typedef struct _workspace { typedef struct _workspace {

742
main.c
View File

@@ -11,458 +11,474 @@
#include "linalg.h" #include "linalg.h"
#define TOGGLE(a) do { (a) = !(a); } while(0) #define TOGGLE(a) do { (a) = !(a); } while(0)
#define SIGN(x) ((x) > 0 ? 1.0 : -1.0)
DrawingContext *screen_context; DrawingContext *screen_context;
// setup everything except cairo and dim, which will be provided by the graphics system // setup everything except cairo and dim, which will be provided by the graphics system
void setupContext(DrawingContext *ctx, int argc, char *argv[]) void setupContext(DrawingContext *ctx, int argc, char *argv[])
{ {
ctx->n_group_elements = NUM_GROUP_ELEMENTS; ctx->n_group_elements = NUM_GROUP_ELEMENTS;
ctx->p[0] = atoi(argv[1]); ctx->n_group_elements_combinatorial = NUM_GROUP_ELEMENTS_COMBINATORIAL;
ctx->p[1] = atoi(argv[2]); ctx->p[0] = atoi(argv[1]);
ctx->p[2] = atoi(argv[3]); ctx->p[1] = atoi(argv[2]);
ctx->k[0] = atoi(argv[4]); ctx->p[2] = atoi(argv[3]);
ctx->k[1] = atoi(argv[5]); ctx->k[0] = atoi(argv[4]);
ctx->k[2] = atoi(argv[6]); ctx->k[1] = atoi(argv[5]);
if(argc > 7) ctx->k[2] = atoi(argv[6]);
ctx->parameter = atof(argv[7]); if(argc > 7)
else ctx->parameter = atof(argv[7]);
ctx->parameter = 1.0; else
// ctx->parameter = 2.77; ctx->parameter = 1.0;
// ctx->parameter = 0.1; if(argc > 8)
ctx->show_boxes = 0; ctx->parameter2 = atof(argv[8]);
ctx->show_boxes2 = 0; else
ctx->show_attractors = 0; ctx->parameter2 = 1.0;
ctx->show_reflectors = 0; if(argc > 12) {
ctx->show_rotated_reflectors = 0; ctx->movie_filename = argv[9];
ctx->show_limit= 0; ctx->movie_parameter_duration = atof(argv[10]);
ctx->show_dual_limit= 0; ctx->movie_parameter2_duration = atof(argv[11]);
ctx->show_text = 1; ctx->movie_n_frames = atoi(argv[12]);
ctx->mode = 0; } else {
ctx->use_rotation_basis = 0; ctx->movie_n_frames = 0;
ctx->limit_with_lines = 1; }
ctx->use_repelling = 0; // ctx->parameter = 2.77;
ctx->show_marking = 1; // ctx->parameter = 0.1;
ctx->marking.x = -0.73679; ctx->show_boxes = 0;
ctx->marking.y = -0.01873; ctx->show_boxes2 = 0;
ctx->show_coxeter_orbit = 0; ctx->show_attractors = 0;
ctx->show_reflectors = 0;
ctx->show_rotated_reflectors = 0;
ctx->show_limit = 0;
ctx->show_dual_limit = 0;
ctx->show_text = 1;
ctx->mode = 0;
ctx->use_rotation_basis = 1;
ctx->limit_with_lines = 0;
ctx->use_repelling = 0;
ctx->show_marking = 0;
ctx->marking.x = -0.73679;
ctx->marking.y = -0.01873;
ctx->show_coxeter_orbit = 0;
ctx->limit_curve = malloc(3*ctx->n_group_elements*sizeof(double)); ctx->limit_curve = malloc(3*ctx->n_group_elements*sizeof(double));
ctx->limit_curve_count = -1; ctx->limit_curve_count = -1;
ctx->group = malloc(ctx->n_group_elements*sizeof(groupelement_t)); ctx->group = malloc(ctx->n_group_elements_combinatorial*sizeof(groupelement_t));
generate_triangle_group(ctx->group, ctx->n_group_elements, ctx->p[0], ctx->p[1], ctx->p[2]); generate_triangle_group(ctx->group, ctx->n_group_elements_combinatorial, ctx->p[0], ctx->p[1], ctx->p[2]);
// the temporary stuff // the temporary stuff
ctx->cartan = gsl_matrix_alloc(3, 3); ctx->cartan = gsl_matrix_alloc(3, 3);
ctx->cob = gsl_matrix_alloc(3, 3); ctx->cob = gsl_matrix_alloc(3, 3);
ctx->ws = workspace_alloc(3); ctx->ws = workspace_alloc(3);
} }
void destroyContext(DrawingContext *ctx) void destroyContext(DrawingContext *ctx)
{ {
free(ctx->limit_curve); free(ctx->limit_curve);
free(ctx->group); free(ctx->group);
gsl_matrix_free(ctx->cartan); gsl_matrix_free(ctx->cartan);
gsl_matrix_free(ctx->cob); gsl_matrix_free(ctx->cob);
workspace_free(ctx->ws); workspace_free(ctx->ws);
} }
void computeRotationMatrix(DrawingContext *ctx, gsl_matrix *result, const char *type) void computeMatrix(DrawingContext *ctx, gsl_matrix *result, const char *type)
{ {
gsl_matrix *tmp = getTempMatrix(ctx->ws); gsl_matrix **gen = getTempMatrices(ctx->ws, 6);
gsl_matrix **gen = getTempMatrices(ctx->ws, 3);
// ERROR(strlen(type) != 2, "Invalid call of computeRotationMatrix()\n"); // ERROR(strlen(type) != 2, "Invalid call of computeRotationMatrix()\n");
initializeTriangleGenerators(gen, ctx->cartan); initializeTriangleGeneratorsCurrent(gen, ctx);
gsl_matrix_set_identity(tmp); gsl_matrix_set_identity(result);
for(int i = 0; i < strlen(type); i++) for(int i = 0; i < strlen(type); i++) {
multiply_right(tmp, gen[type[i]-'a'], ctx->ws); if(type[i] >= 'a' && type[i] <= 'c')
multiply_right(result, gen[type[i]-'a'], ctx->ws);
else if(type[i] >= 'A' && type[i] <= 'C')
multiply_right(result, gen[type[i]-'A'+3], ctx->ws);
}
rotation_frame(tmp, result, ctx->ws); releaseTempMatrices(ctx->ws, 6);
}
releaseTempMatrices(ctx->ws, 4); void computeRotationMatrixFrame(DrawingContext *ctx, gsl_matrix *result, const char *type)
{
gsl_matrix *tmp = getTempMatrix(ctx->ws);
computeMatrix(ctx, tmp, type);
rotation_frame(tmp, result, ctx->ws);
releaseTempMatrices(ctx->ws, 1);
} }
void computeBoxTransform(DrawingContext *ctx, char *word1, char *word2, gsl_matrix *result) void computeBoxTransform(DrawingContext *ctx, char *word1, char *word2, gsl_matrix *result)
{ {
vector_t p[2][3],i[2]; vector_t p[2][3],i[2];
vector_t std[4] = { vector_t std[4] = {
{-1, -1, 1}, {-1, -1, 1},
{-1, 1, 1}, {-1, 1, 1},
{1, 1, 1}, {1, 1, 1},
{1, -1, 1} {1, -1, 1}
}; };
gsl_vector **vertices = getTempVectors(ctx->ws, 4); gsl_vector **vertices = getTempVectors(ctx->ws, 4);
gsl_vector **std_vertices = getTempVectors(ctx->ws, 4); gsl_vector **std_vertices = getTempVectors(ctx->ws, 4);
gsl_matrix *tmp = getTempMatrix(ctx->ws); gsl_matrix *tmp = getTempMatrix(ctx->ws);
gsl_matrix *to_frame = getTempMatrix(ctx->ws); gsl_matrix *to_frame = getTempMatrix(ctx->ws);
gsl_matrix *to_std_frame = getTempMatrix(ctx->ws); gsl_matrix *to_std_frame = getTempMatrix(ctx->ws);
fixedPoints(ctx, word1, p[0]); fixedPoints(ctx, word1, p[0]);
fixedPoints(ctx, word2, p[1]); fixedPoints(ctx, word2, p[1]);
// intersect attracting line with neutral line of the other element // intersect attracting line with neutral line of the other element
for(int j = 0; j < 2; j++) for(int j = 0; j < 2; j++)
i[j] = cross(cross(p[j%2][0],p[j%2][1]),cross(p[(j+1)%2][0],p[(j+1)%2][2])); i[j] = cross(cross(p[j%2][0],p[j%2][1]),cross(p[(j+1)%2][0],p[(j+1)%2][2]));
// box consists of p[0][0], i[0], p[1][0], i[1] // box consists of p[0][0], i[0], p[1][0], i[1]
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
vectorToGsl(std[i], std_vertices[i]); vectorToGsl(std[i], std_vertices[i]);
vectorToGsl(p[0][0], vertices[0]); vectorToGsl(p[0][0], vertices[0]);
vectorToGsl(i[0], vertices[1]); vectorToGsl(i[0], vertices[1]);
vectorToGsl(p[1][0], vertices[2]); vectorToGsl(p[1][0], vertices[2]);
vectorToGsl(i[1], vertices[3]); vectorToGsl(i[1], vertices[3]);
projective_frame(std_vertices, to_std_frame, ctx->ws); projective_frame(std_vertices, to_std_frame, ctx->ws);
projective_frame(vertices, to_frame, ctx->ws); projective_frame(vertices, to_frame, ctx->ws);
invert(to_frame, tmp, ctx->ws); invert(to_frame, tmp, ctx->ws);
multiply(to_std_frame, tmp, result); multiply(to_std_frame, tmp, result);
/* /*
LOOP(i) { LOOP(i) {
LOOP(j) { LOOP(j) {
printf("%.4f ", gsl_matrix_get(result, i, j)); printf("%.4f ", gsl_matrix_get(result, i, j));
} }
printf("\n"); printf("\n");
}*/ }*/
releaseTempVectors(ctx->ws, 8); releaseTempVectors(ctx->ws, 8);
releaseTempMatrices(ctx->ws, 3); releaseTempMatrices(ctx->ws, 3);
} }
void updateMatrices(DrawingContext *ctx) void updateMatrices(DrawingContext *ctx)
{ {
double angle[3]; double angle[3];
LOOP(i) angle[i] = M_PI*ctx->k[i]/ctx->p[i]; LOOP(i) angle[i] = M_PI*ctx->k[i]/ctx->p[i];
cartanMatrix(ctx->cartan, angle[0], angle[1], angle[2], ctx->parameter); cartanMatrix(ctx->cartan, angle[0], angle[1], angle[2], ctx->parameter);
gsl_matrix *tmp = getTempMatrix(ctx->ws); gsl_matrix *tmp = getTempMatrix(ctx->ws);
int nmodes = 5;
if(ctx->use_rotation_basis % 5 == 0) { if(ctx->use_rotation_basis % nmodes == 0) {
gsl_matrix_set(tmp, 0, 0, 0.0); gsl_matrix_set(tmp, 0, 0, 0.0);
gsl_matrix_set(tmp, 0, 1, sqrt(3.0)/2.0); gsl_matrix_set(tmp, 0, 1, sqrt(3.0)/2.0);
gsl_matrix_set(tmp, 0, 2, -sqrt(3.0)/2.0); gsl_matrix_set(tmp, 0, 2, -sqrt(3.0)/2.0);
gsl_matrix_set(tmp, 1, 0, 1.0); gsl_matrix_set(tmp, 1, 0, 1.0);
gsl_matrix_set(tmp, 1, 1, -0.5); gsl_matrix_set(tmp, 1, 1, -0.5);
gsl_matrix_set(tmp, 1, 2, -0.5); gsl_matrix_set(tmp, 1, 2, -0.5);
gsl_matrix_set(tmp, 2, 0, 1.0); gsl_matrix_set(tmp, 2, 0, 1.0);
gsl_matrix_set(tmp, 2, 1, 1.0); gsl_matrix_set(tmp, 2, 1, 1.0);
gsl_matrix_set(tmp, 2, 2, 1.0); gsl_matrix_set(tmp, 2, 2, 1.0);
gsl_matrix_memcpy(ctx->cob, tmp); gsl_matrix_memcpy(ctx->cob, tmp);
} else if(ctx->use_rotation_basis % 5 == 1) { } else if(ctx->use_rotation_basis % nmodes == 1) {
gsl_matrix_memcpy(ctx->cob, ctx->cartan); // is this a good choice of basis for any reason? gsl_matrix_set(tmp, 0, 0, 1.0);
} else if(ctx->use_rotation_basis % 5 == 2) { gsl_matrix_set(tmp, 0, 1, -1.0);
computeRotationMatrix(ctx, tmp, "ba"); gsl_matrix_set(tmp, 0, 2, 0.0);
invert(tmp, ctx->cob, ctx->ws); gsl_matrix_set(tmp, 1, 0, 1.0);
} else if(ctx->use_rotation_basis % 5 == 3) { gsl_matrix_set(tmp, 1, 1, 1.0);
computeBoxTransform(ctx, "bca", "abc", ctx->cob); gsl_matrix_set(tmp, 1, 2, 0.0);
// computeBoxTransform(ctx, "cab", "bca", ctx->cob); gsl_matrix_set(tmp, 2, 0, 0.0);
// computeBoxTransform(ctx, "acb", "cba", ctx->cob); gsl_matrix_set(tmp, 2, 1, 0.0);
} else { gsl_matrix_set(tmp, 2, 2, 1.0);
cartanMatrix(tmp, M_PI/ctx->p[0], M_PI/ctx->p[1], M_PI/ctx->p[2], 1.0); gsl_matrix_memcpy(ctx->cob, ctx->cartan); // is this a good choice of basis for any reason?
diagonalize_symmetric_form(tmp, ctx->cob, ctx->ws); multiply_left(tmp, ctx->cob, ctx->ws);
} } else if(ctx->use_rotation_basis % nmodes == 2) {
computeRotationMatrixFrame(ctx, tmp, "C");
invert(tmp, ctx->cob, ctx->ws);
} else if(ctx->use_rotation_basis % nmodes == 3) {
computeBoxTransform(ctx, "acb", "cba", ctx->cob);
// computeBoxTransform(ctx, "cab", "bca", ctx->cob);
// computeBoxTransform(ctx, "acb", "cba", ctx->cob);
} else {
cartanMatrix(tmp, M_PI/ctx->p[0], M_PI/ctx->p[1], M_PI/ctx->p[2], 1.0);
diagonalize_symmetric_form(tmp, ctx->cob, ctx->ws);
}
releaseTempMatrices(ctx->ws, 1); releaseTempMatrices(ctx->ws, 1);
} }
void output_info(DrawingContext *ctx) void output_info(DrawingContext *ctx)
{ {
vector_t p[4][3]; vector_t p[4][3];
point_t pt; point_t pt;
fixedPoints(ctx, "abc", p[0]); fixedPoints(ctx, "abc", p[0]);
fixedPoints(ctx, "bca", p[1]); fixedPoints(ctx, "bca", p[1]);
fixedPoints(ctx, "cab", p[2]); fixedPoints(ctx, "cab", p[2]);
pt = vectorToPoint(ctx, p[0][0]); pt = vectorToPoint(ctx, p[0][0]);
printf("(abc)-+ = (%f %f)\n", pt.x, pt.y); printf("(abc)-+ = (%f %f)\n", pt.x, pt.y);
pt = vectorToPoint(ctx, p[1][0]); pt = vectorToPoint(ctx, p[1][0]);
printf("(bca)-+ = (%f %f)\n", pt.x, pt.y); printf("(bca)-+ = (%f %f)\n", pt.x, pt.y);
} }
void print(DrawingContext *screen) void print(DrawingContext *screen)
{ {
DrawingContext file; DrawingContext file;
DimensionsInfo dim; DimensionsInfo dim;
cairo_surface_t *surface; cairo_surface_t *surface;
char filename[100]; char filename[100];
time_t t = time(NULL); time_t t = time(NULL);
strftime(filename, sizeof(filename), "screenshot_%Y%m%d_%H%M%S.pdf", localtime(&t)); strftime(filename, sizeof(filename), "screenshot_%Y%m%d_%H%M%S.pdf", localtime(&t));
memcpy(&file, screen, sizeof(file)); memcpy(&file, screen, sizeof(file));
dim.width = screen->dim->width; dim.width = screen->dim->width;
dim.height = screen->dim->width / sqrt(2.0); dim.height = screen->dim->width / sqrt(2.0);
dim.matrix = screen->dim->matrix; dim.matrix = screen->dim->matrix;
dim.matrix.y0 += ((double)dim.height - (double)screen->dim->height) / 2.0; // recenter vertically dim.matrix.y0 += ((double)dim.height - (double)screen->dim->height) / 2.0; // recenter vertically
updateDimensions(&dim); updateDimensions(&dim);
file.dim = &dim; file.dim = &dim;
surface = cairo_pdf_surface_create(filename, (double)dim.width, (double)dim.height); surface = cairo_pdf_surface_create(filename, (double)dim.width, (double)dim.height);
file.cairo = cairo_create(surface); file.cairo = cairo_create(surface);
draw(&file); draw(&file);
cairo_destroy(file.cairo); cairo_destroy(file.cairo);
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
printf("Wrote sceenshot to file: %s\n", filename); printf("Wrote sceenshot to file: %s\n", filename);
} }
int processEvent(GraphicsInfo *info, XEvent *ev) int processEvent(GraphicsInfo *info, XEvent *ev)
{ {
int state; int state;
unsigned long key; unsigned long key;
char filename[100]; char filename[100];
// fprintf(stderr, "Event: %d\n", ev->type); // fprintf(stderr, "Event: %d\n", ev->type);
switch(ev->type) { switch(ev->type) {
case ButtonPress: case ButtonPress:
state = ev->xbutton.state & (ShiftMask | LockMask | ControlMask); state = ev->xbutton.state & (ShiftMask | LockMask | ControlMask);
if(ev->xbutton.button == 1 && state & ShiftMask) { if(ev->xbutton.button == 1 && state & ShiftMask) {
screen_context->marking.x = (double)ev->xbutton.x; screen_context->marking.x = (double)ev->xbutton.x;
screen_context->marking.y = (double)ev->xbutton.y; screen_context->marking.y = (double)ev->xbutton.y;
printf("mouse button pressed: %f, %f\n", screen_context->marking.x, screen_context->marking.y); printf("mouse button pressed: %f, %f\n", screen_context->marking.x, screen_context->marking.y);
cairo_set_matrix(screen_context->cairo, &screen_context->dim->matrix); cairo_set_matrix(screen_context->cairo, &screen_context->dim->matrix);
cairo_device_to_user(screen_context->cairo, &screen_context->marking.x, &screen_context->marking.y); cairo_device_to_user(screen_context->cairo, &screen_context->marking.x, &screen_context->marking.y);
printf("mouse button pressed transformed: %f, %f\n", screen_context->marking.x, screen_context->marking.y); printf("mouse button pressed transformed: %f, %f\n", screen_context->marking.x, screen_context->marking.y);
return STATUS_REDRAW; return STATUS_REDRAW;
} }
break; break;
case KeyPress: case KeyPress:
state = ev->xkey.state & (ShiftMask | LockMask | ControlMask); state = ev->xkey.state & (ShiftMask | LockMask | ControlMask);
key = XkbKeycodeToKeysym(ev->xkey.display, ev->xkey.keycode, 0, !!(state & ShiftMask)); key = XkbKeycodeToKeysym(ev->xkey.display, ev->xkey.keycode, 0, !!(state & ShiftMask));
printf("Key pressed: %ld\n", key); printf("Key pressed: %ld\n", key);
switch(key) { switch(key) {
case XK_Down: case XK_Down:
screen_context->parameter /= exp(0.002); if(ev->xkey.state & ShiftMask)
updateMatrices(screen_context); screen_context->parameter /= exp(0.00005);
computeLimitCurve(screen_context); else
break; screen_context->parameter /= exp(0.002);
case XK_Up: updateMatrices(screen_context);
screen_context->parameter *= exp(0.002); computeLimitCurve(screen_context);
updateMatrices(screen_context); break;
computeLimitCurve(screen_context); case XK_Up:
break; if(ev->xkey.state & ShiftMask)
case XK_Left: screen_context->parameter *= exp(0.00005);
screen_context->parameter /= exp(0.00002); else
updateMatrices(screen_context); screen_context->parameter *= exp(0.002);
computeLimitCurve(screen_context); updateMatrices(screen_context);
break; computeLimitCurve(screen_context);
case XK_Right: break;
screen_context->parameter *= exp(0.00002); case XK_Left:
updateMatrices(screen_context); if(ev->xkey.state & ShiftMask)
computeLimitCurve(screen_context); screen_context->parameter2 /= exp(0.00005);
break; else
case XK_Page_Down: screen_context->parameter2 /= exp(0.002);
screen_context->parameter /= exp(0.02); updateMatrices(screen_context);
updateMatrices(screen_context); computeLimitCurve(screen_context);
computeLimitCurve(screen_context); break;
break; case XK_Right:
case XK_Page_Up: if(ev->xkey.state & ShiftMask)
screen_context->parameter *= exp(0.02); screen_context->parameter2 *= exp(0.00005);
updateMatrices(screen_context); else
computeLimitCurve(screen_context); screen_context->parameter2 *= exp(0.002);
break; updateMatrices(screen_context);
case ' ': computeLimitCurve(screen_context);
screen_context->parameter = 5.57959706; break;
updateMatrices(screen_context); case XK_Page_Down:
computeLimitCurve(screen_context); screen_context->parameter /= exp(0.02);
break; updateMatrices(screen_context);
case XK_Return: computeLimitCurve(screen_context);
// screen_context->parameter = 2.76375163; break;
screen_context->parameter = 5.29063366; case XK_Page_Up:
updateMatrices(screen_context); screen_context->parameter *= exp(0.02);
computeLimitCurve(screen_context); updateMatrices(screen_context);
break; computeLimitCurve(screen_context);
case 'm': break;
printf("matrix.xx = %f;\n", info->dim->matrix.xx); case ' ':
printf("matrix.xy = %f;\n", info->dim->matrix.xy); screen_context->parameter = 5.57959706;
printf("matrix.x0 = %f;\n", info->dim->matrix.x0); updateMatrices(screen_context);
printf("matrix.yx = %f;\n", info->dim->matrix.yx); computeLimitCurve(screen_context);
printf("matrix.yy = %f;\n", info->dim->matrix.yy); break;
printf("matrix.y0 = %f;\n", info->dim->matrix.y0); case XK_Return:
break; // screen_context->parameter = 2.76375163;
case 'i': screen_context->parameter = 5.29063366;
output_info(screen_context); updateMatrices(screen_context);
break; computeLimitCurve(screen_context);
case 'b': break;
TOGGLE(screen_context->show_boxes); case 'm':
break; printf("matrix.xx = %f;\n", info->dim->matrix.xx);
case 'B': printf("matrix.xy = %f;\n", info->dim->matrix.xy);
TOGGLE(screen_context->show_boxes2); printf("matrix.x0 = %f;\n", info->dim->matrix.x0);
break; printf("matrix.yx = %f;\n", info->dim->matrix.yx);
case 'a': printf("matrix.yy = %f;\n", info->dim->matrix.yy);
TOGGLE(screen_context->show_attractors); printf("matrix.y0 = %f;\n", info->dim->matrix.y0);
break; break;
case 'r': case 'i':
TOGGLE(screen_context->show_reflectors); output_info(screen_context);
break; break;
case 'x': case 'b':
TOGGLE(screen_context->show_rotated_reflectors); TOGGLE(screen_context->show_boxes);
break; break;
case 'L': case 'B':
TOGGLE(screen_context->limit_with_lines); TOGGLE(screen_context->show_boxes2);
break; break;
case 'l': case 'a':
TOGGLE(screen_context->show_limit); TOGGLE(screen_context->show_attractors);
break; break;
case 'd': case 'r':
TOGGLE(screen_context->show_dual_limit); TOGGLE(screen_context->show_reflectors);
break; break;
case 'R': case 'x':
screen_context->use_rotation_basis++; TOGGLE(screen_context->show_rotated_reflectors);
updateMatrices(screen_context); break;
computeLimitCurve(screen_context); case 'L':
break; TOGGLE(screen_context->limit_with_lines);
case 'p': break;
print(screen_context); case 'l':
break; TOGGLE(screen_context->show_limit);
case 'M': break;
/* case 'd':
screen_context->limit_with_lines = 0; TOGGLE(screen_context->show_dual_limit);
double parameter_start = screen_context->parameter; break;
for(int i = 0; i <= 1300; i++) { case 'R':
if(i < 400) screen_context->use_rotation_basis++;
screen_context->parameter = exp(log(parameter_start)+0.002*i); updateMatrices(screen_context);
else if(i < 500) computeLimitCurve(screen_context);
screen_context->parameter = exp(log(parameter_start)+0.002*400); break;
else case 'p':
screen_context->parameter = exp(log(parameter_start)+0.002*(900-i)); print(screen_context);
updateMatrices(screen_context); break;
computeLimitCurve(screen_context); case 'M':
draw(screen_context); screen_context->limit_with_lines = 0;
sprintf(filename, "movie3/test%03d.png", i); double parameter_start = screen_context->parameter;
cairo_surface_write_to_png(info->buffer_surface, filename); double parameter2_start = screen_context->parameter2;
printf("Finished drawing %s\n", filename); for(int i = 0; i <= screen_context->movie_n_frames; i++) {
} screen_context->parameter = SIGN(parameter_start)*exp(log(fabs(parameter_start)) +
*/ i*screen_context->movie_parameter_duration/screen_context->movie_n_frames);
/* screen_context->parameter2 = SIGN(parameter2_start)*exp(log(fabs(parameter2_start)) +
screen_context->limit_with_lines = 0; i*screen_context->movie_parameter2_duration/screen_context->movie_n_frames);
double parameter_start = screen_context->parameter; updateMatrices(screen_context);
for(int i = 0; i <= 1300; i++) { computeLimitCurve(screen_context);
if(i < 400) draw(screen_context);
screen_context->parameter = exp(0.003*i); sprintf(filename, "output/%s%03d.png", screen_context->movie_filename, i);
else if(i < 500) cairo_surface_write_to_png(info->buffer_surface, filename);
screen_context->parameter = exp(0.003*400); printf("Finished drawing %s\n", filename);
else }
screen_context->parameter = exp(0.003*(900-i));
updateMatrices(screen_context);
computeLimitCurve(screen_context);
draw(screen_context);
sprintf(filename, "movie5/test%03d.png", i);
cairo_surface_write_to_png(info->buffer_surface, filename);
printf("Finished drawing %s\n", filename);
}
*/
screen_context->limit_with_lines = 0;
for(int i = 0; i <= 1000; i++) {
screen_context->parameter = exp(log(3.0)*((double)i/500-1));
updateMatrices(screen_context);
computeLimitCurve(screen_context);
draw(screen_context);
sprintf(filename, "output/movie8/test%04d.png", i);
// cairo_surface_write_to_png(info->buffer_surface, filename);
printf("Finished drawing %s\n", filename);
}
case 'f':
TOGGLE(screen_context->use_repelling);
computeLimitCurve(screen_context);
break;
case 't':
TOGGLE(screen_context->show_text);
break;
case 'c':
TOGGLE(screen_context->show_coxeter_orbit);
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0':
screen_context->mode = key - '0';
break;
}
return STATUS_REDRAW; case 'f':
TOGGLE(screen_context->use_repelling);
computeLimitCurve(screen_context);
break;
case 't':
TOGGLE(screen_context->show_text);
break;
case 'c':
TOGGLE(screen_context->show_coxeter_orbit);
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0':
screen_context->mode = key - '0';
break;
} }
return STATUS_NOTHING; return STATUS_REDRAW;
}
return STATUS_NOTHING;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
GraphicsInfo *info; GraphicsInfo *info;
screen_context = malloc(sizeof(DrawingContext)); screen_context = malloc(sizeof(DrawingContext));
setupContext(screen_context, argc, argv); setupContext(screen_context, argc, argv);
updateMatrices(screen_context); updateMatrices(screen_context);
computeLimitCurve(screen_context); computeLimitCurve(screen_context);
info = initCairo(0, KeyPressMask, 200, 200, "Triangle group"); info = initCairo(0, KeyPressMask, 200, 200, "Triangle group");
if(!info) if(!info)
return 1; return 1;
/* /*
info->dim->matrix.xx = 274.573171; info->dim->matrix.xx = 274.573171;
info->dim->matrix.xy = 0.000000; info->dim->matrix.xy = 0.000000;
info->dim->matrix.x0 = 583.073462; info->dim->matrix.x0 = 583.073462;
info->dim->matrix.yx = 0.000000; info->dim->matrix.yx = 0.000000;
info->dim->matrix.yy = 274.573171; info->dim->matrix.yy = 274.573171;
info->dim->matrix.y0 = 777.225293; info->dim->matrix.y0 = 777.225293;
*/ */
info->dim->matrix.xx = 274.573171; info->dim->matrix.xx = 274.573171;
info->dim->matrix.xy = 0.000000; info->dim->matrix.xy = 0.000000;
info->dim->matrix.x0 = 910.073462; info->dim->matrix.x0 = 910.073462;
info->dim->matrix.yx = 0.000000; info->dim->matrix.yx = 0.000000;
info->dim->matrix.yy = 274.573171; info->dim->matrix.yy = 274.573171;
info->dim->matrix.y0 = 509.225293; info->dim->matrix.y0 = 509.225293;
updateDimensions(info->dim); updateDimensions(info->dim);
screen_context->dim = info->dim; screen_context->dim = info->dim;
screen_context->cairo = info->buffer_context; screen_context->cairo = info->buffer_context;
startTimer(info); startTimer(info);
while(1) { while(1) {
int result = checkEvents(info, processEvent, NULL); int result = checkEvents(info, processEvent, NULL);
if(result == STATUS_QUIT) if(result == STATUS_QUIT)
return 0; return 0;
else if(result == STATUS_REDRAW) { else if(result == STATUS_REDRAW) {
struct timeval current_time; struct timeval current_time;
double start_time, intermediate_time, end_time; double start_time, intermediate_time, end_time;
gettimeofday(&current_time, 0); gettimeofday(&current_time, 0);
start_time = current_time.tv_sec + current_time.tv_usec*1e-6; start_time = current_time.tv_sec + current_time.tv_usec*1e-6;
draw(screen_context); draw(screen_context);
gettimeofday(&current_time, 0); gettimeofday(&current_time, 0);
intermediate_time = current_time.tv_sec + current_time.tv_usec*1e-6; intermediate_time = current_time.tv_sec + current_time.tv_usec*1e-6;
cairo_set_source_surface(info->front_context, info->buffer_surface, 0, 0); cairo_set_source_surface(info->front_context, info->buffer_surface, 0, 0);
cairo_paint(info->front_context); cairo_paint(info->front_context);
gettimeofday(&current_time, 0); gettimeofday(&current_time, 0);
end_time = current_time.tv_sec + current_time.tv_usec*1e-6; end_time = current_time.tv_sec + current_time.tv_usec*1e-6;
printf("drawing finished in %.2f milliseconds, of which %.2f milliseconds were buffer switching\n", (end_time - start_time) * 1000, (end_time - intermediate_time) * 1000); printf("drawing finished in %.2f milliseconds, of which %.2f milliseconds were buffer switching\n", (end_time - start_time) * 1000, (end_time - intermediate_time) * 1000);
}
waitUpdateTimer(info);
} }
waitUpdateTimer(info);
}
free(screen_context); free(screen_context);
destroyCairo(info); destroyCairo(info);
destroyContext(screen_context); destroyContext(screen_context);
return 0; return 0;
} }

17
main.h
View File

@@ -12,6 +12,11 @@
#define LOOP(i) for(int i = 0; i < 3; i++) #define LOOP(i) for(int i = 0; i < 3; i++)
#define NUM_GROUP_ELEMENTS 10000 #define NUM_GROUP_ELEMENTS 10000
#define NUM_GROUP_ELEMENTS_COMBINATORIAL 100000
// (0,1) -> 2, (1,2) -> 0, (2,0) -> 1
// (1,0) -> 5, (2,1) -> 3, (0,2) -> 4
#define ROTATION_LETTER(x,y) (((y)-(x)+3)%3 == 1 ? ((y)+1)%3 : ((x)+1)%3+3)
typedef struct { typedef struct {
double x[3]; double x[3];
@@ -30,7 +35,13 @@ typedef struct {
// a priori parameter // a priori parameter
int p[3],k[3]; int p[3],k[3];
double parameter; double parameter;
double parameter2;
char *movie_filename;
double movie_parameter_duration;
double movie_parameter2_duration;
int movie_n_frames;
int n_group_elements; int n_group_elements;
int n_group_elements_combinatorial;
int show_boxes; int show_boxes;
int show_boxes2; int show_boxes2;
int show_attractors; int show_attractors;
@@ -66,7 +77,8 @@ typedef enum {
// implemented in limit_set.c // implemented in limit_set.c
void cartanMatrix(gsl_matrix *cartan, double a1, double a2, double a3, double s); void cartanMatrix(gsl_matrix *cartan, double a1, double a2, double a3, double s);
void initializeTriangleGenerators(gsl_matrix **gen, gsl_matrix *cartan); void initializeTriangleGenerators(gsl_matrix **gen, double a1, double a2, double a3, double s, double t, workspace_t *ws);
void initializeTriangleGeneratorsCurrent(gsl_matrix **gen, DrawingContext *ctx);
int computeLimitCurve(DrawingContext *ctx); int computeLimitCurve(DrawingContext *ctx);
// implemented in draw.c // implemented in draw.c
@@ -96,7 +108,8 @@ void setupContext(DrawingContext *ctx, int argc, char *argv[]);
void destroyContext(DrawingContext *ctx); void destroyContext(DrawingContext *ctx);
void print(DrawingContext *screen); void print(DrawingContext *screen);
int processEvent(GraphicsInfo *info, XEvent *ev); int processEvent(GraphicsInfo *info, XEvent *ev);
void computeRotationMatrix(DrawingContext *ctx, gsl_matrix *result, const char *type); void computeMatrix(DrawingContext *ctx, gsl_matrix *result, const char *type);
void computeRotationMatrixFrame(DrawingContext *ctx, gsl_matrix *result, const char *type);
void updateMatrices(DrawingContext *ctx); void updateMatrices(DrawingContext *ctx);
static vector_t vectorFromGsl(gsl_vector *v) static vector_t vectorFromGsl(gsl_vector *v)

View File

@@ -14,6 +14,7 @@ typedef struct _groupelement {
struct _groupelement *parent; struct _groupelement *parent;
struct _groupelement *inverse; struct _groupelement *inverse;
int letter; int letter;
int visited;
} groupelement_t; } groupelement_t;
int generate_triangle_group(groupelement_t *group, int size, int k1, int k2, int k3); int generate_triangle_group(groupelement_t *group, int size, int k1, int k2, int k3);