Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3D curves in a single plot #11

Closed
Sunil7545 opened this issue Jun 4, 2019 · 10 comments
Closed

3D curves in a single plot #11

Sunil7545 opened this issue Jun 4, 2019 · 10 comments
Labels
geometric-objects Uses a geometric object plotting General plotting/rendering topics

Comments

@Sunil7545
Copy link

Sunil7545 commented Jun 4, 2019

Description

Hello everyone, I am quite new to PyVista, I want to plot several 3d curves in a single plot, what would be best way to do it ?

A 3D curve can be seen as a polyline with vertex positions and vertex positions are given as a ndarray (nx3) for a curve with n vertices. I have several ndarrays regarding a set of 3D curves and want to plot them. I like the visual representation of streamlines in PyVista. Can these curve be plotted with similar visuals ?

I am looking forward to your valuable suggestions

Example Data

For example, I am attaching 3 csv files regarding x, y, and z coordinates of 24 different curves
3dcurves.zip

@Sunil7545 Sunil7545 reopened this Jun 4, 2019
@GuillaumeFavelier
Copy link

With this totally unoptimized snippet:

import numpy as np
import pyvista as pv
import csv
from pyvista.utilities import lines_from_points

xfile = open('x_coordinates.csv', 'r')
xreader = csv.reader(xfile, delimiter=',')
x = []
for row in xreader:
    x.append(row)
xfile.close()

yfile = open('y_coordinates.csv', 'r')
yreader = csv.reader(yfile, delimiter=',')
y = []
for row in yreader:
    y.append(row)
yfile.close()

zfile = open('z_coordinates.csv', 'r')
zreader = csv.reader(zfile, delimiter=',')
z = []
for row in zreader:
    z.append(row)
zfile.close()

plotter = pv.Plotter()
plotter.background_color = 'white'
for idx in range(len(x)):
    cx = x[idx]
    cy = y[idx]
    cz = z[idx]
    pts = np.column_stack((cx, cy, cz)).astype(np.float)
    line = lines_from_points(pts)
    plotter.add_mesh(line, show_edges=True)
plotter.show()

I got the following:
image

Did you expect something similar?

Also, I think it should be possible to append/create an UnstructuredGrid dataset and use only one call to add_mesh(). Note that I had to use show_edges=True to actually visualize the result.

@Sunil7545
Copy link
Author

Sunil7545 commented Jun 4, 2019 via email

@GuillaumeFavelier
Copy link

I modified a bit the previous (unoptimized) snippet:

...
plotter = pv.Plotter()
plotter.background_color = 'white'
for idx in range(len(x)):
    cx = x[idx]
    cy = y[idx]
    cz = z[idx]
    pts = np.column_stack((cx, cy, cz)).astype(np.float)

    lines = lines_from_points(pts)
    lines.lines = lines.faces
    tube = lines.tube(0.01).elevation()
    plotter.add_mesh(tube, show_edges=False)
plotter.show()

image

The main modifications are lines.lines = lines.faces which basically updates the lines of the PolyData required by the tube filter. The rest is pretty straightforward, we apply the filters: first the tube with a radius of 0.01 then the elevation filter to add a scalar field corresponding to the Z height.

There is maybe a better/efficient way to achieve this, what do you think @pyvista/developers ?

@Sunil7545
Copy link
Author

Sunil7545 commented Jun 5, 2019 via email

@akaszynski
Copy link
Member

Good start @GuillaumeFavelier!

Here's a little bit of an improvement using splines, which leads to smoother plotting with no breaks along the line.

I'm adding splines to pyvista for the next release, so you won't need to use make_spline and will instead use pv.Spline

import numpy as np
import pyvista as pv

x = np.loadtxt('x_coordinates.csv', delimiter=',')
y = np.loadtxt('y_coordinates.csv', delimiter=',')
z = np.loadtxt('z_coordinates.csv', delimiter=',')


def make_spline(points, n_points=None):
    """Create a spline from points

    Parameters
    ----------
    points : np.ndarray
        Array of points to build a spline out of.  Array must be 3D
        and directionally ordered.

    n_points : int, optional
        Number of points to interpolate along the points array.

    Returns
    -------
    spline : pyvista.PolyData
        Line mesh of spline.

    Examples
    --------
    Construct a spline
    >>> import numpy as np
    >>> import pyvista as pv
    >>> 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)
    >>> points = np.column_stack((x, y, z))
    >>> spline = pv.Spline(points, 1000)
    """
    import vtk
    spline = vtk.vtkParametricSpline()
    vtk_points = pv.vtk_points(points, False)
    spline.SetPoints(vtk_points)
    spline.GetPoints().Modified()
    spline.Modified()

    # get interpolation density
    u_res = n_points
    if u_res is None:
        u_res = points.shape[0]

    return pv.geometric_objects.surface_from_para(spline, u_res)


# convert points to splines
splines = []
for idx in range(x.shape[0]):
    points = np.column_stack((x[idx], y[idx], z[idx]))

    spline = make_spline(points)
    # spline = pv.Spline(points)  # in the next release
    splines.append(spline)


# boring plot
pv.plot(splines)

# exciting plot with scalars
tubes = []
for spline in splines:
    # add scalars here...
    spline['scalars'] = np.arange(spline.n_points)
    tubes.append(spline.tube(0.01))

pv.plot(tubes, smooth_shading=True)

cool

@Sunil7545
Copy link
Author

Sunil7545 commented Jun 5, 2019 via email

@akaszynski
Copy link
Member

Are you running the latest pyvista?

@Sunil7545
Copy link
Author

Sunil7545 commented Jun 5, 2019 via email

@Sunil7545
Copy link
Author

Sunil7545 commented Jun 5, 2019 via email

@akaszynski
Copy link
Member

Not sure what you’re trying to do. Can you provide a code example?

@banesullivan banesullivan added plotting General plotting/rendering topics geometric-objects Uses a geometric object labels Jun 13, 2019
@pyvista pyvista locked and limited conversation to collaborators May 15, 2022
@tkoyama010 tkoyama010 converted this issue into a discussion May 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
geometric-objects Uses a geometric object plotting General plotting/rendering topics
Projects
None yet
Development

No branches or pull requests

4 participants