Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Q&As > Graphics & Imaging > Quartz >

Shearing a Coordinate Space with NSAffineTransform


Q: How do I make an NSAffineTransform that shears a coordinate space?

A: You can use an Affine transform to apply any combination of rotation, scaling, and shearing to a coordinate space. The mathematics of the Affine transformation is quite straightforward, and is described in the Quartz 2D documentation here.

The documentation for the NSAffineTransform class mentions that shearing is possible, but to do so you need to set the appropriate values of the transform structure directly. A more convenient way to achieve this is to add methods to the class to set shear values, using an Objective-C category.



Listing 1. NSAffineTransform_Shearing.h



#import <Cocoa/Cocoa.h>

@interface NSAffineTransform (Shearing)

- (void) shearXBy: (float) xShear yBy: (float) yShear;
- (void) shearXBy:(float) xShear;
- (void) shearYBy:(float) yShear;

@end






Listing 2. NSAffineTransform_Shearing.m



@implementation NSAffineTransform (Shearing)
  
- (void) shearXBy: (float) xShear yBy: (float) yShear;
  {
  NSAffineTransform 
    *shearTransform = [[NSAffineTransform alloc] init];
    
  NSAffineTransformStruct 
    transformStruct = [shearTransform transformStruct];
    
  transformStruct.m21 = xShear;
  transformStruct.m12 = yShear;
  
  [shearTransform setTransformStruct:transformStruct];
  [self appendTransform:shearTransform];
  [shearTransform release];
  }

  // In case you only want to shear one axis at a time...
- (void) shearXBy:(float) xShear { [self shearXBy:xShear yBy:0.0];  }
- (void) shearYBy:(float) yShear  {  [self shearXBy:0.0 yBy:yShear]; }

@end




For an example of code that uses this technique, see the Transformed Image sample code project.


[Jan 29, 2004]