3.2. The `Xform` class: Coordinate transformation

An instance of this class represents an arbitrary transform. Here is the general form of the constructor:

```Xform ( `m` )
```

The argument `m` is the 3×3 transform matrix as a `numpy` array, or a sequence that can be passed to `numpy`'s `array()` constructor to create the transform matrix.

These methods are available on instances of the class:

`.apply ( p )`

Given a point `p` as a `Pt` instance, return a new `Pt` instance representing the transformed point.

`.__call__(self, p)`

Instead of using the `.apply()` method, you may call the `Xform` instance directly. Pass it a `Pt` instance and it returns the transform point.

`.invert ( p )`

Runs the inverse transform. Returns the value `q` such that `.apply(q)` method would return `p`.

`.inverse()`

Returns the inverse transform as an `Xform` instance.

`.compose ( T )`

The argument `T` is another instance of the `Xform` class. The method returns a new transformation that is the composition of both transformations.

For example, if `t1` is an `Xform` instance representing a translation, and `t2` is another `Xform` instance representing a rotation, this expression returns a new `Xform` instance that represents that translation followed by that rotation:

```t1.compose(t2)
```

`.__mul__(self, other)`

Same as `self.compose(self, other)`.

`.offset()`

Returns the net offset of this transform as a `Pt` instance. For example, if the transform moves the origin to (3, 4), this method will return `Pt(3, 4)`.

`.angle()`

Returns the net angle of rotation of this transform in radians.

`.mag()`

Returns the net magnification that this transform has on a vector of length 1, as a scalar.

The `homcoord` module includes three convenience functions for constructing instances of the `Xform` class that represent the three basic transform types.

`Xlate ( *d )`

Returns a translation transform. The arguments `*d` may be:

• Two values specifying the `x` and `y` offsets.

• One iterable argument containing the two values for the `x` and `y` offsets.

Examples:

```x1 = Xlate ( 1.0, 2.0 )  # Move 1 to the right, up 2
x2 = Xlate ( [-1.0, -2.0] )  # Move 1 left, down 2
```
`Xscale ( s )`

Returns a scaling transform. The argument `s` may be either a single number or a sequence of two numbers. If a single number, both coordinates are scaled by multiplying them by `s`. If `s` is a sequence of two values, the `x` coordinate will be multiplied by the first number and the `y` coordinate multiplied by the second number.

Examples:

```x3 = Xscale ( 2.0 )        # Make everything twice as big
x4 = Xscale ( 4.0, 2.0 )    # Quadruple the x, double the y
x5 = Xscale ( [4.0, 2.0] )  # Same as the previous line
```
```Xrotate ( theta )```

Returns a rotation transform. The argument `theta` is the counterclockwise angle of rotation expressed in radians.

```Xrotaround ( p, theta )```

Returns a transform that represents rotation around a given point `p` by an angle `theta`.