Skip to content

Instantly share code, notes, and snippets.

@tfmoraes
Created February 21, 2023 01:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tfmoraes/9424cd0c2f37b887b9ac7d32c2b7b130 to your computer and use it in GitHub Desktop.
Save tfmoraes/9424cd0c2f37b887b9ac7d32c2b7b130 to your computer and use it in GitHub Desktop.
import sys
import vtk
colors = vtk.vtkNamedColors()
reader = vtk.vtkSTLReader()
reader.SetFileName(sys.argv[1])
reader.Update()
# Fill Holes
fillHoles = vtk.vtkFillHolesFilter()
fillHoles.SetInputConnection(reader.GetOutputPort())
fillHoles.SetHoleSize(1000.0)
# Make the triangle winding order consistent
normals = vtk.vtkPolyDataNormals()
normals.SetInputConnection(fillHoles.GetOutputPort())
normals.ConsistencyOn()
normals.SplittingOff()
normals.Update()
normals.GetOutput().GetPointData().SetNormals(
reader.GetOutput().GetPointData().GetNormals()
)
# How many added cells
numOriginalCells = reader.GetOutput().GetNumberOfCells()
numNewCells = normals.GetOutput().GetNumberOfCells()
numCells = 0
it = normals.GetOutput().NewCellIterator()
while not it.IsDoneWithTraversal() and numCells < numOriginalCells:
it.GoToNextCell()
numCells += 1
print(
f"Num original: {numOriginalCells}\nNum new: {numNewCells}\nNum added {numNewCells - numOriginalCells}"
)
holePolyData = vtk.vtkPolyData()
holePolyData.Allocate(normals.GetOutput(), numNewCells - numOriginalCells)
holePolyData.SetPoints(normals.GetOutput().GetPoints())
cell = vtk.vtkGenericCell()
# The remaining cells are the new ones from the hole filler
while not it.IsDoneWithTraversal():
it.GetCell(cell)
holePolyData.InsertNextCell(it.GetCellType(), cell.GetPointIds())
it.GoToNextCell()
# We have to use ConnectivtyFilter and not
# PolyDataConnectivityFilter since the later does not create
# RegionIds cell data.
connectivity = vtk.vtkConnectivityFilter()
connectivity.SetInputData(holePolyData)
connectivity.SetExtractionModeToAllRegions()
connectivity.ColorRegionsOn()
connectivity.Update()
print(f"Found {connectivity.GetNumberOfExtractedRegions()} holes")
# Visualize
# Create a mapper and actor for the fill polydata
filledMapper = vtk.vtkDataSetMapper()
filledMapper.SetInputConnection(connectivity.GetOutputPort())
filledMapper.SetScalarModeToUseCellData()
filledMapper.SetScalarRange(
connectivity.GetOutput().GetCellData().GetArray("RegionId").GetRange()
)
filledActor = vtk.vtkActor()
filledActor.SetMapper(filledMapper)
filledActor.GetProperty().SetDiffuseColor(list(colors.GetColor3d("Peacock")))
# Create a mapper and actor for the original polydata
originalMapper = vtk.vtkPolyDataMapper()
originalMapper.SetInputConnection(reader.GetOutputPort())
backfaceProp = vtk.vtkProperty()
backfaceProp.SetDiffuseColor(list(colors.GetColor3d("Banana")))
originalActor = vtk.vtkActor()
originalActor.SetMapper(originalMapper)
originalActor.SetBackfaceProperty(backfaceProp)
originalActor.GetProperty().SetDiffuseColor(list(colors.GetColor3d("Flesh")))
originalActor.GetProperty().SetRepresentationToWireframe()
# Create a renderer, render window, and interactor
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetSize(512, 512)
renderWindow.AddRenderer(renderer)
renderWindow.SetWindowName("IdentifyHoles")
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Add the actor to the scene
renderer.AddActor(originalActor)
renderer.AddActor(filledActor)
renderer.SetBackground(list(colors.GetColor3d("Burlywood")))
renderer.GetActiveCamera().SetPosition(0, -1, 0)
renderer.GetActiveCamera().SetFocalPoint(0, 0, 0)
renderer.GetActiveCamera().SetViewUp(0, 0, 1)
renderer.GetActiveCamera().Azimuth(60)
renderer.GetActiveCamera().Elevation(30)
renderer.ResetCamera()
# Render and interact
renderWindow.Render()
renderWindowInteractor.Start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment