Developer Documentation
Table of Contents

NSAffineTransform


Inherits from:
NSObject
Conforms to:
NSCoding
NSCopying
NSObject (NSObject)
Declared in:
AppKit/NSAffineTransform.h




Class Description


The NSAffineTransform class provides methods for creating, concatenating, and applying affine transformations. A transformation specifies how points in one coordinate system are transformed to points in another coordinate system. An affine transformation is a special type of transformation that preserves parallel lines in a path but does not necessarily preserve lengths or angles. Scaling, rotation, and translation are the most commonly used manipulations supported by affine transforms, but shearing is also possible.

Graphic transformations rely on a matrix of values to specify how a path will be changed. Points being transformed are multiplied through the matrix to obtain the resulting (transformed) point. You do not need to know anything about matrices and matrix multiplication to use the NSAffineTransform class. NSAffineTransform provides methods that allow you to set scaling, rotation, and translation factors while leaving the matrix mathematics to the transform object.


Creating Transforms


To create a new instance of NSAffineTransform, you can use either the transform class method or you can allocate a new transform object and initialize it using the initWithTransform: method. When you use the transform class method to create a new instance of NSAffineTransform, the new object's matrix is initialized to the identity matrix (which transforms any point to itself). When you use the initWithTransform: method, the new object's matrix is set to the matrix of the specified affine transform.

NSAffineTransform provides direct support for setting scaling, rotation, and translation factors. Use the translateXBy:yBy: method to set translation factors independently for each axis. Use the rotateByDegrees: and rotateByRadians: methods to set rotation factors in degrees or radians. Use the scaleBy: method to set the same scaling factor for both x and y axes, or use the scaleXBy:yBy:method to set independent scaling factors for each axis. If you want to set a combination of factors all at once (or if you want to set shearing factors), you can use the setTransformStruct: method to specify the matrix values directly.

For more information on the mathematics involved in transform manipulations, see "Manipulating Transform Values" .


Using Transforms


Transforms are used most commonly to adjust a view's drawing area by translating the view's origin to some prescribed location on the screen. However, you can also use transforms to arbitrarily scale or rotate paths within their view. Because transformations occur relative to the origin of the local coordinate system, several transforms may need to be concatenated together to generate the proper effect. For example, Figure 0-1 shows a rectangular path and the result of rotating it 45 degrees. In order to rotate the rectangle around its origin, you would need to translate that origin to the center of its coordinate system, apply the rotation, and then translate the rectangle back to its original location. You may need to apply similar techniques when scaling a path.

Rotating a rectangular path 45 degrees

[image: Art/Rotation.gif]

Rather than applying separate transforms to translate, scale, and rotate a single path you can combine a group of transforms into a single transform and apply only that transform. To do this, you must combine the transforms by appending them together with the appendTransform: method. The effects of the appended transform occur after the effects of the original transform. Similarly, you can prepend one transform to another using the prependTransform: method.

Once you have constructed your transform object and set the appropriate scaling, translation, and rotation factors, you can apply the transformation to one or more points. To apply the transform to a single point, use the transformPoint: method. To transform an entire path, use the transformBezierPath: method, which returns a copy of the transformed path leaving the original untouched. You can also transform NSSize values using the transformSize: method, although NSSize values are not affected by translations.

You can also apply a transform to all of the current drawing operations using the concat method. This method appends the transform's matrix to the transformation matrix stored in the current graphic context.


Note: By the time the drawRect: method is invoked, the current transformation is already a concatenation of the screen's, window's and any superview's transformations. Concatenating your transformation to the current transformation modifies subsequent drawing operations within the bounds of your NSView object.

To cancel the effects of a matrix, simply invoke its invert method and apply it again.


Manipulating Transform Values


An NSAffineTransform object uses a 3x3 transformation matrix of the form shown in Figure 0-2.

A 3x3 matrix

[image: Art/Matrix.gif]

where a point (x,y) is transformed into another point (x',y') using these linear equations:

x' = (m11)x + (m21)y + tx
y' = (m12)x + (m22)y + ty

