[ParaView]3Dポリゴン上の滑らかに繋がった面だけを抽出する

0．はじめに
------
今回はParaViewを使って以下のように、ポリゴン上から滑らかに繋がった領域だけを抽出するというのをやってみます。
![Threshold.png](https://qiita-image-store.s3.amazonaws.com/0/304390/028624ee-938c-ff69-8701-09637c451e3a.png)

1．フィルタのパイプライン
--------------
ParaViewの`[Filter] -> [Alphabetical]`から、以下の順番でポリゴンにフィルタをかけていきます。
![パイプライン.png](https://qiita-image-store.s3.amazonaws.com/0/304390/1afebc1e-ddd2-b20f-362b-2b3e20623971.png)

2．GenerateSurfaceNormalsでポリゴンの面を分割する
--------------
`GenerateSurfaceNormals`は、VTKの[vtkPolyDataNormals](https://vtk.org/doc/nightly/html/classvtkPolyDataNormals.html)というフィルタと同じ機能を持つものです。

このフィルタは、基本的にはポリゴンの節点/要素に法線ベクトルを定義するというものなのですが、内蔵フラグをONにすることで色々なことができます。
内蔵フラグは以下になります。

|内蔵フラグ       |機能                         |
|----------------|-------------------------------|
|Splitting              |`Feature Angle`で設定した角度(隣接する要素間のなす角度)で、つながった領域とそうでない領域を区別して分割する。           |
|Consistency            |法線の向きを整える。あべこべに法線が定義されているときなどに利用できる。            |
|Filp Normals           |全法線の向きを反転させる。|
|Non-Manifold Traversal |Non-ManifoldEdges(3つ以上の要素のエッジが重なったときにできる線分)を処理の対象に含める。|
|Conpute Cell Normals   |要素の法線ベクトルを求める。|
|Piece Invariant        |使用するプロセッサーの数に関係なく同じ結果とする。|

今回は、上記のフラグはデフォルト + `Conpute Cell Normals`をONにして、`Feature Angle`を設定した後に `[Apply]` を選択します。
<img width="678" alt="GenerateSurfaceNormals.png" src="https://qiita-image-store.s3.amazonaws.com/0/304390/474630ea-df80-3001-7ecb-8947e025bcca.png">

3．Connectivityで分割された面ごとにIDをつける
--------------
`Connectivity`は、VTKの[vtkConnectivityFilter](https://vtk.org/doc/nightly/html/classvtkConnectivityFilter.html)というフィルタと同じ機能を持つものです。

このフィルタは、重複節点のある点を境界として領域を区別して［要調査］、領域ごとに節点/要素単位で`RegionId`(整数)を振ってくれます。
<img width="678" alt="Connectivity.png" src="https://qiita-image-store.s3.amazonaws.com/0/304390/3d94ceaa-2aad-f12f-e774-72c0683d8595.png">

4．Thresholdで特定のIDがついたポリゴンのみ抽出する
--------------
`Threshold`は、VTKの[vtkThreshold](https://vtk.org/doc/nightly/html/classvtkThreshold.html)というフィルタと同じ機能を持つものです。

このフィルタを利用すると、設定した範囲の数値を持つ節点/要素のみを抽出することができます。今回はモデル上の`K`の面を抽出してみます。

まず、ビューアーの上の部分にある`[Select Cells On (s)]`を選択します。
<img width="678" alt="Threshold2.png" src="https://qiita-image-store.s3.amazonaws.com/0/304390/9abc762c-0d7d-fbd2-d925-39218c5ef6c2.png">
その後、モデル上の抽出したい部分の一部をドラッグすると下図のように要素を選択できるので、
その状態で`[Find data matching various criteria from the current source (v)]`を選択します。
<img width="678" alt="Threshold2_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/304390/ca68b2a3-06e9-ac6d-f723-f8893b8f918f.png">
すると、`Connectivity`で付与した`RegionId`がわかります。
<img width="349" alt="Threshold2_3.png" src="https://qiita-image-store.s3.amazonaws.com/0/304390/c3859def-352e-d8e8-6bf6-79ed0593ea62.png">
この値を`Threshold`の`[Minimum]`と`[Maximum]`に入力して`[Apply]`を選択すると、以下のように`K`の面だけ抽出できます。
<img width="678" alt="Threshold2_4.png" src="https://qiita-image-store.s3.amazonaws.com/0/304390/c27788d5-57d9-2c56-4be7-0f337c49624f.png">

5．他のポリゴンでもやってみる
--------------
曲率の大きい面が多いモデルでもちゃんと特定の面を抽出できます。
![うりぼー.png](https://qiita-image-store.s3.amazonaws.com/0/304390/95ce82d2-1178-23e9-ba96-9a00cd4e0a5a.png)

6．おわりに
------
3Dポリゴン上の滑らかに繋がった面だけを抽出するという処理をParaViewだけでやってみました。
ParaViewのフィルタは基本的にVTKで実装されているので、VTKライブラリを使ってC++やPythonなどでも同じ処理を記述できます。

また、今回の一連の作業はParaView上で`[Tools] -> [Start Trace / Stop Trace]`を利用すると、Pythonスクリプトにすることができるので、Pythonで同じことをしたいという方はそちらをご利用ください。

そのうち今回の方法で作った部分表面データと、[以前の記事](https://qiita.com/torisan_piyopiyo/items/9e98f6ffe7e914d24e3d)で紹介したソルバー間の連携に関しても書ければと思ってます。

参考文献
------
1. [ParaViewを極めたい。：Generate Surface Normals](http://www.paraview-expert.com/filters-generate-surface-normals/)
2. [メッシュWiki：法線ベクトルの生成](http://www.rccm.co.jp/icem/pukiwiki/index.php?%E6%B3%95%E7%B7%9A%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E3%81%AE%E7%94%9F%E6%88%90)