Select Git revision
pendulum-3.c
Forked from
Peter Gerwinski / hp
281 commits behind the upstream repository.
Peter Gerwinski authored
pendulum-3.c 2.29 KiB
#include <gtk/gtk.h>
#include <math.h>
#define WIDTH 320
#define HEIGHT 240
#define GAP (HEIGHT / 20)
#define r GAP
#define visual_length (HEIGHT - 2 * GAP - r)
#define phi0 (-0.5)
#define omega0 0.0
#define t0 0.0
#define g 9.81
#define l 1.0
#define dt 0.02
double t = t0;
double phi_with_sin = phi0;
double omega_with_sin= omega0;
double phi_without_sin = phi0;
double omega_without_sin= omega0;
void draw_pendulum (cairo_t *c, double phi, GdkRGBA *colour)
{
int x = WIDTH / 2 + visual_length * sin (phi);
int y = GAP + visual_length * cos (phi);
gdk_cairo_set_source_rgba (c, colour);
cairo_move_to (c, WIDTH / 2, 10);
cairo_line_to (c, x, y);
cairo_stroke (c);
cairo_arc (c, x, y, r, 0, 2 * G_PI);
cairo_fill (c);
}
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
GdkRGBA orange = { 1.0, 0.5, 0.0, 1.0 };
GdkRGBA green = { 0.0, 0.5, 0.0, 1.0 };
double A = phi0;
double B = 0.5 * M_PI; /* 90° */
double phi_analytic = A * sin (sqrt (g / l) * t + B);
draw_pendulum (c, phi_with_sin, &blue);
draw_pendulum (c, phi_without_sin, &orange);
draw_pendulum (c, phi_analytic, &green);
return FALSE; /* TRUE to stop other handlers from being invoked for the event.
FALSE to propagate the event further. */
}
gboolean timer (GtkWidget *widget)
{
t += dt;
phi_with_sin += omega_with_sin * dt;
omega_with_sin += - dt * g / l * sin (phi_with_sin);
phi_without_sin += omega_without_sin * dt;
omega_without_sin += - dt * g / l * phi_without_sin;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_widget_show (drawing_area);
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_main ();
return 0;
}