Matrix, the protagonist of this article, is a model worker who has been working silently in the background. Although Matrix contributes to all the views we see, we rarely see it. Let’s take a look at where it is.

Since Google has made a good encapsulation of this part, skipping this part will not have a great impact on the actual development, so you can skim it without going into depth. The specific usage and skills of Matrix will be explained in detail in the next chapter.

⚠️ Warning: Turn hardware acceleration off before testing the examples in this article.

Matrix description

Matrix is a Matrix, the main function is coordinate mapping, numerical conversion.

It would look something like this:

Matrix is coordinate mapping, so why do we need Matrix? Here’s a simple example:

As a physical device, the physical coordinate system of my mobile phone screen starts from the upper left corner, but we usually do not use this coordinate system during development, but the coordinate system of the content area.

The graph below, our content area and the screen coordinate system is a notification bar to add a title bar of the distance, so they are not overlap, we in the content area coordinate system when the content of the final drawing must be converted to the actual physical coordinates to draw, Matrix role is to convert these values here.

Assuming a notification bar height of 20 pixels and a navigation bar height of 40 pixels, drawing a point at (0,0) in the content area will eventually translate into drawing a point at (0,60) in the actual coordinate system.

The above is just a simple example. In fact, no matter 2D or 3D, we cannot display graphics on the screen without Matrix, so Matrix is a hard working model behind the scenes.

Matrix characteristics

  • Matrix is applied in View, pictures, animation effects and other aspects. Compared with the canvas operation explained before, it has a wider application scope.
  • More flexible, canvas operation is the encapsulation of Matrix, Matrix is closer to the bottom, is bound to be more flexible than canvas operation.
  • The package is very good, Matrix itself has made a good package for each method, so that developers can easily operate Matrix.
  • It is difficult to understand deeply, the meaning of each value in, and the rules of operation. If you do not understand the matrix, it is also difficult to understand the front multiplication and the back multiplication.

A common misconception

1. Consider that the three parameters (MPERSP_0, MPERSP_1 and MPERSP_2) in the bottom row of Matrix do not have much effect and are only used here to make up the numbers.

In fact, the last line of parameters plays a crucial role in 3D transformation, which will be discussed in more detail in Camera later.

2. The last parameter MPERSP_2 is interpreted as scale

It is true that changing the value of MPERSP_2 can achieve a similar effect to scaling, but this is because of homogeneous coordinates, not the actual function of this parameter.

Matrix fundamentals

Matrix is a Matrix, the most fundamental function is coordinate transformation, we will look at several common transformation principles below:

The transformation we use is affine transformation, affine transformation is linear transformation (scaling, rotation, tangent) and translation transformation (translation) of the compound, because these concepts for our role is not big, here but more introduction, interested in understanding.

There are four basic transformations: Translate, Scale, rotate and skew.

Now let’s look at the parameters that govern each of the four transformations.

As can be seen from the figure above, the last three parameters control perspective. These three parameters are mainly used in 3D effects, usually (0, 0, 1). They are beyond the scope of this article and will be described in detail in a later article.

Since most of our following calculations are based on matrix multiplication rules, if you have returned linear algebra to the teacher, please refer to this: Wikipedia – Matrix Multiplication

1. The zoom (Scale)

Expressed as a matrix:

You may notice that we coordinate a 1 more, this is the use of the homogeneous coordinate system, in our point and vector in the math are said (x, y), both look the same, computers are indistinguishable, so let the computer can also distinguish between them, added a logo, increase after looks like this:

(x, y, 1) minus the point (x, y, 0) minus the vector

In addition, homogeneous coordinates have the property of equal proportions, (2,3,1), (4,6,2)… (2N,3N,N) is the point (2,3). (This is where the misunderstanding of interpreting MPERSP_2 as scale comes from).

Legend:

2. Shear (Skew)

There are two special types of miscuts, horizontal (parallel to the X axis) and vertical (parallel to the Y axis).

Horizontal shear

Expressed as a matrix:

Legend:

Vertical shear

Expressed as a matrix:

Legend:

Composite shear

A combination of horizontal and vertical miscuts.

Expressed as a matrix:

Legend:

3. The rotation (Rotate)

Suppose A point A(x0, y0) is r away from the origin, the Angle between it and the horizontal axis is α degree, and it is rotated θ degree about the origin. After rotation, it is point B(x, y) as follows:

