File: create-spline.py

package info (click to toggle)
python-pyvista 0.44.1-11
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 159,804 kB
  • sloc: python: 72,164; sh: 118; makefile: 68
file content (122 lines) | stat: -rw-r--r-- 2,874 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""
.. _create_spline_example:

Creating a Spline
~~~~~~~~~~~~~~~~~

Create a spline/polyline from a numpy array of XYZ vertices using
:func:`pyvista.Spline`.
"""

from __future__ import annotations

import numpy as np

# sphinx_gallery_thumbnail_number = 2
import pyvista as pv

# %%
# 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, :]

# %%
# Now let's make a function that can create line cells on a
# :class:`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

# %%
line["scalars"] = np.arange(line.n_points)
tube = line.tube(radius=0.1)
tube.plot(smooth_shading=True)


# %%
# 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)


# %%
# 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)

# %%
# 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")


# %%
# The radius of the tube can be modulated with scalars

spline["theta"] = 0.4 * np.arange(len(spline.points))
spline["radius"] = np.abs(np.sin(spline["theta"]))
tube = spline.tube(scalars="radius", absolute=True)
tube.plot(scalars="theta", smooth_shading=True)


# %%
# Ribbons
# +++++++
#
# Ayy of the lines from the examples above can be used to create ribbons.
# Take a look at the :func:`pyvista.PolyDataFilters.ribbon` filter.

ribbon = spline.compute_arc_length().ribbon(width=0.75, scalars='arc_length')
ribbon.plot(color=True)