Transforms
Consider the following example:
This draws a white 50×50
square near the top-right corner of the canvas.
We now insert a scaling transform before the draw_rect
call:
The results in a square twice as big (100×100
) being drawn. Also notice that the square's top-left corner is now located at (20, 20)
.
The canvas.scale
call does not affect any rendering before its call. Instead, it effectively scales the space in which subsequent drawing calls operate.
Transformation Matrices
In its most general form, the canvas supports arbitrary affine transforms that can be represented, in an augmented matrix form, as:
The utility transformation methods (like scale
, rotate
, translate
) are all special cases of this. However, you can always directly specify a transformation matrix. In Python, you can represent these matrices as —
A nested list or tuple representing either a
2×3
matrix (the final row implicitly being0 0 1
) or a3×3
matrix (the final row must be0 0 1
)# 2×3 form scale = [ [2, 0, 0], [0, 2, 0] ] # 3×3 form translate = [ [1, 0, 3], [0, 1, 4], [0, 0, 1] ]A NumPy
2×3
or3×3
arrayidentity = np.eye(3)
Composition
By default, canvas transforms compose. In particular, they chain on the right — that is, the last performed transformation is applied first:
As an example, say we want to rotate this square about its center by 45°
Inserting a canvas.rotate
is insufficient, since it rotates about the origin, which is currently situated at the top-left corner.
To rotate about the square's center (100, 100)
instead, we first want to make it the new origin (0, 0)
. Translating by (-100, -100)
accomplishes this. The composition order described above tells us that the last transform to appear in our code is applied first. So, we do this after the rotate
call:
Finally, we want to translate back the center to its original position. This should occur after the rotation has been performed. So, based on the composition ordering, this translation needs to appear before the rotation in our code:
API
Canvas.scale
Composes a scaling transformation.
- It accepts a scaling factor for each axis (
x
andy
). - Providing a negative scaling factor flips the corresponding axis.
Canvas.rotate
Composes a rotation transformation.
- The rotation angle should be in radians.
- The rotation occurs about the current origin (by default the top-left corner).
Canvas.translate
Composes a translation transformation.
Canvas.transform
The transform
method accepts a transformation matrix and an optional keyword argument reset
(by default False
).
- If
reset
isFalse
(the default case), the given transformation matrix is composed with the existing transformation (as described here). - Otherwise, the given transformation matrix replaces the prior one.
Canvas.reset_transform
Sets the current transformation to identity.
- This is equivalent to
canvas.transform([[1, 0, 0], [0, 1, 0]], reset=True)
.