Expressed as a matrix:

Legend:

4. Translation (Translate)

Here is also one of the advantages of using homogeneous coordinates, actually in front of the three operation using 2 x2 matrix can meet the demand, but the use of 2 x2 matrix, to shift operations to join, and the extension of the coordinates for the homogeneous coordinates, with the extension of the matrix for the 3 x3 algorithm can be unified, four kinds of algorithms are completed you can use the matrix multiplication.

Expressed as a matrix:

Legend:

Matrix recombination principle

In fact, many compound operations of Matrix are realized by Matrix multiplication, which is very simple to understand in principle. However, the use of Matrix multiplication also has its weaknesses. Subsequent operations may affect previous operations, so the order is very important when constructing Matrix.

There are four commonly used transformation operations, each of which has three types in Matrix: pre, POST and set. Please refer to the Matrix method table at the end of this paper. Since Matrix multiplication does not meet the commutative law, there are still great differences between pre, POST and set.

By (pre) before

The front multiplication is equivalent to the matrix multiplication:

This represents a matrix multiplied front and back by a particular matrix to construct the resulting matrix.

After a (post)

The back product is equivalent to the left product of the matrix:

This represents a matrix multiplied by a particular matrix to construct the resulting matrix.

Set (set)

Instead of using matrix multiplication, the setting overwrites the original value, so using the setting may invalidate the previous operation.

combination

There is always a problem with the Matrix article, that is, the theories of pre and post are very awkward. Most articles in China are like this, which seem to be right but hard to understand, and some contents are counterintuitive.

Influenced by these articles, I naturally inherited this theory. It was not until one of my friends raised a question in the comments section that I re-examined the content of this part and made some reflection.

After a long time of reflection, I decided to abandon the theories and conclusions of most articles in China, and only elaborate this part of the theory with rigorous mathematical logic and procedural logic. There may still be some omissions. Please correct me if you find any.

So let’s clarify two false conclusions, remember, false conclusions, false conclusions, false conclusions.

Error Conclusion 1: Pre is executed sequentially and POST is executed in reverse order.

This conclusion is deceptive because it’s not completely wrong and you can easily prove it, for example:

// Matrix Matrix = new Matrix(); matrix.preTranslate(pivotX,pivotY); matrix.preRotate(angle); Log.e("Matrix", matrix.toShortString()); // Matrix Matrix = new Matrix(); matrix.postRotate(angle); matrix.postTranslate(pivotX,pivotY) Log.e("Matrix", matrix.toShortString());Copy the code

These two pieces of code end up being equivalent, so it’s easy to prove that this is true, but is it?

First, from a mathematical point of view, pre and Post are the difference between right and left multiplication, and second, they can’t actually affect the order of operations (program execution order). These two pieces of code are equivalent only because the final simplification formula is the same.

Let the original matrix be M, the translation be T, the rotation be R, the identity matrix be I, and the final result be M prime.

  • Matrix multiplication does not satisfy the commutative law, AIndicates a B BA
  • Matrix multiplication satisfies the associative property of (A)B)C = A(BC)
  • You multiply A matrix times the identity matrix, so A times I is equal to A
// post M' = T*(R*M) = T*(R*M) = T*R*I = T*RCopy the code

Since the final simplification formula is the same, they are equivalent, but this conclusion is not universal.

That is, when the original matrix is not the identity matrix, the two cannot be simplified into the same formula, and the results will naturally be different. In addition, the order of execution is the order of program writing, there is no so-called positive order reverse order.

False conclusion 2: Pre is executed first and post is executed last.

This conclusion is even worse than the last one.

The mistake was made entirely because the person who wrote the article knew English.

Pre: Before. Post, after, afterCopy the code

So you get the idea that pre goes first and post goes after, but from a serious mathematical and procedural point of view, it’s completely impossible, again, pre and Post can’t affect the order of execution, and every time a program executes a statement, it gets a definite result, so, It has no control over the sequence of execution and is completely bullshit.

If forced to explain by this theory, it would look as if post had executed first. For example:

matrix.preRotate(angle);
matrix.postTranslate(pivotX,pivotY);
Copy the code

Also simplify the formula:

// Matrix multiplication satisfies the associative law M '= T*(M*R) = T*M*R = (T*M)*RCopy the code

