HMDT - Logic and Intuition -

about HMDT

Cocoa Programming Tips 1001

Application Kit

NSBezierPath

Application Kit - NSBezierPath

ベジエパスとは

Keywords: Bezier path

NSBezierPath は Bezier 曲線をあつかうためのクラス。Bezier 曲線っていうのは、Illustrator とかで曲線を描くときに、ベジエ曲線ツールを使うでしょ。あれのこと。ちなみに、おぼろげな記憶によると、Bezier というのは、フランスの自動車メーカーで働いていた Bezier さんのこと。彼が自動車をデザインするために考え出したのが、あの曲線らしい。彼の考えた自動車が歴史に残ったかどうかは知らないけど、Bezier 曲線の方は残ったわけだ。

ベジエ曲線をサポートする NSBezierPath クラスを使うと、ビューの上にさまざまな線、図形を描くことができる。これらについて説明しよう。

Application Kit - NSBezierPath

線を引く

Keywords: storkeLineFromPoint

まずは、一番簡単な線を引くことから。線を引くには NSBezierPath の storkeLineFromPoint: を使うのが手っ取り早い。

Application Kit/NSBezierPath.h

+ (void)strokeLineFromPoint:(NSPoint)point1 
        toPoint:(NSPoint)point2;

クラスメソッドなんで、いきなり描くことができる。point1 から point2 に線を引くんだ。このメソッドを、View に focus があたっている状態で呼び出せばいいんだ。一番簡単なのは、drawRect: の中で呼べばいい。

BezierPath/LineView.m (sample)

- (void)drawRect:(NSRect)frameRect
{
    NSPoint	point0 = { 
        frameRect.size.width / 2, 
        frameRect.size.height / 2 };
    NSPoint	point1;
    int		i;
    int		divide = 16;
    
    for(i = 1; i <= divide; i++) {
        point1.x = 100 * cos((2 * M_PI / divide) * i) 
            + point0.x;
        point1.y = 100 * sin((2 * M_PI / divide) * i) 
            + point0.y;
        // 線を引く
        [NSBezierPath strokeLineFromPoint:point0 toPoint:point1];
    }
}

LineView 実行結果は右の通り。point0 から point1 に向かって、放射状に線を引いてみた。線は現在の Graphic Context の色、線の太さを使って描かれるよ。さらにデフォルトでアンチエイリアスがかかるんだ。

■サンプルダウンロード:
BezierPath.tar.gz


Application Kit - NSBezierPath

四角を描く

Keywords: storkeRect, fillRect

次は四角を描いてみる。これもそのものずばり、strokeRect: というクラスメソッドがある。

Application Kit/NSBezierPath.h

+ (void)strokeRect:(NSRect)aRect;
+ (void)fillRect:(NSRect)aRect;

aRect で指定した大きさの四角を描くわけだ。strokeRect: を使うと、外枠だけを描く。中身を塗りつぶす場合は fillRect: を使う。

BezierPath/RectView.m (sample)

- (void)testStrokeRect:(NSRect)frameRect
{
    NSPoint	point0 = { 
        frameRect.size.width / 4, 
        frameRect.size.height / 2 };
    NSPoint	point1;
    NSRect	rect;
    int		i;
    int		divide = 16;
    NSSize	rectSize = { 50, 40 };
    
    for(i = 1; i <= divide; i++) {
        point1.x = 100 * cos((2 * M_PI / divide) * i) 
            + point0.x;
        point1.y = 100 * sin((2 * M_PI / divide) * i) 
            + point0.y;
        
        rect.origin.x = point1.x - rectSize.width / 2;
        rect.origin.y = point1.y - rectSize.height / 2;
        rect.size = rectSize;
        
        // 四角を描く
        [NSBezierPath strokeRect:rect];
    }
}

RectView これが、strokeRect: を使ってみた例。右の図の、左側がこれになる。右側は fillRect を使った場合。このサンプルでは、四角を描く前に、NSColor を使って色を設定してみた。

■関連リンク:
四角を描く (Graphic 関数)

■サンプルダウンロード:
BezierPath.tar.gz

Application Kit - NSBezierPath

