Re: rotating NSBezierPath objects
Re: rotating NSBezierPath objects
- Subject: Re: rotating NSBezierPath objects
- From: Graham Cox <email@hidden>
- Date: Sat, 07 Jul 2012 10:50:26 +1000
On 07/07/2012, at 10:10 AM, William Squires wrote:
> Okay, I see in the doc set that you can perform an NSAffineTransform on an NSBezierPath, but how do I perform a rotation of the NSBezierPath about an arbitrary CGPoint and with a specified angle in radians?
Exactly that - use [NSAffineTransform transformBezierPath:]
You just have to set up the transform correctly (see below)
> Is this something deep in CoreGraphics, or CoreAnimation? If not, I can do the trigonometry myself if I can get the list of points that make up the NSBezierPath, but it seems these aren't exposed, only NSBezierPathElement objects. Help!
> Also, what is the formula for calculating the area of an arbitrary triangle defined by three non-collinear points in 2D space? (i.e. I can't assume the triangle even has a 90 degree angle in it, or any other such shortcuts…)
Google it, there are loads of geometry answers out there. One I use which is overkill for this is to calculate the area of an arbitrary polygon:
(This is a category on NSBezierPath, but the path must be flattened first - it doesn't work if there are curve segments)
- (CGFloat) signedAreaOfFlattenedPath
{
if([self isEmpty])
return 0;
NSInteger m, i, j;
CGFloat a = 0;
NSPoint ap, np;
m = [self elementCount];
for( i = 0; i < m; ++i )
{
j = (i + 1) % m;
[self elementAtIndex:i associatedPoints:&ap];
[self elementAtIndex:j associatedPoints:&np];
// because we are using a flattened path, we can be sure there are no curve elements
a += ((ap.x * np.y) - (np.x * ap.y));
}
return a * 0.5;
}
> Finally, If an NSBezierPath consisting of a closed circuit of points:
>
> …
> NSBezierPath *mySquarePath = [NSBezierPath bezierPath];
>
> [mySquarePath setLineWidth:1.0];
> [mySquarePath moveToPoint:CGPointMake(0.0, 0.0)];
> [mySquarePath lineToPoint:CGPointMake(10.0, 0.0)];
> [mySquarePath lineToPoint:CGPointMake(10.0, 10.0)];
> [mySquarePath lineToPoint:CGPointMake(0.0, 10.0)];
> [mySquarePath closePath];
> …
>
> will [mySquarePath containsPoint:CGPointMake(5.0, 5.0)] return YES even before I fill or stroke the path, or do I have to fill the path first?
Yes. A path is a mathematical definition, it has nothing to do with graphics.
Rotating a path: (again a category method on NSBezierPath)
- (NSBezierPath*) rotatedPath:(CGFloat) angle aboutPoint:(NSPoint) cp
{
// return a rotated copy of the receiver. The origin is taken as point <cp> relative to the original path.
// angle is a value in radians
if( angle == 0.0 )
return self;
else
{
NSBezierPath* copy = [self copy];
NSAffineTransform* xfm = RotationTransform( angle, cp );
[copy transformUsingAffineTransform:xfm];
return [copy autorelease];
}
}
which uses:
NSAffineTransform* RotationTransform( const CGFloat angle, const NSPoint cp )
{
// return a transform that will cause a rotation about the point given at the angle given
NSAffineTransform* xfm = [NSAffineTransform transform];
[xfm translateXBy:cp.x yBy:cp.y];
[xfm rotateByRadians:angle];
[xfm translateXBy:-cp.x yBy:-cp.y];
return xfm;
}
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden