Location : Home > Languages > Perl > Package Title : Math::Project3D |
![]() |
Math::Project3D - 任意の平面への射影
現在のバージョンは 1.010。
use Math::Project3D; my $projection = Math::Project3D->new( plane_basis_vector => [0, 0, 0], plane_direction1 => [.4, 1, 0], plane_direction2 => [.4, 0, 1], projection_vector => [1, 1, 1], # デフォルトは平面の法線 ); $projection->new_function('u,v', 'sin($u)', 'cos($v)', '$u' ); # 射影する前に回転させる。 # z-軸が x-軸になるように全ての点を回転させる。 $projection->rotate([1,0,0]); # ああ、気が変わった。 (<-- フロイト的失言?) $projection->unrotate(); ($plane_coeff1, $plane_coeff2, $distance_coeff) = $projection->project( $u, $v );
本モジュールの背景について説明しよう。ベクトル幾何がお好みでなければ説明 に飛んでもよい。
3つの要素の関数と任意の数のパラメータが与えられれば、本モジュールは3次元の任意の平面の上へのベクトル関数上の個々の点の射影を生成する。
本モジュールはベクトル関数 s(a) = x,y,z と指定された射影ベクトル(デフォルトは射影平面の法線ベクトル)から生成される線分を生成する。法線ベクトルは平面の方向ベクトルの双方に直交するまたは双方のベクトルのベクトル積として定義される。Math::MatrixReal のソルバを用い線形方程式を計算し、交線を求める。
交点は以下のように表現される。
basis point of the plane + i2 * d + i3 * e
i2/i3 は線形方程式を解いて得られる係数であり、 d1/d2 は平面の方向ベクトルである。基本的に方程式は以下のような形態となっている。:
n1*i1 + d1*i2 + e1*i3 = p1 + x(t) n2*i1 + d2*i2 + e2*i3 = p2 + y(t) n3*i1 + d3*i2 + e3*i3 = p3 + z(t)
n1/2/3 は法線ベクトルの要素である。p1/2/3 は基点の座標であり、t は関数ベクトルのパラメータである。i は解である。これで平面上に方向ベクトルと計算された係数とで射影された点を表現することができる。
new
new はクラスメソッドまたはオブジェクトメソッドとして利用される。現在の実装ではどちらでも同じである。
new は新しい Math::Project3D オブジェクトを返す。キー/値の対のリストとして引数の数を渡す必要がある。
plane_basis_vector => [0, 0, 0], plane_directional1 => [.4, 1, 0], plane_directional2 => [.4, 0, 1], projection_vector => [1, 1, 1], # デフォルトは平面の法線
plane_basis ベクトルは射影したい平面の基点の位置を示す。ベクトルは一般的には要素を含む配列参照として渡される。他の方法としては Math::MatrixReal オブジェクトとして渡すという方法がある。
plane_directional1 及び plane_directional2 は平面を計測するベクトルである。これらから射影平面が形成される。
s = plane_basis_vector + coeff1 * plane_dir1 + coeff2 * plane_dir2
生成時に特定する必要がある最後のベクトルは平面への射影関数点に沿ったベクトルである。しかし、平面の方向ベクトルの外積がデフォルトとして使えるので省略することもできる。これにより全ての点が平面へ直交して射影される。
new_function
個のメソッドはクラスまたはオブジェクトメソッドとして利用できる。クラスメソッドとして利用した場合には副次効果はないが、オブジェクトメソッドとして使った場合にはある。これは projection オブジェクトに適用される。
new_function はユーザが特定した要素関数をコンパイルした匿名のサブルーチンを返す。
概要は Math::Project3D::Function を見よ。
ユーザが渡したコンパイルされたベクトル関数に含まれる要素関数のリストを渡すことができる。要素関数と指定するには2つの方法がある。パラメータリストとともに呼び出されたサブルーチン山椒うを渡すこともできるし、評価される妥当な Perl 式を含む文字列を渡すこともできる。2つの構文を混在させることもできる。
要素関数の1つを文字列として指定すれば new_function に対する最初の引数はカンマで区切られたパラメータ名称の文字列でなければならない。これらのパラメータ名称は対応するスカラ変数として文字列の要素関数に利用できる。(例: 't,u' は文字式に適用可能なパラメータは $t 及び $u であることを意味する。)
Math::Project3D::Function における黒魔術のために文字式構文のほうが実行時にはわずかに速くなる。というのは Perl においてはサブルーチン呼び出しには時間がかかるからだ。.
一般的に言ってベンチマーク的には差は小さいのでどちらかの文法をユーザが選ぶことになる。(どちらも私にはミステリだが。) ほぼ間違いなく閉じている構文は閉じているゆえに強力である。結果のベクトル関数の範囲の外側の変数にアクセスする必要がある。簡単な例については Math::Project3D::Function の概要を見るべきである。動的半径を描くなど。
get_function
get_function はオブジェクトの現在のベクトル関数を返す。
set_function
set_function は get_function の反対である。
project
project メソッドはベクトル関数の1点の射影計算を行うために用いられる。関数パラメータのリストが引数として渡されることが想定されている。
失敗すれば(射影ベクトルが平面と平行であるなど)、メソッドは undef を返す。
成功すればメソッドは平面上の射影点の係数と平面から射影ベクトルの長さで始点への距離を返す。(平面の向こう側であれば負になる。)
project_list
project_list はプロジェクトにかかわるラッパであり、様々な処理をしているので遅い。
project_list は引数として配列参照のリストをとる。参照された配列は関数パラメータの集合に含まれる。メソッドは全てのパラメータの射影を計算し、3つの結果(平面上の係数と距離係数)を n*3 行列として(MMR オブジェクトとして。n は射影された点の数)格納する。その行列を返す。
現在では所与の射影ベクトルを使って平面上に点が1つでも射影できなければ不平を言う。点の妥当な結果を保証するために平面の法線ベクトルを射影ベクトルとして用いている。
project_range_callback
多数の点の射影にはこのメソッドは効果を発揮するだろう。最初の引数はあらゆる射影点に対する計算された係数とともに呼び出されたコールバック関数でなければならない。
コールバックの引数は以下のようなものである。射影平面上の単位ベクトルのための2つの係数・射影ベクトルのための係数(平面から点までの距離)・最内範囲(最初のもの)に対応するパラメータが0と異なるたびに加算される整数(この機能は v1.010 から追加)
全ての引数は配列参照でなければならない。参照された配列は1つのパラメータの範囲を示している。これらの配列は1つの数字を含んでおり、1つの静的なパラメータまたは次の形式の3つの数として扱われる。
[ lower boundary, upper boundary, increment ]
たとえば [-1, 1, 0.8] はパラメータ値 -1, -0.2, 0.6 を得る。増分を負の値にすることで上限と下限を入れ替えることもできる。[1, -1, -0.8] は先の例の逆順をもたらす。
Example:
$projection->project_range_callback( sub {...}, # 結果をさらに処理 [ 1, 2, .5], [ 2, 1, .5], [ 0, 10, 4 ], );
これは以下のパラメータを計算値として返す。
1,2,0 1.5,2,0 2,2,0 1,1.5,0 1.5,1.5,0 2,1.5,0 1,1,0 1.5,1,0 2,1,0 1,2,4 etc.
もし点が射影できなければ不平を言う。(射影ベクトルが平面内にはないが平面に平行である場合など)
rotate
引数としてベクトルをとる。(MMR オブジェクトまたは3つの要素を含む配列の配列参照)
メソッドは関数をz-軸(e3)が渡されたベクトルへ帰るために必要な同じ角により元関数の結果を回転する元関数の周りのラッパで置き換える。
例: [1,0,0] を渡すということは e3 は回転して e1 になることを意味する。ここから、全ての点は90°回転し、 e2 に直交する。ラッパ関数と古い関数をコード参照として返す。
この関数は複数回利用することができる。このことは一度関数を回転すると、元の関数は効果的に再度ラップされて回転された関数を回転させることができる。しかしこのおうに再帰の替わりにパフォーマンスを犠牲にすることになる。
unrotate
邪悪なハック(the evil hack)を用いた回転の邪悪なハックを削除する。
オプションで引数として整数を取る。回転を(整数)レベル削除する。回転のレベル(Level of rotation)とは rotate() を用いてラップされた元の回数の回転ラッパを意味する。
整数が渡されなければデフォルトはこれまでの全回転となる。効果的に全回転を取り消すことができる。
削除されたラッパ(回転)の数を返す。
Steffen Mueller, mail at steffen-mueller dot net
Copyright (c) 2002-2003 Steffen Mueller. All rights reserved.
本プログラムはフリーソフトウェアであり、Perl 本体と同等の条件で修正/再配布してもよい。
![]() |
Updated : 2008/02/05 |