def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__( self, module_manager, vtk.vtkLinearSubdivisionFilter(), 'Processing.', ('vtkPolyData',), ('vtkPolyData',), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def __init__(self, grid, vtkish_polydata=None, angle=15): vtkPolyDataPipeline.__init__(self, vtkish_polydata) # Make sure grid argument is correct type assert isinstance(grid, vtkVolumeGrid) self.grid = grid # Split polys with intersection angles greater than angle vtk_dnorm = vtkPolyDataNormals() vtk_dnorm.SetFeatureAngle(angle) vtk_dnorm.SplittingOn() vtk_dnorm.ComputeCellNormalsOff() vtk_dnorm.ComputePointNormalsOff() self.append(vtk_dnorm) relax = self.grid.get_relaxation_factor() if relax is not None: print('relax=',relax) #vtk_subdiv = vtkButterflySubdivisionFilter() vtk_subdiv = vtkLinearSubdivisionFilter() self.append(vtk_subdiv) # Smooth out some of the sharp points. vtk_smooth = vtkSmoothPolyDataFilter() vtk_smooth.SetRelaxationFactor(relax) self.append(vtk_smooth)
def setUp(self): self.vtk_iso = vtkContourFilter() # self.vtk_iso.SetInput(...) self.vtk_dnorm = vtkPolyDataNormals() self.vtk_subdiv = vtkLinearSubdivisionFilter() self.vtk_dmap = vtkPolyDataMapper()
def Subdivide(self, nsub, subfilter='linear'): """ Increase the number of triangles in a single, connected triangular mesh. Uses one of the following vtk subdivision filters to subdivide a mesh. vtkButterflySubdivisionFilter vtkLoopSubdivisionFilter vtkLinearSubdivisionFilter Linear subdivision results in the fastest mesh subdivision, but it does not smooth mesh edges, but rather splits each triangle into 4 smaller triangles. Butterfly and loop subdivision perform smoothing when dividing, and may introduce artifacts into the mesh when dividing. Subdivision filter appears to fail for multiple part meshes. Should be one single mesh. Parameters ---------- nsub : int Number of subdivisions. Each subdivision creates 4 new triangles, so the number of resulting triangles is nface*4**nsub where nface is the current number of faces. subfilter : string, optional Can be one of the following: 'butterfly', 'loop', 'linear' Returns ------- mesh : Polydata object vtkInterface polydata object. Examples -------- >>> from vtkInterface import examples >>> import vtkInterface >>> mesh = vtkInterface.LoadMesh(examples.planefile) >>> submesh = mesh.Subdivide(1, 'loop') """ subfilter = subfilter.lower() if subfilter == 'linear': sfilter = vtk.vtkLinearSubdivisionFilter() elif subfilter == 'butterfly': sfilter = vtk.vtkButterflySubdivisionFilter() elif subfilter == 'loop': sfilter = vtk.vtkLoopSubdivisionFilter() else: raise Exception( "Subdivision filter must be one of the following: " + "'butterfly', 'loop', or 'linear'") # Subdivide sfilter.SetNumberOfSubdivisions(nsub) sfilter.SetInputData(self) sfilter.Update() return PolyData(sfilter.GetOutput())
def __init__(self, grid, vtkish_polydata=None, angle=15): vtkPolyDataPipeline.__init__(self, vtkish_polydata) # Make sure grid argument is correct type assert isinstance(grid, vtkVolumeGrid) self.grid = grid # Split polys with intersection angles greater than angle vtk_dnorm = vtkPolyDataNormals() vtk_dnorm.SetFeatureAngle(angle) vtk_dnorm.SplittingOn() vtk_dnorm.ComputeCellNormalsOff() vtk_dnorm.ComputePointNormalsOff() self.append(vtk_dnorm) relax = self.grid.get_relaxation_factor() if relax is not None: print 'relax=',relax #vtk_subdiv = vtkButterflySubdivisionFilter() vtk_subdiv = vtkLinearSubdivisionFilter() self.append(vtk_subdiv) # Smooth out some of the sharp points. vtk_smooth = vtkSmoothPolyDataFilter() vtk_smooth.SetRelaxationFactor(relax) self.append(vtk_smooth)
def subdivide(actor, N=1, method=0, legend=None): ''' Increase the number of points in actor surface N = number of subdivisions method = 0, Loop method = 1, Linear method = 2, Adaptive method = 3, Butterfly ''' triangles = vtk.vtkTriangleFilter() setInput(triangles, polydata(actor)) triangles.Update() originalMesh = triangles.GetOutput() if method == 0: sdf = vtk.vtkLoopSubdivisionFilter() elif method == 1: sdf = vtk.vtkLinearSubdivisionFilter() elif method == 2: sdf = vtk.vtkAdaptiveSubdivisionFilter() elif method == 3: sdf = vtk.vtkButterflySubdivisionFilter() else: colors.printc('Error in subdivide: unknown method.', 'r') exit(1) if method != 2: sdf.SetNumberOfSubdivisions(N) setInput(sdf, originalMesh) sdf.Update() out = sdf.GetOutput() if legend is None and hasattr(actor, 'legend'): legend = actor.legend sactor = makeActor(out, legend=legend) sactor.GetProperty().SetOpacity(actor.GetProperty().GetOpacity()) sactor.GetProperty().SetColor(actor.GetProperty().GetColor()) sactor.GetProperty().SetRepresentation( actor.GetProperty().GetRepresentation()) return sactor
def setUp(self): self.vtk_iso = vtkContourFilter() #self.vtk_iso.SetInput(...) self.vtk_dnorm = vtkPolyDataNormals() self.vtk_subdiv = vtkLinearSubdivisionFilter() self.vtk_dmap = vtkPolyDataMapper()
def subdivision(self, number_of_subdivisions=3): self.normals() subdivision = vtk.vtkLinearSubdivisionFilter() subdivision.SetNumberOfSubdivisions(number_of_subdivisions) subdivision.SetInputConnection(self.mesh.GetOutputPort()) subdivision.Update() self.mesh = subdivision self.visualize_mesh(True)
def __init__(self, module_manager): SimpleVTKClassModuleBase.__init__(self, module_manager, vtk.vtkLinearSubdivisionFilter(), 'Processing.', ('vtkPolyData', ), ('vtkPolyData', ), replaceDoc=True, inputFunctions=None, outputFunctions=None)
def upsample(inp): triangles = vtk.vtkTriangleFilter() triangles.SetInputData(inp) triangles.Update() subdivisionFilter = vtk.vtkLinearSubdivisionFilter() subdivisionFilter.SetInputData(triangles.GetOutput()) subdivisionFilter.SetNumberOfSubdivisions(2) subdivisionFilter.Update() return subdivisionFilter.GetOutput()
def prepareModel(self, polyData): ''' ''' # import the vmtk libraries try: import vtkvmtkComputationalGeometryPython as vtkvmtkComputationalGeometry import vtkvmtkMiscPython as vtkvmtkMisc except ImportError: logging.error("Unable to import the SlicerVmtk libraries") capDisplacement = 0.0 surfaceCleaner = vtk.vtkCleanPolyData() surfaceCleaner.SetInputData(polyData) surfaceCleaner.Update() surfaceTriangulator = vtk.vtkTriangleFilter() surfaceTriangulator.SetInputData(surfaceCleaner.GetOutput()) surfaceTriangulator.PassLinesOff() surfaceTriangulator.PassVertsOff() surfaceTriangulator.Update() # new steps for preparation to avoid problems because of slim models (f.e. at stenosis) subdiv = vtk.vtkLinearSubdivisionFilter() subdiv.SetInputData(surfaceTriangulator.GetOutput()) subdiv.SetNumberOfSubdivisions(1) subdiv.Update() smooth = vtk.vtkWindowedSincPolyDataFilter() smooth.SetInputData(subdiv.GetOutput()) smooth.SetNumberOfIterations(20) smooth.SetPassBand(0.1) smooth.SetBoundarySmoothing(1) smooth.Update() normals = vtk.vtkPolyDataNormals() normals.SetInputData(smooth.GetOutput()) normals.SetAutoOrientNormals(1) normals.SetFlipNormals(0) normals.SetConsistency(1) normals.SplittingOff() normals.Update() surfaceCapper = vtkvmtkComputationalGeometry.vtkvmtkCapPolyData() surfaceCapper.SetInputData(normals.GetOutput()) surfaceCapper.SetDisplacement(capDisplacement) surfaceCapper.SetInPlaneDisplacement(capDisplacement) surfaceCapper.Update() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy(surfaceCapper.GetOutput()) return outPolyData
def SubdivideMesh(mesh, nsub): """ Subdivides a VTK mesh """ if nsub > 3: subdivide = vtk.vtkLinearSubdivisionFilter() else: subdivide = vtk.vtkLoopSubdivisionFilter() # slower, but appears to be smoother subdivide.SetNumberOfSubdivisions(nsub) if vtk.vtkVersion().GetVTKMajorVersion() > 5: subdivide.SetInputData(mesh) else: subdivide.SetInput(mesh) subdivide.Update() return subdivide.GetOutput()
def SubdivideMesh(mesh, nsub): """ Subdivides a VTK mesh """ if nsub > 3: subdivide = vtk.vtkLinearSubdivisionFilter() else: subdivide = vtk.vtkLoopSubdivisionFilter( ) # slower, but appears to be smoother subdivide.SetNumberOfSubdivisions(nsub) if vtk.vtkVersion().GetVTKMajorVersion() > 5: subdivide.SetInputData(mesh) else: subdivide.SetInput(mesh) subdivide.Update() return subdivide.GetOutput()
def subdivision(poly, num, option='linear'): if option == 'linear': divide = vtk.vtkLinearSubdivisionFilter() elif option == 'loop': divide = vtk.vtkLoopSubdivisionFilter() elif option == 'butterfly': divide = vtk.vtkButterflySubdivisionFilter() else: print("subdivision option: linear, loop or butterfly") raise divide.SetInputData(poly) divide.SetNumberOfSubdivisions(num) divide.Update() return divide.GetOutput()
def GetCube(): surface = vtk.vtkCubeSource() # Triangulate triangulation = vtk.vtkTriangleFilter() triangulation.SetInputConnection(surface.GetOutputPort()) # Subdivide the triangles subdivide = vtk.vtkLinearSubdivisionFilter() subdivide.SetInputConnection(triangulation.GetOutputPort()) subdivide.SetNumberOfSubdivisions(3) # Now the tangents tangents = vtk.vtkPolyDataTangents() tangents.SetInputConnection(subdivide.GetOutputPort()) tangents.Update() return tangents.GetOutput()
def __init__(self, parent=None): super(VTKFrame, self).__init__(parent) self.vtkWidget = QVTKRenderWindowInteractor(self) vl = QtGui.QVBoxLayout(self) vl.addWidget(self.vtkWidget) vl.setContentsMargins(0, 0, 0, 0) self.iren = self.vtkWidget.GetRenderWindow().GetInteractor() # Create source sphereSource = vtk.vtkSphereSource() sphereSource.Update() originalMesh = sphereSource.GetOutput() numberOfViewports = 3 self.vtkWidget.GetRenderWindow().SetSize(200 * numberOfViewports, 200) numberOfSubdivisions = 2 for i in range(numberOfViewports): if i == 0: subdivisionFilter = vtk.vtkLinearSubdivisionFilter() elif i == 1: subdivisionFilter = vtk.vtkLoopSubdivisionFilter() else: subdivisionFilter = vtk.vtkButterflySubdivisionFilter() subdivisionFilter.SetNumberOfSubdivisions(numberOfSubdivisions) subdivisionFilter.SetInputConnection( originalMesh.GetProducerPort()) subdivisionFilter.Update() renderer = vtk.vtkRenderer() self.vtkWidget.GetRenderWindow().AddRenderer(renderer) renderer.SetViewport( float(i) / numberOfViewports, 0, (i + 1.0) / numberOfViewports, 1) # Create a mapper and actor mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(subdivisionFilter.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) renderer.AddActor(actor) renderer.ResetCamera() self._initialized = False
def subdivide_mesh(V, F, order): F2 = F.flatten() F2 = np.insert(F2, range(0, len(F2), 3), int(3), axis=0) vtk_mesh = createPolyData(V, F2) linear = vtk.vtkLinearSubdivisionFilter() linear.SetInputData(vtk_mesh) linear.SetNumberOfSubdivisions(order) linear.Update() subdivided_mesh = vtk.vtkPolyData() subdivided_mesh.ShallowCopy(linear.GetOutput()) VS = numpy_support.vtk_to_numpy(subdivided_mesh.GetPoints().GetData( )) #get vertices of the mesh as a numpy array FS = numpy_support.vtk_to_numpy(subdivided_mesh.GetPolys().GetData() ) #get faces of the mesh as a numpy array FS = np.delete(FS, slice(None, None, 4)) FS = FS.reshape(int(len(FS) / 3), 3) return VS, FS
def __init__(self, parent = None): super(VTKFrame, self).__init__(parent) self.vtkWidget = QVTKRenderWindowInteractor(self) vl = QtGui.QVBoxLayout(self) vl.addWidget(self.vtkWidget) vl.setContentsMargins(0, 0, 0, 0) self.iren = self.vtkWidget.GetRenderWindow().GetInteractor() # Create source sphereSource = vtk.vtkSphereSource() sphereSource.Update() originalMesh = sphereSource.GetOutput() numberOfViewports = 3 self.vtkWidget.GetRenderWindow().SetSize(200*numberOfViewports, 200) numberOfSubdivisions = 2 for i in range(numberOfViewports): if i == 0: subdivisionFilter = vtk.vtkLinearSubdivisionFilter() elif i == 1: subdivisionFilter = vtk.vtkLoopSubdivisionFilter() else: subdivisionFilter = vtk.vtkButterflySubdivisionFilter() subdivisionFilter.SetNumberOfSubdivisions(numberOfSubdivisions) subdivisionFilter.SetInputConnection(originalMesh.GetProducerPort()) subdivisionFilter.Update() renderer = vtk.vtkRenderer() self.vtkWidget.GetRenderWindow().AddRenderer(renderer) renderer.SetViewport(float(i)/numberOfViewports, 0, (i+1.0)/numberOfViewports, 1) # Create a mapper and actor mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(subdivisionFilter.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) renderer.AddActor(actor) renderer.ResetCamera() self._initialized = False
def Execute(self): if self.Surface == None: self.PrintError('Error: No input surface.') subdivisionFilter = None if self.Method == 'linear': subdivisionFilter = vtk.vtkLinearSubdivisionFilter() elif self.Method == 'butterfly': subdivisionFilter = vtk.vtkButterflySubdivisionFilter() elif self.Method == 'loop': subdivisionFilter = vtk.vtkLoopSubdivisionFilter() else: self.PrintError('Error: Unsupported subdivision method.') subdivisionFilter.SetInputData(self.Surface) subdivisionFilter.SetNumberOfSubdivisions(self.NumberOfSubdivisions) subdivisionFilter.Update() self.Surface = subdivisionFilter.GetOutput()
colorIt = vtk.vtkElevationFilter() colorIt.SetInputConnection(sphere.GetOutputPort()) colorIt.SetLowPoint(0, 0, -.5) colorIt.SetHighPoint(0, 0, .5) butterfly = vtk.vtkButterflySubdivisionFilter() butterfly.SetInputConnection(colorIt.GetOutputPort()) butterfly.SetNumberOfSubdivisions(3) lut = vtk.vtkLookupTable() lut.SetNumberOfColors(256) lut.Build() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(butterfly.GetOutputPort()) mapper.SetLookupTable(lut) actor = vtk.vtkActor() actor.SetMapper(mapper) linear = vtk.vtkLinearSubdivisionFilter() linear.SetInputConnection(colorIt.GetOutputPort()) linear.SetNumberOfSubdivisions(3) mapper2 = vtk.vtkPolyDataMapper() mapper2.SetInputConnection(linear.GetOutputPort()) mapper2.SetLookupTable(lut) actor2 = vtk.vtkActor() actor2.SetMapper(mapper2) mapper3 = vtk.vtkPolyDataMapper() mapper3.SetInputConnection(colorIt.GetOutputPort()) mapper3.SetLookupTable(lut) actor3 = vtk.vtkActor() actor3.SetMapper(mapper3) ren1 = vtk.vtkRenderer() ren2 = vtk.vtkRenderer() ren3 = vtk.vtkRenderer()
def Execute(self): if (self.Mesh == None): self.PrintError('Error: no Mesh.') if (self.Source == None): self.PrintError('Error: no Source surface.') if (self.FirstTimeStep == None or self.LastTimeStep == None or self.IntervalTimeStep == None): timesteps = self.Mesh.GetFieldData().GetArray("timesteps") if (timesteps == None): self.PrintError('Error: no Timesteps.') indexList = [] i = 0 while i < self.Mesh.GetFieldData().GetArray( "timesteps").GetNumberOfTuples(): indexList.append(int(timesteps.GetTuple(i)[0])) i += 1 firstTimeStep = indexList[0] else: indexList = list( range(self.FirstTimeStep, self.LastTimeStep + 1, self.IntervalTimeStep)) firstTimeStep = self.FirstTimeStep indexColumn = vtk.vtkIntArray() indexColumn.SetName("index") timeColumn = vtk.vtkDoubleArray() timeColumn.SetName("time") time = 0 timeStepsTable = vtk.vtkTable() timeStepsTable.AddColumn(indexColumn) timeStepsTable.AddColumn(timeColumn) for index in indexList: time += (1. / (len(indexList) - 1)) indexColumn.InsertNextValue(index) timeColumn.InsertNextValue(time) u = self.Source.GetPointData().GetArray("u") if u: v = self.Source.GetPointData().GetArray("v") w = self.Source.GetPointData().GetArray("w") else: u = self.Source.GetPointData().GetArray("u_" + str(firstTimeStep)) v = self.Source.GetPointData().GetArray("v_" + str(firstTimeStep)) w = self.Source.GetPointData().GetArray("w_" + str(firstTimeStep)) speed = vtk.vtkFloatArray() speed.SetNumberOfComponents(u.GetNumberOfComponents()) speed.SetNumberOfTuples(u.GetNumberOfTuples()) speed.SetName('speed') i = 0 while i < u.GetNumberOfTuples(): speed.InsertTuple1( i, vtk.vtkMath.Norm( (u.GetTuple(i)[0], v.GetTuple(i)[0], w.GetTuple(i)[0]))) i += 1 self.Source.GetPointData().AddArray(speed) if self.Subdivide: sd = vtk.vtkLinearSubdivisionFilter() sd.SetInputData(self.Source) sd.SetNumberOfSubdivisions(1) sd.Update() self.Source = sd.GetOutput() self.Source.GetPointData().SetActiveScalars('speed') cp = vtk.vtkClipPolyData() cp.SetInputData(self.Source) cp.GenerateClipScalarsOff() cp.SetValue(self.MinSpeed) cp.Update() self.Source = cp.GetOutput() tracer = vtkvmtk.vtkvmtkStaticTemporalStreamTracer() tracer.SetInputData(self.Mesh) tracer.SetIntegratorTypeToRungeKutta45() tracer.SetTimeStepsTable(timeStepsTable) tracer.SetSeedTime(self.SeedTime) tracer.SetMaximumPropagation(self.MaximumPropagation) tracer.SetInitialIntegrationStep(self.InitialIntegrationStep) tracer.SetMinimumIntegrationStep(self.MinimumIntegrationStep) tracer.SetMaximumIntegrationStep(self.MaximumIntegrationStep) tracer.SetMaximumNumberOfSteps(self.MaximumNumberOfSteps) if self.Vorticity: tracer.SetComputeVorticity(1) if self.IntegrationDirectionBoth: tracer.SetIntegrationDirectionToBoth() tracer.SetSourceData(self.Source) tracer.SetVelocityScale(self.VelocityScale) if self.VectorComponents: tracer.UseVectorComponentsOn() tracer.SetComponent0Prefix(self.Component0Prefix) tracer.SetComponent1Prefix(self.Component1Prefix) tracer.SetComponent2Prefix(self.Component2Prefix) if self.Periodic: tracer.PeriodicOn() tracer.Update() self.Traces = tracer.GetOutput()
def Execute(self): if (self.Mesh == None): self.PrintError('Error: no Mesh.') if (self.Source == None): self.PrintError('Error: no Source surface.') if (self.FirstTimeStep == None or self.LastTimeStep == None or self.IntervalTimeStep == None): timesteps = self.Mesh.GetFieldData().GetArray("timesteps") if (timesteps == None): self.PrintError('Error: no Timesteps.') indexList = [] i = 0 while i < self.Mesh.GetFieldData().GetArray("timesteps").GetNumberOfTuples(): indexList.append(int(timesteps.GetTuple(i)[0])) i+=1 firstTimeStep = indexList[0] else: indexList = range(self.FirstTimeStep,self.LastTimeStep+1,self.IntervalTimeStep) firstTimeStep = self.FirstTimeStep indexColumn = vtk.vtkIntArray() indexColumn.SetName("index") timeColumn = vtk.vtkDoubleArray() timeColumn.SetName("time") time = 0 timeStepsTable = vtk.vtkTable() timeStepsTable.AddColumn(indexColumn) timeStepsTable.AddColumn(timeColumn) for index in indexList: time+=(1./(len(indexList)-1)) indexColumn.InsertNextValue(index) timeColumn.InsertNextValue(time) u = self.Source.GetPointData().GetArray("u") if u: v = self.Source.GetPointData().GetArray("v") w = self.Source.GetPointData().GetArray("w") else: u = self.Source.GetPointData().GetArray("u_"+str(firstTimeStep)) v = self.Source.GetPointData().GetArray("v_"+str(firstTimeStep)) w = self.Source.GetPointData().GetArray("w_"+str(firstTimeStep)) speed = vtk.vtkFloatArray() speed.SetNumberOfComponents(u.GetNumberOfComponents()) speed.SetNumberOfTuples(u.GetNumberOfTuples()) speed.SetName('speed') i=0 while i<u.GetNumberOfTuples(): speed.InsertTuple1(i, vtk.vtkMath.Norm((u.GetTuple(i)[0],v.GetTuple(i)[0],w.GetTuple(i)[0]))) i+=1 self.Source.GetPointData().AddArray(speed) if self.Subdivide: sd = vtk.vtkLinearSubdivisionFilter() sd.SetInputData(self.Source) sd.SetNumberOfSubdivisions(1) sd.Update() self.Source = sd.GetOutput() self.Source.GetPointData().SetActiveScalars('speed') cp = vtk.vtkClipPolyData() cp.SetInputData(self.Source) cp.GenerateClipScalarsOff() cp.SetValue(self.MinSpeed) cp.Update() self.Source = cp.GetOutput() tracer = vtkvmtk.vtkvmtkStaticTemporalStreamTracer() tracer.SetInputData(self.Mesh) tracer.SetIntegratorTypeToRungeKutta45() tracer.SetTimeStepsTable(timeStepsTable) tracer.SetSeedTime(self.SeedTime) tracer.SetMaximumPropagation(self.MaximumPropagation) tracer.SetInitialIntegrationStep(self.InitialIntegrationStep) tracer.SetMinimumIntegrationStep(self.MinimumIntegrationStep) tracer.SetMaximumIntegrationStep(self.MaximumIntegrationStep) tracer.SetMaximumNumberOfSteps(self.MaximumNumberOfSteps) if self.Vorticity: tracer.SetComputeVorticity(1) if self.IntegrationDirectionBoth: tracer.SetIntegrationDirectionToBoth() tracer.SetSourceData(self.Source) tracer.SetVelocityScale(self.VelocityScale) if self.VectorComponents: tracer.UseVectorComponentsOn() tracer.SetComponent0Prefix(self.Component0Prefix) tracer.SetComponent1Prefix(self.Component1Prefix) tracer.SetComponent2Prefix(self.Component2Prefix) if self.Periodic: tracer.PeriodicOn() tracer.Update() self.Traces = tracer.GetOutput()
def CurvaturesDemo(self): def loadStl(fname): """Load the given STL file, and return a vtkPolyData object for it.""" reader = vtk.vtkSTLReader() reader.SetFileName(fname) reader.Update() polydata = reader.GetOutput() return polydata # Read data from stl filter stlFilename = sys.argv[1] reader = vtk.vtkSTLReader() reader.SetFileName(stlFilename) # polydata = loadStl(stlFilename) reader.Update() polydata = reader.GetOutput() print(type(polydata)) mapper = vtk.vtkPolyDataMapper() #if vtk.VTK_MAJOR_VERSION <= 5: # mapper.SetInput(reader.GetOutput()) #else: # mapper.SetInputConnection(reader.GetOutputPort()) #actor = vtk.vtkActor() #actor.SetMapper(mapper) # Create a rendering window and renderer #ren = vtk.vtkRenderer() #renWin = vtk.vtkRenderWindow() #renWin.AddRenderer(ren) # Create a renderwindowinteractor #iren = vtk.vtkRenderWindowInteractor() #iren.SetRenderWindow(renWin) # Assign actor to the renderer #ren.AddActor(actor) # Enable user interface interactor #iren.Initialize() #renWin.Render() #iren.Start() # We are going to handle two different sources. # The first source is a superquadric source. torus = vtk.vtkSuperquadricSource() torus.SetCenter(0.0, 0.0, 0.0) torus.SetScale(1.0, 1.0, 1.0) torus.SetPhiResolution(64) torus.SetThetaResolution(64) torus.SetThetaRoundness(1) torus.SetThickness(0.5) torus.SetSize(0.5) torus.SetToroidal(1) # Rotate the torus towards the observer (around the x-axis) torusT = vtk.vtkTransform() torusT.RotateX(55) torusTF = vtk.vtkTransformFilter() torusTF.SetInputConnection(torus.GetOutputPort()) torusTF.SetTransform(torusT) # The quadric is made of strips, so pass it through a triangle filter as # the curvature filter only operates on polys tri = vtk.vtkTriangleFilter() #tri.SetInputConnection(torusTF.GetOutputPort()) tri.SetInputConnection(reader.GetOutputPort()) # The quadric has nasty discontinuities from the way the edges are generated # so let's pass it though a CleanPolyDataFilter and merge any points which # are coincident, or very close smoother = vtk.vtkSmoothPolyDataFilter() smoother.SetInputConnection(tri.GetOutputPort()) smoother.SetNumberOfIterations(1000) #smoother.Set subdiv = vtk.vtkLinearSubdivisionFilter() subdiv.SetInputConnection(smoother.GetOutputPort()) subdiv.SetNumberOfSubdivisions(1) subdiv.Update() cleaner = vtk.vtkCleanPolyData() cleaner.SetInputConnection(subdiv.GetOutputPort()) cleaner.SetTolerance(0.005) #smoother = vtk.vtkSmoothPolyDataFilter() #smoother.SetInput(cleaner) #smoother.SetNumberOfIterations(100) # The next source will be a parametric function rh = vtk.vtkParametricRandomHills() rhFnSrc = vtk.vtkParametricFunctionSource() rhFnSrc.SetParametricFunction(rh) # Now we have the sources, lets put them into a list. sources = list() sources.append(cleaner) sources.append(cleaner) sources.append(rhFnSrc) sources.append(rhFnSrc) print(len(sources)) # Colour transfer function. ctf = vtk.vtkColorTransferFunction() ctf.SetColorSpaceToDiverging() ctf.AddRGBPoint(0.0, 0.230, 0.299, 0.754) ctf.AddRGBPoint(1.0, 0.706, 0.016, 0.150) cc = list() for i in range(256): cc.append(ctf.GetColor(float(i) / 255.0)) # Lookup table. lut = list() for idx in range(len(sources)): lut.append(vtk.vtkLookupTable()) lut[idx].SetNumberOfColors(256) for i, item in enumerate(cc): lut[idx].SetTableValue(i, item[0], item[1], item[2], 1.0) if idx == 0: lut[idx].SetRange(-10, 10) if idx == 1: lut[idx].SetRange(0, 4) if idx == 2: lut[idx].SetRange(-1, 1) if idx == 3: lut[idx].SetRange(-1, 1) lut[idx].Build() curvatures = list() for idx in range(len(sources)): curvatures.append(vtk.vtkCurvatures()) if idx % 2 == 0: curvatures[idx].SetCurvatureTypeToGaussian() else: curvatures[idx].SetCurvatureTypeToMean() print(curvatures[0].GetOutput()) renderers = list() mappers = list() actors = list() textmappers = list() textactors = list() # Create a common text property. textProperty = vtk.vtkTextProperty() textProperty.SetFontSize(10) textProperty.SetJustificationToCentered() names = [ 'Torus - Gaussian Curvature', 'Torus - Mean Curvature', 'Random Hills - Gaussian Curvature', 'Random Hills - Mean Curvature' ] # Link the pipeline together. for idx, item in enumerate(sources): sources[idx].Update() curvatures[idx].SetInputConnection(sources[idx].GetOutputPort()) mappers.append(vtk.vtkPolyDataMapper()) mappers[idx].SetInputConnection(curvatures[idx].GetOutputPort()) mappers[idx].SetLookupTable(lut[idx]) mappers[idx].SetUseLookupTableScalarRange(1) actors.append(vtk.vtkActor()) actors[idx].SetMapper(mappers[idx]) textmappers.append(vtk.vtkTextMapper()) textmappers[idx].SetInput(names[idx]) textmappers[idx].SetTextProperty(textProperty) textactors.append(vtk.vtkActor2D()) textactors[idx].SetMapper(textmappers[idx]) textactors[idx].SetPosition(150, 16) renderers.append(vtk.vtkRenderer()) # only first two elements corespond to the stl file. # print(len(curvatures)) print(curvatures[2].GetOutput()) # print(curvatures[0].GetOutput().getData()) import inspect print(inspect.getmembers(curvatures[0].GetOutput().GetPointData())) print(curvatures[0].GetOutput().GetPointData().GetScalars()) gridDimensions = 2 for idx in range(len(sources)): if idx < gridDimensions * gridDimensions: renderers.append(vtk.vtkRenderer) rendererSize = 300 # Create the RenderWindow # renderWindow = vtk.vtkRenderWindow() renderWindow.SetSize(rendererSize * gridDimensions, rendererSize * gridDimensions) # Add and position the renders to the render window. viewport = list() for row in range(gridDimensions): for col in range(gridDimensions): idx = row * gridDimensions + col viewport[:] = [] viewport.append( float(col) * rendererSize / (gridDimensions * rendererSize)) viewport.append( float(gridDimensions - (row + 1)) * rendererSize / (gridDimensions * rendererSize)) viewport.append( float(col + 1) * rendererSize / (gridDimensions * rendererSize)) viewport.append( float(gridDimensions - row) * rendererSize / (gridDimensions * rendererSize)) if idx > (len(sources) - 1): continue renderers[idx].SetViewport(viewport) renderWindow.AddRenderer(renderers[idx]) renderers[idx].AddActor(actors[idx]) renderers[idx].AddActor(textactors[idx]) renderers[idx].SetBackground(0.4, 0.3, 0.2) interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(renderWindow) renderWindow.Render() interactor.Start() print(curvatures[1].GetOutput())
def main(): def FlatInterpolation(): for actor in actors: actor.GetProperty().SetInterpolationToFlat() renWin.Render() def GouraudInterpolation(): for actor in actors: actor.GetProperty().SetInterpolationToGouraud() renWin.Render() sourceToUse, displayNormals, gouraudInterpolation, glyphPoints = GetProgramParameters( ) if sourceToUse in Sources().sources: src = Sources().sources[sourceToUse] else: print('The source {:s} is not available.'.format(sourceToUse)) print('Available sources are:\n', ', '.join(sorted(list(Sources().sources.keys())))) return src.Update() # The size of the render window. renWinXSize = 1200 renWinYSize = renWinXSize // 3 minRenWinDim = min(renWinXSize, renWinYSize) # [xMin, xMax, yMin, yMax, zMin, zMax] bounds = src.GetOutput().GetBounds() # Use this to scale the normal glyph. scaleFactor = min(map(lambda x, y: x - y, bounds[1::2], bounds[::2])) * 0.2 src.GetOutput().GetPointData().GetScalars().SetName("Elevation") scalarRange = src.GetOutput().GetScalarRange() butterfly = vtk.vtkButterflySubdivisionFilter() butterfly.SetInputConnection(src.GetOutputPort()) butterfly.SetNumberOfSubdivisions(3) butterfly.Update() linear = vtk.vtkLinearSubdivisionFilter() linear.SetInputConnection(src.GetOutputPort()) linear.SetNumberOfSubdivisions(3) linear.Update() lut = MakeLUT(scalarRange) actors = list() actors.append(MakeSurfaceActor(butterfly, scalarRange, lut)) actors.append(MakeSurfaceActor(linear, scalarRange, lut)) actors.append(MakeSurfaceActor(src, scalarRange, lut)) # Let's visualise the normals. glyphActors = list() if displayNormals: glyphActors.append( GlyphActor(butterfly, glyphPoints, scalarRange, scaleFactor, lut)) glyphActors.append( GlyphActor(linear, glyphPoints, scalarRange, scaleFactor, lut)) glyphActors.append( GlyphActor(src, glyphPoints, scalarRange, scaleFactor, lut)) labelActors = list() labelActors.append(MakeLabel('Butterfly Subdivision', minRenWinDim)) labelActors.append(MakeLabel('Linear Subdivision', minRenWinDim)) labelActors.append(MakeLabel('Original', minRenWinDim)) ren = list() ren.append(vtk.vtkRenderer()) ren.append(vtk.vtkRenderer()) ren.append(vtk.vtkRenderer()) ren[2].SetViewport(0, 0, 1.0 / 3.0, 1) # Original ren[1].SetViewport(1.0 / 3.0, 0, 2.0 / 3.0, 1) # Linear ren[0].SetViewport(2.0 / 3.0, 0, 1, 1) # Butterfly renWin = vtk.vtkRenderWindow() iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) # Orientation markers. om = list() # Make the imaging pipelines. for i in range(0, len(ren)): renWin.AddRenderer(ren[i]) ren[i].AddActor(actors[i]) ren[i].AddActor(labelActors[i]) ren[i].SetBackground(nc.GetColor3d('SlateGray')) if displayNormals: ren[i].AddActor(glyphActors[i]) om.append(MakeOrientationMarker(ren[i], iren)) if gouraudInterpolation: GouraudInterpolation() else: FlatInterpolation() renWin.SetSize(renWinXSize, renWinYSize) renWin.Render() # renWin.SetWindowName() needs to be called after renWin.Render() renWin.SetWindowName('Point Data Subdivision Example') iren.Initialize() # WritePNG(iren.GetRenderWindow().GetRenderers().GetFirstRenderer(), "TestPointDataSubdivision.png") iren.Start()
b = vtkboolPython.vtkPolyDataBooleanFilter() b.SetInputConnection(prev.GetOutputPort()) b.SetInputConnection(1, tf.GetOutputPort()) b.SetOperModeToUnion() b.DecPolysOff() return b cubeA = vtk.vtkCubeSource() cubeA.SetBounds(-16, 16, -8, 8, 0, 9.6) triA = vtk.vtkTriangleFilter() triA.SetInputConnection(cubeA.GetOutputPort()) subA = vtk.vtkLinearSubdivisionFilter() subA.SetInputConnection(triA.GetOutputPort()) subA.SetNumberOfSubdivisions(4) cubeB = vtk.vtkCubeSource() cubeB.SetBounds(-14.8, 14.8, -6.8, 6.8, 0, 8.6) triB = vtk.vtkTriangleFilter() triB.SetInputConnection(cubeB.GetOutputPort()) subB = vtk.vtkLinearSubdivisionFilter() subB.SetInputConnection(triB.GetOutputPort()) subB.SetNumberOfSubdivisions(4) boolA = vtkboolPython.vtkPolyDataBooleanFilter() boolA.SetInputConnection(subA.GetOutputPort())
colorIt = vtk.vtkElevationFilter() colorIt.SetInputConnection(sphere.GetOutputPort()) colorIt.SetLowPoint(0,0,-.5) colorIt.SetHighPoint(0,0,.5) butterfly = vtk.vtkButterflySubdivisionFilter() butterfly.SetInputConnection(colorIt.GetOutputPort()) butterfly.SetNumberOfSubdivisions(3) lut = vtk.vtkLookupTable() lut.SetNumberOfColors(256) lut.Build() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(butterfly.GetOutputPort()) mapper.SetLookupTable(lut) actor = vtk.vtkActor() actor.SetMapper(mapper) linear = vtk.vtkLinearSubdivisionFilter() linear.SetInputConnection(colorIt.GetOutputPort()) linear.SetNumberOfSubdivisions(3) mapper2 = vtk.vtkPolyDataMapper() mapper2.SetInputConnection(linear.GetOutputPort()) mapper2.SetLookupTable(lut) actor2 = vtk.vtkActor() actor2.SetMapper(mapper2) mapper3 = vtk.vtkPolyDataMapper() mapper3.SetInputConnection(colorIt.GetOutputPort()) mapper3.SetLookupTable(lut) actor3 = vtk.vtkActor() actor3.SetMapper(mapper3) ren1 = vtk.vtkRenderer() ren2 = vtk.vtkRenderer() ren3 = vtk.vtkRenderer()
def generate(self, target_reduction = 0.9994, num_subdivisions = 3, resize_factors = None, clipping_factor = 0.0): # Convert to VTI myArguments = 'vmtkimagereader -ifile ' + self.input_path my_pype = pypes.PypeRun(myArguments) vtk_image = my_pype.GetScriptObject('vmtkimagereader','0').Image # Size the image if needed if resize_factors is not None: reduction_filter = vtk.vtkImageResize() reduction_filter.SetInput(vtk_image) reduction_filter.SetMagnificationFactors(resize_factors[0], resize_factors[1], resize_factors[2]) reduction_filter.SetResizeMethodToMagnificationFactors() reduction_filter.Update() # Threshold threshold = vtk.vtkThreshold() if resize_factors is not None: threshold.SetInputConnection(reduction_filter.GetOutputPort()) else: threshold.SetInput(vtk_image) threshold.ThresholdByUpper(1.0) threshold.Update() # Convert to polydata surface = vtk.vtkGeometryFilter() surface.SetInputConnection(threshold.GetOutputPort()) surface.Update() # Triangulate triangle = vtk.vtkTriangleFilter() triangle.SetInputConnection(surface.GetOutputPort()) triangle.Update() # Decimate decimate = vtk.vtkDecimatePro() decimate.SetInputConnection(triangle.GetOutputPort()) decimate.SetTargetReduction(target_reduction) decimate.SetFeatureAngle(15.0) decimate.Update() # Do loop subdivision su = vtk.vtkLinearSubdivisionFilter() su.SetInputConnection(decimate.GetOutputPort()) su.SetNumberOfSubdivisions(num_subdivisions) su.Update() # Clip the boundaries, recommended to ensure straight inlets and outlets if clipping_factor > 0.0: bounds = su.GetOutput().GetBounds() width = bounds[1] - bounds[0] height = bounds[3] - bounds[2] print bounds[2], bounds[3], height p1 = vtk.vtkPlane() p1.SetOrigin(bounds[0] + clipping_factor*width, 0.0, 0) p1.SetNormal(1, 0, 0) p2 = vtk.vtkPlane() p2.SetOrigin(0.0, bounds[2] + clipping_factor*height, 0) p2.SetNormal(0, 1, 0) p3 = vtk.vtkPlane() p3.SetOrigin(bounds[1] - clipping_factor*width, 0.0, 0) p3.SetNormal(-1, 0, 0) p4 = vtk.vtkPlane() p4.SetOrigin(0.0, bounds[3] - clipping_factor*height, 0) p4.SetNormal(0, -1, 0) c1 = vtk.vtkClipPolyData() c1.SetInputConnection(su.GetOutputPort()) c1.SetClipFunction(p1) c1.SetValue(0.0) c2 = vtk.vtkClipPolyData() c2.SetInputConnection(c1.GetOutputPort()) c2.SetClipFunction(p2) c2.SetValue(0.0) # c3 = vtk.vtkClipPolyData() c3.SetInputConnection(c2.GetOutputPort()) c3.SetClipFunction(p3) c3.SetValue(0.0) c4 = vtk.vtkClipPolyData() c4.SetInputConnection(c3.GetOutputPort()) c4.SetClipFunction(p4) c4.SetValue(0.0) su = vtk.vtkGeometryFilter() su.SetInputConnection(c4.GetOutputPort()) su.Update() feature_edges = vtk.vtkFeatureEdges() feature_edges.SetInputConnection(su.GetOutputPort()) feature_edges.Update() clean = vtk.vtkCleanPolyData() clean.SetInputConnection(feature_edges.GetOutputPort()) clean.Update() triangle2 = vtk.vtkTriangleFilter() triangle2.SetInputConnection(clean.GetOutputPort()) triangle2.Update() self.surface = su.GetOutput() self.boundaries = triangle2.GetOutput() return su.GetOutput(), triangle2.GetOutput()
def generate_cylinder_surface(r=10.0, h=20.0, res=100, subdivisions=0, max_edge=0, max_area=0, decimate=0, verbose=False): """ Generates a cylinder surface with minimal number of triangular cells and two circular planes. Args: r (float, optional): cylinder radius (default 10.0) h (float, optional): cylinder high (default 20.0) res (int, optional): resolution (default 100) subdivisions (int, optional): if > 0 (default 0) vtkLinearSubdivi- sionFilter is applied with this number of subdivisions max_edge (float, optional): if > 0 (default 0) vtkAdaptiveSubdivi- sionFilter is applied with this maximal triangle edge length max_area (float, optional): if > 0 (default 0) vtkAdaptiveSubdivi- sionFilter is applied with this maximal triangle area decimate (float, optional): if > 0 (default) vtkDecimatePro is applied with this target reduction (< 1) verbose (boolean, optional): if True (default False), some extra information will be printed out Returns: a cylinder surface (vtk.vtkPolyData) """ print("Generating a cylinder with radius={}, height={} and " "resolution={}".format(r, h, res)) is_positive_number(r) is_positive_number(h) is_positive_number(res) cylinder = vtk.vtkCylinderSource() # the origin around which the cylinder should be centered cylinder.SetCenter(0, 0, 0) # the radius of the cylinder cylinder.SetRadius(r) # the high of the cylinder cylinder.SetHeight(h) # polygonal discretization cylinder.SetResolution(res) # The cylinder is made of strips, so pass it through a triangle filter # to get a triangle mesh tri = vtk.vtkTriangleFilter() tri.SetInputConnection(cylinder.GetOutputPort()) # The cylinder has nasty discontinuities from the way the edges are # generated, so pass it though a CleanPolyDataFilter to merge any # points which are coincident or very close cleaner = vtk.vtkCleanPolyData() cleaner.SetInputConnection(tri.GetOutputPort()) cleaner.SetTolerance(0.005) cleaner.Update() # Reverse normals cylinder_surface = reverse_sense_and_normals(cleaner.GetOutputPort()) # Might contain non-triangle cells after cleaning - remove them cylinder_surface = remove_non_triangle_cells(cylinder_surface) if verbose: print("{} points".format(cylinder_surface.GetNumberOfPoints())) print("{} triangles".format(cylinder_surface.GetNumberOfCells())) if subdivisions > 0: cylinder_linear = vtk.vtkLinearSubdivisionFilter() cylinder_linear.SetNumberOfSubdivisions(subdivisions) cylinder_linear.SetInputData(cylinder_surface) cylinder_linear.Update() cylinder_surface = cylinder_linear.GetOutput() if verbose: print("{} points after linear subdivision".format( cylinder_surface.GetNumberOfPoints())) print("{} triangles after linear subdivision".format( cylinder_surface.GetNumberOfCells())) if max_area > 0 or max_edge > 0: cylinder_adaptive = vtk.vtkAdaptiveSubdivisionFilter() cylinder_adaptive.SetMaximumEdgeLength(max_edge) cylinder_adaptive.SetMaximumTriangleArea(max_area) cylinder_adaptive.SetInputData(cylinder_surface) cylinder_adaptive.Update() cylinder_surface = cylinder_adaptive.GetOutput() if verbose: print("{} points after adaptive subdivision".format( cylinder_surface.GetNumberOfPoints())) print("{} triangles after adaptive subdivision".format( cylinder_surface.GetNumberOfCells())) if decimate > 0: cylinder_decimate = vtk.vtkDecimatePro() cylinder_decimate.SetInputData(cylinder_surface) cylinder_decimate.SetTargetReduction(decimate) cylinder_decimate.PreserveTopologyOn() cylinder_decimate.SplittingOn() cylinder_decimate.BoundaryVertexDeletionOn() cylinder_decimate.Update() cylinder_surface = cylinder_decimate.GetOutput() if verbose: print("{} points after decimation".format( cylinder_surface.GetNumberOfPoints())) print("{} triangles after decimation".format( cylinder_surface.GetNumberOfCells())) return cylinder_surface
ico = vtk.vtkPlatonicSolidSource() ico.SetSolidTypeToIcosahedron() #ico.SetSolidTypeToOctahedron() ico.Update() sphere = vtk.vtkSphereSource() # #dome_sphere.SetCenter(meristem_model.shape_model['dome_center']) sphere.SetRadius(1) sphere.SetThetaResolution(16) sphere.SetPhiResolution(16) sphere.Update() #subdivide = vtk.vtkLoopSubdivisionFilter() #subdivide = vtk.vtkButterflySubdivisionFilter() subdivide = vtk.vtkLinearSubdivisionFilter() subdivide.SetNumberOfSubdivisions(2) subdivide.SetInputConnection(sphere.GetOutputPort()) #subdivide.SetInputConnection(ico.GetOutputPort()) subdivide.Update() decimate = vtk.vtkQuadricClustering() decimate.SetInput(subdivide.GetOutput()) decimate.SetNumberOfDivisions(100,100,100) decimate.SetFeaturePointsAngle(30.0) decimate.CopyCellDataOn() decimate.Update() scale_transform = vtk.vtkTransform() scale_factor = dome_radius/(np.sqrt(2)/2.) scale_transform.Scale(scale_factor,scale_factor,scale_factor)
b = vtkboolPython.vtkPolyDataBooleanFilter() b.SetInputConnection(prev.GetOutputPort()) b.SetInputConnection(1, tf.GetOutputPort()) b.SetOperModeToUnion() return b cubeA = vtk.vtkCubeSource() cubeA.SetBounds(-16, 16, -8, 8, 0, 9.6) triA = vtk.vtkTriangleFilter() triA.SetInputConnection(cubeA.GetOutputPort()) subA = vtk.vtkLinearSubdivisionFilter() subA.SetInputConnection(triA.GetOutputPort()) subA.SetNumberOfSubdivisions(4) cubeB = vtk.vtkCubeSource() cubeB.SetBounds(-14.8, 14.8, -6.8, 6.8, 0, 8.6) triB = vtk.vtkTriangleFilter() triB.SetInputConnection(cubeB.GetOutputPort()) subB = vtk.vtkLinearSubdivisionFilter() subB.SetInputConnection(triB.GetOutputPort()) subB.SetNumberOfSubdivisions(4) boolA = vtkboolPython.vtkPolyDataBooleanFilter() boolA.SetInputConnection(subA.GetOutputPort())
def generate_cone(r, h, res, subdivisions=0, decimate=0.0, smoothing_iterations=0, verbose=False): """ Generates a cone surface with a given base radius and height using VTK. The resulting surface can be smooth if subdivisions, decimate and smoothing options are used. Args: r (int): cone base radius h (int): cone height res (int): resolution subdivisions (int, optional): if > 0 (default 0) vtkLinearSubdivi- sionFilter is applied with this number of subdivisions decimate (float, optional): if > 0 (default 0) vtkDecimatePro is applied with this target reduction (< 1) smoothing_iterations (int, optional): if > 0 (default 0) vtkWindowedSincPolyDataFilter is applied with this number of smoothing iterations verbose (boolean, optional): if True (default False), some extra information will be printed out Returns: a cone surface (vtk.vtkPolyData) """ if verbose: print("Generating a cone surface...") cone = vtk.vtkConeSource() cone.SetRadius(r) cone.SetHeight(h) cone.SetResolution(res) cone.Update() cone_surface = cone.GetOutput() if verbose: print("{} points".format(cone_surface.GetNumberOfPoints())) print("{} triangles".format(cone_surface.GetNumberOfCells())) if subdivisions > 0: cone_linear = vtk.vtkLinearSubdivisionFilter() cone_linear.SetNumberOfSubdivisions(subdivisions) cone_linear.SetInputData(cone_surface) cone_linear.Update() cone_surface = cone_linear.GetOutput() if verbose: print("{} points after subdivision".format( cone_surface.GetNumberOfPoints())) print("{} triangles after subdivision".format( cone_surface.GetNumberOfCells())) if decimate > 0: cone_decimate = vtk.vtkDecimatePro() cone_decimate.SetInputData(cone_surface) cone_decimate.SetTargetReduction(decimate) cone_decimate.PreserveTopologyOn() cone_decimate.SplittingOn() cone_decimate.BoundaryVertexDeletionOn() cone_decimate.Update() cone_surface = cone_decimate.GetOutput() if verbose: print("{} points after decimation".format( cone_surface.GetNumberOfPoints())) print("{} triangles after decimation".format( cone_surface.GetNumberOfCells())) if smoothing_iterations > 0: cone_smooth = vtk.vtkWindowedSincPolyDataFilter() cone_smooth.SetInputData(cone_surface) cone_smooth.SetNumberOfIterations(smoothing_iterations) cone_smooth.BoundarySmoothingOn() cone_smooth.FeatureEdgeSmoothingOn() cone_smooth.SetFeatureAngle(90.0) cone_smooth.SetPassBand(0.1) # the lower the more smoothing cone_smooth.NonManifoldSmoothingOn() cone_smooth.NormalizeCoordinatesOn() cone_smooth.Update() cone_surface = cone_smooth.GetOutput() if verbose: print("{} points after smoothing".format( cone_surface.GetNumberOfPoints())) print("{} triangles after smoothing".format( cone_surface.GetNumberOfCells())) return cone_surface