macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Introduction to Cocoa Graphics, Part 2
Pages: 1, 2, 3

Changing the characteristics of paths

It's possible to change the characteristics of Bezier paths via several methods. For example, we can change the thickness of a stroked path using the method –setLineWidth:, where the argument is a float indicating the width of the line in points. We can change the thickness of the lines of our triangle by adding the following just before we send a stroke message to triangle:

[triangle setLineWidth:10];

This will make our drawing look like the following:

Screen shot.
Figure 3.

If you set the line width to 0 using this method, then the path will be stroked with the smallest width that can be displayed on the screen. I choose a thick line width here to bring out some features about the way path elements are joined to each other.



First, notice how the lower right vertex of the triangle is a very sharp point that extends far beyond what we originally intended for our triangle. The image below shows a thin green line superimposed on top of the thicker red line to highlight the effect I’m speaking of.

Screen shot.
Figure 4.

The reason for this is that by default, lines in a path are joined together using a so-called miter join where the outside edge of the two intersecting lines are extended to a point. This default join style is defined the constant NSMiterLineJoinStyle, which we use to identify the join style in code. We can fix this problem in several ways.

One, we can change the line join style to either NSRoundLineJoinStyle or NSBevelLineJoinStyle using the method -setLineJoinStyle. For example, if we wanted to make the vertices rounded, we would pass the constant NSRoundLineJoinStyle as an argument to setLineJoinStyle:

[triangle setLineJoinStyle:NSRoundLineJoinStyle];

Alternatively, we can flatten the corners by using NSBevelJoinStyle. In the image below, I show the three line join styles side-by-side with a representation of the original path drawn in green.

Screen shot.
Figure 5.

Line joining, however, is not the end of our woes here. Remember our discussion about closing paths and the line join issues associated with it? Well, here is a perfect example of what happens when the path is not officially closed, despite your shape having the appearance of being closed.

Notice in the lower left corner that the lines are never joined. The reason for this is simple enough: this corner is both the start of the path and the end of the path. We never say that these two points -- despite them being the same point -- should be joined. To fix this, we send a closePath message to triangle after our last construction command to close the path off, and now any join style will apply correctly, as shown below:

Screen shot.
Figure 6.

The final code the produced this image is as follows:


- (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);
    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];
    [triangle closePath];
    
    // Fill the path
    [[NSColor blueColor] set];
    [triangle fill];

    // Draw the outline
    [triangle setLineJoinStyle:NSRoundLineJoinStyle];
    [triangle setLineWidth:10];
    [[NSColor redColor] set];
    [triangle stroke];

    // Draw representation of original path
    [triangle setLineWidth:0];
    [[NSColor greenColor] set];
    [triangle stroke];
}

The end

So there you have it! This is how you can create any shape that you may need. NSBezierPath has many more methods that do useful things, many of which we will cover in future columns.

As always, I recommend that you become familiar with the NSBezierPath class reference if you haven’t done so already. For now, I leave you with these most useful tools with which you can do a lot. In the next column we will start to learn about how you can interact with elements of your drawing on screen using the mouse, so stay tuned for some good stuff. See you then!

Michael Beam is a software engineer in the energy industry specializing in seismic application development on Linux with C++ and Qt. He lives in Houston, Texas with his wife and son.


Read more Programming With Cocoa columns.

Return to the Mac DevCenter.