太さの変わるBezier曲線の生成 - その23 [考え中 - 太さの変わるBezier曲線]
内挿方式のAGG方式の検討のおさらい中。NSBezierPathの復習の3回目、サブパスが閉じている場合にSmoothingを行うときの注意と、NSBezierPathのエレメントの微妙な問題、そして制御点を変更するときの方法について。
制御点の追加のしかた
途中だけど、ちょっと整理をしておく。サブパスが図-31のような3つの点からできていたとしよう。
左は閉じていないサブパスで、右は同じ端点を持っている閉じたサブパスである。この二つをSmoothingすることを考えると、図-32のようにならなければいけない。
左右のサブパスを比較すればすぐわかるように端点の数をNとすると追加すべき中間制御点の数Cは となる。閉じている場合、閉じるための線に対応する制御点を置くためには、最初の端点を最後にもういちど追加する必要がある。
逆に、閉じている場合は最初の端点を追加することにすれば式-96は閉じているかどうかに関わらず
となる。エレメントの詳細
エレメントは描画メソッドに直接対応すると言ったが、実は微妙に違っている。それは
- closePathのあとには最後のmoveToPoint:呼び出しが追加される
- 最初にlineToPoint:から始めるとその前に最後のmoveToPoint:呼び出しがもう一度呼ばれる
- lineToPoint:から始めた場合(その前にmoveToPoint:呼び出しはない)lineToPoint:の位置にいったんMoveされてからlineToPoint:が呼ばれる
closePathのすぐ後にlineToPoint:を(moveToPoint:ではなく)を呼ぶとclosePathのあとのmoveToPoint:が生きてしまう。ガイドにはこのような動作を明示的に行う(closePathのあとにmoveToPoint:を本当に呼ぶ)ことを要求しているように読める。
こういった詳細はFrameworkのバージョンで動作が変わってしまうこともあって困り物だけど、今回のような実装はこういった詳細に依存してしまう。
制御点を変更する
エレメントの制御点を変更するためのメソッドとしてsetAssociatedPoints:atIndex:というのがある。しかし残念ながらこれを使ってエレメントのタイプは変更できない。つまり例えばlineTo:で直線を描いた部分を制御点を追加して曲線(curveToを使ったように)にすると言うことはできない。
制御点を変更するメソッドは追加、全削除する以外にはこれしかないので直線を曲線に変更することはできない(曲線を直線にすることは可能だけど)。従って今回のSmoothingメソッドは
- 制御点が変更された新しいブジェクトを返す
- 全削除して自分自身を描き直す
NSBezierPathには制御点の情報以外にもいろいろなAttributeがあって新しいオブジェクトにはそれも全部コピーしなければならない。これは非常に面倒なので新しいオブジェクトを返すとしてもいったん自分自身をコピーしてそのコピーの制御点を全削除したあと、描き直すのが一番簡単で、それなら2番目と手間は同じでコピーする分だけ効率が悪い。
ということで今回は2番目のやり方を採用する。
おさらいはこのくらいにして、次から実装を考える。
コメント 0