Plotting Glyphs (Vectors or PolyData)#

Use vectors in a dataset to plot and orient glyphs/geometric objects.

import numpy as np
import pyvista as pv
from pyvista import examples

Example dataset with normals

mesh = examples.load_random_hills()

Glyphying can be done via the pyvista.DataSetFilters.glyph() filter

Help on method glyph in module pyvista.core.filters.data_set:

glyph(orient=True, scale=True, factor=1.0, geom=None, indices=None, tolerance=None, absolute=False, clamping=False, rng=None, progress_bar=False) method of pyvista.core.pointset.PolyData instance
    Copy a geometric representation (called a glyph) to the input dataset.

    The glyph may be oriented along the input vectors, and it may
    be scaled according to scalar data or vector
    magnitude. Passing a table of glyphs to choose from based on
    scalars or vector magnitudes is also supported.  The arrays
    used for ``orient`` and ``scale`` must be either both point data
    or both cell data.

    orient : bool | str, default: True
        If ``True``, use the active vectors array to orient the glyphs.
        If string, the vector array to use to orient the glyphs.
        If ``False``, the glyphs will not be orientated.

    scale : bool | str | sequence[float], default: True
        If ``True``, use the active scalars to scale the glyphs.
        If string, the scalar array to use to scale the glyphs.
        If ``False``, the glyphs will not be scaled.

    factor : float, default: 1.0
        Scale factor applied to scaling array.

    geom : vtk.vtkDataSet or tuple(vtk.vtkDataSet), optional
        The geometry to use for the glyph. If missing, an arrow glyph
        is used. If a sequence, the datasets inside define a table of
        geometries to choose from based on scalars or vectors. In this
        case a sequence of numbers of the same length must be passed as
        ``indices``. The values of the range (see ``rng``) affect lookup
        in the table.

    indices : sequence[float], optional
        Specifies the index of each glyph in the table for lookup in case
        ``geom`` is a sequence. If given, must be the same length as
        ``geom``. If missing, a default value of ``range(len(geom))`` is
        used. Indices are interpreted in terms of the scalar range
        (see ``rng``). Ignored if ``geom`` has length 1.

    tolerance : float, optional
        Specify tolerance in terms of fraction of bounding box length.
        Float value is between 0 and 1. Default is None. If ``absolute``
        is ``True`` then the tolerance can be an absolute distance.
        If ``None``, points merging as a preprocessing step is disabled.

    absolute : bool, default: False
        Control if ``tolerance`` is an absolute distance or a fraction.

    clamping : bool, default: False
        Turn on/off clamping of "scalar" values to range.

    rng : sequence[float], optional
        Set the range of values to be considered by the filter
        when scalars values are provided.

    progress_bar : bool, default: False
        Display a progress bar to indicate progress.

        Glyphs at either the cell centers or points.

    Create arrow glyphs oriented by vectors and scaled by scalars.
    Factor parameter is used to reduce the size of the arrows.

    >>> import pyvista
    >>> from pyvista import examples
    >>> mesh = examples.load_random_hills()
    >>> arrows = mesh.glyph(
    ...     scale="Normals", orient="Normals", tolerance=0.05
    ... )
    >>> pl = pyvista.Plotter()
    >>> actor = pl.add_mesh(arrows, color="black")
    >>> actor = pl.add_mesh(
    ...     mesh,
    ...     scalars="Elevation",
    ...     cmap="terrain",
    ...     show_scalar_bar=False,
    ... )

    See :ref:`glyph_example` and :ref:`glyph_table_example` for more
    examples using this filter.

Sometimes you might not want glyphs for every node in the input dataset. In this case, you can choose to build glyphs for a subset of the input dataset by using a merging tolerance. Here we specify a merging tolerance of five percent which equates to five percent of the bounding box’s length.

create a subset of arrows using the glyph filter

arrows = mesh.glyph(scale="Normals", orient="Normals", tolerance=0.05)
p = pv.Plotter()
p.add_mesh(arrows, color="black")
p.add_mesh(mesh, scalars="Elevation", cmap="terrain", smooth_shading=True)
e glyphs

A common approach is to load vectors directly to the mesh object and then access the pyvista.DataSet.arrows property to produce glyphs.

sphere = pv.Sphere(radius=3.14)

# make cool swirly pattern
vectors = np.vstack(
        np.sin(sphere.points[:, 0]),
        np.cos(sphere.points[:, 1]),
        np.cos(sphere.points[:, 2]),
array([[ 0.        ,  1.        , -0.99999875],
       [ 0.        ,  1.        , -0.99999875],
       [ 0.33300975,  1.        , -0.9998    ],
       [ 0.83088565,  0.97835207, -0.98625994],
       [ 0.61331964,  0.9901682 , -0.9971885 ],
       [ 0.32600534,  0.99750996, -0.9998    ]], dtype=float32)
# add and scale
sphere["vectors"] = vectors * 0.3

# plot just the arrows
e glyphs

Plot the arrows and the sphere.

p = pv.Plotter()
p.add_mesh(sphere.arrows, lighting=False, scalar_bar_args={'title': "Vector Magnitude"})
p.add_mesh(sphere, color="grey", ambient=0.6, opacity=0.5, show_edges=False)
e glyphs
Open In Colab

Total running time of the script: (0 minutes 1.261 seconds)

Gallery generated by Sphinx-Gallery