なんちゃってMathematicaを作る - その17 [なんちゃってMathematica]
前回はもう先週の話になってしまうんだけど、プロットライブラリの内部設計を始めた。レイヤ構造を持たせること、3種類の座標値を内部的に使って処理を進めること、その3つの座標値はユーザにも開放して混在して使うことを許すこと、なんかを決めた。このへんはずっと前に考察していた。その3種類の座標値にそれぞれ絶対座標と相対座標を持たせる。今日はそれらを混在されることによる問題について。
plot相対座標の指定先がplot絶対座標値だったら、すぐ相対値を解決できる。また、相対指定先がplot相対座標ならその先を見ればいい。どこかで解決されるはずである。
図-の上の場合のように相対Plot座標の相対指定先がPlot座標だった場合は、相対先の値に従って絶対座標に変換できる。ところが下の場合のように、たとえばview座標の相対指定先が、plot座標という場合が起こりえる。 たとえば折れ線のある点に文字列を配置するような場合である。点の上に文字を配置することはできず、ある距離をおかなければならない。その距離は見やすさを考えるとview座標で一定であるべきである。すなわち文字はplot座標を相対指定先にしたview座標で配置されないといけない。
この場合、相対指定の解決は、plot座標がnormalized座標に、さらにview座標に変換されるまで延期されることになる。
ということは、相対座標の解決は「可能になったら実行する」という実装でなければならない。
逆に、plot座標の相対指定先がview座標ということもあるかもしれない。そういう場合の具体的なシチュエーションを思い浮かべられないけど、そういうのにも対応しておくべきであろう。これはあとで考察することにする。
外に出ているplottableがplot座標やnormalized座標で表現されていれば問題ない(単にあらためて最大値最小値をAABBとすればいい)が、normalizedレイヤでplottableがview座標を含んでいた場合、AABBをNSViewのbounding rect(描画領域全体)にそのままマップできない。
なぜならview座標がnormalized座標からの相対指定されている場合がありえるからである。この場合、AABBからview座標がはみ出るとview座標へのマップを変更しないといけないが、はみ出し量はnormalized座標の大きさが決まらないといけない、という堂々巡りになるからである。
また、たとえば折れ線グラフの線幅が指定されているとする。一番端の点はAABBの境界線上にあることが多いだろう。この場合AABBをそのままNSViewのbounding rectにマップすると線が半分切れることになって美しくない。この処理もはみ出し処理と同じことが必要になる。
4.3 絶対座標と相対座標
どの座標も、絶対指定と相対指定が可能であるとする。相対指定はポインタを持っていて「これに対する相対値」という値を保持する。相対指定にはいくつかの制限を加える必要がある。- nilなどの無意味な値は許さない
- ほかのPlotContainerに含まれる座標を相対指定してはいけない
- 相対指定のループはない
plot相対座標の指定先がplot絶対座標値だったら、すぐ相対値を解決できる。また、相対指定先がplot相対座標ならその先を見ればいい。どこかで解決されるはずである。
4.3.1 座標系の混在による問題
さきの座標系の混在を許すこととの関連で問題が発生する。図-の上の場合のように相対Plot座標の相対指定先がPlot座標だった場合は、相対先の値に従って絶対座標に変換できる。ところが下の場合のように、たとえばview座標の相対指定先が、plot座標という場合が起こりえる。 たとえば折れ線のある点に文字列を配置するような場合である。点の上に文字を配置することはできず、ある距離をおかなければならない。その距離は見やすさを考えるとview座標で一定であるべきである。すなわち文字はplot座標を相対指定先にしたview座標で配置されないといけない。
この場合、相対指定の解決は、plot座標がnormalized座標に、さらにview座標に変換されるまで延期されることになる。
ということは、相対座標の解決は「可能になったら実行する」という実装でなければならない。
逆に、plot座標の相対指定先がview座標ということもあるかもしれない。そういう場合の具体的なシチュエーションを思い浮かべられないけど、そういうのにも対応しておくべきであろう。これはあとで考察することにする。
4.4 はみ出しの処理
前回問題になってとりあえずの解決を見たはみ出し処理。4.4.1 はみ出し処理が必要な理由
normalizedレイヤからviewレイヤに変換するとき、normalized座標での[0,1]区間にすべてのplottableが入っているわけではない。それはなぜかというと、AABBはユーザが指定した折れ線や配置されたプリミティブを全部含んでいるけど、自動的に生成された座標軸などは含まれていない。座標軸は指定によって図の中に配置されたり、枠の外に配置されたりする。そしてたとえば刻みが縦と横で一致するように描画したいとき(等方的なx-y座標)、縦横比はユーザが指定したオブジェクトに関して調整されるべきだからである(描画結果として、座標軸が外に描かれた場合、全部が収まるように縮小され、内部の縦横比は一定になるべきである)。外に出ているplottableがplot座標やnormalized座標で表現されていれば問題ない(単にあらためて最大値最小値をAABBとすればいい)が、normalizedレイヤでplottableがview座標を含んでいた場合、AABBをNSViewのbounding rect(描画領域全体)にそのままマップできない。
なぜならview座標がnormalized座標からの相対指定されている場合がありえるからである。この場合、AABBからview座標がはみ出るとview座標へのマップを変更しないといけないが、はみ出し量はnormalized座標の大きさが決まらないといけない、という堂々巡りになるからである。
また、たとえば折れ線グラフの線幅が指定されているとする。一番端の点はAABBの境界線上にあることが多いだろう。この場合AABBをそのままNSViewのbounding rectにマップすると線が半分切れることになって美しくない。この処理もはみ出し処理と同じことが必要になる。
4.4.2 解決手段は前回考察済み
これはシンプレックス法という最適化手法で解決できることがわかったので問題ないが、normalizedレイヤからviewレイヤに変換するコードにこのシンプレックス法を実装しなければならない。シンプレックス法そのものは簡単な線形演算だけど、場合分けをする必要がある。できれば再利用可能なコードがどこかにあるとうれしい。2012-02-12 21:54
nice!(0)
コメント(0)
トラックバック(0)
コメント 0