折れ線を描く

Keywords: bezierPath, moveToPoint, lineToPint, stroke

続いて折れ線を描く方法。ベジェパスには、アンカーポイントというものがあるんだ。そこが、線の“節”ということになる。このアンカーポイントを指定することで、折れ線を描く。

実際にどういう風に描いていくかというと、NSBezierPath には、カレント・ポイントというものがあるんだ。現在の線の先端といったイメージだ。そこから次の点を指定して、線を描く。さらにそこから次の線をひっぱる、、、の繰り返しで線を描いていくんだ。

そのためには、まず空のベジェ曲線を作る。クラスメソッド bezierPath を使う。

Application Kit/NSBezierPath.h

+ (NSBezierPath *)bezierPath;

これで作られるのが、何も含んでいない線ね。次にカレント・ポイントを設定してやらないといけない。それには moveToPoint: を使う。カレント・ポイントが設定されたら、そこから指定した点まで線を引くことができる。それには lintToPoint: を使うんだ。

Application Kit/NSBezierPath.h

- (void)moveToPoint:(NSPoint)point;
- (void)lineToPoint:(NSPoint)point;

あとは、lineToPoint: をくり返し呼ぶことによって線が引けるんだ。そして最後に storoke を呼ぶ。これで、実際に画面に線が描かれる。

Application Kit/NSBezierPath.h

- (void)stroke;

じゃ、実際に使ってみよう。

BezierPath/SpiralView.m

- (void)drawRect:(NSRect)frameRect
{
    NSPoint	point = { 
        frameRect.size.width / 2, 
        frameRect.size.height / 2 };
    int		i;
    int		increment = 5;
    int		diff = increment;
    
    NSBezierPath*	bezier = [NSBezierPath bezierPath];
    [bezier moveToPoint:point];
    
    for(i = 0; i < 6; i++) {
        point.x += diff; point.y += diff;
        diff += increment;
        [bezier lineToPoint:point];
        point.x += diff; point.y -= diff;
        diff += increment;
        [bezier lineToPoint:point];
        point.x -= diff; point.y -= diff;
        diff += increment;
        [bezier lineToPoint:point];
        point.x -= diff; point.y += diff;
        diff += increment;
        [bezier lineToPoint:point];
    }
    
    [bezier stroke];
}

SpiralView このプログラムを実行すると、螺旋が描かれるんだ。やっていることは単純で、はじめに moveToPoint: を呼んで、あとは次々と lineToPoint: を呼んでやるんだ。最後に stroke を呼ぶことによって、線が描かれる。

■サンプルダウンロード:
BezierPath.tar.gz

Application Kit - NSBezierPath

曲線を描く

Keywords: curveToPoint:controlPoint1:controlPoint2:

次は曲線の描き方だ。とはいっても、直線も曲線の一つであるわけだよね。ただ単に曲がっていない曲線というだけ。曲線を描くには curveToPoint:controlPoint1:controlPoint2: を使う。

Application Kit/NSBezierPath.h

- (void)curveToPoint:(NSPoint)aPoint 
                controlPoint1:(NSPoint)controlPoint1 
                controlPoint2:(NSPoint)controlPoint2;

1 つの曲線(または長い曲線のある部分)は、4 つの点で決定されるんだ。まずカレント・ポイント。これが始点になる。次に上のメソッドに出てくる aPoint。これは終点だ。そして曲線の曲がり具合を指示する controlPoint1controlPoint2。この 4 つの点と曲線の曲がり具合の関係は、下の図のようになってるんだ。

ドロー系のグラフィックソフトで絵を描いたことがある人なら、だいたい分かると思う。本来なら、Bezier 曲線の数式的定義を持ち出して説明する必要があるんだけど、ここでは省略。その筋の本をあたってくれ。

サンプルでは、曲線を描いて、それをマウスでドラッグして変更できるようにしてみた。

BezierPath/CurbeView.m

- (void)drawRect:(NSRect)frameRect
{
    NSBezierPath*	bezier = [NSBezierPath bezierPath];
    
    // 曲線を描く
    [[NSColor blackColor] set];
    [bezier moveToPoint:_startPoint];
    [bezier curveToPoint:_endPoint 
            controlPoint1:_ctrlPoint1 
            controlPoint2:_ctrlPoint2];
    [bezier stroke];
    
    ...
}

