0
# Transformations and Geometry
1
2
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.
3
4
## Capabilities
5
6
### Linear Transformations
7
8
Classes for applying linear geometric transformations to 3D objects.
9
10
```python { .api }
11
class LinearTransform:
12
"""
13
Apply linear transformations using 4x4 transformation matrices.
14
15
Parameters:
16
- T: array-like
17
4x4 transformation matrix or list of transformations
18
"""
19
def __init__(self, T): ...
20
21
def apply(self, points):
22
"""
23
Apply transformation to points.
24
25
Parameters:
26
- points: array-like
27
Points to transform
28
29
Returns:
30
numpy.ndarray: Transformed points
31
"""
32
33
class NonLinearTransform:
34
"""
35
Apply non-linear transformations using custom functions.
36
37
Parameters:
38
- func: callable
39
Transformation function
40
- invert: bool, default False
41
Apply inverse transformation
42
"""
43
def __init__(self, func, invert=False): ...
44
45
def apply(self, points):
46
"""
47
Apply non-linear transformation to points.
48
49
Parameters:
50
- points: array-like
51
Points to transform
52
53
Returns:
54
numpy.ndarray: Transformed points
55
"""
56
57
class TransformInterpolator:
58
"""
59
Interpolate between transformation matrices for smooth animations.
60
61
Parameters:
62
- transforms: list
63
List of transformation matrices
64
- times: list, optional
65
Time points for each transformation
66
"""
67
def __init__(self, transforms, times=None): ...
68
69
def evaluate(self, t):
70
"""
71
Evaluate transformation at given time.
72
73
Parameters:
74
- t: float
75
Time parameter (0-1)
76
77
Returns:
78
numpy.ndarray: Interpolated transformation matrix
79
"""
80
```
81
82
### Coordinate System Conversions
83
84
Functions for converting between different coordinate systems commonly used in scientific applications.
85
86
```python { .api }
87
def cart2spher(x, y, z):
88
"""
89
Convert Cartesian to spherical coordinates.
90
91
Parameters:
92
- x, y, z: float or array-like
93
Cartesian coordinates
94
95
Returns:
96
numpy.ndarray: [rho, theta, phi] spherical coordinates
97
"""
98
99
def spher2cart(rho, theta, phi):
100
"""
101
Convert spherical to Cartesian coordinates.
102
103
Parameters:
104
- rho: float or array-like
105
Radial distance
106
- theta: float or array-like
107
Azimuthal angle (radians)
108
- phi: float or array-like
109
Polar angle (radians)
110
111
Returns:
112
numpy.ndarray: [x, y, z] Cartesian coordinates
113
"""
114
115
def cart2cyl(x, y, z):
116
"""
117
Convert Cartesian to cylindrical coordinates.
118
119
Parameters:
120
- x, y, z: float or array-like
121
Cartesian coordinates
122
123
Returns:
124
numpy.ndarray: [rho, theta, z] cylindrical coordinates
125
"""
126
127
def cyl2cart(rho, theta, z):
128
"""
129
Convert cylindrical to Cartesian coordinates.
130
131
Parameters:
132
- rho: float or array-like
133
Radial distance in xy-plane
134
- theta: float or array-like
135
Azimuthal angle (radians)
136
- z: float or array-like
137
Height coordinate
138
139
Returns:
140
numpy.ndarray: [x, y, z] Cartesian coordinates
141
"""
142
143
def cart2pol(x, y):
144
"""
145
Convert 2D Cartesian to polar coordinates.
146
147
Parameters:
148
- x, y: float or array-like
149
2D Cartesian coordinates
150
151
Returns:
152
numpy.ndarray: [rho, theta] polar coordinates
153
"""
154
155
def pol2cart(rho, theta):
156
"""
157
Convert polar to 2D Cartesian coordinates.
158
159
Parameters:
160
- rho: float or array-like
161
Radial distance
162
- theta: float or array-like
163
Angle (radians)
164
165
Returns:
166
numpy.ndarray: [x, y] Cartesian coordinates
167
"""
168
169
def cyl2spher(rho, theta, z):
170
"""
171
Convert cylindrical to spherical coordinates.
172
173
Parameters:
174
- rho: float or array-like
175
Cylindrical radius
176
- theta: float or array-like
177
Azimuthal angle (radians)
178
- z: float or array-like
179
Height coordinate
180
181
Returns:
182
numpy.ndarray: [rho_s, theta_s, phi_s] spherical coordinates
183
"""
184
185
def spher2cyl(rho, theta, phi):
186
"""
187
Convert spherical to cylindrical coordinates.
188
189
Parameters:
190
- rho: float or array-like
191
Spherical radius
192
- theta: float or array-like
193
Azimuthal angle (radians)
194
- phi: float or array-like
195
Polar angle (radians)
196
197
Returns:
198
numpy.ndarray: [rho_c, theta_c, z] cylindrical coordinates
199
"""
200
```
201
202
### Geometric Fitting Functions
203
204
Advanced functions for fitting geometric primitives and analyzing spatial relationships.
205
206
```python { .api }
207
def fit_plane(points, signed=False):
208
"""
209
Fit a plane through 3D points using least squares.
210
211
Parameters:
212
- points: array-like or Points object
213
Input point coordinates
214
- signed: bool, default False
215
Return signed distances from plane
216
217
Returns:
218
Plane: Fitted plane object with normal and center
219
"""
220
221
def fit_sphere(coords):
222
"""
223
Fit a sphere through 3D points.
224
225
Parameters:
226
- coords: array-like or Points object
227
Input point coordinates
228
229
Returns:
230
Sphere: Fitted sphere object with center and radius
231
"""
232
233
def fit_line(points):
234
"""
235
Fit a line through points using linear regression.
236
237
Parameters:
238
- points: array-like or Points object
239
Input point coordinates
240
241
Returns:
242
Line: Fitted line object
243
"""
244
245
def fit_circle(points):
246
"""
247
Fit a circle through 2D or 3D points.
248
249
Parameters:
250
- points: array-like or Points object
251
Input point coordinates
252
253
Returns:
254
tuple: (center, radius, normal) of fitted circle
255
"""
256
```
257
258
### Assembly and Alignment
259
260
Functions for aligning and combining geometric objects.
261
262
```python { .api }
263
def procrustes_alignment(sources, rigid=False):
264
"""
265
Align meshes using Procrustes analysis.
266
267
The Procrustes algorithm aligns multiple point sets in a least-squares sense
268
to their mutual mean, iterating until convergence.
269
270
Parameters:
271
- sources: list of Mesh objects
272
Source meshes to align (must have same number of points)
273
- rigid: bool, default False
274
If True, scaling is disabled (rigid body transformation only)
275
276
Returns:
277
Assembly: Assembly containing aligned meshes
278
"""
279
```
280
281
### Geometric Utility Functions
282
283
Helper functions for common geometric calculations and operations.
284
285
```python { .api }
286
def geometry(obj1, obj2=None):
287
"""
288
Compute geometric properties and relationships between objects.
289
290
Parameters:
291
- obj1: vedo object
292
First object
293
- obj2: vedo object, optional
294
Second object for pairwise calculations
295
296
Returns:
297
dict: Dictionary containing geometric measurements
298
"""
299
300
def vector(x, y=None, z=None):
301
"""
302
Create or normalize 3D vectors.
303
304
Parameters:
305
- x: float, array-like, or tuple
306
X component or complete vector
307
- y: float, optional
308
Y component
309
- z: float, optional
310
Z component
311
312
Returns:
313
numpy.ndarray: 3D vector
314
"""
315
316
def mag(vector):
317
"""
318
Calculate vector magnitude.
319
320
Parameters:
321
- vector: array-like
322
Input vector
323
324
Returns:
325
float: Vector magnitude
326
"""
327
328
def mag2(vector):
329
"""
330
Calculate squared vector magnitude (faster than mag).
331
332
Parameters:
333
- vector: array-like
334
Input vector
335
336
Returns:
337
float: Squared vector magnitude
338
"""
339
340
def norm(vector):
341
"""
342
Normalize vector to unit length.
343
344
Parameters:
345
- vector: array-like
346
Input vector
347
348
Returns:
349
numpy.ndarray: Normalized vector
350
"""
351
352
def precision(x, p):
353
"""
354
Round numbers to specified precision.
355
356
Parameters:
357
- x: float or array-like
358
Input values
359
- p: int
360
Number of decimal places
361
362
Returns:
363
float or array: Rounded values
364
"""
365
366
def round_to_digit(x, digit):
367
"""
368
Round to specified number of significant digits.
369
370
Parameters:
371
- x: float or array-like
372
Input values
373
- digit: int
374
Number of significant digits
375
376
Returns:
377
float or array: Rounded values
378
"""
379
```
380
381
## Usage Examples
382
383
```python
384
import vedo
385
import numpy as np
386
387
# Coordinate system conversions
388
x, y, z = 1.0, 2.0, 3.0
389
390
# Convert to spherical coordinates
391
rho, theta, phi = vedo.cart2spher(x, y, z)
392
print(f"Spherical: rho={rho:.2f}, theta={theta:.2f}, phi={phi:.2f}")
393
394
# Convert back to Cartesian
395
x2, y2, z2 = vedo.spher2cart(rho, theta, phi)
396
print(f"Cartesian: x={x2:.2f}, y={y2:.2f}, z={z2:.2f}")
397
398
# Cylindrical coordinates
399
rho_c, theta_c, z_c = vedo.cart2cyl(x, y, z)
400
print(f"Cylindrical: rho={rho_c:.2f}, theta={theta_c:.2f}, z={z_c:.2f}")
401
402
# Batch coordinate conversion
403
points_cart = np.random.rand(100, 3) * 10
404
points_spher = np.array([vedo.cart2spher(p[0], p[1], p[2]) for p in points_cart])
405
406
# Linear transformations
407
# Create transformation matrix for 45-degree rotation around Z-axis
408
angle = np.pi / 4
409
T = np.array([
410
[np.cos(angle), -np.sin(angle), 0, 0],
411
[np.sin(angle), np.cos(angle), 0, 0],
412
[0, 0, 1, 0],
413
[0, 0, 0, 1]
414
])
415
416
transform = vedo.LinearTransform(T)
417
418
# Apply to mesh
419
mesh = vedo.Sphere()
420
original_points = mesh.points()
421
transformed_points = transform.apply(original_points)
422
mesh.points(transformed_points)
423
424
# Non-linear transformation example
425
def wave_transform(points):
426
"""Apply sinusoidal wave transformation."""
427
result = points.copy()
428
result[:, 2] += 0.5 * np.sin(2 * points[:, 0]) * np.cos(2 * points[:, 1])
429
return result
430
431
nonlinear_transform = vedo.NonLinearTransform(wave_transform)
432
wave_mesh = vedo.Box()
433
wave_points = nonlinear_transform.apply(wave_mesh.points())
434
wave_mesh.points(wave_points)
435
436
# Geometric fitting
437
# Generate noisy circle data
438
t = np.linspace(0, 2*np.pi, 50)
439
circle_points = np.column_stack([
440
2 * np.cos(t) + np.random.normal(0, 0.1, 50),
441
2 * np.sin(t) + np.random.normal(0, 0.1, 50),
442
np.random.normal(0, 0.1, 50)
443
])
444
445
# Fit geometric primitives
446
fitted_plane = vedo.fit_plane(circle_points)
447
fitted_sphere = vedo.fit_sphere(circle_points)
448
fitted_line = vedo.fit_line(circle_points)
449
450
# Procrustes alignment of multiple objects
451
# Create similar but transformed objects
452
original = vedo.load("bunny.obj") # Example mesh
453
shapes = []
454
for i in range(5):
455
shape = original.clone()
456
# Apply random transformations
457
shape.rotate_z(np.random.uniform(0, 360))
458
shape.scale(np.random.uniform(0.8, 1.2))
459
shape.pos(np.random.uniform(-2, 2, 3))
460
shapes.append(shape)
461
462
# Align all shapes
463
aligned_assembly = vedo.procrustes_alignment(shapes, rigid=False)
464
465
# Vector operations
466
v1 = vedo.vector(1, 2, 3)
467
v2 = vedo.vector([4, 5, 6])
468
469
magnitude1 = vedo.mag(v1)
470
magnitude2_sq = vedo.mag2(v2)
471
normalized = vedo.norm(v1)
472
473
print(f"Vector 1: {v1}")
474
print(f"Magnitude: {magnitude1:.2f}")
475
print(f"Normalized: {normalized}")
476
477
# Geometric analysis
478
sphere1 = vedo.Sphere(pos=(0, 0, 0), r=1)
479
sphere2 = vedo.Sphere(pos=(1.5, 0, 0), r=0.8)
480
481
geometry_info = vedo.geometry(sphere1, sphere2)
482
print("Geometric relationship:", geometry_info)
483
484
# Animation with transformation interpolation
485
transforms = []
486
for angle in np.linspace(0, 2*np.pi, 10):
487
T = np.array([
488
[np.cos(angle), -np.sin(angle), 0, 0],
489
[np.sin(angle), np.cos(angle), 0, 0],
490
[0, 0, 1, 0],
491
[0, 0, 0, 1]
492
])
493
transforms.append(T)
494
495
interpolator = vedo.TransformInterpolator(transforms)
496
497
# Create smooth animation
498
animated_mesh = vedo.Cube()
499
for t in np.linspace(0, 1, 100):
500
T_interp = interpolator.evaluate(t)
501
transform_interp = vedo.LinearTransform(T_interp)
502
new_points = transform_interp.apply(animated_mesh.points())
503
animated_mesh.points(new_points)
504
vedo.show(animated_mesh, interactive=False)
505
506
# Precision and rounding utilities
507
values = np.array([3.14159265, 2.71828182, 1.41421356])
508
rounded_3dp = vedo.precision(values, 3)
509
rounded_2sig = vedo.round_to_digit(values, 2)
510
511
print(f"Original: {values}")
512
print(f"3 decimal places: {rounded_3dp}")
513
print(f"2 significant digits: {rounded_2sig}")
514
515
# Visualization of transformations
516
vedo.show([
517
original.c('red'),
518
mesh.c('blue'),
519
wave_mesh.c('green'),
520
fitted_plane.alpha(0.3),
521
aligned_assembly
522
], title="Geometric Transformations", axes=True)
523
```