2019-02-03 12:18:14 +00:00
# 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 ;
2019-02-08 12:03:05 +00:00
ctx - > show_boxes2 = 0 ;
2019-02-03 12:18:14 +00:00
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 ) ) ;
2019-02-08 12:03:05 +00:00
memcpy ( & file , screen , sizeof ( file ) ) ;
2019-02-03 12:18:14 +00:00
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 ;
2019-02-08 12:03:05 +00:00
case ' B ' :
TOGGLE ( screen_context - > show_boxes2 ) ;
break ;
2019-02-03 12:18:14 +00:00
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 ( & current_time , 0 ) ;
start_time = current_time . tv_sec + current_time . tv_usec * 1e-6 ;
draw ( screen_context ) ;
gettimeofday ( & current_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 ( & current_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 ;
}