Concatenation, translation, rotation, and scaling are performed by matrix multiplication. The order in which transformations are multiplied is important because matrix operations are associative, but not commutative (matrix1 × matrix2 matrix2 × matrix1).

You can specify the matrix values directly using the NSAffineTransformStruct, which lets you specify the six values for m11, m12, m21, m22, tx, and ty. You can then use the setTransformStruct: method to associate your matrix values with the transform object. Figure 0-3 shows the standard set of matrices used to implement different effects. You can multiply these matrices together to obtain the formulae for a complex set of translations, scales, rotations, and shears. For translations, scales, and shears, the subscripts of matrix elements indicate the axis affected by values at that location.

Matrices for translation, rotation, scaling, and shearing

[image: Art/MatrixTypes.gif]



Adopted Protocols


NSCoding
- encodeWithCoder:
- initWithCoder:
NSCopying
- copyWithZone:


Method Types


Creating an NSAffineTransform object
+ transform
- initWithTransform:
Accumulating Transformations
- rotateByDegrees:
- rotateByRadians:
- scaleBy:
- scaleXBy:yBy:
- translateXBy:yBy:
- appendTransform:
- prependTransform:
- invert
Setting the Current Transform in the Current Graphics State
- set
- concat
Transforming Data and Objects
- transformBezierPath:
- transformPoint:
- transformSize:
Transformation Struct
- transformStruct
- setTransformStruct:


Class Methods



transform

+ (NSAffineTransform *)transform

Creates and returns a new instance of NSAffineTransform initialized to the identity matrix. The identity matrix transforms any point to itself.

See Also: - initWithTransform:




Instance Methods



appendTransform:

- (void)appendTransform:(NSAffineTransform *)aTransform

Performs a multiplication of the receiver's matrix and aTransform's matrix, and replaces the receiver's matrix with the result. This has the effect of applying aTransform's matrix after the receiver's matrix.

See Also: - prependTransform:



concat

- (void)concat

Appends the receiver's matrix to the current transformation matrix stored in the current graphics context, replacing the current transformation matrix with the result. Concatenation is performed by matrix multiplication-see "Manipulating Transform Values" above.

If this method is invoked from within an NSView's drawRect: method, then the current transformation matrix is an accumulation of the screen, window and any superview's transformation matrices. Invoking this method defines a new user coordinate system whose coordinates are mapped into the former coordinate system according to the receiver's transformation matrix. To undo the concatenation, you must invert the receiver's matrix and invoke this method again.

See Also: - set, - invert



initWithTransform:

- (id)initWithTransform:(NSAffineTransform *)aTransform

Initializes the receiver's matrix to the matrix in aTransform and returns the receiver.

See Also: + transform



invert

- (void)invert

Replaces the receiver's matrix with its inverse matrix. Inverse matrices are useful for undoing the effects of a matrix. If a previous point (x,y) was transformed to (x',y'), inverting the matrix and applying it to point (x',y') will yield the point (x,y).

You can also use them in conjunction with the concat method to remove the effects of concatenating the matrix to the current transformation matrix of the current graphic context.



prependTransform:

- (void)prependTransform:(NSAffineTransform *)aTransform

Prepends the matrix of aTransform to the receiver's matrix. Multiplies aTransform and the receiver's matrix, and replaces the receiver's matrix with the result. This has the effect of applying aTransform before the receiver's transform.

See Also: - appendTransform:



rotateByDegrees:

- (void)rotateByDegrees:(float)angle

Replaces the receiver's transformation matrix with a matrix that applies a rotation of angle degrees. Any previous transformations associated with the matrix are lost and replaced by the rotation.

After invoking this method, applying the receiver's matrix will turn the axes counterclockwise about the current origin by angle degrees.

See Also: - rotateByRadians:, - scaleBy:, - scaleXBy:yBy:, - translateXBy:yBy:



rotateByRadians:

- (void)rotateByRadians:(float)angle

