[cairo-commit]
cairo-demo/sproing ChangeLog, 1.5, 1.6 sproing.c, 1.4, 1.5
Carl Worth
commit at pdx.freedesktop.org
Mon Mar 28 12:02:45 PST 2005
- Previous message: [cairo-commit] roadster/src animator.c, 1.2, 1.3 databasewindow.c,
1.5, 1.6 datasetwindow.c, 1.5, 1.6 db.c, 1.19, 1.20 db.h, 1.8,
1.9 glyph.c, 1.4, 1.5 gotowindow.c, 1.8, 1.9 gpsclient.c, 1.8,
1.9 gui.c, 1.7, 1.8 history.c, 1.1, 1.2 import.c, 1.8,
1.9 import_tiger.c, 1.15, 1.16 importwindow.c, 1.6,
1.7 layers.c, 1.13, 1.14 location.c, 1.2, 1.3 locationset.c,
1.7, 1.8 main.c, 1.16, 1.17 main.h, NONE, 1.1 mainwindow.c,
1.32, 1.33 map.c, 1.34, 1.35 map.h, 1.13,
1.14 map_draw_cairo.c, 1.14, 1.15 map_draw_gdk.c, 1.10,
1.11 point.c, 1.3, 1.4 pointstring.c, 1.4, 1.5 prefs.c, 1.1,
1.2 road.c, 1.2, 1.3 road.h, 1.1, 1.2 scenemanager.c, 1.9,
1.10 search.c, 1.4, 1.5 search_location.c, 1.7,
1.8 search_road.c, 1.15, 1.16 searchwindow.c, 1.15,
1.16 tooltip.c, 1.1, 1.2 track.c, 1.5, 1.6 util.c, 1.4,
1.5 util.h, 1.6, 1.7 welcomewindow.c, 1.5, 1.6
- Next message: [cairo-commit]
cairo-demo/sproing ChangeLog, 1.6, 1.7 sproing.c, 1.5, 1.6
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: cworth
Update of /cvs/cairo/cairo-demo/sproing
In directory gabe:/tmp/cvs-serv30866
Modified Files:
ChangeLog sproing.c
Log Message:
* sproing.c: Reworked to have 2-way springs in the model, rather
than 1-way attractors in the objects. The 2-way behavior lets us
now pull any point around, (which is what's in place here). But
the springs add a bit more bouncing than we'll actually want I
think.
Index: ChangeLog
===================================================================
RCS file: /cvs/cairo/cairo-demo/sproing/ChangeLog,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ChangeLog 28 Mar 2005 14:28:38 -0000 1.5
+++ ChangeLog 28 Mar 2005 20:02:43 -0000 1.6
@@ -1,5 +1,13 @@
2005-03-28 Carl Worth <cworth at cworth.org>
+ * sproing.c: Reworked to have 2-way springs in the model, rather
+ than 1-way attractors in the objects. The 2-way behavior lets us
+ now pull any point around, (which is what's in place here). But
+ the springs add a bit more bouncing than we'll actually want I
+ think.
+
+2005-03-28 Carl Worth <cworth at cworth.org>
+
* sproing.c: (sproing_expose_event), (sproing_button_press_event),
(sproing_motion_notify_event), (create_window): Remove old
scribble names left over from some copy-and-paste.
Index: sproing.c
===================================================================
RCS file: /cvs/cairo/cairo-demo/sproing/sproing.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- sproing.c 28 Mar 2005 14:28:38 -0000 1.4
+++ sproing.c 28 Mar 2005 20:02:43 -0000 1.5
@@ -6,21 +6,31 @@
#include <gdk/gdkx.h>
#include <math.h>
-typedef struct _Point Point;
-struct _Point {
- double x, y;
-};
-
-typedef struct _Vector Vector;
-struct _Vector {
+typedef struct _xy_pair Point;
+typedef struct _xy_pair Vector;
+struct _xy_pair {
double x, y;
};
typedef struct _Model Model;
typedef struct _Object Object;
typedef struct _Attractor Attractor;
+typedef struct _Spring Spring;
-#define MAX_ATTRACTORS 5
+#define MODEL_MAX_SPRINGS 50
+#define MASS_INFINITE -1.0
+
+#define DEFAULT_SPRING_K 2.0
+#define DEFAULT_FRICTION 4.2
+
+struct _Spring {
+ Object *a;
+ Object *b;
+ /* Spring position at rest, from a to b:
+ offset = b.position - a.position
+ */
+ Vector offset;
+};
struct _Attractor {
Object *object;
@@ -28,74 +38,73 @@
};
struct _Object {
- int num_attractors;
- Attractor attractors[MAX_ATTRACTORS];
-
- Vector attractor_offset;
+ Vector force;
Point position;
- Point next_position;
Vector velocity;
- Vector prev_velocity;
- Vector acceleration;
- Vector prev_acceleration;
+
double mass;
double theta;
+
+ int immobile;
};
struct _Model {
int num_objects;
Object *objects;
- Object attractor;
- Object *current_attractor;
- double k; /* Spring constant */
+ int num_springs;
+ Spring springs[MODEL_MAX_SPRINGS];
+
+ Object *anchor_object;
+
double friction; /* Friction constant */
+ double k; /* Spring constant */
};
-
-static void
-model_move_attractor (Model *model, double x, double y)
-{
- model->current_attractor->position.x = x;
- model->current_attractor->position.y = y;
-}
-
static void
-model_init_object (Object *object,
- double position_x, double position_y,
- double velocity_x, double velocity_y, double mass)
+object_init (Object *object,
+ double position_x, double position_y,
+ double velocity_x, double velocity_y, double mass)
{
- object->num_attractors = 0;
-
object->position.x = position_x;
object->position.y = position_y;
object->velocity.x = velocity_x;
object->velocity.y = velocity_y;
- object->prev_velocity.x = velocity_x;
- object->prev_velocity.y = velocity_y;
-
- object->acceleration.x = 0;
- object->acceleration.y = 0;
- object->prev_acceleration.x = 0;
- object->prev_acceleration.y = 0;
object->mass = mass;
+
+ object->force.x = 0;
+ object->force.y = 0;
+
+ object->immobile = 0;
}
static void
-model_add_object_attractor (Object *object, Object *attractor_object,
- double offset_x, double offset_y)
+spring_init (Spring *spring,
+ Object *object_a, Object *object_b,
+ double offset_x, double offset_y)
{
- Attractor *attractor;
+ spring->a = object_a;
+ spring->b = object_b;
+ spring->offset.x = offset_x;
+ spring->offset.y = offset_y;
+}
- attractor = &object->attractors[object->num_attractors];
- object->num_attractors++;
+static void
+model_add_spring (Model *model,
+ Object *object_a, Object *object_b,
+ double offset_x, double offset_y)
+{
+ Spring *spring;
- attractor->object = attractor_object;
- attractor->offset.x = offset_x;
- attractor->offset.y = offset_y;
+ g_assert (model->num_springs < MODEL_MAX_SPRINGS);
+
+ spring = &model->springs[model->num_springs];
+ model->num_springs++;
+
+ spring_init (spring, object_a, object_b, offset_x, offset_y);
}
static void
@@ -107,62 +116,65 @@
model->objects = g_new (Object, width * height);
model->num_objects = width * height;
+ model->num_springs = 0;
+
i = 0;
for (y = 0; y < height; y++)
for (x = 0; x < width; x++) {
- model_init_object (&model->objects[i], 200, 150, 0, 0, 20);
+ object_init (&model->objects[i], 200, 150, 0, 0, 20);
-#if 1
- if (i == 0)
- model_add_object_attractor (&model->objects[i],
- model->current_attractor,
- 0, 0);
-#endif
-
#define CX 0
#define CY 0
#if 0
if (x < CX)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i + 1],
- -hpad, 0);
+ model_add_spring (model,
+ &model->objects[i],
+ &model->objects[i + 1],
+ -hpad, 0);
if (x > CX)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i - 1],
- hpad, 0);
+ model_add_spring (model,
+ &model->objects[i],
+ &model->objects[i - 1],
+ hpad, 0);
if (y < CY)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i + width],
- 0, -vpad);
+ model_add_spring (model,
+ &model->objects[i],
+ &model->objects[i + width],
+ 0, -vpad);
if (y > CY)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i - width],
- 0, vpad);
+ model_add_spring (model,
+ &model->objects[i],
+ &model->objects[i - width],
+ 0, vpad);
#endif
#if 1
if (x > 0)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i - 1],
- hpad, 0);
+ model_add_spring (model,
+ &model->objects[i - 1],
+ &model->objects[i],
+ hpad, 0);
if (y > 0)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i - width],
- 0, vpad);
+ model_add_spring (model,
+ &model->objects[i - width],
+ &model->objects[i],
+ 0, vpad);
#endif
#if 0
if (x < width - 1)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i + 1],
- -hpad, 0);
+ model_add_spring (model,
+ &model->objects[i],
+ &model->objects[i + 1],
+ -hpad, 0);
if (y < height - 1)
- model_add_object_attractor (&model->objects[i],
- &model->objects[i + width],
- 0, -vpad);
+ model_add_spring (model,
+ &model->objects[i],
+ &model->objects[i + width],
+ 0, -vpad);
#endif
i++;
@@ -172,58 +184,92 @@
static void
model_init (Model *model)
{
- model->current_attractor = &model->attractor;
- model_move_attractor (model, 200.5, 140.5);
- model->k = 2.0;
- model->friction = 4.2;
+ model->anchor_object = NULL;
+
+ model->k = DEFAULT_SPRING_K;
+ model->friction = DEFAULT_FRICTION;
model_init_grid (model, 4, 4);
}
static void
-model_step_object (Model *model, Object *object)
+object_apply_force (Object *object, double fx, double fy)
{
- Vector target;
- Vector force;
- int i;
+ object->force.x += fx;
+ object->force.y += fy;
+}
- force.x = 0;
- force.y = 0;
- for (i = 0; i < object->num_attractors; i++) {
- target.x = object->attractors[i].object->position.x +
- object->attractors[i].offset.x;
- target.y = object->attractors[i].object->position.y +
- object->attractors[i].offset.y;
+/* The model here can be understood as a rigid body of the spring's
+ * rest shape, centered on the vector between the two object
+ * positions. This rigid body is then connected by linear-force
+ * springs to each object. This model does degnerate into a simple
+ * spring for linear displacements, and does something reasonable for
+ * rotation.
+ *
+ * There are other possibilities for handling the rotation of the
+ * spring, and it might be interesting to explore something which has
+ * better length-preserving properties. For example, with the current
+ * model, an initial 180 degree rotation of the spring results in the
+ * spring collapsing down to 0 size before expanding back to it's
+ * natural size again.
+ */
+static void
+spring_exert_forces (Spring *spring, double k)
+{
+ Vector da, db;
+ Vector a, b;
- force.x += model->k * (target.x - object->position.x) -
- model->friction * object->velocity.x;
- force.y += model->k * (target.y - object->position.y) -
- model->friction * object->velocity.y;
- }
+ a = spring->a->position;
+ b = spring->b->position;
- object->prev_acceleration.x = object->acceleration.x;
- object->prev_acceleration.y = object->acceleration.y;
- object->acceleration.x = force.x / object->mass;
- object->acceleration.y = force.y / object->mass;
+ /* A nice vector diagram would likely help here, but my ASCII-art
+ * skills aren't up to the task. Here's how to make your own
+ * diagram:
+ *
+ * Draw a and b, and the vector AB from a to b
+ * Find the center of AB
+ * Draw spring->offset so that its center point is on the center of AB
+ * Draw da from a to the initial point of spring->offset
+ * Draw db from b to the final point of spring->offset
+ *
+ * The math below should be easy to verify from the diagram.
+ */
- object->prev_velocity.x = object->velocity.x;
- object->prev_velocity.y = object->velocity.y;
+ da.x = 0.5 * (b.x - a.x - spring->offset.x);
+ da.y = 0.5 * (b.y - a.y - spring->offset.y);
- object->velocity.x +=
- (object->acceleration.x + object->prev_acceleration.x) / 2.0 +
- object->acceleration.x - object->prev_acceleration.x;
- object->velocity.y +=
- (object->acceleration.y + object->prev_acceleration.y) / 2.0 +
- object->acceleration.y - object->prev_acceleration.y;
+ db.x = 0.5 * (a.x - b.x + spring->offset.x);
+ db.y = 0.5 * (a.y - b.y + spring->offset.y);
- object->next_position.x = object->position.x +
- (object->velocity.x + object->prev_velocity.x) / 2.0 +
- object->velocity.x - object->prev_velocity.x;
- object->next_position.y = object->position.y +
- (object->velocity.y + object->prev_velocity.y) / 2.0 +
- object->velocity.y - object->prev_velocity.y;
+ object_apply_force (spring->a, k *da.x, k * da.y);
+
+ object_apply_force (spring->b, k * db.x, k * db.y);
+}
+
+static void
+model_step_object (Model *model, Object *object)
+{
+ Vector acceleration;
object->theta += 0.05;
+
+ /* Slow down due to friction. */
+ object->force.x -= model->friction * object->velocity.x;
+ object->force.y -= model->friction * object->velocity.y;
+
+ acceleration.x = object->force.x / object->mass;
+ acceleration.y = object->force.y / object->mass;
+
+ object->velocity.x += acceleration.x;
+ object->velocity.y += acceleration.y;
+
+ if (! object->immobile) {
+ object->position.x += object->velocity.x;
+ object->position.y += object->velocity.y;
+ }
+
+ object->force.x = 0.0;
+ object->force.y = 0.0;
}
static void
@@ -231,14 +277,11 @@
{
int i;
+ for (i = 0; i < model->num_springs; i++)
+ spring_exert_forces (&model->springs[i], model->k);
+
for (i = 0; i < model->num_objects; i++)
model_step_object (model, &model->objects[i]);
-
- for (i = 0; i < model->num_objects; i++) {
- if (&model->objects[i] == model->current_attractor)
- continue;
- model->objects[i].position = model->objects[i].next_position;
- }
}
static cairo_t *
@@ -283,10 +326,10 @@
static Color blue = { 0, 0, 1 };
static void
-draw_ball (GtkWidget *widget,
- gdouble x,
- gdouble y,
- Color *color)
+draw_ball (GtkWidget *widget,
+ gdouble x,
+ gdouble y,
+ Color *color)
{
cairo_t *cr;
@@ -343,7 +386,7 @@
end_paint (cr);
}
-void
+static void
evaluate_bezier_point (Object *objects,
double u, double v,
double *patch_x, double *patch_y)
@@ -418,6 +461,7 @@
end_paint (cr);
}
+#if 0
static void
draw_spline_spiral (GtkWidget *widget,
Model *model)
@@ -450,6 +494,7 @@
end_paint (cr);
}
+#endif
static gboolean
sproing_expose_event (GtkWidget *widget,
@@ -465,8 +510,10 @@
draw_spline_grid (widget, model);
#endif
- draw_ball (widget, model->current_attractor->position.x,
- model->current_attractor->position.y, &red);
+ if (model->anchor_object)
+ draw_ball (widget,
+ model->anchor_object->position.x,
+ model->anchor_object->position.y, &red);
#if 1
for (i = 0; i < model->num_objects; i++) {
@@ -478,15 +525,59 @@
return TRUE;
}
+static double
+object_distance (Object *object, double x, double y)
+{
+ double dx, dy;
+
+ dx = object->position.x - x;
+ dy = object->position.y - y;
+
+ return sqrt (dx*dx + dy*dy);
+}
+
+static Object *
+model_find_nearest (Model *model, double x, double y)
+{
+ Object *object;
+ double distance, min_distance;
+ int i;
+
+ for (i = 0; i < model->num_objects; i++) {
+ distance = object_distance (&model->objects[i], x, y);
+ if (i == 0 || distance < min_distance) {
+ min_distance = distance;
+ object = &model->objects[i];
+ }
+ }
+
+ return object;
+}
+
static gboolean
sproing_button_press_event (GtkWidget *widget,
GdkEventButton *event,
gpointer data)
{
Model *model = data;
-
- if (event->button == 1)
- model_move_attractor (model, event->x + 0.5, event->y + 0.5);
+ double x, y;
+
+ if (event->button != 1)
+ return TRUE;
+
+ /* Shift by one-half pixel for better stroke alignment */
+ x = event->x + 0.5;
+ y = event->y + 0.5;
+
+ if (model->anchor_object)
+ model->anchor_object->immobile = 0;
+
+ model->anchor_object = model_find_nearest (model, x, y);
+
+ model->anchor_object->immobile = 1;
+
+ model->anchor_object->position.x = x;
+ model->anchor_object->position.y = y;
return TRUE;
}
@@ -502,8 +593,10 @@
gdk_window_get_pointer (event->window, &x, &y, &state);
- if (state & GDK_BUTTON1_MASK)
- model_move_attractor (model, x + 0.5, y + 0.5);
+ if (state & GDK_BUTTON1_MASK) {
+ model->anchor_object->position.x = x + 0.5;
+ model->anchor_object->position.y = y + 0.5;
+ }
return TRUE;
}
@@ -524,7 +617,7 @@
model->friction = gtk_spin_button_get_value (spinbutton);
}
-GtkWidget *
+static GtkWidget *
create_spinners (Model *model)
{
GtkWidget *hbox;
@@ -553,7 +646,7 @@
return hbox;
}
-GtkWidget *
+static GtkWidget *
create_window (Model *model)
{
GtkWidget *window;
@@ -650,7 +743,7 @@
closure.i = 0;
gtk_widget_show_all (gtk_widget_get_toplevel (closure.drawing_area));
closure.model = &model;
- g_timeout_add (10, timeout_callback, &closure);
+ g_timeout_add (100, timeout_callback, &closure);
gtk_main ();
return 0;
- Previous message: [cairo-commit] roadster/src animator.c, 1.2, 1.3 databasewindow.c,
1.5, 1.6 datasetwindow.c, 1.5, 1.6 db.c, 1.19, 1.20 db.h, 1.8,
1.9 glyph.c, 1.4, 1.5 gotowindow.c, 1.8, 1.9 gpsclient.c, 1.8,
1.9 gui.c, 1.7, 1.8 history.c, 1.1, 1.2 import.c, 1.8,
1.9 import_tiger.c, 1.15, 1.16 importwindow.c, 1.6,
1.7 layers.c, 1.13, 1.14 location.c, 1.2, 1.3 locationset.c,
1.7, 1.8 main.c, 1.16, 1.17 main.h, NONE, 1.1 mainwindow.c,
1.32, 1.33 map.c, 1.34, 1.35 map.h, 1.13,
1.14 map_draw_cairo.c, 1.14, 1.15 map_draw_gdk.c, 1.10,
1.11 point.c, 1.3, 1.4 pointstring.c, 1.4, 1.5 prefs.c, 1.1,
1.2 road.c, 1.2, 1.3 road.h, 1.1, 1.2 scenemanager.c, 1.9,
1.10 search.c, 1.4, 1.5 search_location.c, 1.7,
1.8 search_road.c, 1.15, 1.16 searchwindow.c, 1.15,
1.16 tooltip.c, 1.1, 1.2 track.c, 1.5, 1.6 util.c, 1.4,
1.5 util.h, 1.6, 1.7 welcomewindow.c, 1.5, 1.6
- Next message: [cairo-commit]
cairo-demo/sproing ChangeLog, 1.6, 1.7 sproing.c, 1.5, 1.6
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list