0
# Affinity Transformations
1
2
Geometric transformations that preserve straight lines and ratios of distances along straight lines. These transformations include rotation, scaling, translation, skewing, and general affine transformations using transformation matrices.
3
4
## Capabilities
5
6
### Translation
7
8
Move geometries by specified offset distances.
9
10
```python { .api }
11
def translate(geom, xoff=0.0, yoff=0.0, zoff=0.0):
12
"""
13
Translate (move) geometry by offset distances.
14
15
Parameters:
16
- geom: input geometry
17
- xoff: offset distance in X direction
18
- yoff: offset distance in Y direction
19
- zoff: offset distance in Z direction (for 3D geometries)
20
21
Returns:
22
Geometry: translated geometry
23
"""
24
```
25
26
**Usage Example:**
27
28
```python
29
from shapely import affinity
30
from shapely.geometry import Point, Polygon
31
32
# Translate a point
33
point = Point(1, 2)
34
moved_point = affinity.translate(point, xoff=5, yoff=3)
35
print(f"Original: {point}")
36
print(f"Translated: {moved_point}")
37
38
# Translate a polygon
39
square = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
40
moved_square = affinity.translate(square, xoff=10, yoff=5)
41
print(f"Original bounds: {square.bounds}")
42
print(f"Translated bounds: {moved_square.bounds}")
43
```
44
45
### Rotation
46
47
Rotate geometries around a specified origin point.
48
49
```python { .api }
50
def rotate(geom, angle, origin='center', use_radians=False):
51
"""
52
Rotate geometry around an origin point.
53
54
Parameters:
55
- geom: input geometry
56
- angle: rotation angle (degrees by default, radians if use_radians=True)
57
- origin: rotation origin ('center', 'centroid', or (x, y) coordinate)
58
- use_radians: if True, angle is in radians instead of degrees
59
60
Returns:
61
Geometry: rotated geometry
62
"""
63
```
64
65
**Usage Example:**
66
67
```python
68
from shapely import affinity
69
from shapely.geometry import Polygon
70
import math
71
72
# Create a rectangle
73
rect = Polygon([(0, 0), (2, 0), (2, 1), (0, 1)])
74
75
# Rotate 45 degrees around center
76
rotated_45 = affinity.rotate(rect, 45)
77
print(f"Original area: {rect.area}")
78
print(f"Rotated area: {rotated_45.area:.6f}") # Should be same
79
80
# Rotate around specific point
81
rotated_around_origin = affinity.rotate(rect, 90, origin=(0, 0))
82
print(f"Rotated around origin bounds: {rotated_around_origin.bounds}")
83
84
# Rotate using radians
85
rotated_radians = affinity.rotate(rect, math.pi/2, use_radians=True)
86
print(f"90° rotation matches π/2 radians: {rotated_around_origin.equals(rotated_radians)}")
87
```
88
89
### Scaling
90
91
Scale geometries by specified factors along each axis.
92
93
```python { .api }
94
def scale(geom, xfact=1.0, yfact=1.0, zfact=1.0, origin='center'):
95
"""
96
Scale geometry by specified factors.
97
98
Parameters:
99
- geom: input geometry
100
- xfact: scaling factor for X direction
101
- yfact: scaling factor for Y direction
102
- zfact: scaling factor for Z direction (for 3D geometries)
103
- origin: scaling origin ('center', 'centroid', or (x, y) coordinate)
104
105
Returns:
106
Geometry: scaled geometry
107
"""
108
```
109
110
**Usage Example:**
111
112
```python
113
from shapely import affinity
114
from shapely.geometry import Polygon
115
116
# Create a square
117
square = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
118
print(f"Original area: {square.area}")
119
120
# Uniform scaling (double size)
121
double_size = affinity.scale(square, xfact=2.0, yfact=2.0)
122
print(f"2x scaled area: {double_size.area}") # Should be 4x original
123
124
# Non-uniform scaling
125
stretched = affinity.scale(square, xfact=3.0, yfact=0.5)
126
print(f"Stretched area: {stretched.area}") # Should be 1.5x original
127
128
# Scale around specific origin
129
scaled_from_corner = affinity.scale(square, xfact=2.0, yfact=2.0, origin=(0, 0))
130
print(f"Scaled from corner bounds: {scaled_from_corner.bounds}")
131
```
132
133
### Skewing
134
135
Apply shear transformations to geometries.
136
137
```python { .api }
138
def skew(geom, xs=0.0, ys=0.0, origin='center', use_radians=False):
139
"""
140
Skew (shear) geometry by specified angles.
141
142
Parameters:
143
- geom: input geometry
144
- xs: skew angle in X direction
145
- ys: skew angle in Y direction
146
- origin: skew origin ('center', 'centroid', or (x, y) coordinate)
147
- use_radians: if True, angles are in radians instead of degrees
148
149
Returns:
150
Geometry: skewed geometry
151
"""
152
```
153
154
**Usage Example:**
155
156
```python
157
from shapely import affinity
158
from shapely.geometry import Polygon
159
160
# Create a square
161
square = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
162
163
# Skew in X direction (creates parallelogram)
164
skewed_x = affinity.skew(square, xs=30) # 30 degree skew
165
print(f"Original area: {square.area}")
166
print(f"Skewed area: {skewed_x.area:.6f}") # Area should be preserved
167
168
# Skew in both directions
169
skewed_both = affinity.skew(square, xs=15, ys=10)
170
print(f"Double skewed bounds: {skewed_both.bounds}")
171
```
172
173
### General Affine Transformation
174
175
Apply arbitrary affine transformations using transformation matrices.
176
177
```python { .api }
178
def affine_transform(geom, matrix):
179
"""
180
Apply affine transformation using transformation matrix.
181
182
Parameters:
183
- geom: input geometry
184
- matrix: 6-element transformation matrix [a, b, d, e, xoff, yoff]
185
representing the transformation:
186
x' = a*x + b*y + xoff
187
y' = d*x + e*y + yoff
188
189
Returns:
190
Geometry: transformed geometry
191
"""
192
```
193
194
**Usage Example:**
195
196
```python
197
from shapely import affinity
198
from shapely.geometry import Point
199
import math
200
201
# Identity transformation (no change)
202
point = Point(1, 2)
203
identity_matrix = [1, 0, 0, 1, 0, 0] # [a, b, d, e, xoff, yoff]
204
unchanged = affinity.affine_transform(point, identity_matrix)
205
print(f"Identity transform: {point.equals(unchanged)}")
206
207
# Translation using matrix
208
translate_matrix = [1, 0, 0, 1, 5, 3] # translate by (5, 3)
209
translated = affinity.affine_transform(point, translate_matrix)
210
print(f"Matrix translated: {translated}")
211
212
# Compare with translate function
213
also_translated = affinity.translate(point, 5, 3)
214
print(f"Methods equivalent: {translated.equals(also_translated)}")
215
216
# Rotation using matrix (45 degrees)
217
cos_45 = math.cos(math.pi/4)
218
sin_45 = math.sin(math.pi/4)
219
rotation_matrix = [cos_45, -sin_45, sin_45, cos_45, 0, 0]
220
rotated = affinity.affine_transform(point, rotation_matrix)
221
print(f"Matrix rotated: {rotated}")
222
223
# Complex transformation: scale + rotate + translate
224
# Scale by 2, rotate 30°, translate by (10, 5)
225
cos_30 = math.cos(math.pi/6)
226
sin_30 = math.sin(math.pi/6)
227
complex_matrix = [
228
2 * cos_30, # a = 2 * cos(30°)
229
-2 * sin_30, # b = -2 * sin(30°)
230
2 * sin_30, # d = 2 * sin(30°)
231
2 * cos_30, # e = 2 * cos(30°)
232
10, # xoff = 10
233
5 # yoff = 5
234
]
235
complex_transformed = affinity.affine_transform(point, complex_matrix)
236
print(f"Complex transform result: {complex_transformed}")
237
```
238
239
### Chaining Transformations
240
241
Combine multiple transformations for complex effects.
242
243
**Usage Example:**
244
245
```python
246
from shapely import affinity
247
from shapely.geometry import Polygon
248
249
# Create original shape
250
triangle = Polygon([(0, 0), (2, 0), (1, 2)])
251
252
# Chain transformations
253
result = triangle
254
result = affinity.translate(result, xoff=5, yoff=3) # Move to new position
255
result = affinity.rotate(result, 45) # Rotate 45 degrees
256
result = affinity.scale(result, xfact=1.5, yfact=1.5) # Scale up by 50%
257
result = affinity.skew(result, xs=10) # Add slight skew
258
259
print(f"Original centroid: {triangle.centroid}")
260
print(f"Final centroid: {result.centroid}")
261
print(f"Area change: {result.area / triangle.area:.2f}x")
262
```
263
264
## Import Note
265
266
The affinity module is not imported automatically with shapely and must be imported separately:
267
268
```python
269
from shapely import affinity
270
# or
271
import shapely.affinity as affinity
272
```