A python module for scientific visualization, analysis of 3D objects and point clouds.
Geometric transformation utilities, coordinate system conversions, and spatial analysis functions for manipulating and analyzing 3D data. This module provides essential tools for geometric operations and coordinate transformations in 3D space.
Classes for applying linear geometric transformations to 3D objects.
class LinearTransform:
"""
Apply linear transformations using 4x4 transformation matrices.
Parameters:
- T: array-like
4x4 transformation matrix or list of transformations
"""
def __init__(self, T): ...
def apply(self, points):
"""
Apply transformation to points.
Parameters:
- points: array-like
Points to transform
Returns:
numpy.ndarray: Transformed points
"""
class NonLinearTransform:
"""
Apply non-linear transformations using custom functions.
Parameters:
- func: callable
Transformation function
- invert: bool, default False
Apply inverse transformation
"""
def __init__(self, func, invert=False): ...
def apply(self, points):
"""
Apply non-linear transformation to points.
Parameters:
- points: array-like
Points to transform
Returns:
numpy.ndarray: Transformed points
"""
class TransformInterpolator:
"""
Interpolate between transformation matrices for smooth animations.
Parameters:
- transforms: list
List of transformation matrices
- times: list, optional
Time points for each transformation
"""
def __init__(self, transforms, times=None): ...
def evaluate(self, t):
"""
Evaluate transformation at given time.
Parameters:
- t: float
Time parameter (0-1)
Returns:
numpy.ndarray: Interpolated transformation matrix
"""Functions for converting between different coordinate systems commonly used in scientific applications.
def cart2spher(x, y, z):
"""
Convert Cartesian to spherical coordinates.
Parameters:
- x, y, z: float or array-like
Cartesian coordinates
Returns:
numpy.ndarray: [rho, theta, phi] spherical coordinates
"""
def spher2cart(rho, theta, phi):
"""
Convert spherical to Cartesian coordinates.
Parameters:
- rho: float or array-like
Radial distance
- theta: float or array-like
Azimuthal angle (radians)
- phi: float or array-like
Polar angle (radians)
Returns:
numpy.ndarray: [x, y, z] Cartesian coordinates
"""
def cart2cyl(x, y, z):
"""
Convert Cartesian to cylindrical coordinates.
Parameters:
- x, y, z: float or array-like
Cartesian coordinates
Returns:
numpy.ndarray: [rho, theta, z] cylindrical coordinates
"""
def cyl2cart(rho, theta, z):
"""
Convert cylindrical to Cartesian coordinates.
Parameters:
- rho: float or array-like
Radial distance in xy-plane
- theta: float or array-like
Azimuthal angle (radians)
- z: float or array-like
Height coordinate
Returns:
numpy.ndarray: [x, y, z] Cartesian coordinates
"""
def cart2pol(x, y):
"""
Convert 2D Cartesian to polar coordinates.
Parameters:
- x, y: float or array-like
2D Cartesian coordinates
Returns:
numpy.ndarray: [rho, theta] polar coordinates
"""
def pol2cart(rho, theta):
"""
Convert polar to 2D Cartesian coordinates.
Parameters:
- rho: float or array-like
Radial distance
- theta: float or array-like
Angle (radians)
Returns:
numpy.ndarray: [x, y] Cartesian coordinates
"""
def cyl2spher(rho, theta, z):
"""
Convert cylindrical to spherical coordinates.
Parameters:
- rho: float or array-like
Cylindrical radius
- theta: float or array-like
Azimuthal angle (radians)
- z: float or array-like
Height coordinate
Returns:
numpy.ndarray: [rho_s, theta_s, phi_s] spherical coordinates
"""
def spher2cyl(rho, theta, phi):
"""
Convert spherical to cylindrical coordinates.
Parameters:
- rho: float or array-like
Spherical radius
- theta: float or array-like
Azimuthal angle (radians)
- phi: float or array-like
Polar angle (radians)
Returns:
numpy.ndarray: [rho_c, theta_c, z] cylindrical coordinates
"""Advanced functions for fitting geometric primitives and analyzing spatial relationships.
def fit_plane(points, signed=False):
"""
Fit a plane through 3D points using least squares.
Parameters:
- points: array-like or Points object
Input point coordinates
- signed: bool, default False
Return signed distances from plane
Returns:
Plane: Fitted plane object with normal and center
"""
def fit_sphere(coords):
"""
Fit a sphere through 3D points.
Parameters:
- coords: array-like or Points object
Input point coordinates
Returns:
Sphere: Fitted sphere object with center and radius
"""
def fit_line(points):
"""
Fit a line through points using linear regression.
Parameters:
- points: array-like or Points object
Input point coordinates
Returns:
Line: Fitted line object
"""
def fit_circle(points):
"""
Fit a circle through 2D or 3D points.
Parameters:
- points: array-like or Points object
Input point coordinates
Returns:
tuple: (center, radius, normal) of fitted circle
"""Functions for aligning and combining geometric objects.
def procrustes_alignment(sources, rigid=False):
"""
Align meshes using Procrustes analysis.
The Procrustes algorithm aligns multiple point sets in a least-squares sense
to their mutual mean, iterating until convergence.
Parameters:
- sources: list of Mesh objects
Source meshes to align (must have same number of points)
- rigid: bool, default False
If True, scaling is disabled (rigid body transformation only)
Returns:
Assembly: Assembly containing aligned meshes
"""Helper functions for common geometric calculations and operations.
def geometry(obj1, obj2=None):
"""
Compute geometric properties and relationships between objects.
Parameters:
- obj1: vedo object
First object
- obj2: vedo object, optional
Second object for pairwise calculations
Returns:
dict: Dictionary containing geometric measurements
"""
def vector(x, y=None, z=None):
"""
Create or normalize 3D vectors.
Parameters:
- x: float, array-like, or tuple
X component or complete vector
- y: float, optional
Y component
- z: float, optional
Z component
Returns:
numpy.ndarray: 3D vector
"""
def mag(vector):
"""
Calculate vector magnitude.
Parameters:
- vector: array-like
Input vector
Returns:
float: Vector magnitude
"""
def mag2(vector):
"""
Calculate squared vector magnitude (faster than mag).
Parameters:
- vector: array-like
Input vector
Returns:
float: Squared vector magnitude
"""
def norm(vector):
"""
Normalize vector to unit length.
Parameters:
- vector: array-like
Input vector
Returns:
numpy.ndarray: Normalized vector
"""
def precision(x, p):
"""
Round numbers to specified precision.
Parameters:
- x: float or array-like
Input values
- p: int
Number of decimal places
Returns:
float or array: Rounded values
"""
def round_to_digit(x, digit):
"""
Round to specified number of significant digits.
Parameters:
- x: float or array-like
Input values
- digit: int
Number of significant digits
Returns:
float or array: Rounded values
"""import vedo
import numpy as np
# Coordinate system conversions
x, y, z = 1.0, 2.0, 3.0
# Convert to spherical coordinates
rho, theta, phi = vedo.cart2spher(x, y, z)
print(f"Spherical: rho={rho:.2f}, theta={theta:.2f}, phi={phi:.2f}")
# Convert back to Cartesian
x2, y2, z2 = vedo.spher2cart(rho, theta, phi)
print(f"Cartesian: x={x2:.2f}, y={y2:.2f}, z={z2:.2f}")
# Cylindrical coordinates
rho_c, theta_c, z_c = vedo.cart2cyl(x, y, z)
print(f"Cylindrical: rho={rho_c:.2f}, theta={theta_c:.2f}, z={z_c:.2f}")
# Batch coordinate conversion
points_cart = np.random.rand(100, 3) * 10
points_spher = np.array([vedo.cart2spher(p[0], p[1], p[2]) for p in points_cart])
# Linear transformations
# Create transformation matrix for 45-degree rotation around Z-axis
angle = np.pi / 4
T = np.array([
[np.cos(angle), -np.sin(angle), 0, 0],
[np.sin(angle), np.cos(angle), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
transform = vedo.LinearTransform(T)
# Apply to mesh
mesh = vedo.Sphere()
original_points = mesh.points()
transformed_points = transform.apply(original_points)
mesh.points(transformed_points)
# Non-linear transformation example
def wave_transform(points):
"""Apply sinusoidal wave transformation."""
result = points.copy()
result[:, 2] += 0.5 * np.sin(2 * points[:, 0]) * np.cos(2 * points[:, 1])
return result
nonlinear_transform = vedo.NonLinearTransform(wave_transform)
wave_mesh = vedo.Box()
wave_points = nonlinear_transform.apply(wave_mesh.points())
wave_mesh.points(wave_points)
# Geometric fitting
# Generate noisy circle data
t = np.linspace(0, 2*np.pi, 50)
circle_points = np.column_stack([
2 * np.cos(t) + np.random.normal(0, 0.1, 50),
2 * np.sin(t) + np.random.normal(0, 0.1, 50),
np.random.normal(0, 0.1, 50)
])
# Fit geometric primitives
fitted_plane = vedo.fit_plane(circle_points)
fitted_sphere = vedo.fit_sphere(circle_points)
fitted_line = vedo.fit_line(circle_points)
# Procrustes alignment of multiple objects
# Create similar but transformed objects
original = vedo.load("bunny.obj") # Example mesh
shapes = []
for i in range(5):
shape = original.clone()
# Apply random transformations
shape.rotate_z(np.random.uniform(0, 360))
shape.scale(np.random.uniform(0.8, 1.2))
shape.pos(np.random.uniform(-2, 2, 3))
shapes.append(shape)
# Align all shapes
aligned_assembly = vedo.procrustes_alignment(shapes, rigid=False)
# Vector operations
v1 = vedo.vector(1, 2, 3)
v2 = vedo.vector([4, 5, 6])
magnitude1 = vedo.mag(v1)
magnitude2_sq = vedo.mag2(v2)
normalized = vedo.norm(v1)
print(f"Vector 1: {v1}")
print(f"Magnitude: {magnitude1:.2f}")
print(f"Normalized: {normalized}")
# Geometric analysis
sphere1 = vedo.Sphere(pos=(0, 0, 0), r=1)
sphere2 = vedo.Sphere(pos=(1.5, 0, 0), r=0.8)
geometry_info = vedo.geometry(sphere1, sphere2)
print("Geometric relationship:", geometry_info)
# Animation with transformation interpolation
transforms = []
for angle in np.linspace(0, 2*np.pi, 10):
T = np.array([
[np.cos(angle), -np.sin(angle), 0, 0],
[np.sin(angle), np.cos(angle), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
transforms.append(T)
interpolator = vedo.TransformInterpolator(transforms)
# Create smooth animation
animated_mesh = vedo.Cube()
for t in np.linspace(0, 1, 100):
T_interp = interpolator.evaluate(t)
transform_interp = vedo.LinearTransform(T_interp)
new_points = transform_interp.apply(animated_mesh.points())
animated_mesh.points(new_points)
vedo.show(animated_mesh, interactive=False)
# Precision and rounding utilities
values = np.array([3.14159265, 2.71828182, 1.41421356])
rounded_3dp = vedo.precision(values, 3)
rounded_2sig = vedo.round_to_digit(values, 2)
print(f"Original: {values}")
print(f"3 decimal places: {rounded_3dp}")
print(f"2 significant digits: {rounded_2sig}")
# Visualization of transformations
vedo.show([
original.c('red'),
mesh.c('blue'),
wave_mesh.c('green'),
fitted_plane.alpha(0.3),
aligned_assembly
], title="Geometric Transformations", axes=True)Install with Tessl CLI
npx tessl i tessl/pypi-vedo