6
8

More than 3 years have passed since last update.

Python VTKを使ってSTLをVoxelメッシュに変換する

Last updated at Posted at 2020-04-12

はじめに

STLのCADデータからを符号付距離関数(Signed Distance Function: SDF)を使ってVoxelメッシュ作成します。使ったライブラリはPythonのVTKです。なお、コードは全面的に以下の記事を参考にしました。

環境

Windows 10 home

Anaconda(Python 3.7.6)

VTK 8.2

Paraview 5.4.1(STLとvoxelメッシュの表示に利用)

CADデータ(STLデータ)

スタンフォードドラゴン。

stanford_dragon_original.png

ソースコード

import vtk

filename = "./dragon.stl"
#stlファイルを読む
reader = vtk.vtkSTLReader()
reader.SetFileName(filename)
reader.Update()

#Poly dataを取り出す
poly_data = reader.GetOutput()

#メッシュサイズを決める
cell_dims = [50, 50, 50]#x, y, z

#メッシュグリッドを作成する
#x_min:0 x_max:1, y_min:2,y_max:3,z_min:4,z_max:5
bounds = poly_data.GetBounds()
mesh_pitch = [(bounds[1] - bounds[0])/cell_dims[0],
              (bounds[3] - bounds[2])/cell_dims[1],
              (bounds[5] - bounds[4])/cell_dims[2]]
mins = [bounds[0], bounds[2], bounds[4]]

points = vtk.vtkPoints()
for ix in range(cell_dims[0]+1):
    for iy in range(cell_dims[1]+1):
        for iz in range(cell_dims[2]+1):
            x = ix * mesh_pitch[0] + mins[0]
            y = iy * mesh_pitch[1] + mins[1]
            z = iz * mesh_pitch[2] + mins[2]
            points.InsertNextPoint(x,y,z)
structured_base_mesh = vtk.vtkStructuredGrid()
structured_base_mesh.SetExtent(0, cell_dims[0], 0, cell_dims[1], 0, cell_dims[2])
structured_base_mesh.SetPoints(points)

#構造格子データを非構造格子データに変換する
append = vtk.vtkAppendFilter()
append.AddInputData(structured_base_mesh)
append.Update()
base_mesh = append.GetOutput()

#Voxelの中心を座標を求める
cell_centers = vtk.vtkCellCenters()
cell_centers.SetInputData(base_mesh)
cell_centers.Update()

#STLからVoxelメッシュを作成する 
center_points = cell_centers.GetOutput().GetPoints()
cell_list = vtk.vtkIdList()
sdf = vtk.vtkImplicitPolyDataDistance()
sdf.SetInput(poly_data)
distance_sdf = vtk.vtkDoubleArray()
distance_sdf.SetName("sdf")
for idx in range(center_points.GetNumberOfPoints()):
    current_center = center_points.GetPoint(idx)
    distance = sdf.FunctionValue(current_center)
    distance_sdf.InsertNextValue(distance)
    if distance <= 0:
        cell_list.InsertNextId(idx)

base_mesh.GetCellData().SetScalars(distance_sdf)#SDFの値を追加する

extract_cells = vtk.vtkExtractCells()
extract_cells.SetInputData(base_mesh)
extract_cells.SetCellList(cell_list)
extract_cells.Update()

#VoxelデータをVTKファイルで出力する
writer = vtk.vtkXMLDataSetWriter()
writer.SetFileName("closed_voxel.vtu")
writer.SetInputData(extract_cells.GetOutput())
writer.Update()

#SDFの値を入力した格子データをVTKファイルで出力する
#writer = vtk.vtkXMLDataSetWriter()
#writer.SetFileName("all_voxel.vtu")
#writer.SetInputData(base_mesh)
#writer.Update()

stanford_dragon_voxel.png

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8