In fact, because matrix multiplication is associative, it doesn’t matter whether you say right first or left first, it doesn’t matter.

I made a false proof earlier based on this false conclusion:

(this paragraph is doomed to be shame of in my writing course, since it is public articles, should be responsible for the reader, though I before making each article is trying to prove the problem, all sorts of details, avoid appear this kind of mistake, but eventually left such a content, here I sincerely apologize to all my readers.)

For those of you who follow me, please try to see what I have posted on my personal blog and on GitHub. Both platforms are part of the blogfix plan, and any bugs or bugs will be fixed first on these two platforms. In addition, all the repaired articles will be re-published on my microblog @gcssloop. Follow my microblog to get the update or repair news in the first time.


Here is the proof of error:

In practice, we will get the exact result of each operation, but why do we still use the expression existence order? Can you really use pre and Post to influence the order of calculations? As a matter of fact, this is not the case

Matrix matrix = new Matrix(); Matrix. PostScale (0.8 0.5 f, f); matrix.preTranslate(1000, 1000); Log.e(TAG, "MatrixTest" + matrix.toShortString());Copy the code

In the above operation, if the normal idea is followed, the zoom operation is performed before the pan operation, which will not affect the subsequent pan operation, but the execution result finds that the pan distance is changed to (500, 800). ~ ~

In the above example, the calculation of order is no problem, first calculate the scaling, then calculate the translation, and scaling affects the translation because of the previous step after scaling the results of the matrix is right by the translation matrix, this is in accordance with the operation law of matrix multiplication, although that is zooming in the former they affected the shift operation, equivalent to perform the translation operations, The zoom operation is then performed, so the pre operation is performed first, and the post operation is performed after this statement. ~ ~


The above argument is completely wrong, because counterexamples can easily be made:

Matrix matrix = new Matrix(); Matrix. PreScale (0.8 0.5 f, f); matrix.preTranslate(1000, 1000); Log.e(TAG, "MatrixTest" + matrix.toShortString());Copy the code

In the counterexample, the postScale is changed to preScale, but the results are exactly the same, so the sequence argument is simply wrong.

They’re going to get the same result because they’re going to get the same simplification formula, which is S times T

The translation distance is MTRANS_X = 500, MTRANS_Y = 800, because the Matrix already has a scale before Translate. When you’re multiplying by right, it affects the actual numerical calculation, so you can use matrix multiplication.

The final result is:

When T*S, the scaling ratio does not affect MTRANS_X and MTRANS_Y, you can use matrix multiplication to calculate.

How to understand and use Pre and Post?

Forget about the order theory, the order theory, just do the basic matrix multiplication.

Pre: right multiply, M '= M*A Post: left multiply, M' = A*MCopy the code

So how do you use it?

The correct way to use this is to construct the normal Matrix multiplication order first, and then implement this order using pre and POST as appropriate.

Again, the simplest way to think about it is, let’s say I want to rotate around some point.

The method xxxRotate(Angle, pivotX, pivotY) can be used. Since we need to combine and construct a Matrix, this method is not used directly.

First, there are two fundamental theorems:

  • All operations (rotation, translation, scaling, miscutting) are based on the origin of the coordinates by default.
  • The frame state of the previous operation is retained and affects subsequent states.

Based on these two basic theorems, we can calculate the following steps for rotation based on a certain point:

1. First move the origin of the coordinate system to the specified position and use translation T 2. Rotate the coordinate system by using rotation S (rotation around the origin) 3. I'm going to shift the frame back to where I was, and I'm going to shift it by -tCopy the code

The specific formula is as follows:

M is the original matrix, which is the identity matrix, M ‘is the resulting matrix, T is the translation, and R is the rotation

M' = M*T*R*-T = T*R*-T
Copy the code

The pseudo-code written according to the formula is as follows:

Matrix matrix = new Matrix();
matrix.preTranslate(pivotX,pivotY);
matrix.preRotate(angle);
matrix.preTranslate(-pivotX, -pivotY);
Copy the code

Operation around a point can be extended to the general case, namely:

Matrix matrix = new Matrix(); matrix.preTranslate(pivotX,pivotY); // Various operations, rotation, scaling, error cutting, etc., can be performed multiple times. matrix.preTranslate(-pivotX, -pivotY);Copy the code

Formula is:

M' = M*T* ... *-T = T* ... *-T
Copy the code

