In the last issue of Canvas Foundation and Implementation of Bezier Curve Animation, we reviewed the basic operations of Canvas and the implementation principle of Bezier curve. This time, we will supplement one of the basics left over from the previous article: the transform matrix.

Deformation of the transform

The transform(a, B, C, D, dx, dy) method is to multiply the current transformation matrix by the matrix of parameters:

a c dx
b d dy
0 0 1
Copy the code

Parameters are represented as follows:

  • A: Horizontal scaling
  • B: Horizontal tilt deviation
  • C: vertical tilt deviation
  • D: vertical scaling
  • Dx: horizontal movement
  • Dy: vertical movement

The setTransform(A, B, C, D, dx, dy) method resets the current deformation matrix to the identity matrix and then calls the transform method with the same parameters, that is, the method cancellations the current deformation and then sets it to the specified deformation. ResetTransform () resets the current transform to the identity matrix, equivalent to calling setTransform(1, 0, 0, 1, 0, 0), which is the default matrix (identity matrix) below:

1 0 0
0 1 0
0 0 1
Copy the code

Here is a sample diagram and code:

ctx.fillStyle = 'red';
ctx.fillRect(0.0.100.50);

ctx.transform(1.0.0.1.50.50);
ctx.fillStyle = 'orange';
ctx.fillRect(0.0.100.50);

ctx.transform(0.1.1.0.50.50);
ctx.fillStyle = 'yellow';
ctx.fillRect(0.0.100.50);

ctx.transform(1.- 1.1.1.0.0);
ctx.fillStyle = 'lime';
ctx.fillRect(0.0.100.50);
Copy the code

  1. Under the default matrix, a red rectangle is drawn.
  2. Ctx.transform (1, 0, 0, 1, 50, 50) equals ctx.translate(50, 50), the orange rectangle is translated relative to the red rectangle, and now the matrix is:
    1 0 0 | | | 1 0 50 | | 1 0 50 | | 0 1 0, | | 0 1, 50 50 | | = | 0 1 | 0 0 1 | | 0 0 1 | | | 0 0 1Copy the code
  3. CTX. Transform (0, 1, 1, 0, 50, 50)
    1 0 to 50 | | | 0 1 50 | | 0 + 0 * 1 + 1 * 50 * * 0 0 1 * 1 + 0 + 50 * 50 + 0 0 1 * * 50 * 50 + 1 | | 0 1 100 | | 0 1 50, | | 1 0, 50 | = | 0 * 0 + 50 * 1 * 1 + 0 * 1 + 1 * 0 0 0 0 + 50 * * 50 * 50 * 50 + 1 + 1 1 0 100 | | = | | 0 0 1 | | 0 0 1 | | 0 + 0 0 * * * 1 + 1 + 1 * 0 0 0 * 50 + 0 0 0 0 + 1 * * * 50 + 1 * 1 | | | 0 0 1Copy the code

    Translate ctx.Translate (100, 100) in the original state, then tilt it in the horizontal and vertical direction, where the yellow rectangle is now.

  4. CTX. Transform (1, -1, 1, 1, 0, 0), matrix transformation is:
    100 | | 0 1 1 1 0 | | | - 1 of 1 100 | | 100 | 1 0, 1 0 | | - 1 =... 1 1 = | 100 | | 0 0 1 | | 0 0 1 | | | 0 0 1Copy the code

    Equivalent to ctx.setTransform(-1, 1, 1, 1, 100, 100).

Homogeneous coordinates

The canvas transform matrix is the same as the matrix() of CSS3 transform. The function uses homogeneous coordinates.

What are homogeneous coordinates

Let’s take a look at wikipedia’s description of homogeneous coordinates:

