From 4d57fbbcfb5e364daab875ad1ff2a3f7fc2e1bb1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 23 May 2006 12:38:31 -0400 Subject: [PATCH] Add spring forces. --- akamaru.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 6 deletions(-) diff --git a/akamaru.c b/akamaru.c index b26adea..17c70e9 100644 --- a/akamaru.c +++ b/akamaru.c @@ -38,6 +38,7 @@ struct _xy_pair { typedef struct _Object Object; typedef struct _Stick Stick; typedef struct _String String; +typedef struct _Spring Spring; typedef struct _Polygon Polygon; typedef struct _Offset Offset; typedef struct _Model Model; @@ -69,6 +70,11 @@ struct _Offset { int dx, dy; }; +struct _Spring { + Object *a, *b; + int length; +}; + struct _Polygon { int num_points; Point *points; @@ -85,6 +91,8 @@ struct _Model { String *strings; int num_offsets; Offset *offsets; + int num_springs; + Spring *springs; int num_polygons; Polygon *polygons; double k; @@ -184,6 +192,7 @@ model_init_snake (Model *model) model->objects[i].position.y = random() % 200 + 20; model->objects[i].previous_position.x = random() % 200 + 20; model->objects[i].previous_position.y = random() % 200 + 20; + model->objects[i].mass = 1; if (i + 1 < num_objects) { model->sticks[i * 2].a = &model->objects[i]; @@ -220,6 +229,7 @@ model_init_rope (Model *model) model->objects[i].position.y = 40 + i * stick_length; model->objects[i].previous_position.x = 200; model->objects[i].previous_position.y = 40 + i * stick_length; + model->objects[i].mass = 1; if (i + 1 < num_objects) { model->sticks[i].a = &model->objects[i]; @@ -266,6 +276,7 @@ model_init_curtain (Model *model) model->objects[index].position.y = y; model->objects[index].previous_position.x = x; model->objects[index].previous_position.y = y; + model->objects[i].mass = 1; if (j + 1 < num_rope_objects) { stick_index = i * (num_rope_objects - 1) + j; @@ -317,6 +328,7 @@ model_init_grid (Model *model) model->objects[index].position.y = y; model->objects[index].previous_position.x = x; model->objects[index].previous_position.y = y; + model->objects[index].mass = 1; if (i + 1 < num_ropes) { string_index = i * num_rope_objects + j; @@ -340,6 +352,39 @@ model_init_grid (Model *model) model->anchor_object = NULL; } +static void +model_init_molecule (Model *model) +{ + const int num_objects = 8; + const int num_springs = num_objects * 2; + const int spring_length = 50; + int i; + + memset (model, 0, sizeof *model); + model->objects = g_new (Object, num_objects); + model->num_objects = num_objects; + model->springs = g_new (Spring, num_springs); + model->num_springs = num_springs; + model->k = 0.2; + + for (i = 0; i < num_objects; i++) { + model->objects[i].position.x = 200 + i * 20; + model->objects[i].position.y = 200; + model->objects[i].previous_position.x = 200 + i * 20; + model->objects[i].previous_position.y = 200; + model->objects[i].mass = 0; + } + + for (i = 0; i < num_objects; i++) { + model->springs[i * 2].a = &model->objects[i]; + model->springs[i * 2].b = &model->objects[(i + 1) % num_objects]; + model->springs[i * 2].length = spring_length; + model->springs[i * 2 + 1].a = &model->objects[i]; + model->springs[i * 2 + 1].b = &model->objects[(i + 2) % num_objects]; + model->springs[i * 2 + 1].length = spring_length; + } +} + static void model_fini (Model *model) { @@ -354,10 +399,27 @@ static void model_accumulate_forces (Model *model) { int i; + double x, y, dx, dy, distance, displacement; + Vector u; for (i = 0; i < model->num_objects; i++) { model->objects[i].force.x = 0; - model->objects[i].force.y = 3; + model->objects[i].force.y = 3 * model->objects[i].mass; + } + + for (i = 0; i < model->num_springs; i++) { + x = model->springs[i].a->position.x; + y = model->springs[i].a->position.y; + dx = model->springs[i].b->position.x - x; + dy = model->springs[i].b->position.y - y; + distance = sqrt (dx * dx + dy * dy); + u.x = dx / distance; + u.y = dy / distance; + displacement = distance - model->springs[i].length; + model->springs[i].a->force.x += u.x * model->k * displacement; + model->springs[i].a->force.y += u.y * model->k * displacement; + model->springs[i].b->force.x -= u.x * model->k * displacement; + model->springs[i].b->force.y -= u.y * model->k * displacement; } } @@ -374,9 +436,9 @@ model_integrate (Model *model, double step) y = o->position.y; o->position.x = - x + 0.9 * (x - o->previous_position.x) + o->force.x * step * step; + x + 0.8 * (x - o->previous_position.x) + o->force.x * step * step; o->position.y = - y + 0.9 * (y - o->previous_position.y) + o->force.y * step * step; + y + 0.8 * (y - o->previous_position.y) + o->force.y * step * step; o->previous_position.x = x; o->previous_position.y = y; @@ -662,6 +724,31 @@ draw_offsets (cairo_t *cr, } +static void +draw_springs (cairo_t *cr, + Model *model, + Color *color) +{ + int i; + + cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.4); + cairo_new_path (cr); + cairo_set_line_width (cr, 2); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + + for (i = 0; i < model->num_springs; i++) { + cairo_move_to (cr, + model->springs[i].a->position.x, + model->springs[i].a->position.y); + cairo_line_to (cr, + model->springs[i].b->position.x, + model->springs[i].b->position.y); + } + + cairo_stroke (cr); +} + static void draw_polygons (cairo_t *cr, Model *model, Color *color) { @@ -686,7 +773,12 @@ draw_objects (cairo_t *cr, Model *model, Color *color) { int i; + cairo_set_source_rgba (cr, color->red, color->green, color->blue, 0.4); for (i = 0; i < model->num_objects; i++) { + cairo_arc (cr, model->objects[i].position.x, + model->objects[i].position.y, + 3, 0, 2*M_PI); + cairo_fill (cr); } } @@ -694,7 +786,6 @@ static Color blue = { 0, 0, 1 }; static Color green = { 0, 1, 0 }; static Color red = { 1, 0, 0 }; static Color black = { 0, 0, 0 }; -static Color white = { 1, 1, 1 }; typedef struct _Closure Closure; struct _Closure { @@ -719,8 +810,9 @@ draw_model (GtkWidget *widget, Model *model) draw_polygons (cr, model, &blue); draw_sticks (cr, model, &black); draw_strings (cr, model, &green); + draw_springs (cr, model, &black); draw_offsets (cr, model, &blue); - draw_objects (cr, model, &white); + draw_objects (cr, model, &red); cairo_destroy (cr); } @@ -818,7 +910,8 @@ create_model_store (void) { "Rope", model_init_rope }, { "Snake", model_init_snake }, { "Curtain", model_init_curtain }, - { "Grid", model_init_grid } + { "Grid", model_init_grid }, + { "Molecule", model_init_molecule } }; GtkTreeIter iter; -- 2.43.0