247 lines
6.2 KiB
C
247 lines
6.2 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
#include <cairo/cairo-pdf.h>
|
|
#include <X11/XKBlib.h>
|
|
|
|
#include "main.h"
|
|
#include "initcairo.h"
|
|
#include "triangle.h"
|
|
#include "linalg.h"
|
|
|
|
#define TOGGLE(a) do { (a) = !(a); } while(0)
|
|
|
|
DrawingContext *screen_context;
|
|
|
|
// setup everything except cairo and dim, which will be provided by the graphics system
|
|
void setupContext(DrawingContext *ctx)
|
|
{
|
|
ctx->n_group_elements = NUM_GROUP_ELEMENTS;
|
|
ctx->p[0] = 5;
|
|
ctx->p[1] = 5;
|
|
ctx->p[2] = 5;
|
|
ctx->k[0] = 2;
|
|
ctx->k[1] = 2;
|
|
ctx->k[2] = 2;
|
|
ctx->parameter = 3.0;
|
|
ctx->show_boxes = 0;
|
|
ctx->show_boxes2 = 0;
|
|
ctx->show_attractors = 0;
|
|
ctx->show_reflectors = 0;
|
|
ctx->show_limit= 1;
|
|
ctx->limit_with_lines = 1;
|
|
ctx->use_repelling = 0;
|
|
|
|
ctx->limit_curve = malloc(3*ctx->n_group_elements*sizeof(double));
|
|
ctx->limit_curve_valid = 0;
|
|
|
|
ctx->group = malloc(ctx->n_group_elements*sizeof(groupelement_t));
|
|
generate_triangle_group(ctx->group, ctx->n_group_elements, 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);
|
|
}
|
|
|
|
void destroyContext(DrawingContext *ctx)
|
|
{
|
|
free(ctx->limit_curve);
|
|
free(ctx->group);
|
|
|
|
gsl_matrix_free(ctx->cartan);
|
|
gsl_matrix_free(ctx->cob);
|
|
|
|
workspace_free(ctx->ws);
|
|
}
|
|
|
|
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);
|
|
gsl_matrix_memcpy(ctx->cob, ctx->cartan); // is this a good choice of basis
|
|
}
|
|
|
|
void print(DrawingContext *screen)
|
|
{
|
|
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));
|
|
|
|
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;
|
|
|
|
surface = cairo_pdf_surface_create(filename, (double)dim.width, (double)dim.height);
|
|
file.cairo = cairo_create(surface);
|
|
|
|
draw(&file);
|
|
|
|
cairo_destroy(file.cairo);
|
|
cairo_surface_destroy(surface);
|
|
|
|
printf("Wrote sceenshot to file: %s\n", filename);
|
|
}
|
|
|
|
int processEvent(GraphicsInfo *info, XEvent *ev)
|
|
{
|
|
int state;
|
|
unsigned long key;
|
|
|
|
switch(ev->type) {
|
|
|
|
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->parameter /= exp(0.0001);
|
|
updateMatrices(screen_context);
|
|
computeLimitCurve(screen_context);
|
|
break;
|
|
case XK_Right:
|
|
screen_context->parameter *= exp(0.0001);
|
|
updateMatrices(screen_context);
|
|
computeLimitCurve(screen_context);
|
|
break;
|
|
case XK_Page_Down:
|
|
screen_context->parameter /= exp(0.2);
|
|
updateMatrices(screen_context);
|
|
computeLimitCurve(screen_context);
|
|
break;
|
|
case XK_Page_Up:
|
|
screen_context->parameter *= exp(0.2);
|
|
updateMatrices(screen_context);
|
|
computeLimitCurve(screen_context);
|
|
break;
|
|
case ' ':
|
|
screen_context->parameter = 2.890053638;
|
|
updateMatrices(screen_context);
|
|
computeLimitCurve(screen_context);
|
|
break;
|
|
case XK_Return:
|
|
screen_context->parameter = 2.76375163;
|
|
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 '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 'L':
|
|
TOGGLE(screen_context->limit_with_lines);
|
|
break;
|
|
case 'l':
|
|
TOGGLE(screen_context->show_limit);
|
|
break;
|
|
case 'p':
|
|
print(screen_context);
|
|
break;
|
|
case 'f':
|
|
TOGGLE(screen_context->use_repelling);
|
|
computeLimitCurve(screen_context);
|
|
}
|
|
|
|
return STATUS_REDRAW;
|
|
}
|
|
|
|
return STATUS_NOTHING;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
GraphicsInfo *info;
|
|
|
|
screen_context = malloc(sizeof(DrawingContext));
|
|
setupContext(screen_context);
|
|
updateMatrices(screen_context);
|
|
computeLimitCurve(screen_context);
|
|
|
|
info = initCairo(0, KeyPressMask, 200, 200, "Triangle group");
|
|
if(!info)
|
|
return 1;
|
|
|
|
info->dim->matrix.xx = 837.930824;
|
|
info->dim->matrix.xy = -712.651341;
|
|
info->dim->matrix.x0 = 180.427716;
|
|
info->dim->matrix.yx = 712.651341;
|
|
info->dim->matrix.yy = 837.930824;
|
|
info->dim->matrix.y0 = 1412.553240;
|
|
updateDimensions(info->dim);
|
|
|
|
screen_context->dim = info->dim;
|
|
screen_context->cairo = info->buffer_context;
|
|
|
|
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;
|
|
|
|
draw(screen_context);
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
return 0;
|
|
}
|