spring->length = length;
}
+void
+stick_init (Stick *stick, Object *a, Object *b, double length)
+{
+ stick->a = a;
+ stick->b = b;
+ stick->length = length;
+}
+
+void
+string_init (String *string, Object *a, Object *b, double length)
+{
+ string->a = a;
+ string->b = b;
+ string->length = length;
+}
+
void
offset_spring_init (OffsetSpring *spring, Object *a, Object *b,
double dx, double dy)
spring->dy = dy;
}
+void
+spacer_init (Spacer *spacer, Object *a, Object *b, double length)
+{
+ spacer->a = a;
+ spacer->b = b;
+ spacer->length = length;
+}
+
+void
+anchor_init (Anchor *anchor, Object *object, double x, double y)
+{
+ anchor->object = object;
+ anchor->x = x;
+ anchor->y = y;
+}
+
void
polygon_init (Polygon *p, int num_points, ...)
{
p->normals = g_new (Vector, p->num_points);
/* Compute outward pointing normals. p->normals[i] is the normal
* for the edged between p->points[i] and p->points[i + 1]. */
- for (i = 0; i < p->num_points; i++) {
+ for (i = 0; i < p->num_points; i++) {
j = (i + 1) % p->num_points;
dx = p->points[j].x - p->points[i].x;
dy = p->points[j].y - p->points[i].y;
g_free (model->offsets[i].objects);
g_free (model->springs);
g_free (model->offset_springs);
+ g_free (model->spacers);
for (i = 0; i < model->num_polygons; i++)
g_free (model->polygons[i].points);
g_free (model->polygons);
}
}
+static void
+model_constrain_anchor (Model *model, Anchor *anchor)
+{
+ anchor->object->position.x = anchor->x;
+ anchor->object->position.y = anchor->y;
+ anchor->object->previous_position.x = anchor->x;
+ anchor->object->previous_position.y = anchor->y;
+}
+
static void
model_constrain_offset (Model *model, Offset *offset)
{
double dx, dy, x, y, distance, fraction;
int i;
- /* Anchor object constraint. */
- if (model->anchor_object != NULL) {
- model->anchor_object->position.x = model->anchor_position.x;
- model->anchor_object->position.y = model->anchor_position.y;
- model->anchor_object->previous_position.x = model->anchor_position.x;
- model->anchor_object->previous_position.y = model->anchor_position.y;
- }
+ if (model->mouse_anchor.object != NULL)
+ model_constrain_anchor (model, &model->mouse_anchor);
+ for (i = 0; i < model->num_anchors; i++)
+ model_constrain_anchor (model, &model->anchors[i]);
/* String constraints. */
for (i = 0; i < model->num_strings; i++) {
model->strings[i].b->position.y = y + dy * (1 - fraction);
}
+ /* Spacer constraints. */
+ for (i = 0; i < model->num_spacers; i++) {
+ x = model->spacers[i].a->position.x;
+ y = model->spacers[i].a->position.y;
+ dx = model->spacers[i].b->position.x - x;
+ dy = model->spacers[i].b->position.y - y;
+ distance = estimate_distance (dx, dy, model->spacers[i].length);
+ if (distance > model->spacers[i].length)
+ continue;
+ fraction = (distance - model->spacers[i].length) / distance / 2;
+ model->spacers[i].a->position.x = x + dx * fraction;
+ model->spacers[i].a->position.y = y + dy * fraction;
+ model->spacers[i].b->position.x = x + dx * (1 - fraction);
+ model->spacers[i].b->position.y = y + dy * (1 - fraction);
+ }
+
/* Stick constraints. */
for (i = 0; i < model->num_sticks; i++) {
x = model->sticks[i].a->position.x;
model_accumulate_forces (model);
model_integrate (model, delta_t);
- for (i = 0; i < 50; i++)
+ for (i = 0; i < 2; i++)
model_constrain (model);
model->theta += delta_t;