Introduction to Cocoa Graphics, Part 2
Pages: 1, 2, 3
In addition to the methods that take absolute points as their arguments, NSBezierPath declares a set of methods that allow us to indicate relative positions of points. Thus, instead of saying p2
should be at (200, 300)
, we can say that p2
is (100, 200)
relative to p1
. So now p2
is more of a direction vector, as opposed to an absolute location in the plane. Using the method relativeLineToPoint:
, we can rewrite our method as:
 (void)drawRect:(NSRect)rect
{
// The three vertices of the triangle
NSPoint p1 = NSMakePoint(100, 100);
NSPoint rp2 = NSMakePoint(100, 200);
NSPoint rp3 = NSMakePoint(100, 200);
// Constructing the path
NSBezierPath *triangle = [NSBezierPath bezierPath];
[triangle moveToPoint:p1];
[triangle relativeLineToPoint:rp2];
[triangle relativeLineToPoint:rp3];
[triangle closePath];
// Draw the path
[[NSColor blueColor] set];
[triangle stroke]; // or [triangle fill];
}
Learning Cocoa 
Lines aren’t the only things we use to build shapes; we can do curves as well, using the method –curveToPoint:controlPoint1:controlPoint2:
. As you can see, this method is a bit more complicated than making a line, so let me say a thing or two about these "control points" we see in the method name.
Each endpoint of the curve has a control point associated with it. The starting point of the curve (the current point) and controlPoint1
define a vector that is tangent to the curve at the current point.
Similarly, the endpoint of the curve (from the argument list) and controlPoint2
define another vector that is tangent to the curve at the endpoint. Together these two vectors provide enough information for the algorithms behind NSBezierPath to fit a cubic polynomial equation to the provided constraints. This polynomial, in turn, defines a very naturallooking curve. You can see the different parts of a curve in the figure below.

We can incorporate a curve into our triangle to give it a wavy bottom in the following way:
 (void)drawRect:(NSRect)rect
{
// The three vertices of the triangle
NSPoint p1 = NSMakePoint(100, 100);
NSPoint p2 = NSMakePoint(200, 300);
NSPoint p3 = NSMakePoint(300, 100);
// The control points of the curve
NSPoint c1 = NSMakePoint(200, 200);
NSPoint c2 = NSMakePoint(200, 0);
// Constructing the path
NSBezierPath *triangle = [NSBezierPath bezierPath];
[triangle moveToPoint:p1];
[triangle lineToPoint:p2];
[triangle lineToPoint:p3];
[triangle curveToPoint:p1 controlPoint1:c1 controlPoint2:c2];
// Fill the path
[[NSColor blueColor] set];
[triangle fill];
// Draw the outline
[[NSColor redColor] set];
[triangle stroke];
}
Remember that controlPoint1
defines the line from the current point, and controlPoint2
defines the line from the point given in the argument for curveToPoint:
. Notice that in this example, we first filled the shape of the path with blue and then stroked the path using red, effectively creating a red border on the shape, as shown in the image below. When doing multiple stroke or fill commands such as we have done here, more recent strokes or fill will be drawn on top of previous calls to these methods.

With the basics of creating paths under our belts, we’ll now look at a few of the line and curve properties that we can change.