create cylinders from csv file with start and end locations

Hello to all,

I have a .csv file with (x,y,z) positions of start and end positions of cylinders.

I would like to import this into paraview and create the cylinders givent the (x,y,z) of start points, and (x,y,z) of end points and specify the radius.

Is this possible?

I will leave an example .csv file:
foo.csv (1.2 KB)

Best regards

The easiest way is to use a programmable source and to write the reading part in python.

Note that the Tube filter creates a cylinder from lines, so you may just create a simple polydata and apply this filter.

1 Like

In Programmable Source, I tried to use Cylinder Source and it became very complicated. nicolas.vuaille is right, it is much better to use Tube filter.

Just for reference, here is a dirty script for Programmable Source.

import numpy as np
import vtk

# CSV file to define the cylinders
csv_file = 'C:/Users/icem/Desktop/cyl/foo.csv'
# cylinder radius
r = 0.025

# CSV file reading
data = np.genfromtxt(csv_file, skip_header=2, dtype=None, names=['start_x','start_y','start_z','end_x','end_y','end_z'], delimiter=',', autostrip=True)
# obtain starting and ending coordinates of cylinders
start_pnts = np.vstack([data['start_x'],data['start_y'],data['start_z']]).T
end_pnts = np.vstack([data['end_x'],data['end_y'],data['end_z']]).T

appender = vtk.vtkAppendPolyData()

for start_pnt, end_pnt in zip(start_pnts, end_pnts):
    # center coordinates of a cylinder
    center = (start_pnt + end_pnt)*0.5
    # direction vector of a cylinder
    direc = end_pnt - start_pnt
    # height of cylinder
    h = np.linalg.norm(direc)
    # define the local coordinate system of a cylinder
    dir2 = direc / h
    dir1 = np.array([dir2[1], -dir2[0], 0])
    dir1 /= np.linalg.norm(dir1)
    dir3 = np.cross(dir1, dir2)
    # basis transformation matrix of the local coordinate system of a cylinder
    T = np.array([dir1, dir2, dir3]).T
    T = np.concatenate([T, np.zeros((3,1))], axis=1)
    T = np.concatenate([T, np.zeros((1,4))], axis=0)
    T[3, 3] = 1.0
    # create a cylinder
    cyl = vtk.vtkCylinderSource()
    cyl.SetCenter([0,0,0])
    cyl.SetRadius(r)
    cyl.SetHeight(h)
    cyl.SetResolution(100)
    cyl.Update()
    # transforms cylinder along its local coordinate system
    transform = vtk.vtkTransform()
    transform.PostMultiply()
    transform.SetMatrix(T.flatten())
    transform.Translate(center)
    transformFilter = vtk.vtkTransformPolyDataFilter()
    transformFilter.SetInputData(cyl.GetOutput())
    transformFilter.SetTransform(transform)
    transformFilter.Update()

    # add a cylinder to appender
    appender.AddInputData(transformFilter.GetOutput())

appender.Update()

output.DeepCopy(appender.GetOutput())

How can I create the polydata?

When using the Tube filter, the Programmable Source script becomes very simple as follows.

import numpy as np
import vtk

# CSV file to define the cylinders
csv_file = 'C:/Users/icem/Desktop/cyl/foo.csv'
# cylinder radius
r = 0.025

# CSV file reading
data = np.genfromtxt(csv_file, skip_header=2, dtype=None, names=['start_x','start_y','start_z','end_x','end_y','end_z'], delimiter=',', autostrip=True)
# obtain starting and ending coordinates of cylinders
start_pnts = np.vstack([data['start_x'],data['start_y'],data['start_z']]).T
end_pnts = np.vstack([data['end_x'],data['end_y'],data['end_z']]).T

appender = vtk.vtkAppendPolyData()

for start_pnt, end_pnt in zip(start_pnts, end_pnts):
    # creating the central axis of a cylinder    
    line = vtk.vtkLineSource()
    line.SetPoint1(start_pnt)
    line.SetPoint2(end_pnt)
    line.SetResolution(1)
    line.Update()

    # creating a cylinder
    tubefilter = vtk.vtkTubeFilter()
    tubefilter.SetInputData(line.GetOutput())
    tubefilter.SetRadius(r)
    tubefilter.SetNumberOfSides(50)
    tubefilter.CappingOn()
    tubefilter.Update()

    # add a cylinder to appender
    appender.AddInputData(tubefilter.GetOutput())

appender.Update()

output.DeepCopy(appender.GetOutput())
1 Like

This worked!

I am trying to figure out out to ask information to the user (file name, and name of an image to save). I used trace feature to get a python script