Replaces the receiver's transformation matrix with a matrix that applies a rotation of angle radians. Any previous transformations associated with the matrix are lost and replaced by the rotation.

After invoking this method, applying the receiver's matrix will turn the axes counterclockwise about the current origin by angle radians.

See Also: - rotateByDegrees:, - scaleBy:, - scaleXBy:yBy:, - translateXBy:yBy:



scaleBy:

- (void)scaleBy:(float)scale

Replaces the receiver's transformation matrix with a matrix that applies the specified scaling factor along both x and y axes. Any previous transformations associated with the matrix are lost and replaced by the new scaling factor.

Hereafter, applying the receiver's matrix will modify the unit lengths along the current x and y axes by a factor of scale.

See Also: - rotateByDegrees:, - rotateByRadians:, - scaleXBy:yBy:, - translateXBy:yBy:



scaleXBy:yBy:

- (void)scaleXBy:(float)scaleX yBy:(float)scaleY

Replaces the receiver's transformation matrix with a matrix that applies the scaleX factor along the x axis and the scaleY factor along the y axis. Any previous transformations associated with the matrix are lost and replaced by the new scaling factors.

After invoking this method, applying the receiver's matrix will modify the unit length on the x axis by a factor of scaleX and the y axes by a factor of scaleY.

See Also: - rotateByDegrees:, - rotateByRadians:, - scaleBy:, - translateXBy:yBy:



set

- (void)set

Sets the current transformation matrix to the receiver's transformation matrix. The current transformation is stored in the current graphics context and will be applied to subsequent drawing operations. You should use this method sparingly because it removes the existing transformation matrix, which is an accumulation of transformation matrices for the screen, window and any superviews. Instead use the concat method to add this transformation matrix to the current transformation matrix.

setTransformStruct:

- (void)setTransformStruct:(NSAffineTransformStruct)aTransformStruct

Sets the receiver's transformation matrix using the values in aTransformStruct. The matrix is of the form shown in Figure 0-2 and the six-element structure defined by an NSAffineTransformStruct is of the form:
{m11, m12, m21, m22, tx, ty}

NSAffineTransformStruct is an alternate representation of a transformation matrix that can be used to specify matrix values directly.

See Also: - initWithTransform:, - transformStruct



transformBezierPath:

- (NSBezierPath *)transformBezierPath:(NSBezierPath *)aPath

Creates and returns a new NSBezierPath object with each point in aPath transformed by the receiver. The original NSBezierPath object is not modified.

See Also: - transformPoint:, - transformSize:



transformPoint:

- (NSPoint)transformPoint:(NSPoint)aPoint

Returns the result of applying the receiver's transform to aPoint.

See Also: - transformBezierPath:, - transformSize:



transformSize:

- (NSSize)transformSize:(NSSize)aSize

Returns the result of applying the receiver's transform to aSize. Because aSize specifies a width and height, not an x and y coordinate, translation factors are not applied. This method is useful for transforming delta or distance values when you need to take scaling factors into account.

See Also: - transformBezierPath:, - transformPoint:



transformStruct

- (NSAffineTransformStruct)transformStruct

Returns the NSAffineTransformStruct equivalent to the receiver's matrix. The matrix is of the form shown in Figure 0-2 and the six-element structure defined by an NSAffineTransformStruct is of the form:
{m11, m12, m21, m22, tx, ty} 

NSAffineTransformStruct is an alternate representation of a transformation matrix that can be used to specify matrix values directly.

See Also: - initWithTransform:, - setTransformStruct:



translateXBy:yBy:

- (void)translateXBy:(float)deltaX yBy:(float)deltaY

Replaces the receiver's transformation matrix with a matrix that applies the specified translation factors. Subsequent transformations will cause coordinates to be shifted by deltaX units along the x-axis and by deltaY units along the y-axis. Any previous transformations associated with the matrix are lost and replaced by the new scaling factors.

Translation factors do not affect NSSize values, which specify a differential between points.

See Also: - rotateByDegrees:, - rotateByRadians:, - scaleBy:, - scaleXBy:yBy:




Table of Contents