Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Using Transforms in Your Code

When it is time to draw, the code in your view’s drawRect: method must determine where to draw individual pieces of content. The position of some elements, such as images and rectangles, can be specified easily, but for complex elements like paths, transforms are an easy way to change the current drawing location.

In this section:

Creating and Applying a Transform
Undoing a Transformation
Transforming Coordinates
Converting from Window to View Coordinates


Creating and Applying a Transform

To create a new transform object, call the transform class method of NSAffineTransform. The returned transform object is set to the identity transform automatically. After you have added all of the desired transformations to the transform object, you call the concat method to apply them to the current context. Calling concat adds your transformations to the CTM of the current graphics context. The modifications stay in effect until you explicitly undo them, as described in “Undoing a Transformation,” or a previous graphics state is restored.

The following example creates a new transform object and adds several transformations to it.

NSAffineTransform* xform = [NSAffineTransform transform];
 
// Add the transformations
[xform translateXBy:50.0 yBy:20.0];
[xform rotateByDegrees:90.0]; // counterclockwise rotation
[xform scaleXBy:1.0 yBy:2.0];
 
// Apply the changes
[xform concat];

Undoing a Transformation

Once applied, a transform affects all subsequent drawing calls in the current context. To undo a set of transformations, you can either restore a previous graphics state or apply an inverse transform. Both techniques have their advantages and disadvantages, so you should choose a technique based on your needs and the available information.

Restoring a previous graphics state is the simplest way to undo a transformation but has other side effects. In addition to undoing the transform, restoring the graphics state reverts all other attributes in the current drawing environment back to their previous state.

If you want to undo only the current transformation, you can add an inverse transform to the CTM. An inverse transform negates the effects of a given set of transformations using a complementary set of transformations. To create an inverse transform object, you use the invert method of the desired transform object. You then apply this modified transform object to the current context, as shown in the following example:

NSAffineTransform* xform = [NSAffineTransform transform];
 
// Add the transformations
[xform translateXBy:50.0 yBy:20.0];
[xform rotateByDegrees:90.0]; // counterclockwise rotation
[xform concat];
 
// Draw content...
 
// Remove the transformations by applying the inverse transform.
[xform invert];
[xform concat];

You might use this latter technique to draw multiple items using the same drawing attributes but at different positions in your view. Depending on the type of transformations you use, you might also be able to do incremental transformations. For example, if you are calling translateXBy:yBy: only to reposition the origin, you could move the origin incrementally for each successive item. The following example, shows how you might position one item at (10, 10) and the next at (15, 10):

[NSAffineTransform* xform = [NSAffineTransform transform];
// Draw item 1
[xform translateXBy:10.0 yBy:10.0];
[xform concat];
[item1 draw];
 
//Draw item 2
[xform translateXBy:5.0 yBy:0.0]; // Translate relative to the previous  element.
[xform concat];
[item2 draw];
 

Remember that the preceding techniques are used in cases where you do not want to modify your original items directly. Cocoa provides ways to modify geometric coordinates without modifying the current transformation matrix. For more information, see “Transforming Coordinates.”

It is also worth noting that the effectiveness of an inverse transform is limited by mathematical precision. For rotation transforms, which involve taking sines and cosines of the desired rotation angle, an inverse transform may not be precise enough to undo the original rotation completely. In such a situation, you may want to simply save and restore the graphics state to undo the transform.

Transforming Coordinates

If you do not want to change the coordinate system of the current drawing environment, but do want to change the position or orientation of a single object, you have several options. The NSAffineTransform class includes the transformPoint: and transformSize: methods for changing coordinate values directly. Using these methods does not change the CTM of the current graphics context.

If you want to alter the coordinates in a path, you can do so using the transformBezierPath: method of NSAffineTransform. This method returns a transformed copy of the specified Bezier path object. This method differs slightly from the transformUsingAffineTransform: method of NSBezierPath, which modifies the original object.

Converting from Window to View Coordinates

Events sent to your view by the operating system are sent using the coordinate system of the window. Before your view can use any coordinate values included with the event, it must convert those coordinates to its own local coordinate space. The NSView class provides several functions to facilitate the conversion of NSPoint, NSSize, and NSRect structures. Among these methods are convertPoint:fromView: and convertPoint:toView:, which convert points to and from the view’s local coordinate system. For a complete list of conversion methods, see NSView Class Reference.

Important: Cocoa event objects return y coordinate values that are 1-based instead of 0-based. Thus, a mouse click on the bottom left corner of a window or view would yield the point (0, 1) in Cocoa and not (0, 0). Only y-coordinates are 1-based.

The following example converts the mouse location of a mouse event from window coordinates to the coordinates of the local view. To convert to the view’s local coordinate space, you use the convertPoint:fromView: method. The second parameter to this method specifies the view in whose coordinate system the point is currently specified. Specifying nil for the second parameter tells the current view to convert the point from the window’s coordinate system.

NSPoint  mouseLoc = [theView convertPoint:[theEvent locationInWindow] fromView:nil];


< Previous PageNext Page > Hide TOC


Last updated: 2007-10-31




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice