Mac用プロットライブラリ-12 [考え中 - プロットライブラリ]
前回の、プロット座標から相対指定されたView座標が、描画領域からはみ出す場合の処理について。前回の議論はあまりにもナイーブだったことがわかった。もう一度整理し直すことにする。まず、はみ出し問題を扱う前にそれがどこで現れるか、を示すためまずレイヤ構造のおさらい。
ユーザから受けたプロットすべきデータを表示するのを、4つのレイヤに分担させることにした。
Automaticオプションは例えば
などがある。Styleに関するオプションはこの他にもいっぱい考えられる。このへんのパラメータの概念はMathematicaから借りてこよう。
それは
縦横比の指定はユーザがする場合と、Automatic指定を受けてPlotRangeから計算される場合がある。これが前回気がついたはみ出しの問題とからむ。あとでもう一度整理する。
ウィンドウのリサイズとかで描画先のNSViewのRectの大きさが変わったときはNormalized Layerから先を作り直すことになる。結構オーバーヘッドがでかいけど、まあええでしょ。実装が簡単な方がいい。
例えば図-6のような場合を考える。
Plot領域(今の場合、(0,1)区間に収まったNormalized座標の正方形領域)の大きさはView領域に(実際は描画先のNSViewのNSRect)フィットするように拡大縮小される。ここでPlot領域の中のniという位置からviという点がView座標で相対指定されているとする。つまりniはPlotが拡大縮小されるにつれて実際に描画される位置は変わる。そこからviというView座標、つまり画面上のpoint単位で測られる距離だけ離れた位置を指定している、とする。これは文字を書き込む場合など、頻繁にあり得る。このときView領域一杯にPlot領域をマップするのではなく、図のように小さくマップして左右ともView領域内に収まるようにマップする必要がある。
N個のNormalized座標のi番目の(dix, diy)から相対指定されたView座標(Lix, Liy)のNSViewでの描画位置(vix, viy)は
となる。αは拡大の係数で、τはシフトの係数になる。普通は3行3列の行列で書くのだろうけど回転させないので非対角要素が無いからこれの方が簡単。
これがViewからはみ出さないという条件は
となる。ここでWとHはそれぞれViewの長方形の幅と高さ。NSViewではpointで測った画面上での矩形領域の大きさ。相対座標の符号によって不等号の効く方向が決まるので式-1、2のLiの符号によって分けると
となる。つまり、この式のすべてのiについて条件を満足し、かつαが最大(View領域になるべくいっぱい)のものを求めると言う問題になる。これはいわゆる線形計画法の問題に他ならない。線形計画法は物理屋にはあまりなじみは無いけど、資源配分の最大効率化(多くの種類の材料から多くの種類の製品を作るときに利益を最大化するなど)などごく普通に現れる問題なのでよく研究されている。今回の場合、ふたつの変数αとτに関するN個の条件を満足する二つの独立な線形計画問題に帰着する。
また、縦横比が指定されている場合、縦横比εを
として
となるから、条件式は
となって、みっつの変数α、τx、τyに関する2N個の条件を満足する線形計画法とみなせる。
線形計画法としては非常に単純な問題である。
とは言うものの、じつは線形計画法はあまりよく知らない。シンプレックス法というアルゴリズムがあってそれでプログラマチックに解ける、ということぐらいしか知らない。gslの中にも線形計画法は入っていない。MathematicaにはLinearProgramingという関数いっぱつで解けるらしいけどブラックボックスで中身はわからない。
しょうがないのでちょっと勉強しよう。
いや今日は、悩んでたことが知らないなりにも線形計画法という一般的な問題と見なせるということがわかっただけでも収穫。こういうのは充実感があるがな。うれしい。
ユーザから受けたプロットすべきデータを表示するのを、4つのレイヤに分担させることにした。
- Automatic Layer
- Primitive Layer
- Normalized Layer
- View Layer
1.Automatic Layer
Automatic Layerは- ユーザが指定した、あるいは暗黙のオプションを展開してPrimitiveの集合に変換する
- Primitve Layerのインスタンスを作る
Automaticオプションは例えば
Key | 値 | Automatic指定したときの意味 |
---|---|---|
PlotRange | 範囲指定 {{xl,xh},{yl,yh}} | データ全体が表示領域一杯になる |
AspectRatio | 縦横比 | 座標軸の刻みが等方になる |
AxesOrigin | 軸の交差位置 | PlotRange内できりのいいところ |
LineStyle | 線の描き方 | 適当な色を付ける |
などがある。Styleに関するオプションはこの他にもいっぱい考えられる。このへんのパラメータの概念はMathematicaから借りてこよう。
2.Primitive Layer
は、PrimitiveをPlot座標からNormalized座標に変換する。それは
- PlotRange指定から変換行列を作る
- Normalized Layerのインスタンスを作る
- 変換行列を使ってNormalized Primitiveに変換する
3.Normalized Layer
は、描画先のViewのRectを使ってView座標に変換するのが仕事。これはAspectRatioの指定によってちょっと違う。縦横比の値 | NSViewの上でその縦横比になるような変換行列を作る |
FillInRect | NSViewいっぱいになるような変換行列を作る |
4.View Layer
は、View座標に変換されたPrimitiveを、NSBezierPathなどに展開してNSViewの上に描画する。オプションで指定されているStyle、例えば- 線の太さ
- 線の色
- マーカを置く
- 影付け、スムージングなどの描画
ウィンドウのリサイズとかで描画先のNSViewのRectの大きさが変わったときはNormalized Layerから先を作り直すことになる。結構オーバーヘッドがでかいけど、まあええでしょ。実装が簡単な方がいい。
はみ出し問題
さて、やっと問題のはみ出しについて。 前回、繰り返しのアルゴリズムで収束する、と書いたけどちゃんとそれを保証する方法があった。それをもう一度整理する。例えば図-6のような場合を考える。
Plot領域(今の場合、(0,1)区間に収まったNormalized座標の正方形領域)の大きさはView領域に(実際は描画先のNSViewのNSRect)フィットするように拡大縮小される。ここでPlot領域の中のniという位置からviという点がView座標で相対指定されているとする。つまりniはPlotが拡大縮小されるにつれて実際に描画される位置は変わる。そこからviというView座標、つまり画面上のpoint単位で測られる距離だけ離れた位置を指定している、とする。これは文字を書き込む場合など、頻繁にあり得る。このときView領域一杯にPlot領域をマップするのではなく、図のように小さくマップして左右ともView領域内に収まるようにマップする必要がある。
N個のNormalized座標のi番目の(dix, diy)から相対指定されたView座標(Lix, Liy)のNSViewでの描画位置(vix, viy)は
これがViewからはみ出さないという条件は
また、縦横比が指定されている場合、縦横比εを
線形計画法としては非常に単純な問題である。
とは言うものの、じつは線形計画法はあまりよく知らない。シンプレックス法というアルゴリズムがあってそれでプログラマチックに解ける、ということぐらいしか知らない。gslの中にも線形計画法は入っていない。MathematicaにはLinearProgramingという関数いっぱつで解けるらしいけどブラックボックスで中身はわからない。
しょうがないのでちょっと勉強しよう。
いや今日は、悩んでたことが知らないなりにも線形計画法という一般的な問題と見なせるということがわかっただけでも収穫。こういうのは充実感があるがな。うれしい。
2008-05-12 23:49
nice!(0)
コメント(0)
トラックバック(0)
コメント 0