# Hinge joints chain movement (2D)

I have some problems with hinge joint chain movement calculations...

Here is my algorithm for segments location/rotation adjustments after a previous segment update (C#):

void AdjustLocation()
{
float halfWidth = Size.Width / 2;

// Translations
Vector parentBack = PrevSegment.Center - (halfWidth * new Vector(Cos(PrevSegment.Rotation), Sin(PrevSegment.Rotation))); // Green on the pic
Vector front = this.Center + (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation))); // Blue on the pic

// Const spacing between segments
float spacing = *some_value*;

Vector dv = parentBack - front;
float k = spacing / dv.Length;

// New front location
front = parentBack - (dv * k);
// New rotation
dv = front - this.Center;
this.Rotation = Atan2(dv.Y, dv.X);

// Translate back to the center
this.Center = front - (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation)));

}


It's working (partially), but it seems I'm missing something as it doesn't behave like a chain. Segments always move one by another although they should not always do this. Also overlapped sections of a long chain form a "knot" going all the way to the end of the chain before its "untangling". What am I missing?

Btw: everything screws up with negative spacing values.

P.S. Tried to visualize the algorithm on the picture: I figured it out myself.

void AdjustLocation()
{
float halfWidth = Size.Width / 2;

// Current segment back positions
Vector offset = (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation)));
Vector backPos = this.Center - offset;

Vector newFrontPos;
if (SegmentsSpacing > 0)
{
// Current segment front position
Vector frontPos = this.Center + offset;

// Parent segment back position
offset = (halfWidth * new Vector(Cos(PrevSegment.Rotation), Sin(PrevSegment.Rotation)));
Vector parentBackPos = PrevSegment.Center - offset;

// Find delta
Vector dv = parentBackPos - frontPos;
float k = SegmentsSpacing / dv.Length;

// Calculate new front position
newFrontPos = parentBackPos - (dv * k);
}
else
{
// Calculate new front position
offset = ((halfWidth + SegmentsSpacing) * new Vector(Cos(PrevSegment.Rotation), Sin(PrevSegment.Rotation)));
newFrontPos = PrevSegment.Center - offset;
}

// Calculate new rotation
Vector dv = newFrontPos - backPos;
this.Rotation = Atan2(dv.Y, dv.X);
// Translate back to center
this.Center = newFrontPos - (halfWidth * new Vector(Cos(this.Rotation), Sin(this.Rotation)));