Note
Click here to download the full example code
Creating a Spline¶
Create a spline/polyline from a numpy array of XYZ vertices
# sphinx_gallery_thumbnail_number = 2
import pyvista as pv
import numpy as np
Create a dataset to plot
def make_points():
"""Helper to make XYZ points"""
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
return np.column_stack((x, y, z))
points = make_points()
points[0:5, :]
Out:
array([[ 2.44929360e-15, 5.00000000e+00, -2.00000000e+00],
[ 1.21556036e+00, 4.68488752e+00, -1.95959596e+00],
[ 2.27700402e+00, 4.09249671e+00, -1.91919192e+00],
[ 3.12595020e+00, 3.27840221e+00, -1.87878788e+00],
[ 3.72150434e+00, 2.30906573e+00, -1.83838384e+00]])
Now let’s make a function that can create line cells on a
pyvista.PolyData
mesh given that the points are in order for the
segments they make.
def lines_from_points(points):
"""Given an array of points, make a line set"""
poly = pv.PolyData()
poly.points = points
cells = np.full((len(points)-1, 3), 2, dtype=np.int_)
cells[:, 1] = np.arange(0, len(points)-1, dtype=np.int_)
cells[:, 2] = np.arange(1, len(points), dtype=np.int_)
poly.lines = cells
return poly
line = lines_from_points(points)
line
PolyData | Information |
---|---|
N Cells | 99 |
N Points | 100 |
X Bounds | -4.084e+00, 4.084e+00 |
Y Bounds | -3.281e+00, 5.000e+00 |
Z Bounds | -2.000e+00, 2.000e+00 |
N Arrays | 0 |
line["scalars"] = np.arange(line.n_points)
tube = line.tube(radius=0.1)
tube.plot(smooth_shading=True)

Out:
[(14.087887028287454, 14.946060132268393, 14.087887028287454),
(4.440892098500626e-16, 0.8581731039809382, 0.0),
(0.0, 0.0, 1.0)]
That tube has sharp edges at each line segment. This can be mitigated by creating a single PolyLine cell for all of the points
def polyline_from_points(points):
poly = pv.PolyData()
poly.points = points
the_cell = np.arange(0, len(points), dtype=np.int_)
the_cell = np.insert(the_cell, 0, len(points))
poly.lines = the_cell
return poly
polyline = polyline_from_points(points)
polyline["scalars"] = np.arange(polyline.n_points)
tube = polyline.tube(radius=0.1)
tube.plot(smooth_shading=True)

Out:
[(14.086813345437829, 14.944844858005826, 14.086377144241794),
(0.00031734610427580634, 0.8583488586722716, -0.0001188550917605724),
(0.0, 0.0, 1.0)]
You could also interpolate those points onto a parametric spline
# Create spline with 1000 interpolation points
spline = pv.Spline(points, 1000)
Plot spline as a tube
# add scalars to spline and plot it
spline["scalars"] = np.arange(spline.n_points)
tube = spline.tube(radius=0.1)
tube.plot(smooth_shading=True)

Out:
[(14.115423714961896, 14.971821105327496, 14.114901935901532),
(0.0003743171691894531, 0.85677170753479, -0.0001474618911743164),
(0.0, 0.0, 1.0)]
The spline can also be plotted as a plain line
# generate same spline with 400 interpolation points
spline = pv.Spline(points, 400)
# plot without scalars
spline.plot(line_width=4, color="k")

Out:
[(13.745872971968165, 14.603470084623805, 13.745872971968165),
(0.0, 0.8575971126556396, 0.0),
(0.0, 0.0, 1.0)]
Ribbons¶
Ayy of the lines from the examples above can be used to create ribbons.
Take a look at the pyvista.PolyDataFilters.ribbon()
filter.
ribbon = spline.compute_arc_length().ribbon(width=0.75, scalars='arc_length')
ribbon.plot(color=True)

Out:
[(16.68578476672845, 17.41423101192193, 17.248056957776118),
(0.07060718536376953, 0.799053430557251, 0.632879376411438),
(0.0, 0.0, 1.0)]
Total running time of the script: ( 0 minutes 3.562 seconds)