Day 25: Drawing: NSAffineTransform, part 2
Yesterday I gave a short explanation of how NSAffineTransform works and I’ll give some concrete examples today. We’ll be going to draw a rectangle like below. Note that its frame is in the center of the view.
- (void)drawRect:(NSRect)dirtyRect
{
NSSize size = [self bounds].size;
NSRect midRect = NSMakeRect((size.width-100)/2, (size.height-50)/2, 100, 50);
NSAffineTransform *t = [NSAffineTransform transform];
//do our transformations here
[t concat];
[[NSBezierPath bezierPathWithRect:midRect] stroke];
[t invert];
[t concat];
}
The first basic transformation is just moving the origin: [t translateXBy:100 yBy:100];. Easy enough. We scale the X and Y as follows: [t scaleXBy:1.0 yBy:2.0];. Obvious tip, make sure you don’t scale by 0. Especially not when you want to invert your matrix; it’ll throw an exception.
Now a more complex transformation; rotating around a certain point, let’s say the center of our rectangle. To do so, we need to move the origin to this specific point, then rotate and then move the origin back. It’s important to note that any consequitive transformations are applied on top of the current which means that a translation after a rotation is different from a translation before a rotation (except when rotating by 0 of course).
NSPoint mid = NSMakePoint(NSMidX(midRect), NSMidY(midRect));
[t translateXBy:mid.x yBy:mid.y];
[t rotateByDegrees:45];
[t translateXBy:-mid.x yBy:-mid.y];
Dont forget to invert and concat your matrix after your drawing code is done. And I’ll repeat what I said yesterday; inverting a transform is cheaper than creating a new graphics context, so do this whenever you can.