vtkClipPolyData/DataSetまとめ（随時更新）

# vtkClipPolyData/DataSetについて

ソースとなる形状を元に表示する形状の領域を制限する、`Clip`についてまとめていきます

`STL`のようにvertices,lines,triangleで形状を表現する場合は`vtkPolyData`
`OpenFOAM`のように非構造格子で表現する場合は、`vtkDataSet`という使いわけでしょうか、
まだ詳しくはわかっていません

### vtkClipPolyDataのclassリファレンス
https://vtk.org/doc/nightly/html/classvtkClipPolyData.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/88ff57ed-23c8-86c7-7f85-332aced7c27b.png)


### vtkClipDataSetのclassリファレンス
https://vtk.org/doc/nightly/html/classvtkClipDataSet.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/02c8edc8-a908-5495-80b9-28b5fb498800.png)



# paraviewで機能の確認


Clip機能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/2cd21159-6a68-c914-df78-7de1d6dba90c.png)


ClipTypeをPlaneにした場合は、原点(Origin)と法線(Normal)を指定した平面を用いて表示領域を制限する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/da8221ca-f978-1b60-a920-3557fde58d89.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/8830e760-eeea-23bf-ba84-887c5424052a.png)

Invertのチェックを切り替えることで、表示する領域を逆転させることができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/18726cc0-ff6b-f26e-5066-0fe506397dbf.png)

Crinkle clipを適用すると、平面に含まれるメッシュは元の形状を維持する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/cf7bb616-9ea7-2661-33d5-8a9c24ca0a19.png)


# pythonでの動作確認

### 環境
python 3.7
vtk 8.1.2
### ベースとなるコード(平面(plane)を用いてClipを行う例
)

``` python
import vtk

filename = "flange.stl"
reader = vtk.vtkSTLReader()
reader.SetFileName(filename)
reader.Update()

normal='y' # e.g. x,y,z,-x,-y,-z,X,Y,Z,-X,-Y,or -Z

NORMALS = {
    'x': [1, 0, 0],
    'y': [0, 1, 0],
    'z': [0, 0, 1],
    '-x': [-1, 0, 0],
    '-y': [0, -1, 0],
    '-z': [0, 0, -1],
}
normal = NORMALS[normal.lower()] # or e.g. [1.0/sqrt(2.0), 1.0/sqrt(2.0), 0]
origin = (0,0,0)
invert=True

plane = vtk.vtkPlane()
plane.SetNormal(normal)
plane.SetOrigin(origin)

alg = vtk.vtkClipPolyData()
alg.SetInputConnection(reader.GetOutputPort())

alg.SetClipFunction(plane)
alg.SetInsideOut(invert)
alg.Update()

# mapper
mapper = vtk.vtkCompositePolyDataMapper2()
mapper.SetInputConnection(alg.GetOutputPort()) #mapperにfilterを設定
mapper.SetScalarModeToUseCellFieldData() #scalarデータ用に設定

# actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)             #actorにmapperを設定
actor.GetProperty().EdgeVisibilityOn()

# renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)            #rendererにactorを設定

##背景色の設定
renderer.GradientBackgroundOn()      #グラデーション背景を設定
renderer.SetBackground2(0.2,0.4,0.6) #上面の色
renderer.SetBackground(1,1,1)        #下面の色

#Window
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(renderer)         #Windowにrendererを設定
iren = vtk.vtkRenderWindowInteractor();
iren.SetRenderWindow(renWin);
renWin.SetSize(850, 850)
renWin.Render()
iren.Start();
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/dfd2450d-ba9f-e8c1-9061-84df3a2619b2.png)


### SetClipFunction(vtkImplicitFunction e.g. vtkPlane)

`vtkPlane`などのClipのソースとなるオブジェクトをセットします

`vtkImplicitFunction`の継承先の一覧
https://vtk.org/doc/nightly/html/classvtkImplicitFunction.html

### SetInsideOut(boolean)

`Invert`の切り替えを行うメソッド

`InsideOutOn()` or `InsideOutOff()`でも設定可能

### 四角形(Cube)を用いてClipを行う例

`vtkBox`を用いて`BoundingBox`の座標を指定します
https://vtk.org/doc/nightly/html/classvtkBox.html

``` python

box = vtk.vtkBox()
box.SetXMin(0.0,-0.001,-0.01) # [xMin,yMin,zMin]
box.SetXMax(0.1,0.1,0.1)      # [xMax,yMax,zMax]

alg = vtk.vtkClipPolyData()
alg.SetInputConnection(reader.GetOutputPort())

alg.SetClipFunction(box)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/59f5fa4b-c591-f9e0-16a2-491eb6fa6b44.png)



# OpenFOAMの場合の例

`OpenFOAM`は非構造格子であることから`vtkClipDataSet`を用いる

``` python
import vtk

filename = "case1.foam"
reader = vtk.vtkOpenFOAMReader()
reader.SetFileName(filename)
reader.CreateCellToPointOn()
reader.DecomposePolyhedraOn()
reader.EnableAllCellArrays()
reader.Update()

n_step = reader.GetTimeValues().GetNumberOfValues()
latest_time = reader.GetTimeValues().GetValue(n_step-1)
reader.UpdateTimeStep(latest_time)
reader.Update()


normal='y' # e.g. x,y,z,-x,-y,-z,X,Y,Z,-X,-Y,or -Z

NORMALS = {
    'x': [1, 0, 0],
    'y': [0, 1, 0],
    'z': [0, 0, 1],
    '-x': [-1, 0, 0],
    '-y': [0, -1, 0],
    '-z': [0, 0, -1],
}

normal = NORMALS[normal.lower()] # or e.g. [1.0/sqrt(2.0), 1.0/sqrt(2.0), 0]

origin = (0,0,0)
invert=False

plane = vtk.vtkPlane()
plane.SetNormal(normal)
plane.SetOrigin(origin)

alg = vtk.vtkClipDataSet()
alg.SetInputConnection(reader.GetOutputPort())
alg.SetClipFunction(plane)
alg.SetInsideOut(invert)
alg.Update()

filter = vtk.vtkGeometryFilter()
filter.SetInputConnection(alg.GetOutputPort())
# filter.SetInputConnection(reader.GetOutputPort()) //clipOff時
filter.Update()

# mapper
mapper = vtk.vtkCompositePolyDataMapper2()
mapper.SetInputConnection(filter.GetOutputPort()) #mapperにfilterを設定
mapper.SetScalarModeToUseCellFieldData() #scalarデータ用に設定

# actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)             #actorにmapperを設定
actor.GetProperty().EdgeVisibilityOn()

# renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)            #rendererにactorを設定

##背景色の設定
renderer.GradientBackgroundOn()      #グラデーション背景を設定
renderer.SetBackground2(0.2,0.4,0.6) #上面の色
renderer.SetBackground(1,1,1)        #下面の色

#Window
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(renderer)         #Windowにrendererを設定
iren = vtk.vtkRenderWindowInteractor();
iren.SetRenderWindow(renWin);
renWin.SetSize(850, 850)
renWin.Render()
iren.Start();
```

Clip前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/41f439cf-1389-d4ea-ed06-209a08b8bd9e.png)


Clip後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132299/f4ff5090-74e8-1c9b-789d-25540997efb6.png)