In mathematics, homogeneous coordinates, or projective coordinates, are a system of coordinates for projective geometry, just as cartesian coordinates are for Euclidean geometry. The term was introduced by Auguste Ferdinand Mobius in his book Der Barycentrische Calcul in 1827. Homogeneous coordinates allow the coordinates of points including points at infinity to be expressed in finite coordinates. Formulas using homogeneous coordinates are generally simpler and more symmetric than cartesian coordinates. Homogeneous coordinates have a wide range of applications, including computer graphics and 3D computer vision. The use of homogeneous coordinates allows the computer to perform affine transformations and, in general, its projection transformations can be expressed simply as matrices. If the homogeneous coordinates of a point are multiplied by a nonzero scalar, the resulting coordinates represent the same point. Because homogeneous coordinates are also used to represent points at infinity, this extension requires one more dimension than the projection space to represent coordinates. For example, in homogeneous coordinates, you need two values to represent a point on the projection line, three values to represent a point on the projection plane. The real projection plane can be thought of as a Euclidean plane with additional points, called infinity points, and considered to lie on a new line (called infinity line). Each infinity point corresponding to a direction (given by the slope of a line) can be informally defined as the limit of a point moving in that direction from the origin. Parallel lines in the Euclidean plane can be thought of as intersecting at infinity corresponding to their common direction. Given a point (x, y) on the Euclidean plane, the triplet (xZ, yZ, Z) of any non-zero real number Z is called the homogeneous coordinate of the point. By definition, another set of homogeneous coordinates of the same point can be obtained by multiplying the values in homogeneous coordinates by a non-zero real number. For example, a point on the cartesian coordinate (1,2) can be labeled (1,2,1) or (2,4,2) in homogeneous coordinates. The original Cartesian coordinates can be retrieved by dividing the first two values by the third. Thus, unlike cartesian coordinates, a point can have an infinite number of homogeneous coordinate representations. The equation of a line passing through the origin (0, 0) can be written as nx + my = 0, where n and m cannot both be 0. In terms of parameters, x = mt and y = − nt can be written. If Z=1/t, the Cartesian coordinates of the points on the line can be written as (m/Z, − n/Z). In homogeneous coordinates, it is written as (m, − n, Z). As t approaches infinity, that is, as the point moves away from the origin, Z approaches 0, and the homogeneous coordinate of the point becomes (m, −n, 0). Therefore, (m, −n, 0) can be defined as the homogeneous coordinate of the point at infinity in the direction of the line nx + my = 0. Because every line in the Euclidean plane will be parallel to some line passing through the origin, and because parallel lines will have the same infinity point, every infinity point on the Euclidean plane will have its homogeneous coordinates. In general, any point on the projection plane can be represented as a triplet (X, Y, Z), which is called the homogeneous or projected coordinate of the point, where X, Y and Z are not all 0. A point represented by a homogeneous coordinate table is represented if all the values in the coordinate are multiplied by an identical non-zero real number. Conversely, two homogeneous coordinates represent the same point if and only if one of them can be obtained by multiplying the other by an identical nonzero constant. When Z is not 0, the point represents this (X/Z, Y/Z) in the Euclidean plane. When Z is 0, this point represents an infinity point.

In simple terms, homogeneous coordinates are N+1 dimensions for N dimensions. Compared to cartesian coordinates, there is an extra variable w. When this variable W is not zero, (x, y, w) represents the point (x/w, y/w); When this variable w is 0, it represents the point at infinity, so (x, y, 0) can also represent the vector (x, y).

If you don’t understand the variable W, imagine that you have a coordinate system in front of you, and your vertical distance from the coordinate system is the variable W.

Why use homogeneous coordinates

Why do we use homogeneous coordinates? It is mainly convenient for computer graphics to carry out affine geometric transformation. In simple terms, it is to use matrix multiplication to achieve the effect of translation, rotation, scale and deflection of the graph at the same time.

Combined with the above example, if homogeneous coordinates are used, the transformed coordinates of the points in the rectangle can be obtained by the following matrix formula:

X | a c e | | | | ax + cy + e | | b, d, f, | | | = | y, bx + dy + f | | 0 0 1 | | 1 | | 1 | x' = ax + cy + e
y' = bx + dy + f
Copy the code

Translate (), rotate(), scale() and other methods correspond to transform() :

  1. Translate (x, y) translates to transform(1, 0, 0, 1, x, y);
  2. Rotation: Rotate by a radian, using the following two methods
    let a;
    let sin = Math.sin(a);
    let cos = Math.cos(a);
    ctx.rotate(a);
    / / equivalent
    ctx.transform(cos, sin, -sin, cos, 0.0);
    Copy the code
  3. Scale: Scale (x, y) equals transform(x, 0, 0, y, 0, 0).
  4. Skew: similar to skew(x, y) method in CSS3.
    let x = Math.PI / 6;
    let y = Math.PI / 3;
    let tanx = Math.tan(x);
    let tany = Math.tan(y);
    ctx.transform(1, tanx, tany, 1.0.0);
    Copy the code

conclusion

Ok, the above is the homogeneous coordinate of basic (2D) in computer graphics, and the transform deformation principle common to CSS3 and Canvas. (If there are any mistakes in the article, please point them out!)