Skip to main content

pyvista-trimesh

banner

A PyVista accessor for Trimesh. Point-in-mesh, proximity queries, sampling, repair, smoothing, voxelization, and ICP are all reachable as mesh.trimesh.<op> on any pv.PolyData.

import pyvista as pv

cube = pv.Cube()
cube.trimesh.is_watertight  # True
cube.trimesh.volume  # 1.0
cube.trimesh.signed_distance([[0, 0, 0]])  # array([-0.5])

Once installed, the accessor registers itself via PyVista's plugin entry-point system. There is nothing to import.

Why

PyVista wraps VTK, and VTK is brittle for several common triangle-mesh operations: vtkSelectEnclosedPoints misclassifies points on non-trivial inputs, there is no proximity or signed-distance API, and repair is awkward. Trimesh has working implementations of all of these. This package wires them up as a single .trimesh accessor that converts on demand, caches the default Trimesh conversion on the dataset, runs the operation, and hands back a fresh pv.PolyData.

mesh.trimesh.select_enclosed_points(...) mirrors pv.PolyData.select_enclosed_points and routes through Trimesh's contains (rtree-accelerated ray cast). It is the implementation originally proposed in pyvista/pyvista#6898.

Install

pip install pyvista-trimesh

For the rtree-backed contains, GLB / GLTF / 3MF readers, voxel grids, and quadric decimation:

pip install "pyvista-trimesh[extras]"

Requires Python 3.10+ and PyVista 0.48+.

Quick start

import numpy as np
import pyvista as pv

# Point-in-mesh on a 3D grid
sphere = pv.Sphere(radius=1.0)
grid = pv.ImageData(dimensions=(21, 21, 21), spacing=(0.1, 0.1, 0.1), origin=(-1, -1, -1))
result = sphere.trimesh.select_enclosed_points(grid)
inside = result.threshold(0.5, scalars='SelectedPoints')

# Signed distance from a query cloud to the surface
queries = np.random.default_rng(0).standard_normal((100, 3))
sdf = sphere.trimesh.signed_distance(queries)  # negative inside, positive outside

# Even Poisson-style surface samples
samples = sphere.trimesh.sample_surface(500, even=True, seed=0)

# Voxelize into a PyVista ImageData
vox = sphere.trimesh.voxelized(pitch=0.1)

# Iterative closest point against another mesh
moved = sphere.copy()
moved.translate((0.5, 0.0, 0.0), inplace=True)
matrix, registered, cost = moved.trimesh.register(sphere)

# Drop down to the raw Trimesh when you need it
tmesh = sphere.trimesh.to_trimesh()

Output chains with the rest of PyVista:

finished = cube.trimesh.subdivide(2).clean().compute_normals()

The accessor