But in this way, the translation function of the two adjustment centers is pulled too far apart, so it is usually written like this:

Matrix matrix = new Matrix(); // Various operations, rotation, scaling, error cutting, etc., can be performed multiple times. matrix.postTranslate(pivotX,pivotY); matrix.preTranslate(-pivotX, -pivotY);Copy the code

The formula is:

M' = T*M* ... *-T = T* ... *-T
Copy the code

And you can see that this simplifies to the same thing.

So, pre and Post are used to adjust the order of multiplication, normally you should build the multiplication order formula forward, and then adjust the writing according to the actual situation.

In the construction of Matrix, I suggest to use one kind of multiplication as far as possible, namely, front multiplication or back multiplication, so that the operation sequence is easy to determine and problems are easy to troubleshoot. Of course, because matrix multiplication does not meet the commutative law, the results of forward multiplication and backward multiplication are different, so it should be used in combination with specific situation analysis.

Here we construct the same matrix in different pairs:

Note:

  • 1. Since Matrix multiplication does not meet the commutative law, please ensure that the Initial Matrix is used, otherwise the calculation results may be different.
  • 2. Pay attention to the order of construction. The order will affect the result.
  • 3.Initial Matrix refers to the new Matrix, or reset Matrix, which is an identity Matrix.

1. Pre only:

// use pre, M' = M*T*S = T*S Matrix M = new Matrix(); m.reset(); m.preTranslate(tx, ty); m.preScale(sx, sy);Copy the code

Expressed as a matrix:

2. Only by post:

// use post, M '= T*S*M = T*S Matrix M = new Matrix(); m.reset(); m.postScale(sx, sy); // Execute first as far as possible. m.postTranslate(tx, ty);Copy the code

Expressed as a matrix:

3. The mixed:

M '= T*M*S = T*S Matrix M = new Matrix(); m.reset(); m.preScale(sx, sy); m.postTranslate(tx, ty);Copy the code

Or:

M '= T*M*S = T*S Matrix M = new Matrix(); m.reset(); m.postTranslate(tx, ty); m.preScale(sx, sy);Copy the code

Because there are only two steps here, and the sequence is specified, swapping code does not affect the results.

Expressed as a matrix:

Note: Since matrix multiplication does not satisfy the commutative law, please ensure that the initial matrix is the identity matrix. If the initial matrix is not the identity matrix, the operation results will be different.

Although there are many different ways of writing it, the final simplification formula is the same, and these different ways of writing are all calculated backwards from the same formula.

Matrix method table

This list of methods, I’ll leave it here for you to see, and the instructions will be in the next article.

Method category The relevant API Abstract
Basic method equals hashCode toString toShortString Compare, get a hash, and convert to a string
Numerical operations set reset setValues getValues Set, reset, set values, get values
Numerical calculation mapPoints mapRadius mapRect mapVectors Compute the transformed value
Set (set) setConcat setRotate setScale setSkew setTranslate Set the transform
By (pre) before preConcat preRotate preScale preSkew preTranslate By transformation before
After a (post) postConcat postRotate postScale postSkew postTranslate After take the transform
Special methods setPolyToPoly setRectToRect rectStaysRect setSinCos Some special operations
Matrix related invert isAffine isIdentity Find the inverse matrix, affine matrix, identity matrix…

conclusion

Matrix focuses on understanding, and it will be more handy to use after understanding its principle.

Sequel:

  • Android Custom control advanced 01- Custom control development routines and processes
  • Android custom controls advanced 02-Canvas drawing graphics
  • Android custom controls advanced 03-Canvas Canvas operation
  • Android custom controls advanced 04-Canvas picture text
  • Android custom controls advanced 05-PATH basic operations
  • Android custom control advanced 06-Path bezier curve
  • The end of Android Custom controls Advanced 07-Path
  • Android custom controls advanced 08-PathMeasure details
  • Android custom control advanced 09- Control core Matrix principle
  • Android custom control advanced 10- control core Matrix Camera
  • Android custom controls Advanced 11- Event distribution mechanism principle
  • Android Custom controls Advanced 11- Event distribution mechanism 01
  • Android Custom controls Advanced 12- Event distribution mechanism principle 02
  • Android custom controls advanced 13-MotionEvent details
  • Android Custom Controls Advanced 14- Special controls event handling scheme