2017年03月28日

modo10.2v1のスクリプトについて調べてみた その70

引き続き「TD SDK」について調べてみたい。

今回は「modo.mathutils」モジュールについて調べてみたい。

まずは「Matrix3」クラス。これは3X3の行列を扱うクラスだ。初期化メソッド「__init__()」は以下のようになっていて、引数として「なし」、「lx.object.Unknown」、「lx.object.Matrix」、「Matrix4」、「Matrix3」、「tuple」、「list」がとれるようになっている。

 class Matrix3(object):
    """Matrix3 class """

    def __init__(self, other=None):
        """Initializes a Matrix object

        :param other: Copies from other Matrix3 (optional)
        :type other: Matrix3
        returns: Matrix3
        """

        self.m = []
        self.size = 3

        self.setIdentity()
        if other:
            # TODO: look into removing redundant conversion
            if isinstance(other, lx.object.Unknown):
                inmat = lx.object.Matrix(other)
                self.set(inmat.Get3())
            if isinstance(other, lx.object.Matrix):
                self.set(other.Get3())
            if isinstance(other, Matrix4):
                for row in range(3):
                    for column in range(3):
                        self.m[row][column] = other[row][column]
            else:
                self.set(other)
                
    @staticmethod
    def _getIdentity(size=None):

        mat = []
        size = 3 if size is None else size

        for row in range(size):
            r = [0.0 for i in range(size)]
            r[row] = 1.0
            mat.append(r)
        return mat
               
    def set(self, other, transpose=True):
        """Copy values from other Matrix

        :param Matrix other: Source Matrix
        """
        if isinstance(other, Matrix3):
            self.m = [list(row[:]) for row in other.m]
        elif isinstance(other, (tuple, list)):
            # Input is a 3x3 matrix
            if len(other[0]) == 3:
                self.m = [list(row[:]) for row in other]
            # Input is a 4x4 matrix
            else:
                self.m = [list(row[:]) for row in other]

引数なしでインスタンスを作った場合は3X3の単位行列が生成される。

from modo.mathutils import *

m = Matrix3()
print m

# Result: 
Matrix3([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])

| 1 0 0 |
| 0 1 0 |
| 0 0 1 |

ここで使われている「_getIdentity(n)」はクラスメソッドでnXnの単位行列が生成できる。引数なしなら3X3の単位行列が生成される。

from modo.mathutils import *

print Matrix3._getIdentity(5)

# Result: 
Matrix3([[1.0, 0.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 0.0, 1.0]])

「lx.object.Unknown」はCOMの基本インターフェースで渡ってくる場合で「value」値がmodoから渡される時かな。渡されたオブジェクトは「lx.object.Matrix」インターフェースを持っているものとしてラッピングされて、「Get3()」メソッドを使って3X3の値が取り出されて「self.m」に2次元のリストとしてセットされる。

「Matrix4」の時は3X3の部分だけがコピーされて残りの1行は捨てられる。

四則演算のオーバーライドは「*」乗算のみのようで、しかもMatrix3どうしの乗算のみがサポートされているようだ。下のプログラムを見るとなんでmatrixTmpとmatrixResultを作ったかよくわからないけど、この乗算でオペランドのマトリクスが変化する事は無いようだ。

 def __mul__(self, other):
     """
     Multiply with other matrix
        
     :param other: Matrix to multiply with
     :type other: Matrix3
        
     """
     matrixTmp, matrixResult = self.__class__(), self.__class__()

     for i in range(self.size):
         for j in range(self.size):
             matrixTmp.m[i][j] = 0.0

     for i in range(self.size):
         for j in range(self.size):
             for k in range(self.size):
                 matrixTmp.m[i][j] += self.m[i][k] * other.m[k][j]

     for i in range(self.size):
         for j in range(self.size):
             matrixResult.m[i][j] = matrixTmp.m[i][j]

     return matrixResult

このモジュールには「Vector3」クラスと言う3次元ベクトルを扱うクラスもあるけど、これを変換する行列は「Matrix4」クラスの方で行うようで、「Matrix3」で変換したい場合は一度「Matrix4」に直してから行う必要があるようだ。

from modo.mathutils import *
m = Matrix3([[1.0,4.0,1.0],[4.0,3.0,6.0],[1.0,2.0,1.0]])
m4 = Matrix4(m)
v = Vector3([1,2,3])
v.mulByMatrixAsPoint(m4)
print v

# Result: 
Vector3(12.000000, 16.000000, 16.000000)

つづきはまた次回。

modo10ブログ目次



take_z_ultima at 11:30│Comments(0)TrackBack(0)modo | CG

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 

Archives