MarchingCubes.png

MarchingCubes.zip @ Delphi XE7 Update1

 

 

マーチングキューブ法を用いて、ボリュームデータの等値面をポリゴンモデルとして抽出します。

マーチングキューブ法 - Wikipedia

代表的な応用例としては、医療で用いられる 臓器の3D可視化 などが上げられます。人体の断層画像を積層した空間的な密度データから、特定の臓器の境界面を抽出しているわけですね。

当サンプルでは、単純な スカラー値:Single の3次元配列としてボリュームデータを与えた上で、指定した閾値を結ぶ曲面を生成します。最終的なポリゴンの構造を考えずに濃度分布だけで形状が作れるので、非常に柔軟なモデリング手法としても役立ちます。

実装は以下を参考にしました。

Polygonising a scalar field (Marching Cubes)

 

アルゴリズムとしては、まず空間を格子状に区切り、ボリュームデータをそれぞれの格子点上で離散的に定義します。そして境界面の濃度を決めると、各格子点は物体の内外に二分されます。

Polygonising a scalar field (Marching Cubes)

そこで各格子区画(ボクセル)別に見てみると、8つの角のぞれぞれが物体の内外に位置するので、すべての組み合わせは 2^8 = 256 通りあります。そして物体の境界面は、内側の格子点と外側の格子点の間にあることは明白です。すると対称性などして、以下の15通りのポリゴンパターンに整理できます。

 MarchingCubes.png

図1: 15個の基本となる立体図形 @ マーチングキューブ法 - Wikipedia

 

 細かい実装の話は別にして、今回は TISOModel というクラスにまとめました。TISOModel は FMX クラスなので、TViewport3D 配下に 3Dオブジェクト として組み入れることができます。使い方としては、とりあえずインスタンスを生成。

     _Model :TISOModel;

_Model := TISOModel.Create( Self );
     with _Model do
     begin
          Parent         := Viewport3D1;
          MaterialSource := LightMaterialSource1;
          DivX           := 100;  // X軸方向の分割数
          DivY           := 100;  // Y軸方向の分割数
DivZ := 100;  // Z軸方向の分割数
Width := 5; Height := 5; Depth := 5; Threshold := 0.5;  //等値面の濃度値 end;

その後、格子点のスカラー値である TISOModel.Volume[ X,Y,Z ] プロパティに値を入れていく。 なお補間処理の関係上、余白の格子点が一列必要となるので、インデックス範囲は [ -1..分割数+1 ] となる。 

procedure TForm1.MakeVolume;
var
   X, Y, Z :Integer;
begin
     with _Model do
     begin
          for Z := 0-1 to 100+1 do
          begin
               for Y := 0-1 to 100+1 do
               begin
                    for X := 0-1 to 100+1 do
                    begin
                         Volume[ X, Y, Z ] := ~;
                    end;
               end;
          end;
     end;
end;
_Model.MakeModel;    //ポリゴンモデルの生成

そしてボリューム上の濃度を設定した上で、TISOModel.MakeModel メソッドを呼び出し、ポリゴンモデルを生成させる。