Re: Affine Transform
Re: Affine Transform
- Subject: Re: Affine Transform
- From: Terry Heaford <email@hidden>
- Date: Mon, 13 Feb 2006 07:05:05 +0000
Erik,
Thank you very much. My interest is back after a good nights sleep,
although I am away from my computer until tomorrow.
I will report back on my progress.
Once again, thanks
--Terry
On 12 Feb 2006, at 22:17, Erik Buck wrote:
In this case, you are not learning Cocoa as much as you are
learning very basic graphics programming. You will have the same
difficulty with any framework.
You might want an introductory graphics textbook, but you seem to
have gotten over some of the conceptual issues already without one.
There are several very nice explanations of frame and bounds
available. I will point you to page 201 in "Cocoa Programming"
because I have a self serving interest ;)
Here is complete code for a view that I just now whipped up to draw
an image with any rotation. The view automatically adjusts its own
frame to be large enough to show the whole image as it is rotated.
If you put an instance of this view in a scroll view, the scroll
view will automatically adjust its scroll bars as needed.
I will send a 48k xcode 2.2 project that build a whole test app to
anyone who requests it.
/* SimpleRotatingImageView */
#import <Cocoa/Cocoa.h>
@interface SimpleRotatingImageView : NSView
{
float angleDegrees;
NSImage *image;
BOOL shouldUseMinRect;
}
- (NSImage *)image;
- (void)setImage:(NSImage *)anImage;
- (IBAction)takeAngleFrom:(id)sender;
- (IBAction)takeImageFrom:(id)sender;
- (IBAction)takeShouldUseMinRectFrom:(id)sender;
@end
#import "SimpleRotatingImageView.h"
@implementation SimpleRotatingImageView
- (id)initWithFrame:(NSRect)frameRect
{
if ((self = [super initWithFrame:frameRect]) != nil)
{
angleDegrees = 0.0f;
}
return self;
}
- (void)dealloc
{
[self setImage: nil];
[super dealloc];
}
- (void)drawRect:(NSRect)rect
{
// Erase background
[[NSColor blackColor] set];
NSRectFill([self bounds]);
// Rotate coordinate system abount center of bounds
NSAffineTransform *newTransform = [NSAffineTransform transform];
[newTransform translateXBy:[self bounds].size.width/2.0 yBy:
[self bounds].size.height/2.0];
[newTransform rotateByDegrees:-angleDegrees];
[newTransform translateXBy:-[self bounds].size.width/2.0 yBy:-
[self bounds].size.height/2.0];
[newTransform concat];
// Draw current image centered in bounds
NSImage *currentImage = [self image];
NSRect imageRect = NSZeroRect;
imageRect.size = [currentImage size];
[currentImage drawAtPoint:NSMakePoint([self bounds].size.width/
2.0-imageRect.size.width/2.0,
[self bounds].size.height/
2.0-imageRect.size.height/2.0)
fromRect:imageRect
operation:NSCompositeSourceOver fraction:1.0f];
// Draw center point just for reference
[[NSColor redColor] set];
NSRectFill(NSMakeRect([self bounds].size.width/2.0 - 5, [self
bounds].size.height/2.0 - 5, 10, 10));
}
- (void)adjustFrame
{
// Resize the frame to be large enough to show all of the
current image even if it is rotated.
NSSize imageSize = [image size];
NSAffineTransform *newTransform = [NSAffineTransform transform];
[newTransform translateXBy:imageSize.width/2.0
yBy:imageSize.height/2.0];
if(shouldUseMinRect)
{
[newTransform rotateByDegrees:-angleDegrees];
}
else
{ // This will result in the largest frame needed for any angle
[newTransform rotateByDegrees:45.0f];
}
[newTransform translateXBy:-imageSize.width/2.0 yBy:-
imageSize.height/2.0];
// Transform all four corners of the rectangle that encloses the
current image
NSPoint point0 = [newTransform transformPoint:NSZeroPoint];
NSPoint point1 = [newTransform transformPoint:NSMakePoint
(0.0f, imageSize.height)];
NSPoint point2 = [newTransform transformPoint:NSMakePoint
(imageSize.width, imageSize.height)];
NSPoint point3 = [newTransform transformPoint:NSMakePoint
(imageSize.width, 0.0f)];
// Find the minimum and maximum coordinates of the transformed
rectangle that encloses the current image
float minX = MIN(MIN(MIN(point0.x, point1.x), point2.x),
point3.x);
float minY = MIN(MIN(MIN(point0.y, point1.y), point2.y),
point3.y);
float maxX = MAX(MAX(MAX(point0.x, point1.x), point2.x),
point3.x);
float maxY = MAX(MAX(MAX(point0.y, point1.y), point2.y),
point3.y);
// Set the frame size large enough to enclose the minimum and
maximum coordinates of the transformed rectangle
[self setFrameSize:NSMakeSize(maxX - minX, maxY - minY)];
}
- (IBAction)takeShouldUseMinRectFrom:(id)sender
{
shouldUseMinRect = (BOOL)[sender intValue];
[self adjustFrame];
[self setNeedsDisplay:YES];
}
- (IBAction)takeAngleFrom:(id)sender
{
angleDegrees = [sender floatValue];
[self adjustFrame];
[self setNeedsDisplay:YES];
}
- (NSImage *)image
{
return image;
}
- (void)setImage:(NSImage *)anImage
{
[anImage retain];
[image release];
image = anImage;
[self adjustFrame];
[self setNeedsDisplay:YES];
}
- (IBAction)takeImageFrom:(id)sender
{
[self setImage:[sender image]];
}
@end
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40btopenworld.com
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden