Search code examples
pythonvtkevenly

I want to make evenly distributed sphere in vtk (python)


As you can see in title, I want to make evenly distributed sphere in vtk (python)

First, I saw this link " Evenly distributing n points on a sphere " which is a method to create evenly distributed sphere. Through that link, I got the x,y,z coordinates of evenly distributed sphere.

Secondly, That is not actually a problem what I have to solve. The problem is even though I have x,y,z coordinates of evenly distributed sphere, I can't make a polydata at vtk(python)..

import numpy as np
import mpl_toolkits.mplot3d
import matplotlib.pyplot as plt
import vtk
from scipy.spatial import Delaunay

num_pts = 1000
indices = np.arange(0, num_pts, dtype=float) + 0.5

phi = np.arccos(1 - 2*indices/num_pts)
theta = np.pi * (1 + 5**0.5) * indices

x, y, z = np.cos(theta) * np.sin(phi), np.sin(theta) * np.sin(phi), np.cos(phi);

# x,y,z is coordination of evenly distributed shpere
# I will try to make poly data use this x,y,z 

points = vtk.vtkPoints()


for i in range(len(x)):
    array_point = np.array([x[i], y[i], z[i]] )
    points.InsertNextPoint(x[i],y[i],z[i])


#   tri = Delaunay(points) (Do I have to use this function??)

poly = vtk.vtkPolyData()
poly.SetPoints(points)

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(poly)

actor = vtk.vtkActor()
actor.SetMapper(mapper)

ren = vtk.vtkRenderer()
ren.AddActor(actor)
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)

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

renWin.Render()
iren.Start()

The code doesn't throw any error, but polydata didn't come up at my vtk window,, What should I have to do to solve this problem ?

-Tae Young.


Solution

  • Good work. Now that you have added points to a sphere polydata, we need to generate a surface out of the points. We do this using vtkDelaunay3D filter. It will generate a 3D mesh of tetrahedrals. So to get an actual spherical surface we will have to extract the surface using vtkDataSetSurfaceFilter. These are done below:

    import numpy as np
    import vtk
    
    num_pts = 1000
    indices = np.arange(0, num_pts, dtype=float) + 0.5
    
    phi = np.arccos(1 - 2*indices/num_pts)
    theta = np.pi * (1 + 5**0.5) * indices
    
    x, y, z = np.cos(theta) * np.sin(phi), np.sin(theta) * np.sin(phi), np.cos(phi);
    
    # x,y,z is coordination of evenly distributed shpere
    # I will try to make poly data use this x,y,z 
    
    points = vtk.vtkPoints()
    
    
    for i in range(len(x)):
        array_point = np.array([x[i], y[i], z[i]] )
        points.InsertNextPoint(x[i],y[i],z[i])
    
    poly = vtk.vtkPolyData()
    poly.SetPoints(points)
    
    # To create surface of a sphere we need to use Delaunay triangulation
    d3D = vtk.vtkDelaunay3D()
    d3D.SetInputData( poly ) # This generates a 3D mesh
    
    # We need to extract the surface from the 3D mesh
    dss = vtk.vtkDataSetSurfaceFilter()
    dss.SetInputConnection( d3D.GetOutputPort() )
    dss.Update()
    
    # Now we have our final polydata
    spherePoly = dss.GetOutput()
    
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputData(spherePoly)
    
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    
    ren = vtk.vtkRenderer()
    ren.AddActor(actor)
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren)
    
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)
    
    renWin.Render()
    iren.Start()