[SML 7298] はじめまして & Jun に関して質問

AOKI Atsushi aoki @ sra.co.jp
2007年 4月 19日 (木) 05:05:46 JST


SRA先端技術研究所の青木です。(現在、私事で有給休暇中。)

無限ループの不具合を確認しました。佐藤さん、報告を有り難うご
ざいました。

まず、メソッドの修正案を云々する前に、当該のメッセージ式につ
いて整理しておきましょう。

aPlane := JunPlane on: aPoint vertical: aLine

このメッセージ式は、ある点(aPoint)を通り、ある線(aLine)に
垂直な平面(aPlane)を求めます。

応答される平面を表現するオブジェクトの内部構成は、方程式型で
あり、次のようなものです。

ax + by + cz + d = 0

ですから、インスタンス変数に a b c d を持ちます。数学であれば、
これだけでいいのですが、じゅんにおける「可視化」したいという
要求を満たすことができません。そこで、平面上の3点、p1 p2 p3
をインスタンス変数に保持しています。

さて、問題は、ある点(aPoint)を通り、ある線(aLine)に垂直な
平面(aPlane)を求めた際に、p1 p2 p3 を求められるか、というこ
とになります。

p1 は、ある点(aPoint)そのままでいいでしょう。そして、p2 は、
ある点(aPoint)から、ある線(aLine)への足(nearestPoint)で
いいでしょう。残るは、p3 です。

その p3 の求め方には、たくさんの方法があります。現在、実装さ
れている方法は、紆余曲折を経て、今の状態になっているのでしょ
う。開発ログを調べると、数人の方々の手を煩わせ、何回も修正が
入っているメソッドでした。

そこで、佐藤さんがお訊ねの件ですが、

 > ここで質問があります。この修正は、今回のケース "JunPlane on:
 > 0 , 1 , 1 vertical: (0 , 0 , 0 to: -1 , 0 , 0)" でたまたまう
 > まくいっただけなのでしょうか、それとも、あらゆるケースで通用
 > するものなのでしょうか。どなたかご回答いただければ幸いです。

たまたまうまくいっただけ、だと思われます。あらゆるケースを確
かめること自体が難しい上に、同次座標変換の回数を極力減らして、
計算誤差の入り込みを抑える必要がありますから、なかなか手強い。

以下に、佐藤さんからの不具合報告を鑑みて、私が考えたコードを
示します。回転系を用いていますので、有効桁数が16桁程度に落
ちてしまいますが、あながち使えないこともないでしょう。

| thePoint theLine p1 p2 line angle plane p3 |
thePoint := 0 , 1 , 1.
theLine := 0 , 0 , 0 to: -1 , 0 , 0.
p1 := thePoint.
p2 := theLine nearestPointFromPoint: p1.
line := p1 to: p2.
angle := 90 asDegrees.
(p2 equal: theLine first)
     ifTrue:
         [plane := JunPlane
                     on: p1
                     on: p2
                     on: theLine last.
         plane := plane transform: (angle transformationToRotate: line).
         (plane whichSide: theLine last) > 0
             ifFalse:
                 [plane := JunPlane
                             on: p2
                             on: p1
                             on: theLine last.
                 plane := plane transform: (angle transformationToRotate: line)].
         p3 := plane p3]
     ifFalse:
         [plane := JunPlane
                     on: p1
                     on: p2
                     on: theLine first.
         plane := plane transform: (angle transformationToRotate: line).
         (plane whichSide: theLine first) < 0
             ifFalse:
                 [plane := JunPlane
                             on: p2
                             on: p1
                             on: theLine first.
                 plane := plane transform: (angle transformationToRotate: line)].
         p3 := plane p3].
plane asJunOpenGL3dObjectWithPoints showWithUnitAxes.
^p3

最後のところで、求めた3点を平面と共に可視化しておきました。
ご検討いただければ幸いです。

------------------------------------------------------------
R2D2 (AOKI Atsushi)        http://www.sra.co.jp/people/aoki/




SML メーリングリストの案内