Skip to content

Path Visual

The Path visual renders continuous polylines — sequences of connected line segments that form a single open or closed path. It supports batch rendering with multiple disconnected paths per visual, per-vertex styling and optional variable thickness, making it well-suited for contours, trajectories, and line-based annotations.

Note

This visual is powerful and high-quality, but not optimized or scalable to millions of points. For very large datasets, use the lower-quality but more scalable Basic visual instead, with the line_strip primitive and groups.

Path visual

Overview

  • Renders connected polylines from vertex sequences
  • Supports per-vertex color and linewidth
  • Each group of vertices forms an independent path
  • Optional cap and join styles for line ends and corners

Warning

Dashed paths are not yet implemented.


When to use

Use the path visual when:

  • You want to draw 2D or 3D trajectories or contours
  • You need continuous, styled polylines with thickness
  • You want to render multiple independent paths in one visual

Attributes

Per-item

Attribute Type Description
position (N, 3) float32 Vertex positions in NDC
color (N, 4) uint8 RGBA color per vertex
linewidth (N,) float32 Line thickness in pixels

Per-visual (uniform)

Attribute Type Description
cap enum Cap style at the start/end of each path
join enum Join style between connected segments

Cap and join styles are defined by enums from the Vulkan line rendering system.

Cap types

Each path endpoint can be rendered with a custom cap style:

Cap Name Image
round cap_round
triangle_in cap_triangle_in
triangle_out cap_triangle_out
square cap_square
butt cap_butt

Joint styles

Cap Name
square
round

Grouping paths

Each visual can include multiple independent paths. Use visual.set_position() to specify how the data is grouped. You can pass either:

  • A list of arrays, where each array defines one path
  • A single position array, and an additional argument groups which is either:

    • int: number of paths (the position array is split in that number of equal size sub-paths)
    • np.ndarray: an array of group size integers

Each group becomes a separate, continuous polyline.


Large-scale paths

For very large paths (e.g. time series with millions of points), you may prefer the Basic visual with line_strip topology. This will be more efficient but offers no line width or styling.


Example

import numpy as np

import datoviz as dvz


def generate_data(n_groups=20, n_samples=10_000):
    N = n_groups * n_samples

    t = np.linspace(-1, 1, n_samples)
    group_indices = np.arange(n_groups)
    y_base = np.linspace(-1, 1, n_groups)

    positions = np.zeros((N, 3), dtype=np.float32)
    linewidths = np.zeros(N, dtype=np.float32)

    for i, g in enumerate(group_indices):
        freq = 1 + 1.5 * np.exp(0.1 * i)
        phase = g * np.pi / 4
        y_offset = y_base[i]
        y = y_offset + 0.1 * np.sin(2 * np.pi * freq * (t + 1) / 2 + phase)

        start = i * n_samples
        end = (i + 1) * n_samples
        positions[start:end, 0] = t
        positions[start:end, 1] = y
        positions[start:end, 2] = 0.0

    t = np.linspace(0, n_groups - 0.25, N).astype(np.float32)
    t = np.mod(t, 1)
    colors = dvz.cmap('hsv', t, 0, 1)

    positions[:, 0] *= 0.9
    positions[:, 1] *= 0.8

    linewidths = np.linspace(0, 1, N)
    linewidths = 8 + 6 * np.sin(2 * (n_groups - 1) * np.pi * linewidths)
    linewidths = linewidths.astype(np.float32)

    return N, positions, colors, linewidths


n_groups = 20
n_samples = 1_000
N = n_groups * n_samples
N, position, color, linewidth = generate_data(n_groups=n_groups, n_samples=n_samples)
lengths = np.full(n_groups, n_samples, dtype=np.uint32)

app = dvz.App()
figure = app.figure()
panel = figure.panel()
panzoom = panel.panzoom()

visual = app.path()
visual.set_position(position, groups=n_groups)
visual.set_data(color=color, linewidth=linewidth, cap='round', join='round')
panel.add(visual)

app.run()
app.destroy()

Summary

The path visual is ideal for rendering styled, continuous line sequences.

  • ✔️ Variable thickness and color
  • ✔️ Multiple independent paths per visual
  • ✔️ Custom caps and joins
  • ❌ No dashed line support yet

See also:

  • Segment for unconnected lines
  • Basic for large 1-pixel polylines