Created
February 21, 2023 01:26
-
-
Save tfmoraes/9424cd0c2f37b887b9ac7d32c2b7b130 to your computer and use it in GitHub Desktop.
Python version of CXX IdentifyHoles (https://kitware.github.io/vtk-examples/site/Cxx/Meshes/IdentifyHoles/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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