Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having a hard time understanding NSBezierPath's curveToPoint: method

I'm trying to get to grips with drawing (fairly basic) shapes in Cocoa. I understand how to create paths with straight edges (duh!), but when it comes to doing curves, I just can't get my head around what inputs will produce what shaped curve. Specifically, I have no idea how the controlPoint1: and controlPoint2: arguments to the method influence the shape.

I'm trying to approximate the shape of a tab in Google Chrome:

Google Chrome Tab

And the code I'm using is:

-(void)drawRect:(NSRect)dirtyRect {
    NSSize size = [self bounds].size;

    CGFloat height = size.height;
    CGFloat width = size.width;

    NSBezierPath *path = [NSBezierPath bezierPath];
    [path setLineWidth:1];

    [path moveToPoint:NSMakePoint(0, 0)];

    [path curveToPoint:NSMakePoint(width * 0.1, height)
         controlPoint1:NSMakePoint(width * 0.05, height)
         controlPoint2:NSMakePoint(width * 0.03, height * 0.05)];

    [path lineToPoint:NSMakePoint(width * 0.9, height)];

    [path curveToPoint:NSMakePoint(width, 0)
         controlPoint1:NSMakePoint(width * 0.95, height)
         controlPoint2:NSMakePoint(width * 0.97, height * 0.05)];

    [path closePath];

    [[NSColor colorWithCalibratedWhite:0.98 alpha:1] set];
    [path fill];

    [[NSColor colorWithCalibratedWhite:0.6 alpha:1] set];
    [path stroke];
}

I'm failing horribly.

See, this is why we can't have nice things :(

My Attempt

Can anyone give me some pointers about how to think when it comes to drawing curves? An example that draws this path would be great too, but really it's just understanding these inputs to curveToPoint:controlPoint1:controlPoint2: that's holding me back.

UPDATE | Thanks to @Ahruman's answer I finally got it to start taking shape. It's not 100% (missing the curves on the bottom corners, but it's actually a symmetrical shape at least now :)

Getting there

like image 235
d11wtq Avatar asked Dec 21 '10 13:12

d11wtq


2 Answers

The line between the current drawing point (implicit) and control point 1 is the tangent of the curve at its beginning. The line between control point 2 and the “to” point is the tangent at the end of the curve. These correspond to the ends of the two tangent controls you see in any vector drawing application with Bézier paths. If you haven’t used one, Inkscape is free.

like image 88
Jens Ayton Avatar answered Sep 21 '22 09:09

Jens Ayton


The image below illustrates the accepted answer,

Cubic Bézier curve

control point 1 is the tangent of the curve at its beginning.

This would be the dotted line from Start Point to Control Point 1 in Bézier curve

The line between control point 2 and the “to” point is the tangent at the end of the curve

This is the dotted line between Endpoint and Control Point 2.

This image is from official Apple documentation.

like image 30
Andrew-Dufresne Avatar answered Sep 21 '22 09:09

Andrew-Dufresne