mesh.trimesh is a per-instance accessor. It converts the PolyData into a trimesh.Trimesh on demand, caches the default conversion until the dataset is modified (tracked by VTK's MTime), runs the operation, and converts the result back. The input is left untouched.

mesh.trimesh  # accessor instance, cached on the dataset
mesh.trimesh.to_trimesh()  # raw trimesh.Trimesh
mesh.trimesh.<operation>(...)  # any method below

The default conversion triangulates the input. PyVista primitives like pv.Cube and pv.Cylinder work directly.

Point-in-mesh and proximity

Method Returns
select_enclosed_points(points, check_surface=True, inside_out=False) copy of points with a SelectedPoints mask
contains(points) boolean array, True where the point is inside the closed surface
signed_distance(points) signed distance per query (negative inside, positive outside)
closest_point(points) (closest, distance, triangle_id) tuple

Sampling

Method Returns
sample_surface(count, even=False, seed=None) vertex-only PolyData on the surface
sample_volume(count, seed=None) vertex-only PolyData inside the volume

Repair and smoothing

Method Notes
repair(fill_holes=True, fix_normals=True, fix_winding=True, fix_inversion=True) hole filling, winding and inversion fixes
fill_holes() patch boundary holes only
smooth(method='taubin', iterations=10, lamb=0.5, nu=0.5) 'taubin', 'humphrey', or 'laplacian'

Subdivision and decimation

Method Notes
subdivide(iterations=1) Loop midpoint subdivision
subdivide_to_size(max_edge, max_iter=10) adaptive, edge-length driven
simplify_quadric(face_count=None, percent=None, aggression=7) quadric edge-collapse decimation

simplify_quadric requires the optional fast-simplification dependency, included in [extras].

Splits and slicing

Method Returns
split(only_watertight=False) list of disconnected components
section(normal, origin=None) polylines along one slice
section_multiplane(plane_origin, plane_normal, heights) one PolyData per requested slice height

Hulls and bounding shapes

Method Returns
convex_hull() triangulated convex hull
bounding_box(oriented=False) AABB or minimum-volume oriented box
bounding_sphere() smallest enclosing sphere
bounding_cylinder() minimum-volume bounding cylinder

Voxelization

Method Returns
voxelized(pitch, fill=True) binary pv.ImageData (filled cell-data); fill=False keeps shell

Ray tracing

Method Notes
ray_intersections(origins, directions, multiple_hits=True) NumPy ray engine, no Embree required

Registration and transforms

Method Notes
register(other, max_iterations=20) ICP alignment; returns (matrix, registered, cost) tuple
apply_transform(matrix) apply a 4x4 transform via Trimesh

other is a pv.DataSet, a trimesh.Trimesh, or an (N, 3) point-cloud array.

Properties

Property Returns
is_watertight, is_winding_consistent, is_volume structural validity flags
volume, area mass properties
euler_number V - E + F
center_mass, moment_inertia volumetric centroid and inertia tensor
principal_inertia_components eigenvalues of the inertia tensor

Module-level helpers

For inputs that do not start from an existing PolyData:

from pyvista_trimesh import (
    convex_hull,
    load_mesh,
    primitive_annulus,
    primitive_box,
    primitive_capsule,
    primitive_icosphere,
)

hull = convex_hull(points)  # (N, 3) point cloud
mesh = load_mesh('model.glb')  # any format Trimesh supports
ball = primitive_icosphere(subdivisions=4)  # uniform-area triangulation
washer = primitive_annulus(r_min=0.4, r_max=1.0, height=0.2)

load_mesh handles GLB, GLTF, DAE, 3MF, OFF, and the rest of Trimesh's reader set. The result is a single pv.PolyData (scenes are concatenated).

For everything that already has a PyVista equivalent (pv.Cube, pv.Sphere, pv.Cylinder, ...), use PyVista directly and chain through .trimesh.

Conversion utilities

The accessor handles conversion automatically. Reach for these when you want a one-shot conversion outside the accessor:

from pyvista_trimesh import from_trimesh, to_trimesh

tmesh = to_trimesh(polydata, triangulate=True)  # PolyData -> Trimesh
poly = from_trimesh(tmesh)  # Trimesh -> PolyData

These wrap PyVista's built-in pv.to_trimesh / pv.from_trimesh (added in PyVista 0.47). Attribute mappings (vertex / face attributes, metadata, user_dict) match exactly.

Caveats

  • Point-in-mesh requires a closed surface. select_enclosed_points raises RuntimeError if the input is not watertight. Pass check_surface=False to skip the check.
  • signed_distance requires a watertight surface. For open meshes, use closest_point and take the unsigned distance.
  • Optional dependencies enable extra features. voxelized and select_enclosed_points use rtree when available, simplify_quadric requires fast-simplification, and the GLB / GLTF readers need shapely and friends. [extras] installs all of them.
  • Cell data is dropped by the cached default conversion. Pass pass_data=True to to_trimesh (or mesh.trimesh.to_trimesh(pass_data=True)) when you need round-tripping.

Development

git clone https://github.com/pyvista/pyvista-trimesh
cd pyvista-trimesh
just sync       # uv sync --extra dev
just test       # pytest with coverage
just lint       # pre-commit run --all-files
just typecheck  # mypy
just build      # wheel + sdist

Acknowledgements

  • Trimesh by Michael Dawson-Haggerty and contributors.
  • PyVista for the accessor system and the rest of the visualization stack.
  • The point-in-mesh implementation is the port of pyvista/pyvista#6898.

License

MIT.

Metadata

Release files for pyvista-trimesh 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyvista-trimesh 0.1.0
File Size Uploaded
pyvista_trimesh-0.1.0.tar.gz 1.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyvista-trimesh 0.1.0
File Interpreter ABI Platform
pyvista_trimesh-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.9 MB

Release files / pyvista_trimesh-0.1.0.tar.gz

Download URL pyvista_trimesh-0.1.0.tar.gz
Size 1.9 MB
Tags Source
SHA-256 checksum
How to use checksums
ecf6aa4979ba2275aaf1a79a97da8388953cc89b10b51ba867dabc50835ac153
BLAKE2b-256 checksum
How to use checksums
9f2296019cde1587280f64b2693797573bdfbdf16a8b1327325d6f917b45f41e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

Release files / pyvista_trimesh-0.1.0-py3-none-any.whl

Download URL pyvista_trimesh-0.1.0-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1cd2eb25e12a0b42cfb0e39e41476bc554d4e7058bd3667ab9ac688b2ec44609
BLAKE2b-256 checksum
How to use checksums
2a34f903edcc63775334e08dd43d6c23e9da8944bfd20341b5eea02750f51374
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page