[vtkusers] Solidify-Modifier for VTK

Andras Lasso lasso at queensu.ca
Thu May 3 22:22:50 EDT 2018


Yes, if you extrude in surface normal direction then there is a high chance that you will have self-intersecting faces. If you need a solution that guarantees accurate thickness and never generates self-intersecting faces, then you can compute a distance map using vtkImplicitModeller and create a surface from it using vtkContourFilter. Of course, computation time and memory need may be magnitudes higher than simple linear extrusion if you need highly accurate output.

By the way, it seems that your code does something very similar to vtkLinearExtrusionFilter. You might be able to simply use vtkLinearExtrusionFilter as is, or with an optional pre-shrinking step using vtkWarpVector (if you want to center the shell around the original surface).

Andras

-----Original Message-----
From: vtkusers <vtkusers-bounces at vtk.org> On Behalf Of sebastian_a
Sent: Thursday, May 3, 2018 1:08 PM
To: vtkusers at vtk.org
Subject: [vtkusers] Solidify-Modifier for VTK

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: https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fvtk.1045678.n5.nabble.com%2FVTK-Users-f1224199.html&data=02%7C01%7Classo%40queensu.ca%7C7ade740d2ac14ede567708d5b11873d7%7Cd61ecb3b38b142d582c4efb2838b925c%7C1%7C0%7C636609640949708331&sdata=vRH7ArAVsdhBuCbV4y0q5Mrwjpy67kt4lP31CcyAt3I%3D&reserved=0
_______________________________________________
Powered by https://na01.safelinks.protection.outlook.com/?url=www.kitware.com&data=02%7C01%7Classo%40queensu.ca%7C7ade740d2ac14ede567708d5b11873d7%7Cd61ecb3b38b142d582c4efb2838b925c%7C1%7C0%7C636609640949708331&sdata=uIJtEXHJ8hM6aVa2LvtwxcLH72mpiIY8o7EIj7sPKUQ%3D&reserved=0

Visit other Kitware open-source projects at https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.kitware.com%2Fopensource%2Fopensource.html&data=02%7C01%7Classo%40queensu.ca%7C7ade740d2ac14ede567708d5b11873d7%7Cd61ecb3b38b142d582c4efb2838b925c%7C1%7C0%7C636609640949708331&sdata=81ZsUqp2OK267v2r0Fi4ojqZSclsuUCC4Ncx5YIi2SA%3D&reserved=0

Please keep messages on-topic and check the VTK FAQ at: https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.vtk.org%2FWiki%2FVTK_FAQ&data=02%7C01%7Classo%40queensu.ca%7C7ade740d2ac14ede567708d5b11873d7%7Cd61ecb3b38b142d582c4efb2838b925c%7C1%7C0%7C636609640949708331&sdata=8Lw8%2BW41hXqOpKz2nFdotPXd12n%2BOnjMs4vqH2UulhE%3D&reserved=0

Search the list archives at: https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmarkmail.org%2Fsearch%2F%3Fq%3Dvtkusers&data=02%7C01%7Classo%40queensu.ca%7C7ade740d2ac14ede567708d5b11873d7%7Cd61ecb3b38b142d582c4efb2838b925c%7C1%7C0%7C636609640949708331&sdata=uGL6MPhkkxNkm%2BIhENhvUihWTzlwlSoGKWLweUe1Jtg%3D&reserved=0

Follow this link to subscribe/unsubscribe:
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fvtk.org%2Fmailman%2Flistinfo%2Fvtkusers&data=02%7C01%7Classo%40queensu.ca%7C7ade740d2ac14ede567708d5b11873d7%7Cd61ecb3b38b142d582c4efb2838b925c%7C1%7C0%7C636609640949708331&sdata=MZNBfIJS0tZbEVQvawfnAQbhMhrEApMmfgnxWDbOIzY%3D&reserved=0


More information about the vtkusers mailing list