How can I evenly fan out a hand of cards?

Given a set of playing cards (rectangle images with a width and height) how can I rotate and position each one so that they appear in a 'fan' pattern, much like you would hold a hand of cards in real life. What math is needed to do this?

UPDATE

Here is the final, in browser implementation in JavaScript: https://cosmicrealms.com/blog/2013/03/16/hand-of-cards/ and http://jsfiddle.net/tyyvk/108/

• Sir, you seem to have too many aces in your hand. Please step away from the table. – Tomas Andrle Jan 14 '12 at 18:53
• The fiddle needs to be updated to use a later version of MooTools. – tomdemuyt Feb 16 '18 at 17:00
• – Anko Mar 5 at 14:09

Theory

Since you didn't specify in what platform you're implementing this, I'll give a description of the algorithm in a language-agnostic way:

1. First stack every card on top of each other by giving them the same initial position.
2. Then for each card apply a rotation (usually centered around one of the bottom corners, but moving this origin around will essentialy allow you to tweak the look of the fan).
3. Increment the angle of rotation between each call, depending on the number of cards and how much you want them to be spread.

That the rotation is centered around one of the card's bottom corners (or near the corner) should be evident from looking at it:

Implementation

As for how to implement this, it depends on your platform. On XNA you can simply use the Origin parameter of SpriteBatch.Draw to change the center of your rotation.

Here's what I got with the following code (with a few tweaks to the origin to make it look better - basically the origin starts near the right corner and ends up near the left corner):

int cards = 20;
float range = MathHelper.ToRadians(90);
float initialAngle = MathHelper.ToRadians(-45);
float increment = range / cards;
Vector2 leftCorner = new Vector2(0, texture.Height * 0.9f);
Vector2 rightCorner = new Vector2(texture.Width, texture.Height * 0.9f);
Vector2 fanPosition = new Vector2(400, 300);
spriteBatch.Begin();
for (float angle = 0; angle < range; angle+=increment)
{
float cardAngle = initialAngle + angle;
Vector2 cardOrigin = Vector2.Lerp(rightCorner, leftCorner, angle / range);
spriteBatch.Draw(texture, fanPosition, null, Color.White, cardAngle, cardOrigin, 1f, SpriteEffects.None, 0f);
}
spriteBatch.End();


And the result:

• I'd add that the look can be tweaked by using a different centre of rotation, if you want to span a smaller arc you should use a rotation point that lies below the card. – aaaaaaaaaaaa Jan 9 '12 at 21:24
• @eBusiness You're right, I'll add that in. – David Gouveia Jan 9 '12 at 21:44
• Thanks a lot David! I've implemented the code you've shown in JavaScript here: jsfiddle.net/tyyvk/7 – Sembiance Jan 14 '12 at 21:25