まずはVTKをインストールします。
CMake本家HP
の "Download" のページからソースまたはコンパイル済バイナリを
ダウンロードしましょう
ソースをダウンロードした方は展開してコンパイル、インストールしましょ
う
VTK本家HP の "Get The Software" のページで "Download the official release (4.2)" をクリックし、
両方展開した後、VTKディレクトリに入りましょう。 以下のコマンドを実行します。
%cmake .
エラーが無いことを確認し、以下を実行します。
%ccmake .
矢印の↑/↓ボタンで各項目に移動し、Enter を押して変更します。
あとはコンパイルします。 以下を実行して終わるまでコーヒーでも飲んで待ちましょう。
%make
無事終わればあとはインストールです。 もしエラーが出てコンパイルに失敗した人は エラーメッセージを見て頑張って修正しましょう。
%su - #make install
無事インストール完了です。
サンプルを動かして遊びましょう("Example" ディレクトリにあります)。
%cmake . %makeで実行ファイルができるので、それを実行してください。
%vtkpython hoge.py
%vtk hoge.tcl
VTK については以下が役に立つと思います。
次にRuby-VTKをインストールします。
現在 cygwin にはインストールできません。
VTK が "g++" の "-m win32" オプション付でコンパイルされるのに対し、
cygwin official の ruby がおそらく 上記オプションなしでコンパイルされて
いることが原因と考えられます。
Ruby-VTK HP
から "ruby-vtk-{version}.tar.gz" をダウンロードします。
展開後、 "ruby-vtk-{version}" ディレクトリに入ります。
以下を実行してください。
%ruby extconf.rb %make %su - #make install
エラー無く終われば無事インストール完了です。
エラーがでた場合は、
あなたの環境(OS, C++コンパイラ, rubyバージョン)と
エラーメッセージを作者に報告してください。
サンプルを試しましょう。 "sample" ディレクトリにいくつかサンプルがあります。
では実際に Ruby-VTK を使ってみましょう。 使用するためには
require "vtk"
とします。 ロード時間が気になる方は必要なコンポーネントだけロードすることもできます (vtk/Common, vtk/Filtering, vtk/Graphics, vtk/IO, vtk/Imaging, vtk/Rendering, vtk/Patented, vtk/Parallel, vtk/Hybrid)。
とりあえず VTK の バージョンでも調べてみましょう
%irb -r vtk irb(main):001:0> Vtk::VTK_VERSION => "4.2.6"
あなたがインストールした VTK のバージョンが表示されたはずです。
VTK のクラスの名前は "vtkObject" のように 小文字の vtk が先頭についています。
Ruby-VTK ではすべてのクラスが Vtkモジュールの下に定義されています。
それぞれのクラスは "Vtk::Object" のように
VTK のクラス名の先頭の vtk を除いた名前となります。
いくつか例外があります。
VTK には、
"vtk3DS vtk3DSImporter, vtk3DWidget"
といったクラスがあります。
Ruby のクラス名(定数) は一文字目に数字をとることができませんので
"Vtk::3DS" といった名前にはできません。
したがってこれらは
"Vtk::H3DS, Vtk::H3DSImporter, VTK::H3DWidget"
というようになります。
ちなみに、"H" はこれらが所属する "Hybrid" の "H" です。
VTK では、クラス作成に "New()" 関数を呼びます。 Ruby-Vtk では、他のクラスと同様に "new" クラスメソッドを呼びます。
ren = Vtk::Renderer.new
VTK では、使い終わったら "Delete()" メソッドを呼んであげる必要があります。 Ruby-Vtk では、GCが面倒を見てくれるのでそのような操作は必要ありません。
メソッド名は VTKのメソッドの名前そのままです。
例えば、VTK で
vtkPoints *points vtkPoints::New(); points->InsertNextPoint(1,2,3);
は、Ruby-VTK では
points = Vtk::Points.new points.InsertNextPoint(1,2,3)
となります。
Ruby-VTK オリジナルの機能が "vtk/Misc" です。 現在 "NArray" から "vtkArray" への変換が用意されています。
nary = NArray.byte(100).indgen vary = nary.to_va # => Vtk::CharArray nary = NArray.sint(100).indgen vary = nary.to_va # => Vtk::ShortArray nary = NArray.int(100).indgen vary = nary.to_va # => Vtk::IntArray or Vtk::LongArray nary = NArray.sfloat(100).indgen vary = nary.to_va # => Vtk::FloatArray nary = NArray.float(100).indgen vary = nary.to_va # => Vtk::DoubleArray
では実際にNetCDFファイルデータを使って、
等値面を描く例を見てみましょう。
使用する ソースコード および データファイル はこちらです。
water.rb,water.nc
ソースコードを順番に見ていきましょう。
require "numru/gphys" require "vtk" include Vtk include NumRu p "open" fname = "water.nc" vname = "Cloud_water_content" gphys = GPhys::IO.open(fname,vname) shape = gphys.shape val = gphys.val x = gphys.coord(0).val y = gphys.coord(1).val yfact = (x.max-x.min)/(y.max-y.min) z = gphys.coord(2).val zfact = (x.max-x.min)/(z.max-z.min) x = x.to_va y = y.to_va z = z.to_va f = val.reshape!(shape[0]*shape[1]*shape[2]).to_va
まずは "GPhys" を用いて "NetCDF" ファイルからデータを読み出し、 "NArray" にし、 その後 "Vtk::Array" に変換しています。
data = RectilinearGrid.new data.SetDimensions(*shape) data.SetXCoordinates(x) data.SetYCoordinates(y) data.SetZCoordinates(z) data.GetPointData.SetScalars(f)
ここから VTK の本番です。 "Vtk::RectilinearGrid" という格子点データ(不等間隔も許す)を作って、 先ほどのデータを入れています。
surface = ContourFilter.new surface.SetInput(data) surface.SetValue(0,0.0007)
0.0007の値の等値面を作ります。 データを変換する際はこのように "Filter" を利用します。
mapper = PolyDataMapper.new mapper.SetInput(surface.GetOutput) mapper.SetScalarModeToUsePointFieldData actor = Actor.new actor.SetMapper(mapper) actor.GetProperty.SetOpacity(0.5) actor.SetScale(1,yfact,zfact)
"Mapper", "Actor" は "Filter" を実際に表示するためのデータに変換します。 "SetOpacity" は透明度を設定しています。 "SetScale" は軸のスケールの設定です。
outline = RectilinearGridOutlineFilter.new outline.SetInput(data) mapper_ol = PolyDataMapper.new mapper_ol.SetInput(outline.GetOutput) actor_ol = Actor.new actor_ol.SetMapper(mapper_ol) actor_ol.SetScale(1,yfact,zfact)
アウトラインを作っています。
#axes bounds = data.GetBounds length = data.GetLength axes = Axes.new axes.SetOrigin(bounds[0],bounds[2],bounds[4]) axes.SetScaleFactor(length*0.8) tube_ax = TubeFilter.new tube_ax.SetInput(axes.GetOutput) tube_ax.SetRadius(length/50) tube_ax.SetNumberOfSides(6) mapper_ax = PolyDataMapper.new mapper_ax.SetInput(tube_ax.GetOutput) actor_ax = Actor.new actor_ax.SetMapper(mapper_ax)
軸を作っています。
# graphics stuff renderer = Renderer.new renWin = RenderWindow.new renWin.AddRenderer(renderer) iren = RenderWindowInteractor.new iren.SetRenderWindow(renWin) # read data //set up renderer renderer.AddActor(actor_ax) renderer.AddActor(actor_ol) renderer.AddActor(actor) renderer.SetBackground(1,1,1) renWin.SetSize(500,500) renderer.SetBackground(0.1, 0.2, 0.4) # interact with data iren.Initialize renWin.Render iren.Start
実際に描画するウィンドウや、 マウスやキーボードの操作(おまかせ)を設定しています。
実際に実行してみましょう。 このデータは赤道域の雲水量のデータです。 なんだか雲らしいものが見えますね。
マウスの左ボタンでカメラの回転、 中ボタンでカメラの平行移動、 右ボタンでズームです。 キーボードの "q" で終了します。
スクリーンショット先ほどの例で異なる値の等値面を見たい場合は、 ソースコードを書き換える必要があります。 なにかマウスでボタンをスライドさせて インターラクティブにその値を自由に変えてみたい、 なんて欲がでてきます。
VTKは比較的簡単に他のGUIツールと組み合わせることができます。 GTKを使う場合、 いくつかインストールする必要があります。
では次の rubyコードを実行してみましょう。
surface.rb
%ruby surface.rb water.nc Cloud_water_content
下にスライドがありますね。 動かしてみましょう。 等値面が変わるのが分かります。
スクリーンショット
同様に X,Y,Z面で切った断面をインターラクティブに動かす例です。
plane.rb
%ruby plane.rb water.nc Cloud_water_contentスクリーンショット