Chandler@Berlin -8ページ目

Chandler@Berlin

ベルリン在住

前回の python コードは,単純な三角形メッシュを作成し,データをセットしていた.このメッシュには一枚の四角形があるだけであまり面白いものではないが,例としては十分であろう.シーンを下から見た様子を画像に示しておく.



ここではどうやって TriMesh の3つのメンバに C++ でアクセスするのかということになる.Python のオブジェクトのメンバは attribute であり,これにアクセスする一般的な方法も考えられる.しかし,それは複雑なので,ここではC++側がpython の class に関して知識があるとしよう.そうすると,この例では3つのメ
ンバにアクセスすることになる.

- self.__material_name
       string, しかし private なメンバであり,get_material_name() を使ってアクセスする
- self.vertex_list
       float (実は numpy.float64) の長さ 3 の numpy.array の list である.
- self.face_idx_list
       int (実は numpy.int64) の長さ 3 の numpy.array の list である.


subsection self.__material_name|へのアクセス方法

self.__material_name へのアクセス方法.TriMesh のオブジェクトはpytrimesh として渡されるとする.

std::string const matname = extract< std::string >(pytrimesh.attr("get_material_name")());

ここでは boost::python::object のメンバ attr を使ってメンバ関数を得,そのoperator() を使って python の string を得る.コードの最後にある () に注意して欲しい.

    pytrimesh.attr("get_material_name")

ではなく,

    pytrimesh.attr("get_material_name")()

である.

しかし object のoperator() はやはり object を返すため, extract を使ってC++ の std::stringに object を返す.これは python の build-in の objectが返ってくるので比較的簡単であった.

ここで2つ注意しておこう.

- 存在しない attribute にアクセスすると AttributeError exception が発生する.例えば以下のコードはその例である.

boost::python::object const vlist = pytrimesh.attr("vertex_list_non_exist");

- private のメンバにはアクセスすることができない.したがって以下の方法は失敗する.
   std::string const matname = extract< std::string >(pytrimesh.attr("__material_name"));

次回は numpy.array の list を C++ に渡す方法である.


以前,http://shitohichiumaya.blogspot.com/2010/08/boostpython-how-to-pass-python-object.htmlにて, python の dict や list,つまり python の buildin の class のobject を C++ のコードに渡すという話をした.


今回は user の作った python の class の object を渡すということをしてみよう.また,numpy.array の numpy.int64 を extract< int > しようとすると起こる TypeError (TypeError: No registered converter was able to produce aC++ rvalue of type int from this Python object of type numpy.int64())をどうやって避けたら良いかについて述べよう.

まずは python 側のコードである.

Ameba ではコードを正しく表示できないので,コードに関してはこちらの記事をご覧下さい.

---python code ---

このコードは単純な三次元の三角形メッシュのクラスを定義している.各三角形の頂点は 3つの float値を持つ numpy.array を使って表現されており,面は 頂点の index を使って表現されている. index が 1 から始まっているのは,wavefront obj ファイルという三次元の形状を定義するファイルと同じ構成のためである.また,メッシュは material の名前を private なメンバに持っている.この TriMesh の object にアクセスするための boost.python C++ コードは以下である.

---Code C++ ---

コンパイル方法は以下の通り.もちろん python boost が install されていることが前提だ.

---sh-script---

この python code を走らせると,結果は以下のようになる.
@[34]bash % python test_passobj2_mod.py
triangle mesh info
# materialname = diffuse_material
# vertices = 4
# faces = 2

trimesh.get_material_name() = diffuse_material
--- vertex_list ---
len(numpy_list_obj) = 4
float[3] = 552.8 0 0
float[3] = 0 0 0
float[3] = 0 0 559.2
float[3] = 549.6 0 559.2
--- face_idx_list ---
len(numpy_list_obj) = 2
int[3] = 1 2 3
int[3] = 1 3 4

C++ の出力が python で入力したものと一致することがわかる.今回はコードを示した,次回からは少し詳し内容を見ていこう.
今年は heartbreak で明けた.行列には固有値を全て掛けるとそれはdeterminant になるという性質がある.(固有値の和は trace である.この二つの性質は驚きである.) これは行列の対角化を使った驚くほど簡単で素敵な証明があるので紹介しよう.

行列 A は
$Chandler@Berlin-eq01
と対角化できる.まあ,これがそうなのだというまでの道程がちょっと長く,それがこの証明を簡潔にしているということがあると思うが,これを認めてもらえるとしよう.この行列式をとると,
Chandler@Berlin-eq02
ところで,
Chandler@Berlin-eq03
である.なぜなら,
Chandler@Berlin-eq04

であるからだ.すると, determinant はスカラ値であるから,交換可能で,
Chandler@Berlin-eq05
なんと簡単な証明だろうか.しかし一つ注意しないといけないのは,$S^{-1}$が存在する時のみこの証明は正しいことである.だから完全な証明ではないが,それでも私はこの簡潔さが好きだ.

参考文献
* Gilbert Strang, Introduction to Linear Algebra, Chapter 6.