0
# Geometric Transformations
1
2
Transform meshes through rotation, translation, and general 4x4 transformation matrices with support for rotation around arbitrary axes and points.
3
4
## Capabilities
5
6
### Rotation Operations
7
8
Rotate meshes around arbitrary axes with optional rotation points and pre-computed rotation matrices.
9
10
```python { .api }
11
def rotate(self, axis, theta=0, point=None):
12
"""
13
Rotate the mesh around an axis by a given angle.
14
15
Parameters:
16
- axis (array-like): Rotation axis vector [x, y, z]
17
- theta (float): Rotation angle in radians (use math.radians() for degrees)
18
- point (array-like, optional): Rotation point [x, y, z]
19
Defaults to origin [0, 0, 0]
20
21
Notes:
22
- Uses Euler-Rodrigues formula for efficient rotation
23
- Rotates both vertices and normal vectors
24
- Point parameter allows rotation around arbitrary points
25
- Positive angles produce clockwise rotation (legacy behavior)
26
"""
27
28
def rotate_using_matrix(self, rotation_matrix, point=None):
29
"""
30
Rotate using a pre-computed rotation matrix.
31
32
Parameters:
33
- rotation_matrix (numpy.array): 3x3 or 4x4 rotation matrix
34
- point (array-like, optional): Rotation point [x, y, z]
35
36
Notes:
37
- More efficient when applying same rotation to multiple meshes
38
- Matrix must have unit determinant for valid rotation
39
- Supports both 3x3 rotation and 4x4 transformation matrices
40
"""
41
42
@classmethod
43
def rotation_matrix(cls, axis, theta):
44
"""
45
Generate a rotation matrix for the given axis and angle.
46
47
Parameters:
48
- axis (array-like): Rotation axis vector [x, y, z]
49
- theta (float): Rotation angle in radians
50
51
Returns:
52
numpy.array: 3x3 rotation matrix
53
54
Notes:
55
- Uses Euler-Rodrigues formula for numerical stability
56
- Returns identity matrix if axis is zero vector
57
- Axis vector is automatically normalized
58
"""
59
```
60
61
### Translation Operations
62
63
Move meshes through 3D space with vector-based translation.
64
65
```python { .api }
66
def translate(self, translation):
67
"""
68
Translate the mesh by a given vector.
69
70
Parameters:
71
- translation (array-like): Translation vector [dx, dy, dz]
72
73
Notes:
74
- Translation vector must be length 3
75
- Adds translation to all vertex coordinates
76
- Does not affect normal vectors (translation-invariant)
77
"""
78
```
79
80
### General Transformations
81
82
Apply combined rotation and translation using 4x4 transformation matrices.
83
84
```python { .api }
85
def transform(self, matrix):
86
"""
87
Apply a 4x4 transformation matrix to the mesh.
88
89
Parameters:
90
- matrix (numpy.array): 4x4 transformation matrix
91
[R | t]
92
[0 | 1]
93
where R is 3x3 rotation, t is 3x1 translation
94
95
Notes:
96
- Matrix must be exactly 4x4 shape
97
- Rotation part (matrix[0:3, 0:3]) must have unit determinant
98
- Translation part is matrix[0:3, 3]
99
- Applies rotation to vertices and normals, translation only to vertices
100
"""
101
```
102
103
## Usage Examples
104
105
### Basic Rotations
106
107
```python
108
import math
109
import numpy as np
110
from stl import mesh
111
112
# Load a mesh
113
my_mesh = mesh.Mesh.from_file('model.stl')
114
115
# Rotate 45 degrees around Z-axis
116
my_mesh.rotate([0, 0, 1], math.radians(45))
117
118
# Rotate around X-axis
119
my_mesh.rotate([1, 0, 0], math.pi/2) # 90 degrees
120
121
# Rotate around arbitrary axis
122
axis = [1, 1, 0] # Diagonal axis
123
my_mesh.rotate(axis, math.radians(30))
124
```
125
126
### Rotation Around Specific Points
127
128
```python
129
import math
130
import numpy as np
131
from stl import mesh
132
133
my_mesh = mesh.Mesh.from_file('model.stl')
134
135
# Find the center of the mesh
136
center = (my_mesh.max_ + my_mesh.min_) / 2
137
138
# Rotate around the mesh center
139
my_mesh.rotate([0, 0, 1], math.radians(45), point=center)
140
141
# Rotate around a specific point
142
rotation_point = [10, 20, 30]
143
my_mesh.rotate([1, 0, 0], math.radians(90), point=rotation_point)
144
```
145
146
### Using Rotation Matrices
147
148
```python
149
import math
150
import numpy as np
151
from stl import mesh
152
153
my_mesh = mesh.Mesh.from_file('model.stl')
154
155
# Create a rotation matrix
156
axis = [0, 1, 0] # Y-axis
157
angle = math.radians(60)
158
rot_matrix = mesh.Mesh.rotation_matrix(axis, angle)
159
160
# Apply to multiple meshes efficiently
161
my_mesh.rotate_using_matrix(rot_matrix)
162
163
# Can also create custom rotation matrices
164
theta = math.radians(45)
165
cos_t, sin_t = math.cos(theta), math.sin(theta)
166
z_rotation = np.array([
167
[cos_t, -sin_t, 0],
168
[sin_t, cos_t, 0],
169
[0, 0, 1]
170
])
171
my_mesh.rotate_using_matrix(z_rotation)
172
```
173
174
### Translation Operations
175
176
```python
177
import numpy as np
178
from stl import mesh
179
180
my_mesh = mesh.Mesh.from_file('model.stl')
181
182
# Simple translation
183
my_mesh.translate([5, 10, -2])
184
185
# Move to origin (center the mesh)
186
center = (my_mesh.max_ + my_mesh.min_) / 2
187
my_mesh.translate(-center)
188
189
# Move to specific position
190
target_position = [100, 200, 50]
191
current_center = (my_mesh.max_ + my_mesh.min_) / 2
192
offset = target_position - current_center
193
my_mesh.translate(offset)
194
```
195
196
### Combined Transformations
197
198
```python
199
import math
200
import numpy as np
201
from stl import mesh
202
203
my_mesh = mesh.Mesh.from_file('model.stl')
204
205
# Create a 4x4 transformation matrix
206
# Combine 45-degree Z rotation with translation
207
angle = math.radians(45)
208
cos_a, sin_a = math.cos(angle), math.sin(angle)
209
210
transform_matrix = np.array([
211
[cos_a, -sin_a, 0, 10], # Rotation + X translation
212
[sin_a, cos_a, 0, 20], # Rotation + Y translation
213
[0, 0, 1, 5 ], # Z translation
214
[0, 0, 0, 1 ] # Homogeneous coordinate
215
])
216
217
my_mesh.transform(transform_matrix)
218
```
219
220
### Chaining Transformations
221
222
```python
223
import math
224
import numpy as np
225
from stl import mesh
226
227
my_mesh = mesh.Mesh.from_file('model.stl')
228
229
# Center the mesh at origin
230
center = (my_mesh.max_ + my_mesh.min_) / 2
231
my_mesh.translate(-center)
232
233
# Scale (simulate by creating scaled copy of vertices)
234
# Note: NumPy STL doesn't have direct scaling, but you can modify vectors
235
scale_factor = 2.0
236
my_mesh.vectors *= scale_factor
237
238
# Rotate around origin
239
my_mesh.rotate([0, 0, 1], math.radians(45))
240
241
# Move to final position
242
my_mesh.translate([100, 200, 50])
243
```
244
245
### Transformation Utilities
246
247
```python
248
import math
249
import numpy as np
250
from stl import mesh
251
252
def create_transform_matrix(rotation_axis, rotation_angle, translation):
253
"""Create a 4x4 transformation matrix."""
254
# Get 3x3 rotation matrix
255
rot_3x3 = mesh.Mesh.rotation_matrix(rotation_axis, rotation_angle)
256
257
# Create 4x4 matrix
258
transform = np.eye(4)
259
transform[0:3, 0:3] = rot_3x3
260
transform[0:3, 3] = translation
261
262
return transform
263
264
# Usage
265
my_mesh = mesh.Mesh.from_file('model.stl')
266
transform = create_transform_matrix(
267
rotation_axis=[0, 0, 1],
268
rotation_angle=math.radians(30),
269
translation=[5, 10, 0]
270
)
271
my_mesh.transform(transform)
272
```
273
274
## Mathematical Notes
275
276
### Rotation Matrix Properties
277
278
- Rotation matrices are orthogonal with unit determinant
279
- The library uses Euler-Rodrigues formula for numerical stability
280
- Positive angles produce clockwise rotations (legacy behavior)
281
- Rotation matrices preserve distances and angles
282
283
### Coordinate System
284
285
- Right-handed coordinate system is assumed
286
- Z-axis typically points "up" in 3D printing contexts
287
- STL files may use different coordinate conventions
288
289
### Performance Considerations
290
291
- `rotate_using_matrix()` is more efficient for repeated rotations
292
- Pre-compute rotation matrices when applying the same rotation to multiple meshes
293
- Large meshes benefit from vectorized NumPy operations
294
295
## Error Handling
296
297
- **AssertionError**: Raised for invalid matrix dimensions or non-unit determinants
298
- **TypeError**: Raised for incorrect parameter types (e.g., wrong point format)
299
- **ValueError**: Raised for invalid transformation matrix properties