Visualization Tool Kit(VTK)など

本稿で扱う行列は右手座標系である.

座標変換基礎

検索エンジンからローカルやらワールドやら左やら右やらでやってくる訪問者が少なからずいる.
あまりにも多いので最後に Appendix として記載していた本節を冒頭に移動させることにした.

変換行列はA座標系におけるB座標系の位置・姿勢を表す同次変換行列であり,T_A_Bなどと表記する.一般的にAは左上や右上に,Bは右下に表記する.
T_A_C = T_A_B T_B_C
のようにA→B→Cと座標系を変換していくことが可能である.

さて,T_A_Bは座標系Aから座標系Bへの変換行列であるが,ここに座標系Bにおける点P_Bをかける.
P_A = T_A_B P_B
すなわち点P_Bは座標系Bから座標系Aへと変換されることになる.

ローカル・グローバル変換

実際に回転行列を右掛け・左掛けしてみれば自ずと答えは得られるのだが,なぜ手で確かめようとしないのか甚だ疑問である.
少なくともそれが自力でできないのであれば3Dプログラミングやロボット制御などできるわけがないのだが.

m * rotZ(a) = [3,3]( (m11 cos(a), - m12 sin(a), m13),(m21 sin(a), m22 cos(a), m23), (m31, m32, m33) )

以上の結果から,mのZ軸(m13, m23, m33)は変化が無いことがわかる.
すなわち,ローカルのZ軸回りに回転したことは明らかである.
同様に二次元の同次変換行列に対して左から平行移動をかけてみると

trans(tx,ty) * m = [3,3]( (m11, m12, tx),(m21, m22, ty),(0,0,1) )

となる.明らかにそのままグローバル座標系でtx,tyだけ平行移動しているわけだから,左掛けはグローバルになる.

Web上での検索するより,手でこの程度の計算をしたほうがはるかに早く確証のある答えが得られる.
こんなレビューも何も無い個人的なメモを勝手に脳内にコピー&ペーストしてわかったつもりになるのが最も手に負えない.
なぜ左・右でグローバルやローカルになるのか3分かけて式を展開すれば自明であることに数十分もWeb検索に時間をかけて,
正しいかどうかもわからない記述を見ていったい何がわかるというのか.少なくとも勉強・調査はウェブサーフィンをすることではない.
理解せずに脳内にコピー&ペーストして左手系に対してそのまま使い間違ってると文句を言ってくる輩までいるから困る.

vtkTransformおよびvtkProp3Dにおける座標変換

vtkの3Dオブジェクトの基本クラスはvtkProp3Dである。内部ではvtkTransformを使いオブジェクトの移動,回転,スケーリングを行っている.

vtkTransform::PostMultiply: M = A * M, 既存の行列が右掛けされる

この関数の命名については少し誤解を生じやすいと思うが,代入する行列が後ろ(右)に掛けられるのではなく,現在のTransformがPostMultiplyされる.

 vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
  transform->PostMultiply();
  transform->Translate(10.0, 0.0, 0.0);
  transform->RotateZ(40.0);

この場合は、T = RotZ(40.0) TransZ(10) という座標変換になる.オブジェクトをZ軸回りに回転し、X'軸(回転後のX軸)方向に平行移動する。

 vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
  transform->PostMultiply();
  transform->RotateZ(40.0);
  transform->Translate(10.0, 0.0, 0.0);

変換行列は T = TransZ(10) RotZ(40.0) となり、平行移動後、ローカルのZ軸周りに回転する。(グローバルのX軸上で周る)
すなわち、PostMultiplyを指定して代入していった場合は「グローバル軸における変換」をすることになります。

Prop3D::MatrixとProp3D::UserMatrix

ではProp3D内部ではどのように計算されいるのか。
Prop3DはMatrixとUserMatrixの二種類の行列と、Position, Orientation, Origin, Scaleといったパラメータをもつ。
vtkProp3D::ComputeMatrix()にこれらのパラメータを使った計算のルーチンがある。

    this->GetOrientation();
    this->Transform->Push();
    this->Transform->Identity();
    this->Transform->PostMultiply();

    // shift back to actor's origin
    this->Transform->Translate(-this->Origin[0], -this->Origin[1], -this->Origin[2]);

    // scale
    this->Transform->Scale(this->Scale[0], this->Scale[1], this->Scale[2]);

    // rotate
    this->Transform->RotateY(this->Orientation[1]);
    this->Transform->RotateX(this->Orientation[0]);
    this->Transform->RotateZ(this->Orientation[2]);

    // move back from origin and translate
    this->Transform->Translate(this->Origin[0] + this->Position[0], this->Origin[1] + this->Position[1], this->Origin[2] + this->Position[2]); 

    // apply user defined transform last if there is one
    if (this->UserTransform)
      {
      this->Transform->Concatenate(this->UserTransform->GetMatrix());
      }

    this->Transform->PreMultiply();
    this->Transform->GetMatrix(this->Matrix);
    this->MatrixMTime.Modified();
    this->Transform->Pop();

よって、

Matrix = UserMatrix Trans(pos) Trans(origin) RotZ RotX RotY Scale Trans(-origin)

という順序で計算している。また、Prop3D::MatrixにはUserMatrixも含まれている。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

メニュー

チュートリアル

アルゴリズム(数学)

並列計算

STL

#include<memory> #include<string> #include<sstream> #include<algorithm> #include<functional> #include<numeric>

Media Foundation

【メニュー編集】
Wiki記法ガイド

メンバーのみ編集できます