[vtkusers] Solidify-Modifier for VTK

sebastian_a seb.an at icloud.com
Thu May 3 13:08:07 EDT 2018


Hello,

I created a Blender-like Solidify-Algorithm. Maybe it helps someone.

Unfortunately, also like the one in Blender, it has the following problem:
If the Solidification-Thickness to large (for example larger than half the
distance to an opponent face), it creates inside-out-errors.

Do you have any suggestions how to fix this nicely?

Thanks, Sebastian



import vtk
import numpy as np


solidificationThickness = 2

# polydataSource = vtk.vtkSTLReader()
# polydataSource.SetFileName("testmodel.stl")
# polydataSource.Update()

polydataSource = vtk.vtkSphereSource()
polydataSource.SetRadius(10)
polydataSource.SetThetaResolution(5)
polydataSource.SetPhiResolution(3)
polydataSource.Update()

# remove double vertices
cleanPolyData = vtk.vtkCleanPolyData()
cleanPolyData.SetInputData(polydataSource.GetOutput())
cleanPolyData.Update()

# create normals
normals = vtk.vtkPolyDataNormals()
normals.SetComputeCellNormals(1)
normals.SetInputData(cleanPolyData.GetOutput())
normals.SplittingOff()
normals.Update()

polydata = vtk.vtkPolyData()
polydata.DeepCopy(normals.GetOutput())
numberOfPoints = polydata.GetNumberOfPoints()
print polydata.GetNumberOfPoints()

# get boundary edges, used later
featureEdges = vtk.vtkFeatureEdges()
featureEdges.BoundaryEdgesOn()
featureEdges.ColoringOff()
featureEdges.FeatureEdgesOff()
featureEdges.NonManifoldEdgesOff()
featureEdges.ManifoldEdgesOff()
featureEdges.SetInputData(normals.GetOutput())
featureEdges.Update()

# check for intersection
cellLocator = vtk.vtkOBBTree()
cellLocator.SetDataSet(polydata)
cellLocator.BuildLocator()

addingPoints = []
addingPolys = []


for pointID in range(numberOfPoints):
  cellIDs = vtk.vtkIdList()
  polydata.GetPointCells(pointID, cellIDs)
  normalsArray = []

  
  # ilterate through all cells/faces which contain point
  for id in xrange(cellIDs.GetNumberOfIds()):
    # faceData = []
    n = []
   
n.append(polydata.GetCellData().GetArray('Normals').GetValue(cellIDs.GetId(id)*3))
   
n.append(polydata.GetCellData().GetArray('Normals').GetValue(cellIDs.GetId(id)*3
+ 1))
   
n.append(polydata.GetCellData().GetArray('Normals').GetValue(cellIDs.GetId(id)*3
+ 2))

    normalsArray.append(np.array(n) * (-1))

  # calculate position of new vert
  dir_vec = np.zeros(3)
  
  for n in normalsArray:
    dir_vec = dir_vec + np.array(n)

  dir_vec_norm = dir_vec / np.linalg.norm(dir_vec)
  proj_length = np.dot(dir_vec_norm, np.array(normalsArray[0]))
  dir_vec_finallenght = dir_vec_norm * proj_length
  vertex_neu = np.array(polydata.GetPoint(pointID)) + (dir_vec_finallenght *
solidificationThickness)

  addingPoints.append(vertex_neu)

for cellID in range(polydata.GetNumberOfCells()):
  pointIDs = vtk.vtkIdList()
  polydata.GetCellPoints(cellID, pointIDs)

  newPointIDs = vtk.vtkIdList()
  for i in reversed(range(pointIDs.GetNumberOfIds())):
    newPointIDs.InsertNextId(int(pointIDs.GetId(i) + numberOfPoints))

  addingPolys.append(newPointIDs)

doubleSurfacePoints = vtk.vtkPoints()
doubleSurfacePolys = vtk.vtkCellArray()

doubleSurfacePoints.DeepCopy(polydata.GetPoints())
doubleSurfacePolys.DeepCopy(polydata.GetPolys())

addedPoints = vtk.vtkPoints()

for p in addingPoints:
  doubleSurfacePoints.InsertNextPoint(p)
  addedPoints.InsertNextPoint(p)
for p in addingPolys:
  doubleSurfacePolys.InsertNextCell(p)

doubleSurfacePD = vtk.vtkPolyData()
doubleSurfacePD.SetPoints(doubleSurfacePoints)
doubleSurfacePD.SetPolys(doubleSurfacePolys)

# add faces to boundary edges
mergePoints = vtk.vtkMergePoints()
mergePoints.InitPointInsertion(doubleSurfacePD.GetPoints(),
doubleSurfacePD.GetBounds())
mergePoints.SetDataSet(doubleSurfacePD)
mergePoints.BuildLocator()

watertightPolys = vtk.vtkCellArray()
watertightPolys.DeepCopy(doubleSurfacePD.GetPolys())
watertightPoints = vtk.vtkPoints()
watertightPoints.DeepCopy(doubleSurfacePD.GetPoints())

for e in range(featureEdges.GetOutput().GetNumberOfCells()):
  pointIDs = vtk.vtkIdList()
  featureEdges.GetOutput().GetCellPoints(e, pointIDs)
  if pointIDs.GetNumberOfIds() == 2: # -> Edge
    matchingPointIDs = []
    newPointIDs = vtk.vtkIdList()
    for p in range(2):
     
matchingPointIDs.append(mergePoints.IsInsertedPoint(featureEdges.GetOutput().GetPoint(pointIDs.GetId(p))))
    if not (-1) in matchingPointIDs: # edge vertex not found in original pd,
should not happen
      newPointIDs.InsertNextId(matchingPointIDs[1])
      newPointIDs.InsertNextId(matchingPointIDs[0])
      newPointIDs.InsertNextId(matchingPointIDs[0]+numberOfPoints)
      newPointIDs.InsertNextId(matchingPointIDs[1]+numberOfPoints)
      watertightPolys.InsertNextCell(newPointIDs)

watertightPD = vtk.vtkPolyData()
watertightPD.SetPoints(watertightPoints)
watertightPD.SetPolys(watertightPolys)


# triangulate new connecting faces
triangleFilter = vtk.vtkTriangleFilter()
triangleFilter.SetInputData(watertightPD)
triangleFilter.Update()


# visualize
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(triangleFilter.GetOutput())
actor = vtk.vtkActor()
actor.GetProperty().SetEdgeVisibility(1)
actor.GetProperty().SetOpacity(0.5)
actor.GetProperty().BackfaceCullingOn()
#actor.GetProperty().SetRepresentationToWireframe()
actor.SetMapper(mapper)

camera = vtk.vtkCamera()
camera.SetPosition(1,1,1)
camera.SetFocalPoint(0,0,0)

renderer = vtk.vtkRenderer()
renWin   = vtk.vtkRenderWindow()
renWin.AddRenderer(renderer)

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

renderer.AddActor(actor)
renderer.SetActiveCamera(camera)
renderer.ResetCamera()
renderer.SetBackground(1,1,1)

renWin.SetSize(300,300)

renWin.Render()
iren.Start()



--
Sent from: http://vtk.1045678.n5.nabble.com/VTK-Users-f1224199.html


More information about the vtkusers mailing list