- Inherits from:
- NSObject
- Conforms to:
- NSCoding
- NSCopying
- NSObject (NSObject)
Declared in:
- AppKit/NSAffineTransform.h
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.
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" .
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
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.
An NSAffineTransform object uses a 3x3 transformation matrix of the form shown in Figure 0-2.
A 3x3 matrix
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
NSCoding
- - encodeWithCoder:
- - initWithCoder:
NSCopying
- - copyWithZone:
- 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:
+ (NSAffineTransform *)transform
See Also: - initWithTransform:
- (void)appendTransform:(NSAffineTransform
*)aTransform
See Also: - prependTransform:
- (void)concat
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.
- (id)initWithTransform:(NSAffineTransform
*)aTransform
See Also: + transform
- (void)invert
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.
- (void)prependTransform:(NSAffineTransform
*)aTransform
See Also: - appendTransform:
- (void)rotateByDegrees:(float)angle
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:
- (void)rotateByRadians:(float)angle
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:
- (void)scaleBy:(float)scale
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:
- (void)scaleXBy:(float)scaleX
yBy:(float)scaleY
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:
- (void)set
- (void)setTransformStruct:(NSAffineTransformStruct)aTransformStruct
{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
- (NSBezierPath *)transformBezierPath:(NSBezierPath
*)aPath
See Also: - transformPoint:, - transformSize:
- (NSPoint)transformPoint:(NSPoint)aPoint
See Also: - transformBezierPath:, - transformSize:
- (NSSize)transformSize:(NSSize)aSize
See Also: - transformBezierPath:, - transformPoint:
- (NSAffineTransformStruct)transformStruct
{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:
- (void)translateXBy:(float)deltaX
yBy:(float)deltaY
Translation factors do not affect NSSize values, which specify a differential between points.
See Also: - rotateByDegrees:, - rotateByRadians:, - scaleBy:, - scaleXBy:yBy: