From 78769593a755c4b82b69c41bf7749b7bbb560f60 Mon Sep 17 00:00:00 2001 From: Florian Stecker Date: Sun, 5 Feb 2023 15:10:16 -0500 Subject: [PATCH] movie command line arguments --- main.c | 737 +++++++++++++++++++++++++++++---------------------------- main.h | 4 + 2 files changed, 379 insertions(+), 362 deletions(-) diff --git a/main.c b/main.c index 03e1c0b..1f8568f 100644 --- a/main.c +++ b/main.c @@ -11,461 +11,474 @@ #include "linalg.h" #define TOGGLE(a) do { (a) = !(a); } while(0) +#define SIGN(x) ((x) > 0 ? 1.0 : -1.0) DrawingContext *screen_context; // setup everything except cairo and dim, which will be provided by the graphics system void setupContext(DrawingContext *ctx, int argc, char *argv[]) { - ctx->n_group_elements = NUM_GROUP_ELEMENTS; - ctx->n_group_elements_combinatorial = NUM_GROUP_ELEMENTS_COMBINATORIAL; - 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; - if(argc > 8) - ctx->parameter2 = atof(argv[8]); - else - ctx->parameter2 = 1.0; -// ctx->parameter = 2.77; -// ctx->parameter = 0.1; - ctx->show_boxes = 0; - ctx->show_boxes2 = 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 = 2; - 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->n_group_elements = NUM_GROUP_ELEMENTS; + ctx->n_group_elements_combinatorial = NUM_GROUP_ELEMENTS_COMBINATORIAL; + 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; + if(argc > 8) + ctx->parameter2 = atof(argv[8]); + else + ctx->parameter2 = 1.0; + if(argc > 12) { + ctx->movie_filename = argv[9]; + ctx->movie_parameter_duration = atof(argv[10]); + ctx->movie_parameter2_duration = atof(argv[11]); + ctx->movie_n_frames = atoi(argv[12]); + } else { + ctx->movie_n_frames = 0; + } + // ctx->parameter = 2.77; + // ctx->parameter = 0.1; + ctx->show_boxes = 0; + ctx->show_boxes2 = 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_count = -1; + ctx->limit_curve = malloc(3*ctx->n_group_elements*sizeof(double)); + ctx->limit_curve_count = -1; - ctx->group = malloc(ctx->n_group_elements_combinatorial*sizeof(groupelement_t)); - generate_triangle_group(ctx->group, ctx->n_group_elements_combinatorial, ctx->p[0], ctx->p[1], ctx->p[2]); + ctx->group = malloc(ctx->n_group_elements_combinatorial*sizeof(groupelement_t)); + generate_triangle_group(ctx->group, ctx->n_group_elements_combinatorial, ctx->p[0], ctx->p[1], ctx->p[2]); - // the temporary stuff - ctx->cartan = gsl_matrix_alloc(3, 3); - ctx->cob = gsl_matrix_alloc(3, 3); - ctx->ws = workspace_alloc(3); + // the temporary stuff + ctx->cartan = gsl_matrix_alloc(3, 3); + ctx->cob = gsl_matrix_alloc(3, 3); + ctx->ws = workspace_alloc(3); } void destroyContext(DrawingContext *ctx) { - free(ctx->limit_curve); - free(ctx->group); + free(ctx->limit_curve); + free(ctx->group); - gsl_matrix_free(ctx->cartan); - gsl_matrix_free(ctx->cob); + gsl_matrix_free(ctx->cartan); + gsl_matrix_free(ctx->cob); - workspace_free(ctx->ws); + workspace_free(ctx->ws); } void computeMatrix(DrawingContext *ctx, gsl_matrix *result, const char *type) { - gsl_matrix **gen = getTempMatrices(ctx->ws, 6); + gsl_matrix **gen = getTempMatrices(ctx->ws, 6); -// ERROR(strlen(type) != 2, "Invalid call of computeRotationMatrix()\n"); + // ERROR(strlen(type) != 2, "Invalid call of computeRotationMatrix()\n"); - initializeTriangleGeneratorsCurrent(gen, ctx); - gsl_matrix_set_identity(result); - for(int i = 0; i < strlen(type); i++) { - 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); - } + initializeTriangleGeneratorsCurrent(gen, ctx); + gsl_matrix_set_identity(result); + for(int i = 0; i < strlen(type); i++) { + 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); + } - releaseTempMatrices(ctx->ws, 6); + releaseTempMatrices(ctx->ws, 6); } 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); + 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) { - vector_t p[2][3],i[2]; - vector_t std[4] = { - {-1, -1, 1}, - {-1, 1, 1}, - {1, 1, 1}, - {1, -1, 1} - }; + vector_t p[2][3],i[2]; + vector_t std[4] = { + {-1, -1, 1}, + {-1, 1, 1}, + {1, 1, 1}, + {1, -1, 1} + }; - gsl_vector **vertices = getTempVectors(ctx->ws, 4); - gsl_vector **std_vertices = getTempVectors(ctx->ws, 4); - gsl_matrix *tmp = getTempMatrix(ctx->ws); - gsl_matrix *to_frame = getTempMatrix(ctx->ws); - gsl_matrix *to_std_frame = getTempMatrix(ctx->ws); + gsl_vector **vertices = getTempVectors(ctx->ws, 4); + gsl_vector **std_vertices = getTempVectors(ctx->ws, 4); + gsl_matrix *tmp = getTempMatrix(ctx->ws); + gsl_matrix *to_frame = getTempMatrix(ctx->ws); + gsl_matrix *to_std_frame = getTempMatrix(ctx->ws); - fixedPoints(ctx, word1, p[0]); - fixedPoints(ctx, word2, p[1]); + fixedPoints(ctx, word1, p[0]); + fixedPoints(ctx, word2, p[1]); - // 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])); + // 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])); - // 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++) - vectorToGsl(std[i], std_vertices[i]); + for(int i = 0; i < 4; i++) + vectorToGsl(std[i], std_vertices[i]); - vectorToGsl(p[0][0], vertices[0]); - vectorToGsl(i[0], vertices[1]); - vectorToGsl(p[1][0], vertices[2]); - vectorToGsl(i[1], vertices[3]); + vectorToGsl(p[0][0], vertices[0]); + vectorToGsl(i[0], vertices[1]); + vectorToGsl(p[1][0], vertices[2]); + vectorToGsl(i[1], vertices[3]); - projective_frame(std_vertices, to_std_frame, ctx->ws); - projective_frame(vertices, to_frame, ctx->ws); - invert(to_frame, tmp, ctx->ws); - multiply(to_std_frame, tmp, result); + projective_frame(std_vertices, to_std_frame, ctx->ws); + projective_frame(vertices, to_frame, ctx->ws); + invert(to_frame, tmp, ctx->ws); + multiply(to_std_frame, tmp, result); - /* - LOOP(i) { - LOOP(j) { - printf("%.4f ", gsl_matrix_get(result, i, j)); - } - printf("\n"); - }*/ + /* + LOOP(i) { + LOOP(j) { + printf("%.4f ", gsl_matrix_get(result, i, j)); + } + printf("\n"); + }*/ - releaseTempVectors(ctx->ws, 8); - releaseTempMatrices(ctx->ws, 3); + releaseTempVectors(ctx->ws, 8); + releaseTempMatrices(ctx->ws, 3); } void updateMatrices(DrawingContext *ctx) { - double angle[3]; - LOOP(i) angle[i] = M_PI*ctx->k[i]/ctx->p[i]; - cartanMatrix(ctx->cartan, angle[0], angle[1], angle[2], ctx->parameter); + double angle[3]; + LOOP(i) angle[i] = M_PI*ctx->k[i]/ctx->p[i]; + 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) { - 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); - gsl_matrix_set(tmp, 1, 0, 1.0); - gsl_matrix_set(tmp, 1, 1, -0.5); - gsl_matrix_set(tmp, 1, 2, -0.5); - gsl_matrix_set(tmp, 2, 0, 1.0); - gsl_matrix_set(tmp, 2, 1, 1.0); - gsl_matrix_set(tmp, 2, 2, 1.0); - gsl_matrix_memcpy(ctx->cob, tmp); - } 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) { - computeRotationMatrixFrame(ctx, tmp, "C"); - invert(tmp, ctx->cob, ctx->ws); - } else if(ctx->use_rotation_basis % 5 == 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); - } + if(ctx->use_rotation_basis % nmodes == 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); + gsl_matrix_set(tmp, 1, 0, 1.0); + gsl_matrix_set(tmp, 1, 1, -0.5); + gsl_matrix_set(tmp, 1, 2, -0.5); + gsl_matrix_set(tmp, 2, 0, 1.0); + gsl_matrix_set(tmp, 2, 1, 1.0); + gsl_matrix_set(tmp, 2, 2, 1.0); + gsl_matrix_memcpy(ctx->cob, tmp); + } else if(ctx->use_rotation_basis % nmodes == 1) { + 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, 0.0); + gsl_matrix_set(tmp, 2, 0, 0.0); + gsl_matrix_set(tmp, 2, 1, 0.0); + gsl_matrix_set(tmp, 2, 2, 1.0); + gsl_matrix_memcpy(ctx->cob, ctx->cartan); // is this a good choice of basis for any reason? + 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) { - vector_t p[4][3]; - point_t pt; + vector_t p[4][3]; + point_t pt; - fixedPoints(ctx, "abc", p[0]); - fixedPoints(ctx, "bca", p[1]); - fixedPoints(ctx, "cab", p[2]); + 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); + 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; - DimensionsInfo dim; - cairo_surface_t *surface; + DrawingContext file; + DimensionsInfo dim; + cairo_surface_t *surface; - char filename[100]; - time_t t = time(NULL); - strftime(filename, sizeof(filename), "screenshot_%Y%m%d_%H%M%S.pdf", localtime(&t)); + char filename[100]; + time_t t = time(NULL); + 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.height = screen->dim->width / sqrt(2.0); - dim.matrix = screen->dim->matrix; - dim.matrix.y0 += ((double)dim.height - (double)screen->dim->height) / 2.0; // recenter vertically - updateDimensions(&dim); - file.dim = &dim; + dim.width = screen->dim->width; + dim.height = screen->dim->width / sqrt(2.0); + dim.matrix = screen->dim->matrix; + dim.matrix.y0 += ((double)dim.height - (double)screen->dim->height) / 2.0; // recenter vertically + updateDimensions(&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); - draw(&file); + draw(&file); - cairo_destroy(file.cairo); - cairo_surface_destroy(surface); + cairo_destroy(file.cairo); + 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 state; - unsigned long key; - char filename[100]; + int state; + unsigned long key; + char filename[100]; -// fprintf(stderr, "Event: %d\n", ev->type); + // fprintf(stderr, "Event: %d\n", ev->type); - switch(ev->type) { - case ButtonPress: - state = ev->xbutton.state & (ShiftMask | LockMask | ControlMask); + 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; + 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); - key = XkbKeycodeToKeysym(ev->xkey.display, ev->xkey.keycode, 0, !!(state & ShiftMask)); - printf("Key pressed: %ld\n", key); + case KeyPress: + state = ev->xkey.state & (ShiftMask | LockMask | ControlMask); + key = XkbKeycodeToKeysym(ev->xkey.display, ev->xkey.keycode, 0, !!(state & ShiftMask)); + printf("Key pressed: %ld\n", key); - switch(key) { - case XK_Down: - screen_context->parameter /= exp(0.002); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case XK_Up: - screen_context->parameter *= exp(0.002); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case XK_Left: - screen_context->parameter2 /= exp(0.002); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case XK_Right: - screen_context->parameter2 *= exp(0.002); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case XK_Page_Down: - screen_context->parameter /= exp(0.02); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case XK_Page_Up: - screen_context->parameter *= exp(0.02); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case ' ': - screen_context->parameter = 5.57959706; - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case XK_Return: -// screen_context->parameter = 2.76375163; - screen_context->parameter = 5.29063366; - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case 'm': - printf("matrix.xx = %f;\n", info->dim->matrix.xx); - printf("matrix.xy = %f;\n", info->dim->matrix.xy); - printf("matrix.x0 = %f;\n", info->dim->matrix.x0); - printf("matrix.yx = %f;\n", info->dim->matrix.yx); - 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; - case 'B': - TOGGLE(screen_context->show_boxes2); - break; - case 'a': - TOGGLE(screen_context->show_attractors); - break; - case 'r': - TOGGLE(screen_context->show_reflectors); - break; - case 'x': - TOGGLE(screen_context->show_rotated_reflectors); - break; - case 'L': - TOGGLE(screen_context->limit_with_lines); - break; - case 'l': - TOGGLE(screen_context->show_limit); - break; - case 'd': - TOGGLE(screen_context->show_dual_limit); - break; - case 'R': - screen_context->use_rotation_basis++; - updateMatrices(screen_context); - computeLimitCurve(screen_context); - break; - case 'p': - print(screen_context); - break; - case 'M': - /* - screen_context->limit_with_lines = 0; - double parameter_start = screen_context->parameter; - for(int i = 0; i <= 1300; i++) { - if(i < 400) - screen_context->parameter = exp(log(parameter_start)+0.002*i); - else if(i < 500) - screen_context->parameter = exp(log(parameter_start)+0.002*400); - else - screen_context->parameter = exp(log(parameter_start)+0.002*(900-i)); - updateMatrices(screen_context); - computeLimitCurve(screen_context); - draw(screen_context); - sprintf(filename, "movie3/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; - double parameter_start = screen_context->parameter; - for(int i = 0; i <= 1300; i++) { - if(i < 400) - screen_context->parameter = exp(0.003*i); - else if(i < 500) - screen_context->parameter = exp(0.003*400); - 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); - } + switch(key) { + case XK_Down: + if(ev->xkey.state & ShiftMask) + screen_context->parameter /= exp(0.00005); + else + screen_context->parameter /= exp(0.002); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case XK_Up: + if(ev->xkey.state & ShiftMask) + screen_context->parameter *= exp(0.00005); + else + screen_context->parameter *= exp(0.002); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case XK_Left: + if(ev->xkey.state & ShiftMask) + screen_context->parameter2 /= exp(0.00005); + else + screen_context->parameter2 /= exp(0.002); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case XK_Right: + if(ev->xkey.state & ShiftMask) + screen_context->parameter2 *= exp(0.00005); + else + screen_context->parameter2 *= exp(0.002); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case XK_Page_Down: + screen_context->parameter /= exp(0.02); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case XK_Page_Up: + screen_context->parameter *= exp(0.02); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case ' ': + screen_context->parameter = 5.57959706; + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case XK_Return: + // screen_context->parameter = 2.76375163; + screen_context->parameter = 5.29063366; + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case 'm': + printf("matrix.xx = %f;\n", info->dim->matrix.xx); + printf("matrix.xy = %f;\n", info->dim->matrix.xy); + printf("matrix.x0 = %f;\n", info->dim->matrix.x0); + printf("matrix.yx = %f;\n", info->dim->matrix.yx); + 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; + case 'B': + TOGGLE(screen_context->show_boxes2); + break; + case 'a': + TOGGLE(screen_context->show_attractors); + break; + case 'r': + TOGGLE(screen_context->show_reflectors); + break; + case 'x': + TOGGLE(screen_context->show_rotated_reflectors); + break; + case 'L': + TOGGLE(screen_context->limit_with_lines); + break; + case 'l': + TOGGLE(screen_context->show_limit); + break; + case 'd': + TOGGLE(screen_context->show_dual_limit); + break; + case 'R': + screen_context->use_rotation_basis++; + updateMatrices(screen_context); + computeLimitCurve(screen_context); + break; + case 'p': + print(screen_context); + break; + case 'M': + screen_context->limit_with_lines = 0; + double parameter_start = screen_context->parameter; + double parameter2_start = screen_context->parameter2; + 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)) + + i*screen_context->movie_parameter2_duration/screen_context->movie_n_frames); + updateMatrices(screen_context); + computeLimitCurve(screen_context); + draw(screen_context); + sprintf(filename, "output/%s%03d.png", screen_context->movie_filename, 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[]) { - GraphicsInfo *info; + GraphicsInfo *info; - screen_context = malloc(sizeof(DrawingContext)); - setupContext(screen_context, argc, argv); - updateMatrices(screen_context); - computeLimitCurve(screen_context); + screen_context = malloc(sizeof(DrawingContext)); + setupContext(screen_context, argc, argv); + updateMatrices(screen_context); + computeLimitCurve(screen_context); - info = initCairo(0, KeyPressMask, 200, 200, "Triangle group"); - if(!info) - return 1; + info = initCairo(0, KeyPressMask, 200, 200, "Triangle group"); + if(!info) + return 1; -/* - info->dim->matrix.xx = 274.573171; - info->dim->matrix.xy = 0.000000; - info->dim->matrix.x0 = 583.073462; - info->dim->matrix.yx = 0.000000; - info->dim->matrix.yy = 274.573171; - info->dim->matrix.y0 = 777.225293; -*/ + /* + info->dim->matrix.xx = 274.573171; + info->dim->matrix.xy = 0.000000; + info->dim->matrix.x0 = 583.073462; + info->dim->matrix.yx = 0.000000; + info->dim->matrix.yy = 274.573171; + info->dim->matrix.y0 = 777.225293; + */ - info->dim->matrix.xx = 274.573171; - info->dim->matrix.xy = 0.000000; - info->dim->matrix.x0 = 910.073462; - info->dim->matrix.yx = 0.000000; - info->dim->matrix.yy = 274.573171; - info->dim->matrix.y0 = 509.225293; + info->dim->matrix.xx = 274.573171; + info->dim->matrix.xy = 0.000000; + info->dim->matrix.x0 = 910.073462; + info->dim->matrix.yx = 0.000000; + info->dim->matrix.yy = 274.573171; + info->dim->matrix.y0 = 509.225293; - updateDimensions(info->dim); + updateDimensions(info->dim); - screen_context->dim = info->dim; - screen_context->cairo = info->buffer_context; + screen_context->dim = info->dim; + screen_context->cairo = info->buffer_context; - startTimer(info); + startTimer(info); - while(1) { - int result = checkEvents(info, processEvent, NULL); - if(result == STATUS_QUIT) - return 0; - else if(result == STATUS_REDRAW) { - struct timeval current_time; - double start_time, intermediate_time, end_time; - gettimeofday(¤t_time, 0); - start_time = current_time.tv_sec + current_time.tv_usec*1e-6; + while(1) { + int result = checkEvents(info, processEvent, NULL); + if(result == STATUS_QUIT) + return 0; + else if(result == STATUS_REDRAW) { + struct timeval current_time; + double start_time, intermediate_time, end_time; + gettimeofday(¤t_time, 0); + start_time = current_time.tv_sec + current_time.tv_usec*1e-6; - draw(screen_context); + draw(screen_context); - gettimeofday(¤t_time, 0); - intermediate_time = current_time.tv_sec + current_time.tv_usec*1e-6; + gettimeofday(¤t_time, 0); + 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_paint(info->front_context); + cairo_set_source_surface(info->front_context, info->buffer_surface, 0, 0); + cairo_paint(info->front_context); - gettimeofday(¤t_time, 0); - 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); - } - waitUpdateTimer(info); + gettimeofday(¤t_time, 0); + 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); } + waitUpdateTimer(info); + } - free(screen_context); - destroyCairo(info); - destroyContext(screen_context); + free(screen_context); + destroyCairo(info); + destroyContext(screen_context); - return 0; + return 0; } diff --git a/main.h b/main.h index f365728..0bf963e 100644 --- a/main.h +++ b/main.h @@ -36,6 +36,10 @@ typedef struct { int p[3],k[3]; 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_combinatorial; int show_boxes;