diff --git a/draw.c b/draw.c index ce37c52..5a66ca0 100644 --- a/draw.c +++ b/draw.c @@ -65,6 +65,30 @@ int fixedPoints(DrawingContext *ctx, const char *word, vector_t *out) return count; } +int wordEigenvalues(DrawingContext *ctx, const char *word, double *out) +{ + gsl_matrix *tmp = getTempMatrix(ctx->ws); + gsl_vector *ev = getTempVector(ctx->ws); + gsl_matrix **gen = getTempMatrices(ctx->ws, 3); + + initializeTriangleGenerators(gen, ctx->cartan); + + gsl_matrix_set_identity(tmp); + for(int i = 0; i < strlen(word); i++) { + if(word[i] == ' ') + continue; + multiply_right(tmp, gen[word[i]-'a'], ctx->ws); + } + int count = real_eigenvalues(tmp, ev, ctx->ws); + + LOOP(i) out[i] = gsl_vector_get(ev, i); + + releaseTempMatrices(ctx->ws, 4); + releaseTempVectors(ctx->ws, 1); + + return count; +} + // level 1: the elementary drawing functions, drawPoint, drawSegment2d void drawPoint(DrawingContext *ctx, point_t p) @@ -98,7 +122,7 @@ void drawSegment2d(DrawingContext *ctx, point_t a, point_t b) // level 2: drawVector, drawCovector, drawSegment -static point_t vectorToPoint(DrawingContext *ctx, vector_t in) +point_t vectorToPoint(DrawingContext *ctx, vector_t in) { double x[3]; point_t out; @@ -155,6 +179,53 @@ void drawSegment(DrawingContext *ctx, vector_t a, vector_t b) drawSegment2d(ctx, vectorToPoint(ctx, a), vectorToPoint(ctx, b)); } +void drawSegmentWith(DrawingContext *ctx, vector_t a, vector_t b, vector_t line, int contains) +{ + point_t a_ = vectorToPoint(ctx,a); + point_t b_ = vectorToPoint(ctx,b); + double x[3]; + double cofactor; + double r, tline, tminus, tplus; + double coeff0, coeff1, coeff2; + point_t m, xminus, xplus; + + // multiply line with inverse of cob to get it as implicit line x in chart + LOOP(i) x[i] = 0.0; + 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) + - 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]; + } + + // 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]); + + if((tline < 0 || tline > 1) != contains) { + drawSegment2d(ctx, a_, b_); + } else { // need to draw complementary semgent + // find t so that s(t) is at radius r from center, |s(t)-m| = r + m.x = ctx->dim->center_x; + m.y = ctx->dim->center_y; + r = ctx->dim->radius; + // 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; + coeff1 = (a_.x - m.x)*(b_.x - a_.x) + (a_.y - m.y)*(b_.y - a_.y); + coeff2 = (b_.x - a_.x)*(b_.x - a_.x) + (b_.y - a_.y)*(b_.y - a_.y); + if(coeff1*coeff1 - coeff0*coeff2 <= 0) + return; + tplus = (- coeff1 + sqrt(coeff1*coeff1 - coeff0*coeff2))/coeff2; + tminus = (- coeff1 - sqrt(coeff1*coeff1 - coeff0*coeff2))/coeff2; + xplus.x = a_.x + tplus * (b_.x - a_.x); + xplus.y = a_.y + tplus * (b_.y - a_.y); + xminus.x = a_.x + tminus * (b_.x - a_.x); + xminus.y = a_.y + tminus * (b_.y - a_.y); + if(tplus > 1) + drawSegment2d(ctx, b_, xplus); + if(tminus < 0) + drawSegment2d(ctx, a_, xminus); + } +} + // level 3: boxes and polygons void drawPolygon(DrawingContext *ctx, int segments, int sides, ...) @@ -244,19 +315,18 @@ void drawBoxStd(DrawingContext *ctx, const char *word, char base) drawBox(ctx, word1, word2); } -void drawRotationOrbit(DrawingContext *ctx, const char *word, vector_t start) +void drawRotationOrbitFrame(DrawingContext *ctx, gsl_matrix *frame, vector_t start) { vector_t v[3], w; point_t p; double parameter, startangle; int iterations = 200; - gsl_matrix *frame = getTempMatrix(ctx->ws); gsl_matrix *inverse = getTempMatrix(ctx->ws); gsl_vector *start_v = getTempVector(ctx->ws); gsl_vector *start_in_frame = getTempVector(ctx->ws); cairo_t *C = ctx->cairo; - computeRotationMatrix(ctx, frame, word); +// computeRotationMatrix(ctx, frame, word); 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]); @@ -284,10 +354,20 @@ void drawRotationOrbit(DrawingContext *ctx, const char *word, vector_t start) cairo_stroke(C); - releaseTempMatrices(ctx->ws, 2); + releaseTempMatrices(ctx->ws, 1); releaseTempVectors(ctx->ws, 2); } +void drawRotationOrbit(DrawingContext *ctx, const char *word, vector_t start) +{ + gsl_matrix *frame = getTempMatrix(ctx->ws); + + computeRotationMatrix(ctx, frame, word); + drawRotationOrbitFrame(ctx, frame, start); + + releaseTempMatrices(ctx->ws, 1); +} + void drawDualRotationOrbit(DrawingContext *ctx, const char *word, vector_t start) { vector_t v[3], w; @@ -333,10 +413,10 @@ void drawDualRotationOrbit(DrawingContext *ctx, const char *word, vector_t start releaseTempVectors(ctx->ws, 2); } -void drawArc(DrawingContext *ctx, const char *word, vector_t start, vector_type_t starttype, vector_t end, vector_type_t endtype, vector_t third, int contain) +void drawArcWithOutput(DrawingContext *ctx, const char *word, vector_t start, vector_type_t starttype, vector_t end, vector_type_t endtype, vector_t third, int contain, vector_t *start_vector_out, vector_t *end_vector_out, int dontdraw) { - vector_t v[3], w; - point_t p; + vector_t v[3], w, w_; + point_t p, p_; double radius, angle_start, angle_end, angle_third, angle, angle_end_delta, sign, angle_start_final, angle_end_final, angle_end_other; int iterations = 200; gsl_matrix *frame = getTempMatrix(ctx->ws); @@ -418,29 +498,54 @@ void drawArc(DrawingContext *ctx, const char *word, vector_t start, vector_type_ break; } - for(int k = 0; k <= iterations; k++) { - angle = angle_start_final + (double)k/(double)iterations * ANGLE_DIFF(angle_end_final, angle_start_final); + // output the start end end point + /* + LOOP(i) w.x[i] = v[2].x[i] / radius + cos(angle_start_final) * v[0].x[i] + sin(angle_start_final) * v[1].x[i]; + p = vectorToPoint(ctx, w); + LOOP(i) w.x[i] = v[2].x[i] / radius + cos(angle_end_final) * v[0].x[i] + sin(angle_end_final) * v[1].x[i]; + p_ = vectorToPoint(ctx, w); + printf("\\draw (%f,%f) -- (%f,%f);\n", p.x, p.y, p_.x, p_.y); + */ - LOOP(i) w.x[i] = v[2].x[i] / radius + cos(angle) * v[0].x[i] + sin(angle) * v[1].x[i]; - p = vectorToPoint(ctx, w); + if(!dontdraw) { + for(int k = 0; k <= iterations; k++) { + angle = angle_start_final + (double)k/(double)iterations * ANGLE_DIFF(angle_end_final, angle_start_final); - if(isInsideBB(ctx, p)) { - if(!previous_inside) - cairo_move_to(C, p.x, p.y); - else - cairo_line_to(C, p.x, p.y); - previous_inside = 1; - } else { - previous_inside = 0; + LOOP(i) w.x[i] = v[2].x[i] / radius + cos(angle) * v[0].x[i] + sin(angle) * v[1].x[i]; + p = vectorToPoint(ctx, w); + + if(isInsideBB(ctx, p)) { + if(!previous_inside) + cairo_move_to(C, p.x, p.y); + else + cairo_line_to(C, p.x, p.y); + previous_inside = 1; + } else { + previous_inside = 0; + } } } + if(start_vector_out) + LOOP(i) start_vector_out->x[i] = v[2].x[i] / radius + + cos(angle_start_final) * v[0].x[i] + + sin(angle_start_final) * v[1].x[i]; + if(end_vector_out) + LOOP(i) end_vector_out->x[i] = v[2].x[i] / radius + + cos(angle_end_final) * v[0].x[i] + + sin(angle_end_final) * v[1].x[i]; + cairo_stroke(C); releaseTempMatrices(ctx->ws, 2); releaseTempVectors(ctx->ws, 2); } +void drawArc(DrawingContext *ctx, const char *word, vector_t start, vector_type_t starttype, vector_t end, vector_type_t endtype, vector_t third, int contain) +{ + drawArcWithOutput(ctx, word, start, starttype, end, endtype, third, contain, 0, 0, 0); +} + // level 4: draw the actual image components void drawReflectors(DrawingContext *ctx) @@ -506,10 +611,12 @@ char *conjugate_word(const char *word, int modifier, const char *conj, char *buf return buffer; } -void drawCurvedBox(DrawingContext *ctx, int base, const char *conj) +void drawCurvedBox(DrawingContext *ctx, int base, const char *conj, int style) { - vector_t p[6][3]; + vector_t p[10][3]; vector_t l[2][3]; + vector_t corner1, corner2; + vector_t tmp1, tmp2; char word[100]; int modifier = base - 'A'; @@ -525,21 +632,64 @@ void drawCurvedBox(DrawingContext *ctx, int base, const char *conj) fixedPoints(ctx, word, p[4]); conjugate_word("abaca cab acaba", modifier, conj, word); fixedPoints(ctx, word, p[5]); + conjugate_word("bca cab acb", modifier, conj, word); + fixedPoints(ctx, word, p[6]); + conjugate_word("abca cab acba", modifier, conj, word); + fixedPoints(ctx, word, p[7]); + conjugate_word("abacababa", modifier, conj, word); + fixedPoints(ctx, word, p[8]); + conjugate_word("bacabab", modifier, conj, word); + fixedPoints(ctx, word, p[9]); + +// 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[1][j] = cross(p[1][(3-j)%3], p[1][(4-j)%3]); + // main conic conjugate_word("ab", modifier, conj, word); - drawArc(ctx, word, p[0][0], VT_POINT, p[2][0], VT_POINT, p[1][0], 0); - conjugate_word("bcab", modifier, conj, word); - drawArc(ctx, word, p[2][0], VT_POINT, l[1][0], VT_LINE, p[4][0], 1); - conjugate_word("ab", modifier, conj, word); - drawArc(ctx, word, p[1][0], VT_POINT, p[3][0], VT_POINT, p[0][0], 0); - conjugate_word("abcaba", modifier, conj, word); - drawArc(ctx, word, p[3][0], VT_POINT, l[0][0], VT_LINE, p[5][0], 1); + drawArcWithOutput(ctx, word, p[0][0], VT_POINT, p[2][0], VT_POINT, p[1][0], 0, &tmp1, &tmp2, style != 1); + if(style == 2) + drawSegment(ctx, tmp1, tmp2); + if(style == 3) { + drawVector(ctx, tmp1); + drawVector(ctx, tmp2); + } - drawCovector(ctx, l[0][0]); - drawCovector(ctx, l[1][0]); + conjugate_word("ab", modifier, conj, word); + drawArcWithOutput(ctx, word, p[1][0], VT_POINT, p[3][0], VT_POINT, p[0][0], 0, &tmp1, &tmp2, style != 1); + if(style == 2) + drawSegment(ctx, tmp1, tmp2); + if(style == 3) { + drawVector(ctx, tmp1); + drawVector(ctx, tmp2); + } + + conjugate_word("bcabcb", modifier, conj, word); + drawArcWithOutput(ctx, word, p[2][0], VT_POINT, l[1][0], VT_LINE, p[6][0], 1, &tmp1, &tmp2, style != 1); // only 1st cutoff + if(style == 2) + drawSegment(ctx, tmp1, tmp2); + + corner1 = tmp2; + + conjugate_word("abcabcba", modifier, conj, word); + drawArcWithOutput(ctx, word, p[3][0], VT_POINT, l[0][0], VT_LINE, p[7][0], 1, &tmp1, &tmp2, style != 1); // only 1st cutoff + if(style == 2) + drawSegment(ctx, tmp1, tmp2); + corner2 = tmp2; + + if(style == 1 || style == 2) { + drawSegmentWith(ctx, p[0][0], corner2, l[1][1], 0); + drawSegmentWith(ctx, p[1][0], corner1, l[0][1], 0); + } else if(style == 3) + { + drawVector(ctx, corner1); + drawVector(ctx, corner2); + } } @@ -547,18 +697,119 @@ void drawBoxes(DrawingContext *ctx) { gsl_matrix *rot = getTempMatrix(ctx->ws); gsl_matrix **gen = getTempMatrices(ctx->ws, 3); + gsl_matrix *frame = getTempMatrix(ctx->ws); cairo_t *C = ctx->cairo; 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]); - fixedPoints(ctx, "abc", p[3]); + cairo_set_line_width(C, 2.0/ctx->dim->scalefactor); + cairo_set_source_rgb(C, 0.6, 0.6, 0.6); + + drawRotationOrbit(ctx, "ab", p[0][0]); + drawRotationOrbit(ctx, "bc", p[0][0]); + drawRotationOrbit(ctx, "ca", p[0][0]); + + if(ctx->mode >= 2) { + cairo_set_source_rgb(C, 0.6, 0.6, 1); + drawRotationOrbit(ctx, "bcabcb", p[1][0]); // bcC + drawRotationOrbit(ctx, "abcabcba", p[0][0]); // abcC + drawRotationOrbit(ctx, "bcabcabacb", p[1][0]); // bcabC'' + drawRotationOrbit(ctx, "bacabcacab", p[3][0]); // bacaC' + drawRotationOrbit(ctx, "bcacabcacacb", p[4][0]); // bcacaC' bcacabacb + } + + cairo_set_source_rgb(C, 1, 0, 1); +// drawRotationOrbit(ctx, "bacabcacab", p[3][0]); // ababcba + cairo_set_source_rgb(C, 0, 0, 0); + fixedPoints(ctx, "abababcbaba", p[3]); +// drawRotationOrbit(ctx, "abababcabcbababa", p[3][0]); // bab abc bab + + cairo_set_source_rgb(C, 0, 0, 1); +// fixedPoints(ctx, "cab", p[3]); +// drawRotationOrbit(ctx, "cabc", p[3][0]); +// fixedPoints(ctx, "bca", p[3]); +// drawRotationOrbit(ctx, "bcabcb", p[3][0]); +// fixedPoints(ctx, "bc abc cb", p[3]); +// drawRotationOrbit(ctx, "bcabcb", p[3][0]); + + fixedPoints(ctx, "bc bca cb", p[3]); +// drawRotationOrbit(ctx, "bcbcacbc", p[3][0]); + + /* + cairo_set_source_rgb(C, 0, 0, 0); + strncpy(word,"abc",100); + for(int i = 0; i < 9; i++) { + conjugate_word(word, 0, "ab", word2); + strncpy(word, word2, 100); + fixedPoints(ctx, word, ptmp); + drawVector(ctx, ptmp[0]); +// drawVector(ctx, ptmp[2]); + } + + strncpy(word,"bca",100); + for(int i = 0; i < 9; i++) { + conjugate_word(word, 0, "ab", word2); + strncpy(word, word2, 100); + fixedPoints(ctx, word, ptmp); + drawVector(ctx, ptmp[0]); +// drawVector(ctx, ptmp[2]); + } + + + strncpy(word,"abc",100); + for(int i = 0; i < 9; i++) { + conjugate_word(word, 0, "bc", word2); + strncpy(word, word2, 100); + fixedPoints(ctx, word, ptmp); + drawVector(ctx, ptmp[0]); + } + + strncpy(word,"cab",100); + for(int i = 0; i < 9; i++) { + conjugate_word(word, 0, "bc", word2); + strncpy(word, word2, 100); + fixedPoints(ctx, word, ptmp); + drawVector(ctx, ptmp[0]); + } + + strncpy(word,"cab",100); + for(int i = 0; i < 9; i++) { + conjugate_word(word, 0, "ca", word2); + strncpy(word, word2, 100); + fixedPoints(ctx, word, ptmp); + drawVector(ctx, ptmp[0]); + } + + strncpy(word,"abc",100); + for(int i = 0; i < 9; i++) { + conjugate_word(word, 0, "ca", word2); + strncpy(word, word2, 100); + fixedPoints(ctx, word, ptmp); + drawVector(ctx, ptmp[0]); + } + */ + + /* + cairo_set_source_rgb(C, 1, 0, 0); + drawVector(ctx, p[0][0]); + cairo_set_source_rgb(C, 0, 0.6, 0); + drawVector(ctx, p[1][0]); + cairo_set_source_rgb(C, 0, 0, 1); + drawVector(ctx, p[2][0]); + */ + + /* fixedPoints(ctx, "ab abc ba", p[4]); fixedPoints(ctx, "abab abc baba", p[5]); fixedPoints(ctx, "ababab abc bababa", p[6]); @@ -567,7 +818,6 @@ void drawBoxes(DrawingContext *ctx) fixedPoints(ctx, "bababa abc ababab", p[9]); fixedPoints(ctx, "baba abc abab", p[10]); fixedPoints(ctx, "ba abc ab", p[11]); - fixedPoints(ctx, "bca", p[12]); fixedPoints(ctx, "b abc b", p[13]); fixedPoints(ctx, "bab abc bab", p[14]); @@ -577,43 +827,50 @@ void drawBoxes(DrawingContext *ctx) fixedPoints(ctx, "ababab bca bababa", p[18]); fixedPoints(ctx, "abab bca baba", p[19]); fixedPoints(ctx, "ab bca ba", p[20]); + */ +// initializeTriangleGenerators(gen, ctx->cartan); - initializeTriangleGenerators(gen, ctx->cartan); - - for(int i = 0; i < 22; i++) LOOP(j) l[i][j] = cross(p[i][(3-j)%3], p[i][(4-j)%3]); +// for(int i = 0; i < 22; i++) LOOP(j) l[i][j] = cross(p[i][(3-j)%3], p[i][(4-j)%3]); // LOOP(i) LOOP(j) alpha[i].x[j] = gsl_matrix_get(ctx->cartan, i, j); - cairo_set_line_width(C, 2.0/ctx->dim->scalefactor); + /* + gsl_matrix_set(frame, 0, 0, 2.0); + gsl_matrix_set(frame, 0, 1, 0.0); + gsl_matrix_set(frame, 0, 2, 1.0); + gsl_matrix_set(frame, 1, 0, -1.0); + gsl_matrix_set(frame, 1, 1, sqrt(3)); + gsl_matrix_set(frame, 1, 2, 1.0); + gsl_matrix_set(frame, 2, 0, -1.0); + gsl_matrix_set(frame, 2, 1, -sqrt(3)); + gsl_matrix_set(frame, 2, 2, 1.0);*/ +// drawRotationOrbitFrame(ctx, frame, p[0][0]); - cairo_set_source_rgb(C, 0, 0, 0); - drawRotationOrbit(ctx, "ab", p[0][0]); // drawRotationOrbit(ctx, "bc", p[0][0]); - cairo_set_source_rgb(C, 0.5, 0.5, 1); // drawRotationOrbit(ctx, "ca", p[0][0]); +/* for(int i = 0; i < 18; i++) { if(i == 0) cairo_set_source_rgb(C, 1, 0, 0); - else if(i == 8 || i == 10) + else if(i == 8) cairo_set_source_rgb(C, 0, 0, 1); else if(i == 9) cairo_set_source_rgb(C, 0, 0.6, 0); else cairo_set_source_rgb(C, 0, 0, 0); drawVector(ctx, p[3+i][0]); - drawCovector(ctx, l[3+i][0]); - } - - cairo_set_source_rgb(C, 0, 0, 1.0); +// drawCovector(ctx, l[3+i][0]); +} +*/ // drawRotationOrbit(ctx, "ab", cross(l[0][0], l[2][1])); // drawRotationOrbit(ctx, "abca", p[0][0]); cairo_restore(C); - releaseTempMatrices(ctx->ws, 4); + releaseTempMatrices(ctx->ws, 5); } void drawBoxes2(DrawingContext *ctx) @@ -624,6 +881,216 @@ void drawBoxes2(DrawingContext *ctx) cairo_save(C); initializeTriangleGenerators(gen, ctx->cartan); + vector_t p[4][3]; + + fixedPoints(ctx, "abc", p[0]); + fixedPoints(ctx, "bca", p[1]); + fixedPoints(ctx, "cab", p[2]); + + 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); + drawCurvedBox(ctx, 'A', "", 2); + + cairo_set_source_rgb(C, 0, 0, 1); +// drawCurvedBox(ctx, 'C', "ab", 2); + + cairo_set_source_rgb(C, 0, 0.8, 0.5); +// 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 >= 4) { + drawCurvedBox(ctx, 'C', "b", 2); + drawCurvedBox(ctx, 'C', "bab", 2); + drawCurvedBox(ctx, 'C', "babab", 2); + } + + if(ctx->mode >= 5) { + cairo_set_source_rgb(C, 0.8, 0, 0.5); + drawCurvedBox(ctx, 'B', "abca", 2); + drawCurvedBox(ctx, 'B', "abcaca", 2); + drawCurvedBox(ctx, 'B', "aba", 2); + drawCurvedBox(ctx, 'B', "abaca", 2); + drawCurvedBox(ctx, 'B', "ababca", 2); + drawCurvedBox(ctx, 'B', "ababcaca", 2); + drawCurvedBox(ctx, 'B', "ababa", 2); + drawCurvedBox(ctx, 'B', "ababaca", 2); + drawCurvedBox(ctx, 'B', "abababca", 2); + drawCurvedBox(ctx, 'B', "abababcaca", 2); + drawCurvedBox(ctx, 'B', "abababa", 2); + drawCurvedBox(ctx, 'B', "abababaca", 2); + + drawCurvedBox(ctx, 'B', "bca", 2); + drawCurvedBox(ctx, 'B', "bcaca", 2); + drawCurvedBox(ctx, 'B', "ba", 2); + drawCurvedBox(ctx, 'B', "baca", 2); + drawCurvedBox(ctx, 'B', "babca", 2); + drawCurvedBox(ctx, 'B', "babcaca", 2); + drawCurvedBox(ctx, 'B', "baba", 2); + drawCurvedBox(ctx, 'B', "babaca", 2); + drawCurvedBox(ctx, 'B', "bababca", 2); + drawCurvedBox(ctx, 'B', "bababcaca", 2); + drawCurvedBox(ctx, 'B', "bababa", 2); + drawCurvedBox(ctx, 'B', "bababaca", 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]; @@ -680,6 +1147,7 @@ void drawBoxes2(DrawingContext *ctx) cairo_set_source_rgb(C, 0, 0, 0); drawCovector(ctx, rotation_line); +*/ // for(int j = 0; j < 5; j++) // drawCovector(ctx, reflection_line[j]); @@ -773,12 +1241,12 @@ void drawDualLimitCurve(DrawingContext *ctx) cairo_t *C = ctx->cairo; cairo_save(C); - cairo_set_source_rgb(C, 0, 0, 0); + cairo_set_source_rgb(C, 0.5, 0.5, 1); int n = 18; vector_t p[n][3]; vector_t l[n][3]; - + vector_t ptmp[3], ltmp[3]; fixedPoints(ctx, "abc", p[0]); fixedPoints(ctx, "ab abc ba", p[1]); @@ -800,8 +1268,7 @@ void drawDualLimitCurve(DrawingContext *ctx) fixedPoints(ctx, "baba bca abab", p[16]); fixedPoints(ctx, "ba bca ab", p[17]); - -/* + /* fixedPoints(ctx, "abc", p[0]); fixedPoints(ctx, "ac abc ca", p[1]); fixedPoints(ctx, "acac abc caca", p[2]); @@ -821,7 +1288,7 @@ void drawDualLimitCurve(DrawingContext *ctx) fixedPoints(ctx, "cacaca bca acacac", p[15]); fixedPoints(ctx, "caca bca acac", p[16]); fixedPoints(ctx, "ca bca ac", p[17]); -*/ + */ /* fixedPoints(ctx, "cab", p[2]); @@ -830,25 +1297,43 @@ void drawDualLimitCurve(DrawingContext *ctx) fixedPoints(ctx, "a cab a", p[5]); */ + /* for(int i = 0; i < n; i++) { LOOP(j) l[i][j] = cross(p[i][(3-j)%3], p[i][(4-j)%3]); drawCovector(ctx, l[i][0]); - drawCovector(ctx, l[i][2]); - } +// drawCovector(ctx, l[i][2]); +}*/ + + fixedPoints(ctx, "abc", ptmp); + drawCovector(ctx, cross(ptmp[0], ptmp[1])); + fixedPoints(ctx, "bca", ptmp); + drawCovector(ctx, cross(ptmp[0], ptmp[1])); + fixedPoints(ctx, "cab", ptmp); + drawCovector(ctx, cross(ptmp[0], ptmp[1])); + fixedPoints(ctx, "babcb", ptmp); + drawCovector(ctx, cross(ptmp[0], ptmp[1])); + fixedPoints(ctx, "cbcac", ptmp); + drawCovector(ctx, cross(ptmp[0], ptmp[1])); + fixedPoints(ctx, "acaba", ptmp); + drawCovector(ctx, cross(ptmp[0], ptmp[1])); cairo_restore(C); } void drawLimitCurve(DrawingContext *ctx) { + int close_points = 0; cairo_t *C = ctx->cairo; cairo_save(C); - cairo_set_source_rgb(C, 0.0, 0.0, 0.0); +// cairo_set_source_rgb(C, 0.6, 0.6, 0.6); + cairo_set_source_rgb(C, 0, 0, 0); if(ctx->limit_with_lines) { int previous_inside = 0; + cairo_new_path(C); + for(int i = 0; i < ctx->limit_curve_count; i++) { point_t p; p.x = ctx->limit_curve[3*i]; @@ -873,7 +1358,7 @@ void drawLimitCurve(DrawingContext *ctx) p.y = ctx->limit_curve[3*i+1]; if(isInsideBB(ctx, p)) { - cairo_arc(C, p.x, p.y, 0.5/ctx->dim->scalefactor, 0, 2*M_PI); + cairo_arc(C, p.x, p.y, 2.0/ctx->dim->scalefactor, 0, 2*M_PI); cairo_close_path(C); cairo_fill(C); } @@ -883,12 +1368,81 @@ void drawLimitCurve(DrawingContext *ctx) cairo_restore(C); } +void drawCoxeterOrbit(DrawingContext *ctx) +{ + gsl_matrix *rot = getTempMatrix(ctx->ws); + gsl_matrix **gen = getTempMatrices(ctx->ws, 3); + gsl_vector *eval = getTempVector(ctx->ws); + gsl_matrix *coxeter_fixedpoints = getTempMatrix(ctx->ws); + gsl_vector *startpoint_coxeterbasis = getTempVector(ctx->ws); + gsl_vector *startpoint_globalbasis = getTempVector(ctx->ws); + gsl_vector *startpoint_drawbasis = getTempVector(ctx->ws); + cairo_t *C = ctx->cairo; + vector_t cox[3][3]; + vector_t abcb[3]; + double ev[3]; + vector_t v, start; + point_t p; + int first = 1; + + cairo_save(C); + initializeTriangleGenerators(gen, ctx->cartan); + + cairo_set_source_rgb(C, 1, 0, 1); + + fixedPoints(ctx, "abc", cox[0]); + fixedPoints(ctx, "bca", cox[1]); + fixedPoints(ctx, "cab", cox[2]); +// fixedPoints(ctx, "babc", abcb); + wordEigenvalues(ctx, "abc", ev); + LOOP(i) LOOP(j) gsl_matrix_set(coxeter_fixedpoints, j, i, cox[0][i].x[j]); + + //printf("coxeter eigenvalues: %f %f %f\n", ev[0], ev[1], ev[2]); + +// LOOP(i) gsl_vector_set(startpoint_globalbasis, i, cox[1][0].x[i]); + + gsl_vector_set(startpoint_drawbasis, 0, ctx->marking.x); + 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); + + solve(coxeter_fixedpoints, startpoint_globalbasis, startpoint_coxeterbasis, ctx->ws); + LOOP(i) start.x[i] = gsl_vector_get(startpoint_coxeterbasis, i); + + for(int t = -1000; t < 1000; t++) { + LOOP(i) v.x[i] = 0; + LOOP(i) LOOP(j) v.x[j] += pow(fabs(ev[i]),t*0.01)*start.x[i]*cox[0][i].x[j]; + p = vectorToPoint(ctx, v); + + if(first) { + cairo_move_to(C, p.x, p.y); + first = 0; + } else { + cairo_line_to(C, p.x, p.y); + } + } + cairo_stroke(C); + + for(int t = -20; t < 20; t++) { + LOOP(i) v.x[i] = 0; + LOOP(i) LOOP(j) v.x[j] += (ev[i]<0&&t%2?-1:1)*pow(fabs(ev[i]),t/3.0)*start.x[i]*cox[0][i].x[j]; + drawVector(ctx, v); + } + + cairo_set_source_rgb(C, 0, 0, 0); + LOOP(i) drawVector(ctx, abcb[i]); + + cairo_restore(C); + releaseTempMatrices(ctx->ws, 5); + releaseTempVectors(ctx->ws, 4); +} + void drawText(DrawingContext *ctx) { cairo_move_to(ctx->cairo, 15, 30); cairo_set_source_rgb(ctx->cairo, 0, 0, 0); char buf[100]; - sprintf(buf, "t = exp(%.8f) = %.8f", log(ctx->parameter), ctx->parameter); + sprintf(buf, "t = exp(%.8f) = %.8f, marking = (%.5f, %.5f)", log(ctx->parameter), ctx->parameter, ctx->marking.x, ctx->marking.y); cairo_show_text(ctx->cairo, buf); } @@ -931,6 +1485,14 @@ void draw(DrawingContext *ctx) if(ctx->show_boxes2) drawBoxes2(ctx); + if(ctx->show_marking) + { + cairo_set_source_rgb(C, 1, 0, 1); + drawPoint(ctx, ctx->marking); + } + + if(ctx->show_coxeter_orbit) + drawCoxeterOrbit(ctx); } cairo_identity_matrix(C); // text is in screen coordinates diff --git a/limit_set.c b/limit_set.c index bbe648a..91537b3 100644 --- a/limit_set.c +++ b/limit_set.c @@ -44,6 +44,7 @@ int computeLimitCurve(DrawingContext *ctx) int success = 0; int column = ctx->use_repelling ? 2 : 0; + double x,y; // int column = 1; ctx->limit_curve_count = -1; @@ -52,7 +53,7 @@ int computeLimitCurve(DrawingContext *ctx) initializeTriangleGenerators(gen, cartan_pos); gsl_matrix_set_identity(elements[0]); for(int i = 1; i < ctx->n_group_elements; i++) - multiply(elements[group[i].parent->id], gen[group[i].letter], elements[i]); + multiply(gen[group[i].letter], elements[group[i].parent->id], elements[i]); diagonalize_symmetric_form(cartan_pos, cob_pos, ws); multiply_many(ws, coxeter_pos, 3, gen[0], gen[1], gen[2]); int ev_count_pos = real_eigenvectors(coxeter_pos, coxeter_fixedpoints_pos, ws); @@ -71,7 +72,7 @@ int computeLimitCurve(DrawingContext *ctx) initializeTriangleGenerators(gen, ctx->cartan); gsl_matrix_set_identity(elements[0]); for(int i = 1; i < ctx->n_group_elements; i++) - multiply(elements[group[i].parent->id], gen[group[i].letter], elements[i]); + multiply(gen[group[i].letter], elements[group[i].parent->id], elements[i]); multiply_many(ws, coxeter, 3, gen[0], gen[1], gen[2]); int ev_count = real_eigenvectors(coxeter, coxeter_fixedpoints, ws); @@ -84,8 +85,19 @@ int computeLimitCurve(DrawingContext *ctx) for(int i = 0; i < ctx->n_group_elements; i++) { multiply_many(ws, fixedpoints, 3, ctx->cob, elements[i], coxeter_fixedpoints); - ctx->limit_curve[3*i ] = gsl_matrix_get(fixedpoints, 0, column)/gsl_matrix_get(fixedpoints, 2, column); - ctx->limit_curve[3*i+1] = gsl_matrix_get(fixedpoints, 1, column)/gsl_matrix_get(fixedpoints, 2, column); + x = ctx->limit_curve[3*i ] = 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); + + if((x - ctx->marking.x)*(x - ctx->marking.x) + (y - ctx->marking.y)*(y - ctx->marking.y) < 25e-10) + { + printf("limit point %d is close: length %d, ", i, group[i].length); + for(groupelement_t *cur = &group[i]; cur->parent; cur = cur->parent) + fputc('a' + cur->letter, stdout); // bcbcbca, bacbcacab, bc bca cb + fputc('\n',stdout); + } + + // bca abc acb = abc + } qsort(ctx->limit_curve, ctx->n_group_elements, 3*sizeof(double), compareAngle); diff --git a/linalg.c b/linalg.c index 6256dca..4327edb 100644 --- a/linalg.c +++ b/linalg.c @@ -242,6 +242,30 @@ eigenvectors_out: return success; } +int real_eigenvalues(gsl_matrix *g, gsl_vector *eval_real, workspace_t *ws) +{ + gsl_matrix *g_ = getTempMatrix(ws); + + gsl_matrix_memcpy(g_, g); + gsl_eigen_nonsymmv_params(0, ws->work_nonsymmv); + int r = gsl_eigen_nonsymmv(g_, ws->eval_complex, ws->evec_complex, ws->work_nonsymmv); + ERROR(r, "gsl_eigen_nonsymmv failed!\n"); + + gsl_eigen_nonsymmv_sort(ws->eval_complex, ws->evec_complex, GSL_EIGEN_SORT_ABS_DESC); + + int real = 0; + + for(int i = 0; i < ws->n; i++) { + if(FCMP(GSL_IMAG(gsl_vector_complex_get(ws->eval_complex, i)), 0) == 0) {// real + gsl_vector_set(eval_real, real, GSL_REAL(gsl_vector_complex_get(ws->eval_complex, i))); + real++; + } + } + + releaseTempMatrices(ws, 1); + return real; +} + // only fills in the real eigenvectors and returns their count int real_eigenvectors(gsl_matrix *g, gsl_matrix *evec_real, workspace_t *ws) { diff --git a/linalg.h b/linalg.h index c8c75fe..f2d9bbe 100644 --- a/linalg.h +++ b/linalg.h @@ -50,6 +50,7 @@ double trace(gsl_matrix *g); double determinant(gsl_matrix *g, workspace_t *ws); int eigenvectors(gsl_matrix *g, gsl_matrix *evec, workspace_t *ws); int real_eigenvectors(gsl_matrix *g, gsl_matrix *evec, workspace_t *ws); +int real_eigenvalues(gsl_matrix *g, gsl_vector *evec, workspace_t *ws); void eigenvectors_symm(gsl_matrix *g, gsl_vector *eval, gsl_matrix *evec, workspace_t *ws); int diagonalize_symmetric_form(gsl_matrix *A, gsl_matrix *cob, workspace_t *ws); void projective_frame(gsl_vector **vertices, gsl_matrix *result, workspace_t *ws); diff --git a/main.c b/main.c index de02746..ea62504 100644 --- a/main.c +++ b/main.c @@ -15,16 +15,19 @@ DrawingContext *screen_context; // setup everything except cairo and dim, which will be provided by the graphics system -void setupContext(DrawingContext *ctx) +void setupContext(DrawingContext *ctx, int argc, char *argv[]) { ctx->n_group_elements = NUM_GROUP_ELEMENTS; - ctx->p[0] = 9; - ctx->p[1] = 9; - ctx->p[2] = 9; - ctx->k[0] = 4; - ctx->k[1] = 4; - ctx->k[2] = 4; - ctx->parameter = 5.35; + ctx->p[0] = atoi(argv[1]); + ctx->p[1] = atoi(argv[2]); + ctx->p[2] = atoi(argv[3]); + ctx->k[0] = atoi(argv[4]); + ctx->k[1] = atoi(argv[5]); + ctx->k[2] = atoi(argv[6]); + if(argc > 7) + ctx->parameter = atof(argv[7]); + else + ctx->parameter = 1.0; // ctx->parameter = 2.77; // ctx->parameter = 0.1; ctx->show_boxes = 0; @@ -35,9 +38,14 @@ void setupContext(DrawingContext *ctx) ctx->show_limit= 1; ctx->show_dual_limit= 0; ctx->show_text = 1; + ctx->mode = 0; ctx->use_rotation_basis = 0; - ctx->limit_with_lines = 1; + ctx->limit_with_lines = 0; ctx->use_repelling = 0; + ctx->show_marking = 1; + 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_count = -1; @@ -137,21 +145,7 @@ void updateMatrices(DrawingContext *ctx) gsl_matrix *tmp = getTempMatrix(ctx->ws); - if(ctx->use_rotation_basis % 4 == 0) { - 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); - gsl_matrix_set(tmp, 0, 1, -1.0); - gsl_matrix_set(tmp, 0, 2, 0.0); - gsl_matrix_set(tmp, 1, 0, 1.0); - gsl_matrix_set(tmp, 1, 1, 1.0); - gsl_matrix_set(tmp, 1, 2, 1.0); - gsl_matrix_set(tmp, 2, 0, 0.0); - gsl_matrix_set(tmp, 2, 1, -1.0); - gsl_matrix_set(tmp, 2, 2, 1.0); - multiply_left(tmp, ctx->cob, ctx->ws); - - /* + if(ctx->use_rotation_basis % 5 == 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, 2, -sqrt(3.0)/2.0); @@ -162,13 +156,12 @@ void updateMatrices(DrawingContext *ctx) gsl_matrix_set(tmp, 2, 1, 1.0); gsl_matrix_set(tmp, 2, 2, 1.0); gsl_matrix_memcpy(ctx->cob, tmp); - */ - -// gsl_matrix_set_identity(ctx->cob); // is this a good choice of basis for any reason? - } else if(ctx->use_rotation_basis % 4 == 1) { + } else if(ctx->use_rotation_basis % 5 == 1) { + gsl_matrix_memcpy(ctx->cob, ctx->cartan); // is this a good choice of basis for any reason? + } else if(ctx->use_rotation_basis % 5 == 2) { computeRotationMatrix(ctx, tmp, "ba"); invert(tmp, ctx->cob, ctx->ws); - } else if(ctx->use_rotation_basis % 4 == 2) { + } else if(ctx->use_rotation_basis % 5 == 3) { computeBoxTransform(ctx, "bca", "abc", ctx->cob); // computeBoxTransform(ctx, "cab", "bca", ctx->cob); // computeBoxTransform(ctx, "acb", "cba", ctx->cob); @@ -180,6 +173,21 @@ void updateMatrices(DrawingContext *ctx) releaseTempMatrices(ctx->ws, 1); } +void output_info(DrawingContext *ctx) +{ + vector_t p[4][3]; + point_t pt; + + fixedPoints(ctx, "abc", p[0]); + fixedPoints(ctx, "bca", p[1]); + fixedPoints(ctx, "cab", p[2]); + + pt = vectorToPoint(ctx, p[0][0]); + printf("(abc)-+ = (%f %f)\n", pt.x, pt.y); + pt = vectorToPoint(ctx, p[1][0]); + printf("(bca)-+ = (%f %f)\n", pt.x, pt.y); +} + void print(DrawingContext *screen) { DrawingContext file; @@ -216,7 +224,22 @@ int processEvent(GraphicsInfo *info, XEvent *ev) unsigned long key; char filename[100]; +// fprintf(stderr, "Event: %d\n", ev->type); + switch(ev->type) { + case ButtonPress: + state = ev->xbutton.state & (ShiftMask | LockMask | ControlMask); + + if(ev->xbutton.button == 1 && state & ShiftMask) { + screen_context->marking.x = (double)ev->xbutton.x; + screen_context->marking.y = (double)ev->xbutton.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_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); + return STATUS_REDRAW; + } + break; case KeyPress: state = ev->xkey.state & (ShiftMask | LockMask | ControlMask); @@ -273,6 +296,9 @@ int processEvent(GraphicsInfo *info, XEvent *ev) printf("matrix.yy = %f;\n", info->dim->matrix.yy); printf("matrix.y0 = %f;\n", info->dim->matrix.y0); break; + case 'i': + output_info(screen_context); + break; case 'b': TOGGLE(screen_context->show_boxes); break; @@ -348,6 +374,12 @@ int processEvent(GraphicsInfo *info, XEvent *ev) 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; @@ -356,12 +388,12 @@ int processEvent(GraphicsInfo *info, XEvent *ev) return STATUS_NOTHING; } -int main() +int main(int argc, char *argv[]) { GraphicsInfo *info; screen_context = malloc(sizeof(DrawingContext)); - setupContext(screen_context); + setupContext(screen_context, argc, argv); updateMatrices(screen_context); computeLimitCurve(screen_context); diff --git a/main.h b/main.h index ba6a8dd..9829f45 100644 --- a/main.h +++ b/main.h @@ -39,8 +39,12 @@ typedef struct { int show_limit; int show_dual_limit; int show_text; + int mode; int use_rotation_basis; int limit_with_lines; + int show_marking; + point_t marking; + int show_coxeter_orbit; int use_repelling; gsl_matrix *cartan, *cob; @@ -70,6 +74,7 @@ vector_t cross(vector_t a, vector_t b); int fixedPoints(DrawingContext *ctx, const char *word, vector_t *out); void drawPoint(DrawingContext *ctx, point_t p); void drawSegment2d(DrawingContext *ctx, point_t a, point_t b); +point_t vectorToPoint(DrawingContext *ctx, vector_t v); void drawVector(DrawingContext *ctx, vector_t v); void drawCovector(DrawingContext *ctx, vector_t v); void drawSegment(DrawingContext *ctx, vector_t a, vector_t b); @@ -87,7 +92,7 @@ void drawText(DrawingContext *ctx); void draw(DrawingContext *ctx); // implemented in main.c -void setupContext(DrawingContext *ctx); +void setupContext(DrawingContext *ctx, int argc, char *argv[]); void destroyContext(DrawingContext *ctx); void print(DrawingContext *screen); int processEvent(GraphicsInfo *info, XEvent *ev);