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];
}
}
実行結果は右の通り。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];
}
}
これが、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];
}
このプログラムを実行すると、螺旋が描かれるんだ。やっていることは単純で、はじめに 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。これは終点だ。そして曲線の曲がり具合を指示する controlPoint1 と controlPoint2。この 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];
...
}
_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 角形までを描いてみた。
■サンプルダウンロード:
BezierPath.tar.gz
Application Kit - NSBezierPath
線のスタイル
Keywords: setLineWidth, setLineCapStyle, setLineJoinStyle
NSBezierPath は線のスタイルを細かく設定できるんだ。まず、線の太さ。これは setLineWith: で設定できる。
Application Kit/BezierPath.h
- (void)setLineWidth:(float)lineWidth;
次に、線の端点。これは CapStyle と呼ばれて、3 種類設定できる。右の図みたいな感じだ。端点を設定するには、setLineCapStyle: を使う。引き数として、左から順に、NSButtLineCapStyle、NSRoundLineCapStyle、NSSquareLineCapStyle を設定する。
Application Kit/BezierPath.h
- (void)setLineCapStyle:(NSLineCapStyle)lineCapStyle;
次は、線の結合の仕方。もう、分かってきたでしょ。図を見れば一目瞭然だ。これらは setLineJoinStyle: を使うんだ。指定する引き数は、上から順に、NSRoundLineJoinStyle、NSMiterLineJoinStyle、NSBevelLineJoinStyle だ。
Application Kit/BezierPath.h
- (void)setLineJoinStyle:(NSLineJoinStyle)lineJoinStyle;
サンプルプログラムでは、これらの値を自由に変えて試すことができるよ。
■サンプルダウンロード:
BezierPath.tar.gz