TransformByメソッド
VLA オブジェクトの図形共通のメソッドで変換マトリックスを使用する vla-TransformBy メソッドがあります。このメソッドは、図形を変換マトリックスに従って変換します。これを使って、実際に変換マトリックスを使用してみます。
obj 引数は VLA オブジェクトを指定し、matrix 引数は変換マトリックスを表したセーフ配列を格納したバリアント型変数を指定します。この変換マトリックスの ActiveX 用の変換は vlax-tmatrix 関数で LISP のリストから直接できます。
座標を平行移動する変換マトリックスを使ってみます。
次の例は、選択した図形を WCS の XYZ 軸の方向を基準に、(10.0 20.0 30.0)だけ移動します。
(setq amatrix (translation-matrix '(10.0 20.0 30.0))) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix amatrix) ) )
座標を拡大縮小するスケールの変換マトリックスを使ってみます。
次の例は、選択した図形を WCS 原点を基準に XYZ 座標を 2 倍にします。
(setq amatrix (scale-matrix '(2.0 2.0 2.0))) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix amatrix) ) )
各軸を異なる縮尺でスケール変換することも理論上考えられますが、TransformBy メソッドは受け付けません。
先の例では WCS の原点を基準に拡大されました。次の例は、図形を選択した位置を基準に拡大することを考えます。平行移動の変換マトリックスを使用して選択点が相対的に WCS の原点になるよう図形を平行移動し、そこで拡大した後、再び元の位置に平行移動するという一連の操作を行う変換マトリックスを使用します。この操作で選択点は WCS 上での座標が必要なので trans 関数で entsel 関数で得られた UCS の座標から変換して使用します。
(setq amatrix (scale-matrix '(2.0 2.0 2.0))) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (setq point (trans (cadr selInfo) acUCS acWorld)) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix (matrix:Product-r (list (translation-matrix point) amatrix (translation-matrix (vector:Invert point)) ) ) ) ) )
上の例で「(translation-matrix (vector:Invert point))」を「(matrix:Inverse (translation-matrix point))」と書くこともできますが、逆行列を求める方法はより計算コストがかかります。matrix:Product-r 関数はリストにおさめられた変換マトリックスのすべての積をとる関数です。座標に対しては、リストの後ろの変換マトリックスの操作から順に作用します。
次は座標を回転する変換マトリックスを使ってみます。
次の例は、選択した図形を WCS 原点を通る WCS の X 軸を基準に 30 度回転します。
(setq amatrix (rotate-matrix:X-axis (/ PI 6))) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix amatrix) ) )
上の例では X 軸の回転だけでしたが、他の軸でも回転させたければ、その変換マトリックスの積をとります。次の変換マトリックスは、X 軸で回転させた後 Z 軸で 90 度回転させます。
(rotate-matrix:Z-axis (/ PI 2))
(rotate-matrix:X-axis (/ PI 6))
)
上の回転の例では WCS の原点を通る WCS の軸を中心とした回転でしたが、選択点を通る WCS の軸と平行な回転を行いたい場合、拡大縮小と同じく平行移動の変換マトリックスを使用して選択点が相対的に WCS の原点になるよう図形を平行移動し、そこで回転した後、再び元の位置に戻すという一連の操作を行う変換マトリックスを使用します。この操作で選択点は WCS 上での座標が必要なので trans 関数で entsel 関数で得られた UCS の座標から変換して使用します。
(setq amatrix (rotate-matrix:X-axis (/ PI 6))) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (setq point (trans (cadr selInfo) acUCS acWorld)) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix (matrix:Product-r (list (translation-matrix point) amatrix (translation-matrix (vector:Invert point)) ) ) ) ) )
各操作の基準点の変更は以上までで見たとおりですが、平行移動、回転、拡大縮小の操作はすべて WCS の軸の向きによったものでした。
任意の基準点に加えて任意の軸の向きを考える例として、UCS の場合を考えてみます。この場合は UCS の原点が相対的に WCS の原点になるように平行移動するのと同時に軸の方向もそろうように変換をしてから、拡大縮小や回転の操作を行って元の位置に戻します。最初の UCS の座標を WCS のそれに合うように変換するものが UCS を表す変換マトリックスの逆行列で、最後の元に戻す操作が UCS の変換マトリックスになります。なお、以降の実行例では、WCS とは異なる任意の位置、任意の軸の向きに UCS を変更して行ってください。
次の例は、選択した図形を UCS の XYZ 軸を基準に図形を (10.0 20.0 30.0) だけ平行移動します。
(setq amatrix (matrix:Product-r (list (UCS-Matrix) (translation-matrix '(10.0 20.0 30.0)) (matrix:Inverse (UCS-Matrix)) ) ) ) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix amatrix) ) )
次の例は、UCS の原点を基準に UCS のXYZ 軸方向に座標を 2 倍し、UCS の X 軸を中心に 30 度回転します。
(setq amatrix (matrix:Product-r (list (UCS-Matrix) (rotate-matrix:X-axis (/ PI 6)) (scale-matrix '(2.0 2.0 2.0)) (matrix:Inverse (UCS-Matrix)) ) ) ) (while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix amatrix) ) )
加えてさらに UCS の原点ではなく選択した点の座標が回転や拡大縮小の基準点となるように考えてみます。選択点を相対的に UCS の原点となるように平行移動させる操作と元に戻す操作を前後に加えます。この操作が入る位置に注意してください。順番が異なると、期待通りの変換となりません。今回の場合の選択点は、UCS 原点からの座標が必要なので、entsel 関数から得られた選択点の座標をそのまま使用します。
(while (setq selInfo (entsel "\n図形を選択(選択なしで終了)[最後(L)]:")) (setq point (cadr selInfo)) (vla-TransformBy (vlax-ename->VLA-object (car selInfo)) (vlax-tmatrix (matrix:Product-r (list (UCS-Matrix) (translation-matrix point) (rotate-matrix:X-axis (/ PI 6)) (scale-matrix '(2.0 2.0 2.0)) (translation-matrix (vector:Invert point)) (matrix:Inverse (UCS-Matrix)) ) ) ) ) )
最後の例になると、行列の積の順番を間違えないことが肝心であると言っている意味が実感していただけると思います。