5

scipy.spatial.Delaunay 関数を使用して、Python の Matlab delaunayn 関数によって実行される N 次元 Delaunay 三角形分割を複製しようとしています。ただし、Matlab 関数は私が望んで期待する結果をもたらしますが、scipy は別の結果をもたらします。どちらも QHull ライブラリのラッパーであることを考えると、これは奇妙だと思います。Matlab は、その呼び出しで暗黙的にさまざまなパラメーターを設定していると思います。私がそれらの 2 つの間で再現しようとしている状況は、Matlab のドキュメントにあります。

セットアップは、以下のように中心にポイントを持つ立方体を持つことです。形状を視覚化するために提供した青い線ですが、この問題には何の目的も意味もありません。

中心に点がある立方体

この結果から予想される三角形分割は、12 個のシンプリス (Matlab の例にリストされています) になり、次のようになります。

Matlab の三角測量

ただし、この python に相当するものは「余分な」単純化を生成します。

x = np.array([[-1,-1,-1],[-1,-1,1],[-1,1,-1],[1,-1,-1],[1,1,1],[1,1,-1],[1,-1,1],[-1,1,1],[0,0,0]])
simp = scipy.spatial.Delaunay(x).simplices

返される変数simpは、M x N 配列である必要があります。ここで、M は見つかったシンプレックスの数 (私の場合は 12 である必要があります) であり、N はシンプレックス内のポイントの数です。この場合、各シンプレックスは N が 4 であることを意味する四面体である必要があります。

私が見つけたのは、M が実際には 18 であり、余分な 6 つのシンプリックスは四面体ではなく、立方体の 6 つの面であるということです。

何が起きてる?返されるシンプリックスを四面体のみに制限するにはどうすればよいですか? この単純なケースを使用して問題を示したので、この問題に合わせていないソリューションが必要です。

編集

Amro の回答のおかげで、これを理解することができ、Matlab と Scipy の間で簡単に一致させることができました。これには 2 つの要因がありました。まず、指摘したように、Matlab と Scipy は異なる QHull オプションを使用します。次に、QHull はボリュームがゼロのシンプリスを返します。Matlab はこれらを削除しますが、Scipy は削除しません。上記の例では、6 つの余分なシンプリスがすべて立方体のゼロ ボリュームの同一平面上にあるため、これは明らかです。これらは、次のコードを使用して、N 次元で削除できます。

N = 3 # The dimensions of our points
options = 'Qt Qbb Qc' if N <= 3 else 'Qt Qbb Qc Qx' # Set the QHull options
tri = scipy.spatial.Delaunay(points, qhull_options = options).simplices
keep = np.ones(len(tri), dtype = bool)
for i, t in enumerate(tri):
    if abs(np.linalg.det(np.hstack((points[t], np.ones([1,N+1]).T)))) < 1E-15:
        keep[i] = False # Point is coplanar, we don't want to keep it
tri = tri[keep]

他の条件に対処する必要があると思いますが、ポイントには既に重複が含まれていないことが保証されており、方向条件は識別できる出力に影響を与えていないようです.

4

1 に答える 1

3

MATLAB と SciPy 関数を比較したいくつかのメモ:

  • MATLAB docs によると、デフォルトで Qt Qbb Qc3 次元入力に Qhull オプションを使用しますが、SciPy Qt Qbb Qc Qz.

  • 問題があるかどうかはわかりませんが、NumPy 配列はndgridMATLAB で作成されたポイントと同じ順序ではありません。

実際、 の MATLAB コードを見ると、次のedit delaunayn.m3 つの追加ステップが実行されていることがわかります。

  • 最初に重複したポイントをマージmergeDuplicatePointsします(これはあなたの場合の問題ではありません)
  • 次に、ポイントの向きの規則を適用します(コードを参照)
  • 最後に、Qhull (MEX 関数として実装qhullmx) から結果を取得した後、数行のコードの上に次のコメントがあります。

    縮退の存在によって作成された可能性のあるゼロ ボリューム シンプリスを取り除きます。

このファイルは著作権で保護されているため、ここにはコードを掲載しませんが、各自で確認してください。

于 2016-04-13T17:39:36.373 に答える