CurveView _startPoint_endPoint_ctrlPoint1_ctrlPoint2 の 4 つの点を設定してやることによって、曲線が描けるんだ。あと、このプログラムでは、これらの 4 つのコントロールポイントも描いている。さらに、これらをドラッグで動かすことができるんだ。動かすためには、mouseDown: の中で、マウスをトラッキングしてやる必要がある。詳しくは、コードの中を見てね。

■サンプルダウンロード:
BezierPath.tar.gz

Application Kit - NSBezierPath

パスを閉じる

Keywords: closePath

ここでは、閉じられた線を考える。四角とか、円とかは閉じられた BezierPath として扱うことができるんだ。パスを閉じるには、closePath を使う。

Application Kit/NSBezierPath.h

- (void)closePath;

これを呼ぶと、カレント・ポイントから、最初の点までの線が加えられて、線が閉じるんだ。ということで、多角形を書く手順は、

  • moveToPoint: を呼ぶ
  • lineToPoint: を必要なだけ呼ぶ
  • closePath を呼ぶ

という風にまとめられるんだ。これを使って多角形をつくる関数を作ってみた。

BezierPath/PolygonView.m

- (NSBezierPath*)makePolygonPath:(NSBezierPath*)bezierPath 
                polygonNumber:(int)polyNum
                origin:(NSPoint)origin 
                radius:(float)radius
{
    int	i;
    
    for(i = 0; i <= polyNum; i++) {
        NSPoint	tmpPoint = origin;
        tmpPoint.x += radius * 
            cos(M_PI_2 + 2 * M_PI * (i / (float)polyNum));
        tmpPoint.y += radius * 
            sin(M_PI_2 + 2 * M_PI * (i / (float)polyNum));
        
        if(i == 0) {
            [bezierPath moveToPoint:tmpPoint];
        }
        else {
            [bezierPath lineToPoint:tmpPoint];
        }
    }
    // 線を閉じる
    [bezierPath closePath];
    
    return bezierPath;
}

この関数、makePolygonPath:polygonNumber:origin:radius: は bezierPath を渡して、多角形をつくる関数だ。他の引き数として、辺の数(polygonNumber)、中心の座標(origin)、中心からの半径(radius)を設定する。関数の中では、sin、cos を使って、各頂点の座標を求めて、moveToPoint:lineToPoint: を呼び出す。最後に closePath を呼び出して終わりだ。これを使って、3 角形から 12 角形までを描いてみた。

PolygonView

■サンプルダウンロード:
BezierPath.tar.gz

Application Kit - NSBezierPath

線のスタイル

Keywords: setLineWidth, setLineCapStyle, setLineJoinStyle

NSBezierPath は線のスタイルを細かく設定できるんだ。まず、線の太さ。これは setLineWith: で設定できる。

Application Kit/BezierPath.h

- (void)setLineWidth:(float)lineWidth;

cap 次に、線の端点。これは CapStyle と呼ばれて、3 種類設定できる。右の図みたいな感じだ。端点を設定するには、setLineCapStyle: を使う。引き数として、左から順に、NSButtLineCapStyleNSRoundLineCapStyleNSSquareLineCapStyle を設定する。


Application Kit/BezierPath.h

- (void)setLineCapStyle:(NSLineCapStyle)lineCapStyle;

join 次は、線の結合の仕方。もう、分かってきたでしょ。図を見れば一目瞭然だ。これらは setLineJoinStyle: を使うんだ。指定する引き数は、上から順に、NSRoundLineJoinStyleNSMiterLineJoinStyleNSBevelLineJoinStyle だ。


Application Kit/BezierPath.h

- (void)setLineJoinStyle:(NSLineJoinStyle)lineJoinStyle;

サンプルプログラムでは、これらの値を自由に変えて試すことができるよ。

■サンプルダウンロード:
BezierPath.tar.gz

back to top content

Copyright © 2002-2006 HMDT. All rights reserved.