Inverse Kinematics
This is a pair of rotation expressions you can use to implement inverse kinematics (IK) in After Effects. This code is based on expressions developed by Brian Maffitt for his wonderful "Total Training for After Effects" DVD series. I've modified them somewhat to allow anchor points to be inset from the edge of the objects.
IK allows you to position a chain of objects based on the movement of the object at the end of the chain. For example, moving a hand would cause the upper and lower arm components to rotate at their joints to accomodate the hand's movement.
Here's the code for the rotation of the upper arm:
A = toWorld(anchorPoint);
L = thisComp.layer("lowerArm");
B = L.toWorld(L.anchorPoint);
L = thisComp.layer("Null 1");
C = L.toWorld(L.anchorPoint);
L = thisComp.layer("hand");
H = L.toWorld(L.anchorPoint);
a = length(A,B);
b = length(B,C);
c = length(H,A);
x = (a*a - b*b + c*c)/(2*c);
beta = Math.acos(clamp(x/a,-1,1));
D = H - A;
delta = Math.atan2(D[1],D[0]);
radiansToDegrees(delta - beta);
And here's the code for the rotation of the lower arm:
B = toWorld(anchorPoint);
L = thisComp.layer("upperArm");
A = L.toWorld(L.anchorPoint);
L = thisComp.layer("Null 1");
C = L.toWorld(L.anchorPoint);
L = thisComp.layer("hand");
H = L.toWorld(L.anchorPoint);
a = length(A,B);
b = length(B,C);
c = length(H,A);
x = (a*a - b*b + c*c)/(2*c);
y = c - x;
alpha = Math.acos(clamp(y/b,-1,1));
beta = Math.acos(clamp(x/a,-1,1));
radiansToDegrees(alpha + beta);
The math behind these is somewhat complex, but if you know trig it's kind of fun to figure out how it works.
Here's the way you set this up. First, import the pieces for your IK chain (note that if you need to scale the pieces you should do that first in another application, because it will screw up the angle calculations if you do it in your comp). Also note that these expressions assume that your pieces start out horizontal. If they start out vertical, you will need to adjust the upper arm expression by subtracting 90 degrees from the result, by changing the last line to this:
radiansToDegrees(delta - beta) - 90;
Next you need to move the anchor points to the joints (move the upper arm's anchor point to the sholder, the lower arm's to the elbow and the hand's to the wrist). Next you align the pieces to form your chain. Then create a null layer ("Null 1" in this example) and position it so its anchor point is at the same place as the hand's anchor point. Now make the upper arm the parent of the lower arm, and the lower arm the parent of the null. Note that the hand has no parent. Now apply the expressions for rotation.
If you've done everything right, you should be able to move the hand around in the comp and the arm will follow.
To get the mirror image solution (so the the arm pieces bend the other way) you would change the last line of the upper arm expression to:
radiansToDegrees(delta + beta);
and change the last line of the lower arm expression to:
-radiansToDegrees(alpha + beta);