For the Matrix PreXXX and PostXXX understanding of when to use

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/One_Month/article/details/89478898

In the Custom View when we draw the bitmap when
canvas.drawBitmap (bitmap, Matrix, Paint)
way to use the Matrix, which is a matrix, online chart illustrating the influence of the matrix

Effects of each numerical matrix 1.Matrix

Matrix determinant
Effects of the first row of the X-axis, respectively, is scaled scale, skew shearing, translation Trans
second row affect the Y-axis, similar to the first row, matrix multiplication is applied to the pattern
Specific matrix behavior control, images from the Internet
which is affected by the rotation and displacement, there is a DESCRIPTION scaling and shearing
Scale and Shear
give a scale, scaling example of
Zoom calculated
the right hand side is a point and the coordinates of the original data matrix, matrix multiplication, row by row
x = K1 * X0 + 0 * Y0 + 0 * 1 = K1 * X0
can be seen that the X coordinates are scaled k1 times
y = 0 * X0 + k2 *
Y0 + 0 * 1 = K2 * Y0 can be seen that the Y coordinate times scaled K2 times

That is, the impact on the image shows two position for zoom

2. say about the basic difference between the Pre and Post

Base notes to the end here, that I later encountered preXXX method and postXXX confused methods
such as
translation
1.preTranslate (), the source explained

   /**
     * Preconcats the matrix with the specified translation. M' = M * T(dx, dy)
     */
    public boolean preTranslate(float dx, float dy) {
        nPreTranslate(native_instance, dx, dy);
        return true;
    }
    
M' = M * T(dx, dy)
也就是原矩阵在左边,要实现平移转换的的操作在右边,也可以说是原矩阵的左乘

T(dx, dy)就是一个函数表示,表示构造一个平移矩阵
M为原矩阵,当新建一个Matrix,就是一个单位矩阵,下图就是个单位矩阵,
斜边为1,其余为0

Matrix

2.如果是postTranslate,源码说明

 /**
     * Postconcats the matrix with the specified translation. M' = T(dx, dy) * M
     */
    public boolean postTranslate(float dx, float dy) {
        nPostTranslate(native_instance, dx, dy);
        return true;

M' = T(dx, dy) * M
也就是原矩阵的右乘

矩阵乘法的特性是:
矩阵乘法不满足交换律,即 AB ≠ BA
矩阵乘法满足结合律,即 (AB)C = A(BC)
矩阵与单位矩阵相乘结果不变,即 A * I = A

对于左乘和右乘有什么影响,特别是多个操作结合,比如preTranslate,preScale
等等。计算起来很复杂

网上有一种说法,说的是

preXXX就是先执行,postXXX就是后执行,但是其实我们知道,代码的执行顺序
是根据你写的代码先后,preXXX和postXXX在我们调用的时候就已经执行,得到
了新的Matrix,比如执行preTranslate,preScale
M’ = M * T * S T表示preTranslate,S表示preScale
调用了M*T就已经产生新的Matrix内部结构,然后再和S操作

所以我们在用的时候我想可以这么理解

用法结论

就是在执行逻辑上,比如,我们想要先位移,再缩放,再旋转,我们想要的是执行这个结果
就可以preRotate,preScale,preTranslate,按这个顺序调用,内部公式就是
M’ = M * R * S * T
我们可以逻辑上认为越靠右边的行为越先执行,但是代码执行顺序不是如此,只是我们为了
达到目标效果,逻辑上这么想,内部经历了复杂计算对应了我们的逻辑执行顺序,
得到我们想要的Matrix,这个Matrix实现了这个逻辑顺序下的计算,但是具体内部是怎么计算
出来的,我也无法得知,也期待有喜欢研究的道友讲解

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

		//保存画布状态
        canvas!!.save()
        //重置Matrix,避免后续影响
        mMatrix.reset()
        //画布平移,將画布中心移动到屏幕中心
        canvas.translate(width/2f,height/2f)
        //先画出原图做对比
        canvas.drawBitmap(bitmap,0f,0f,null)

		//先画一个只旋转和平移的图,为了和下面的操作对比,看scale和translate谁先执行
		(逻辑上)
        mMatrix.preRotate(90f)
        mMatrix.preTranslate(100f,100f)
        canvas.drawBitmap(bitmap,mMatrix,null)
        mMatrix.reset()
        //实现我们之前说的平移,缩放,旋转的操作,按这个顺序
        mMatrix.preRotate(progress)
        mMatrix.preScale(0.5f,0.5f)
        mMatrix.preTranslate(100f,100f)

        canvas.drawBitmap(bitmap,mMatrix,null)
        canvas.restore()
    }

效果图如下
Renderings

最右边的是原图,可以看到在屏幕中心点开始绘制
最左边的是没有缩放的
最小的是3个操作都有的

我平移了(100,100),也就是向右100,向下100(屏幕坐标系是向下为Y轴正向)

假设是先做的缩放再做的平移,那么缩放时候是在原点缩放,也就是屏幕中心,那么他的左上角还应该是(0,0),然后平移了(100,100),左上角旋转后现在最终视觉上成了右上角,
那么右上角坐标现在应该是(-100,100)

但是我们看到只做了旋转和平移的那张图,也就是最左边的,他明显更加远离原点,说明他的位置才是(-100,100)
所以就说明最小的那张图先做了平移操作,坐标变成(100,100),旋转后变成(-100,100),最后坐了缩放,缩放是根据原点缩放,所以那个点缩放了一般变成了(-50,50),所以就是我们说的顺序

再做个实验,如果我们最后一步是postTranslate,能不能达到我们逻辑上的最后做平移呢

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
//        canvas!!.drawBitmap(bitmap,Rect(0,0,(bitmap.width*progress).toInt() ,bitmap.height),
//                RectF(0f,0f,bitmap.width*progress,bitmap.height.toFloat()), Paint())

//        canvas!!.drawBitmap(bitmap,0f,0f,null)
//        canvas.translate(0f,bitmap.height.toFloat()+200f)
        canvas!!.save()
        mMatrix.reset()
        canvas.translate(width/2f,height/2f)
        canvas.drawBitmap(bitmap,0f,0f,null)

        mMatrix.preRotate(progress)
        mMatrix.preTranslate(100f,100f)
        canvas.drawBitmap(bitmap,mMatrix,null)
        mMatrix.reset()
        mMatrix.preRotate(progress)
        mMatrix.preScale(0.5f,0.5f)
        //改成postTranslate,之前是preTranslate
        mMatrix.postTranslate(100f,100f)

        canvas.drawBitmap(bitmap,mMatrix,null)
        canvas.restore()
    }
    这样公式就变成
    M' = T * M * R * S

Look renderings
Renderings
can see the upper left corner and the origin of the moving distance
and then look at the upper right corner from the left in the figure to the origin, the same as the distance between them, indicating that the picture first experienced
the scale, origin of the coordinate unchanged, then to the lower right moves 100, 100, also proved that the above
approach is feasible.

Say it again

The order of execution of the code is not in accordance with pre and post and have to perform, but we want to do if
we let him achieve an effect logic, you can follow the instructions above to think about ways to the rational use of
pre and post, each can the formula written out, and then from right to left to see the formula, look at the final results
are not consistent and conjecture.

If there are counter-examples, welcome to give me a message, giving me the opportunity to correct, thank you

Reference article:
Custom View Advanced -Matrix principle

This reference article is a blog series, can learn a lot of things Custom View, you can see

Guess you like

Origin blog.csdn.net/One_Month/article/details/89478898