读书笔记,WebGL编制程序指南

By admin in 4858美高梅 on 2019年3月28日

一、前言

一、前言

转自:

如果是涉嫌到游戏或动画的编制程序,大家很只怕会用到几何变换。即使在高等高校过线性代数的话,大家就会精晓,无论是2d照旧3d的几何变换,矩阵都以完结线性别变化换的一个重点工具。任意线性别变化换都足以用矩阵表示为便于计算的一模一样情势,并且七个转移也得以很简单地经过矩阵的相乘连接在联合署名。本作品首要对如下的更换实行简单的包裹,并简要解说在那之中的变换原理:
  1.平移变换:只改变图形的岗位,不更改大小。
  2.旋转变换:保持图形各部分之间的涉嫌,变换后形状不变。
  3.比例变换:可转移图形大小和形态。
  4.错切变换:引起图形角度关系的转移,甚至造成图形发生畸变。
  5.对称变换:使图形对称于x轴或y轴或y=x或y=-x的变换。
 
  程序中,大家将定义三个矩阵类Matrix,个中的matrix属性保存以二维数组表示的矩阵格局,当大家起先化矩阵对象时,必要传入该矩阵的现实性数额:
  
 
                var mtx= new matrix({
                    matrix:[
                       [1,0,0],
                       [0,1,0],
                       [0,0,1]
                    ]
                });
 
  由于在转换进程中须要用到矩阵操作的片段通用方法,因而大家能够先在矩阵类中丰富这一个实例方法:
 
            /**
            *矩阵相加
            **/
            add:function(mtx){
                var omtx=this.matrix;
                var newMtx=[];
               
if(!mtx.length||!mtx[0].length||mtx.length!=omtx.length||mtx[0].length!=omtx[0].length){//若是矩阵为空,或行或列不对等,则赶回
                    return;
                }
                for(var i=0,len1=omtx.length;i<len1;i++){
                    var rowMtx=omtx[i];
                    newMtx.push([]);
                    for(var j=0,len2=rowMtx.length;j<len2;j++){
                        newMtx[i][j]=rowMtx[j]+mtx[i][j];
                    }
                }
                this.matrix=newMtx;
                return this;
            },
            /**
            *读书笔记,WebGL编制程序指南。矩阵相乘
            **/
            multiply:function(mtx){
                var omtx=this.matrix;
                var mtx=mtx.matrix;
                var newMtx=[];
                //和数字相乘
                if(cg.core.isNum(mtx)){
                    for(var i=0,len1=omtx.length;i<len1;i++){
                        var rowMtx=omtx[i];
                        newMtx.push([]);
                        for(var j=0,len2=rowMtx.length;j<len2;j++){
                            omtx[i][j]*=mtx;   
                        }
                    }
                    return new matrix({matrix:newMtx});
                }
                //和矩阵相乘
                var sum=0;
                for(var i=0,len1=omtx.length;i<len1;i++){
                    var rowMtx=omtx[i];   
                    newMtx.push([]);
                    for(var m=0,len3=mtx[0].length;m<len3;m++){
                        for(var j=0,len2=rowMtx.length;j<len2;j++){
                            sum+=omtx[i][j]*mtx[j][m];   
                        }
                        newMtx[newMtx.length-1].push(sum);
                        sum=0;
                    }
                }
                this.matrix=newMtx;
                return this;       
            },
 
  每一种操作完结后,重临对象自我,那样的链式调用有利于大家对矩阵展开频仍连连的操作,达成部分列的图片变换。
 
2D坐标系下的变换:
  2d坐标系下,大家应用如下的转移矩阵:

      今日持续第5章的就学内容,开头上学复合变换的文化。

      后天再而三第6章的上学内容,初步上学复合变换的学识。

Matrix的数学原理

4858美高梅 1

 

 

在Android中,假设您用Matrix进行过图像处理,那么势必理解Matrix那个类。Android中的Matrix是二个3
x 3的矩阵,其内容如下:

个中,左上区域(abde)负责图形的缩放、旋转、对称、错切等转移,cf负责平移变换。

二、正文

二、正文

4858美高梅 2 

  2d平移:

    
 **
Example1: 复合变换
**

    
 **
Example1: 复合变换
**

Matrix的对图像的拍卖可分为四类基本转移:

  使点运动一定位移,大家使用的变换矩阵是:

      
在书中,小编为我们封装了一套用于转移的矩阵对象:Matrix4对象。它包括以下两种艺术:

      
在书中,小编为大家封装了一套用于转移的矩阵对象:Matrix4对象。它包罗以下二种方法:

Translate           平移变换

 4858美高梅 3

  1. Matrix4.setIdentity():
    将Matrix4实例化为单位矩阵
  2. Matrix4.setTranslate(x,y,z):
    将Matrix4实例设置为平移变换矩阵,在x轴平移距离为x,在y轴平移距离为y,在z轴平移距离为z;

  3. Matrix4.setScale(x,y,z):
    将Matrix4实例设置为缩放变换矩阵,缩放因子分别为x,y,z;

  4. Matrix4.setRotate(angle,x,y,z):
    将Matrix4实例设置为旋转变换矩阵,角度为angle,旋转轴为(x,y,z);
  5. Matrix4.translate(x,y,z):
    将Matrix4实例本人乘以叁个平移变换矩阵;
  6. Matrix4.rototate(angle,x,y,z):
    将Matrix4实例本人乘以三个旋转变换矩阵;
  7. Matrix4.scale(x,y,z): 将Matrix4实例本人乘以三个缩放变换矩阵;
  8. Matrix4.set(m): 将Matrix4设置为m;
  9. Matrix4.elements:
    类型化数组包蕴了Matrix4实例的矩阵元素;

    var modelMatrix = new Matrix4();
    modelMatrix.setRotate(ANGLE,0,0,1);
    modelMatrix.translate(Tx,0,0);

    … …

    gl.uniformMatrix4fv(u_ModelMatrix,false,modelMatrix.elements);

  1. Matrix4.setIdentity():
    将Matrix4实例化为单位矩阵
  2. Matrix4.setTranslate(x,y,z):
    将Matrix4实例设置为平移变换矩阵,在x轴平移距离为x,在y轴平移距离为y,在z轴平移距离为z;

  3. Matrix4.setScale(x,y,z):
    将Matrix4实例设置为缩放变换矩阵,缩放因子分别为x,y,z;

  4. Matrix4.setRotate(angle,x,y,z):
    将Matrix4实例设置为旋转变换矩阵,角度为angle,旋转轴为(x,y,z);
  5. Matrix4.translate(x,y,z):
    将Matrix4实例自己乘以二个平移变换矩阵;
  6. Matrix4.rototate(angle,x,y,z):
    将Matrix4实例本身乘以一个旋转变换矩阵;
  7. Matrix4.scale(x,y,z): 将Matrix4实例本人乘以2个缩放变换矩阵;
  8. Matrix4.set(m): 将Matrix4设置为m;
  9. Matrix4.elements:
    类型化数组包蕴了Matrix4实例的矩阵成分;

    var modelMatrix = new Matrix4();
    modelMatrix.setRotate(ANGLE,0,0,1);
    modelMatrix.translate(Tx,0,0);

    … …

    gl.uniformMatrix4fv(u_ModelMatrix,false,modelMatrix.elements);

Rotate                旋转变换

 

 

 

Scale                  缩放变换

使x,y点平移Tx,Ty的位移,则使[x,y,1]矩阵与地点的矩阵相乘,具体的包装如下:

         Example2:
动画

         Example2:
动画

Skew                  错切变换

            /**
            *2d平移
            **/
            translate2D:function(x,y){
                var changeMtx= new matrix({
                    matrix:[
                       [1,0,0],
                       [0,1,0],
                       [x,y,1]
                    ]
                });
                return this.multiply(changeMtx);
            },
  2d缩放:

 requestAnimationFrame(func):
请求浏览器在以往某时刻回调函数func以实现重绘。我们理应在回调函数最终重复发起该请求。

 requestAnimationFrame(func):
请求浏览器在明日某时刻回调函数func以成功重绘。我们理应在回调函数最终再度发起该请求。

 

  2d坐标轴下以原点为参考点时,缩放变换使用的转换矩阵如下:

var tick = function() {
    currentAngle = animate(currentAngle);  // Update the rotation angle
    draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
    requestAnimationFrame(tick, canvas); // Request that the browser calls tick
};
tick();
var tick = function() {
    currentAngle = animate(currentAngle);  // Update the rotation angle
    draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix);   // Draw the triangle
    requestAnimationFrame(tick, canvas); // Request that the browser calls tick
};
tick();

从字面上理解,矩阵中的MSCALE用于拍卖缩放变换,MSKEW用于拍卖错切变换,MTRANS用于拍卖平移变换,MPE君越SP用于拍卖透视变换。实际中本来无法完全依据字面上的传教去领略Matrix。同时,在Android的文书档案中,未看到用Matrix举行透视变换的有关评释,所以本文也不商量那上边包车型客车标题。

 4858美高梅 4

 

 

 

 

鉴于浏览器执行Tick()的命宫是不可控的,大家须求让三角匀速的转动,那么就要求控制时间:

出于浏览器执行Tick()的时日是不可控的,大家要求让三角匀速的旋转,那么就须要控制时间:

本着各类变换,Android提供了pre、set和post二种操作办法。个中

使[x,y,1]矩阵与地方的矩阵相乘,则可得出相对于原点缩放后的坐标值。

var g_last = Date.now();
function animate(angle) {
  // Calculate the elapsed time
  var now = Date.now();
  var elapsed = now - g_last;
  g_last = now;
  // Update the current rotation angle (adjusted by the elapsed time)
  var newAngle = angle + ANGLE_STEP * (elapsed / 1000.0);
  return newAngle %= 360;
}
var g_last = Date.now();
function animate(angle) {
  // Calculate the elapsed time
  var now = Date.now();
  var elapsed = now - g_last;
  g_last = now;
  // Update the current rotation angle (adjusted by the elapsed time)
  var newAngle = angle + ANGLE_STEP * (elapsed / 1000.0);
  return newAngle %= 360;
}

set用于安装Matrix中的值。

  可是不少情状下,咱们兴许要求相对于任意点进行缩放而不单单限制于相对于原点的缩放,因此大家那边最佳封装相对于坐标轴上任意点的缩放方法。绝对于任意点的缩放其实也是由相对于原点的缩放转换而来,相对于点(x1,y1)的缩放计算具体步骤如下:

 

 

pre是先乘,因为矩阵的乘法不满意沟通律,由此先乘、后乘必须求严苛差别。先乘也就是矩阵运算中的右乘。

  把坐标原点平移至(x1,y1)–>进行相对于原点的转移–>把坐标原点平移回去

三、结尾

三、结尾

post是后乘,因为矩阵的乘法不知足沟通律,因而先乘、后乘必须求严加差距。后乘约等于矩阵运算中的左乘。

  矩阵总结:

     下星期天继续立异第5章。

     下一周天继续革新第四章。

 

 4858美高梅 5

除平移变换(Translate)外,旋转变换(Rotate)、缩放变换(Scale)和错切变换(Skew)都能够围绕一个基本点来展开,要是不钦点,在暗许情状下是围绕(0,
0)来拓展相应的转移的。

 

 

由此对任意点缩放的法子封装如下:

下边大家来看望多种转移的现实性意况。由于具备的图片都以有点构成,由此大家只要求着眼一个点有关变换即可。

            /**
            *2d缩放
            **/               
            scale2D:function(scale,point){//缩放比,参考点
                var
sx=scale[0],sy=scale[1],x=point[0],y=point[1];

 

                var changeMtx= new matrix({
                    matrix:[
                       [sx,0,0],
                       [0,sy,0],
                       [(1-sx)*x,(1-sy)*y,1]
                    ]
                });   
                return this.multiply(changeMtx);               
               
            },
  2d对称变换:

一 、 平移变换

  2d对称变换使用的变换矩阵如下:

借使有1个点的坐标是4858美高梅 6 ,将其移动到4858美高梅 7 ,再假定在x轴和y轴方向移动的尺寸分别为:

 4858美高梅 8

4858美高梅 9

 

正如图所示:

不等的相反相成变换,通过abde的值的转移来兑现:

4858美高梅 10

    相对于x轴的转移:b=d=0 a=1 e=-1

探囊取物明白:

    相对于y轴的转移:b=d=0 a=-1 e=1

4858美高梅 11

    相对于原点的转换:b=d=0 a=-1 e=-1

假使用矩阵来表示的话,就足以写成:

    相对于y=x的变换:b=d=1 a=e=0

4858美高梅 12 

    现对于y=-x的变换:b=d=-1 a=e=0

 

  由此乘以不一致的转移矩阵,就能够赢得不相同的更换效果:

二 、 旋转变换

            /**
            *2d对称变换
            **/                   
            symmet2D:function(axis){//对称轴
                var changeMtx;
                axis==”x”&&(changeMtx= new matrix({//相对于x轴对称
                    matrix:[
                       [1,0,0],
                       [0,-1,0],
                       [0,0,1]
                    ]
                }));               
                axis==”y”&&(changeMtx= new matrix({//相对于y轴对称
                    matrix:[
                       [-1,0,0],
                       [0,1,0],
                       [0,0,1]
                    ]
                }));   
                axis==”xy”&&(changeMtx= new matrix({//相对于原点对称
                    matrix:[
                       [-1,0,0],
                       [0,-1,0],
                       [0,0,1]
                    ]
                }));   
                axis==”y=x”&&(changeMtx= new matrix({//相对于y=x对称
                    matrix:[
                       [0,1,0],
                       [1,0,0],
                       [0,0,1]
                    ]
                }));   
                axis==”y=-x”&&(changeMtx= new matrix({//相对于y=-x对称
                    matrix:[
                       [0,-1,0],
                       [-1,0,0],
                       [0,0,1]
                    ]
                }));
                return this.multiply(changeMtx);               
            },
  2d错切变换:

 

  所谓的错切变换,正是图片发生倾斜等的失真,例如下图中分头是x方向和y方向下的错切变换:

2.1    围绕坐标原点旋转:

    
  4858美高梅 13
  错切变换下的转移矩阵为:
  4858美高梅 14
  [x,y]改换后的坐标为:[x+by,dx+y,1],能够见到,当b不为0,d为0时,y值不变,x轴依照b的值作线性增进,由此能够得出上边的a图。当b为0,d不为0时,x值不变,y轴根据d的值作线性增进,因而得以得出上面的b图。
  错切变换的卷入:
 

假设有二个点4858美高梅 15 ,绝对坐标原点顺时针旋转4858美高梅 16后的情形,同时假设P点离坐标原点的离开为r,如下图:

 /**
            *2d错切变换
            **/               
            shear2D:function(kx,ky){
                var changeMtx= new matrix({
                    matrix:[
                       [1,kx,0],
                       [ky,1,0],
                       [0,0,1]
                    ]
                });   
                return this.multiply(changeMtx);
            },
  2d旋转变换:

4858美高梅 17

  旋转变换和缩放变换一样,同样有相对于原点变换和相对于任意点变换那三种意况,由此那里也一直封装相对于任意点变换的不二法门。

那么,

  相对于任意点(x1,y1)旋转=把坐标原点平移到(x1,y1)–>相对于原点旋转
–>把原点平移回去

4858美高梅 18

  相对于原点的旋转变换矩阵为:

一经用矩阵,就足以代表为:

    4858美高梅 19
  由此相对于任意点旋转的更换矩阵为:
  
  4858美高梅 20
  所以封装方法如下:
 

4858美高梅 21

 

 

  /**
            *2d旋转
            **/           
            rotate2D:function(angle,point){
                var x=point[0],y=point[1];
                var cos=Math.cos;
                var sin=Math.sin;
                var changeMtx= new matrix({
                    matrix:[
                       [cos(angle),sin(angle),0],
                       [-sin(angle),cos(angle),0],
                      
[(1-cos(angle))*x+y*sin(angle),(1-cos(angle))*y-x*sin(angle),1]
                    ]
                });   
                return this.multiply(changeMtx);
            },
  

2.2    围绕有个别点旋转

  由于3D坐标轴下的更换和2D坐标轴下的没有太大距离,所以这边就不作详述,上边包车型客车总体源码也蕴藏了3d坐标轴下几何变换的有的,感兴趣的童鞋也得以看看~

一旦是环绕某些点4858美高梅 22顺时针旋转4858美高梅 23,那么能够用矩阵表示为:

 

4858美高梅 24

  此外我们兴许会认为dom或canvas的条件下,并不设有真正含义上的z坐标,由此3d坐标轴下的几何变换并从未多粗情绪。其实,即使达成持续真正含义上的3D,不过贯彻伪3D还是能够的,视觉上,大家得以把成分z轴的坐标值通过xy的坐标值以及成分尺寸的变化来表示,关于那上边的剧情能够参照hongru的rotate3D种类作品。

能够改为:

 

4858美高梅 25

  最后提供具有源码(包蕴3D坐标轴下的几何变换部分):

很显然,

View Code

1.   

    /**
    *
    *矩阵 www.2cto.com
    *
    **/
    cnGame.register(“cnGame”, function(cg) {
        var matrix=function(options){
4858美高梅,            if (!(this instanceof arguments.callee)) {
                return new arguments.callee(options);
            }
            this.init(options);
        };
        matrix.prototype={
            /**
            *初始化
            **/           
            init:function(options){
                this.matrix=[];
                this.setOptions(options);
            },
            /**
            *设置参数
            **/
            setOptions: function(options) {
                cg.core.extend(this, options);
            },
            /**
            *矩阵相加
            **/
            add:function(mtx){
                var omtx=this.matrix;
                var newMtx=[];
               
if(!mtx.length||!mtx[0].length||mtx.length!=omtx.length||mtx[0].length!=omtx[0].length){//倘诺矩阵为空,或行或列不等于,则赶回
                    return;
                }
                for(var i=0,len1=omtx.length;i<len1;i++){
                    var rowMtx=omtx[i];
                    newMtx.push([]);
                    for(var j=0,len2=rowMtx.length;j<len2;j++){
                        newMtx[i][j]=rowMtx[j]+mtx[i][j];
                    }
                }
                this.matrix=newMtx;
                return this;
            },
            /**
            *矩阵相乘
            **/
            multiply:function(mtx){
                var omtx=this.matrix;
                var mtx=mtx.matrix;
                var newMtx=[];
                //和数字相乘
                if(cg.core.isNum(mtx)){
                    for(var i=0,len1=omtx.length;i<len1;i++){
                        var rowMtx=omtx[i];
                        newMtx.push([]);
                        for(var j=0,len2=rowMtx.length;j<len2;j++){
                            omtx[i][j]*=mtx;   
                        }
                    }
                    return new matrix({matrix:newMtx});
                }
                //和矩阵相乘
                var sum=0;
                for(var i=0,len1=omtx.length;i<len1;i++){
                    var rowMtx=omtx[i];   
                    newMtx.push([]);
                    for(var m=0,len3=mtx[0].length;m<len3;m++){
                        for(var j=0,len2=rowMtx.length;j<len2;j++){
                            sum+=omtx[i][j]*mtx[j][m];   
                        }
                        newMtx[newMtx.length-1].push(sum);
                        sum=0;
                    }
                }
                this.matrix=newMtx;
                return this;       
            },
            /**
            *2d平移
            **/
            translate2D:function(x,y){
                var changeMtx= new matrix({
                    matrix:[
                       [1,0,0],
                       [0,1,0],
                       [x,y,1]
                    ]
                });
                return this.multiply(changeMtx);
            },
            /**
            *2d缩放
            **/               
            scale2D:function(scale,point){//缩放比,参考点
                var
sx=scale[0],sy=scale[1],x=point[0],y=point[1];

  4858美高梅 26是将坐标原点移动到点4858美高梅 27后,4858美高梅 28 的新坐标。

                var changeMtx= new matrix({
                    matrix:[
                       [sx,0,0],
                       [0,sy,0],
                       [(1-sx)*x,(1-sy)*y,1]
                    ]
                });   
                return this.multiply(changeMtx);               
               
            },
            /**
            *2d对称变换
            **/                   
            symmet2D:function(axis){//对称轴
                var changeMtx;
                axis==”x”&&(changeMtx= new matrix({//相对于x轴对称
                    matrix:[
                       [1,0,0],
                       [0,-1,0],
                       [0,0,1]
                    ]
                }));               
                axis==”y”&&(changeMtx= new matrix({//相对于y轴对称
                    matrix:[
                       [-1,0,0],
                       [0,1,0],
                       [0,0,1]
                    ]
                }));   
                axis==”xy”&&(changeMtx= new matrix({//相对于原点对称
                    matrix:[
                       [-1,0,0],
                       [0,-1,0],
                       [0,0,1]
                    ]
                }));   
                axis==”y=x”&&(changeMtx= new matrix({//相对于y=x对称
                    matrix:[
                       [0,1,0],
                       [1,0,0],
                       [0,0,1]
                    ]
                }));   
                axis==”y=-x”&&(changeMtx= new matrix({//相对于y=-x对称
                    matrix:[
                       [0,-1,0],
                       [-1,0,0],
                       [0,0,1]
                    ]
                }));
                return this.multiply(changeMtx);               
            },
            /**
            *2d错切变换
            **/               
            shear2D:function(kx,ky){
                var changeMtx= new matrix({
                    matrix:[
                       [1,kx,0],
                       [ky,1,0],
                       [0,0,1]
                    ]
                });   
                return this.multiply(changeMtx);
            },
            /**
            *2d旋转
            **/           
            rotate2D:function(angle,point){
                var x=point[0],y=point[1];
                var cos=Math.cos;
                var sin=Math.sin;
                var changeMtx= new matrix({
                    matrix:[
                       [cos(angle),sin(angle),0],
                       [-sin(angle),cos(angle),0],
                      
[(1-cos(angle))*x+y*sin(angle),(1-cos(angle))*y-x*sin(angle),1]
                    ]
                });   
                return this.multiply(changeMtx);
            },
            /**
            *3d平移
            **/
            translate3D:function(x,y,z){
                var changeMtx= new matrix({
                    matrix:[
                       [1,0,0,0],
                       [0,1,0,0],
                       [0,0,1,0],
                       [x,y,z,1]
                    ]
                });
                return this.multiply(changeMtx);
            },
            /**
            *3d缩放
            **/               
            scale3D:function(scale,point){//缩放比数组,参考试场点数组
                var
sx=scale[0],sy=scale[1],sz=scale[2],x=point[0],y=point[1],z=point[2];           
                var changeMtx= new matrix({
                    matrix:[
                       [sx,0,0,0],
                       [0,sy,0,0],
                       [0,0,sz,0],
                       [(1-sx)*x,(1-sy)*y,(1-sz)*z,1]
                    ]
                });   
                return this.multiply(changeMtx);               
               
            },           
            /**
            *3d旋转
            **/           
            rotate3D:function(angle,axis){
                var cos=Math.cos;
                var sin=Math.sin;
                var changeMtx;

2.     

                axis==”x”&&(changeMtx=new matrix({
                                matrix:[
                                   [1,0,0,0],
                                   [0,cos(angle),sin(angle),0],
                                   [0,-sin(angle),cos(angle),0],
                                   [0,0,0,1]
                                ]
                            }));   

4858美高梅 29

                axis==”y”&&(changeMtx=new matrix({
                                matrix:[
                                   [cos(angle),0,-sin(angle),0],
                                   [0,1,0,0],
                                   [sin(angle),0,cos(angle),0],
                                   [0,0,0,1]
                                ]
                            }));                       
                axis==”z”&&(changeMtx=new matrix({
                                matrix:[
                                   [cos(angle),sin(angle),0,0],
                                   [-sin(angle),cos(angle),0,0],
                                   [0,0,1,0],
                                   [0,0,0,1]
                                ]
                            }));                                   
                return this.multiply(changeMtx);
            },           
        };
        this.Matrix=matrix;
    });
   
 

是将上一步变换后的4858美高梅 30,围绕新的坐标原点顺时针旋转4858美高梅 31 。

 参考资料:总结机图形学

3.     

 

4858美高梅 32

摘自 Cson’s Room

经过上一步旋转变换后,再将坐标原点移回到原来的坐标原点。

 

为此,围绕某一点开始展览旋转变换,能够分为一个步骤,即首先将坐标原点移至该点,然后围绕新的坐标原点实行旋转变换,再然后将坐标原点移回到原先的坐标原点。

 

③ 、 缩放变换

辩论上而言,八个点是不设有何样缩放变换的,但考虑到具有图像都以由点构成,因而,假如图像在x轴和y轴方向分别放大k1k2倍的话,那么图像中的全数点的x坐标和y坐标均会分别放大k1k2倍,即

4858美高梅 33

用矩阵表示正是:

4858美高梅 34

缩放变换比较好通晓,就不多说了。

 

肆 、 错切变换

错切变换(skew)在数学上又叫做谢伊r
mapping(可译为“剪切变换”)或许Transvection(压缩合并),它是一种对比新鲜的线性别变化换。错切变换的机能正是让全数点的x坐标(或者y坐标)保持不变,而相应的y坐标(或者x坐标)则按比例发生位移,且活动的大小和该点到x轴(或y轴)的垂直距离成正比。错切变换,属于等面积变换,即3个形态在错切变换的上下,其面积是非常的。

譬如说下图,各点的y坐标保持不变,但其x坐标则按百分比发生了移动。那种情形将水平错切。

4858美高梅 35

下图各点的x坐标保持不变,但其y坐标则按百分比发生了运动。那种意况叫垂直错切。

4858美高梅 36 

比方1个点4858美高梅 37因此错切变换后获得4858美高梅 38,对于水平错切而言,应该有如下事关:

4858美高梅 39

用矩阵表示便是:

4858美高梅 40

扩大到3 x 3的矩阵正是底下那样的样式:

4858美高梅 41 

同理,对于垂直错切,能够有:

4858美高梅 42

在数学上严俊的错切变换便是地点这样的。在Android中除去有地方说到的情景外,还是能够而且展热水平、垂直错切,那么方式上正是:

4858美高梅 43

 

5、 对称变换

除去上边讲到的4中基本转移外,事实上,大家还足以采取Matrix,进行对称变换。所谓对称变换,正是通过变化后的图像和原图像是有关某些对称轴是对称的。比如,某点4858美高梅 44 经过对称变换后得到4858美高梅 45

若是对称轴是x轴,难么,

4858美高梅 46

用矩阵表示便是:

4858美高梅 47

一旦对称轴是y轴,那么,

4858美高梅 48

用矩阵表示就是:

4858美高梅 49

如若对称轴是y = x,如图:

4858美高梅 50

那么,

4858美高梅 51

很简单能够解得:

4858美高梅 52

用矩阵表示便是:

4858美高梅 53

相同的道理,倘若对称轴是y = -x,那么用矩阵表示正是:

4858美高梅 54 

新鲜地,假诺对称轴是y = kx,如下图:

4858美高梅 55

那么,

4858美高梅 56

很不难可解得:

4858美高梅 57

用矩阵表示正是:

4858美高梅 58

k = 0时,即y =
0
,也正是对称轴为x轴的状态;当k趋于无穷大时,即x =
0
,也正是对称轴为y轴的气象;当k =1时,即y = x,也正是对称轴为y =
x
的情况;当k = –1时,即y = -x,也正是对称轴为y =
-x
的情状。简单验证,那和我们日前说到的4中具体情状是相适合的。

 

万一对称轴是y = kx +
b
那样的情景,只须求在上头的根底上加码四遍平移变换即可,即先将坐标原点移动到(0,
b
),然后做地点的关于y =
kx
的相辅相成变换,再然后将坐标原点移回到原先的坐标原点即可。用矩阵表示大概是如此的:

4858美高梅 59

亟待尤其注意:在事实上编制程序中,大家知晓显示器的y坐标的正向和数学中y坐标的正向刚好是倒转的,所以在数学上y
= x
和显示器上的y =
-x
才是的确的同一个事物,反之亦然。也便是说,假诺要使图片在显示屏上看起来像根据数学意义上y
= x
对称,那么需选用那种转移:

4858美高梅 60

要使图片在显示器上看起来像依据数学意义上y =
-x
对称,那么需选用那种转移:
4858美高梅 61 

有关对称轴为y = kx y = kx + b的图景,同样要求考虑那地点的题材。

其次局地 代码验证

在第三有的中讲到的各个图像变换的证实代码如下,一共列出了10种状态。假使要验证其中的某一种情景,只需将相应的代码反注释即可。试验中用到的图形:

4858美高梅 62

其尺寸为162 x 251。

4858美高梅 63

其尺寸为162 x 251。

  1 <pre name="code" class="java">package com.pat.testtransformmatrix;  
  2   
  3 import android.app.Activity;  
  4 import android.content.Context;  
  5 import android.graphics.Bitmap;  
  6 import android.graphics.BitmapFactory;  
  7 import android.graphics.Canvas;  
  8 import android.graphics.Matrix;  
  9 import android.os.Bundle;  
 10 import android.util.Log;  
 11 import android.view.MotionEvent;  
 12 import android.view.View;  
 13 import android.view.Window;  
 14 import android.view.WindowManager;  
 15 import android.view.View.OnTouchListener;  
 16 import android.widget.ImageView;  
 17   
 18 public class TestTransformMatrixActivity extends Activity  
 19 implements  
 20 OnTouchListener  
 21 {  
 22     private TransformMatrixView view;  
 23     @Override  
 24     public void onCreate(Bundle savedInstanceState)  
 25     {  
 26         super.onCreate(savedInstanceState);  
 27         requestWindowFeature(Window.FEATURE_NO_TITLE);  
 28         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);  
 29   
 30         view = new TransformMatrixView(this);  
 31         view.setScaleType(ImageView.ScaleType.MATRIX);  
 32         view.setOnTouchListener(this);  
 33           
 34         setContentView(view);  
 35     }  
 36       
 37     class TransformMatrixView extends ImageView  
 38     {  
 39         private Bitmap bitmap;  
 40         private Matrix matrix;  
 41         public TransformMatrixView(Context context)  
 42         {  
 43             super(context);  
 44             bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sophie);  
 45             matrix = new Matrix();  
 46         }  
 47   
 48         @Override  
 49         protected void onDraw(Canvas canvas)  
 50         {  
 51             // 画出原图像  
 52             canvas.drawBitmap(bitmap, 0, 0, null);  
 53             // 画出变换后的图像  
 54             canvas.drawBitmap(bitmap, matrix, null);  
 55             super.onDraw(canvas);  
 56         }  
 57   
 58         @Override  
 59         public void setImageMatrix(Matrix matrix)  
 60         {  
 61             this.matrix.set(matrix);  
 62             super.setImageMatrix(matrix);  
 63         }  
 64           
 65         public Bitmap getImageBitmap()  
 66         {  
 67             return bitmap;  
 68         }  
 69     }  
 70   
 71     public boolean onTouch(View v, MotionEvent e)  
 72     {  
 73         if(e.getAction() == MotionEvent.ACTION_UP)  
 74         {  
 75             Matrix matrix = new Matrix();  
 76             // 输出图像的宽度和高度(162 x 251)  
 77             Log.e("TestTransformMatrixActivity", "image size: width x height = " +  view.getImageBitmap().getWidth() + " x " + view.getImageBitmap().getHeight());  
 78             // 1. 平移  
 79             matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());  
 80             // 在x方向平移view.getImageBitmap().getWidth(),在y轴方向view.getImageBitmap().getHeight()  
 81             view.setImageMatrix(matrix);  
 82               
 83             // 下面的代码是为了查看matrix中的元素  
 84             float[] matrixValues = new float[9];  
 85             matrix.getValues(matrixValues);  
 86             for(int i = 0; i < 3; ++i)  
 87             {  
 88                 String temp = new String();  
 89                 for(int j = 0; j < 3; ++j)  
 90                 {  
 91                     temp += matrixValues[3 * i + j ] + "\t";  
 92                 }  
 93                 Log.e("TestTransformMatrixActivity", temp);  
 94             }  
 95               
 96   
 97 //          // 2. 旋转(围绕图像的中心点)  
 98 //          matrix.setRotate(45f, view.getImageBitmap().getWidth() / 2f, view.getImageBitmap().getHeight() / 2f);  
 99 //            
100 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠  
101 //          matrix.postTranslate(view.getImageBitmap().getWidth() * 1.5f, 0f);  
102 //          view.setImageMatrix(matrix);  
103 //  
104 //          // 下面的代码是为了查看matrix中的元素  
105 //          float[] matrixValues = new float[9];  
106 //          matrix.getValues(matrixValues);  
107 //          for(int i = 0; i < 3; ++i)  
108 //          {  
109 //              String temp = new String();  
110 //              for(int j = 0; j < 3; ++j)  
111 //              {  
112 //                  temp += matrixValues[3 * i + j ] + "\t";  
113 //              }  
114 //              Log.e("TestTransformMatrixActivity", temp);  
115 //          }  
116               
117               
118 //          // 3. 旋转(围绕坐标原点) + 平移(效果同2)  
119 //          matrix.setRotate(45f);  
120 //          matrix.preTranslate(-1f * view.getImageBitmap().getWidth() / 2f, -1f * view.getImageBitmap().getHeight() / 2f);  
121 //          matrix.postTranslate((float)view.getImageBitmap().getWidth() / 2f, (float)view.getImageBitmap().getHeight() / 2f);  
122 //            
123 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠  
124 //          matrix.postTranslate((float)view.getImageBitmap().getWidth() * 1.5f, 0f);  
125 //          view.setImageMatrix(matrix);  
126 //            
127 //          // 下面的代码是为了查看matrix中的元素  
128 //          float[] matrixValues = new float[9];  
129 //          matrix.getValues(matrixValues);  
130 //          for(int i = 0; i < 3; ++i)  
131 //          {  
132 //              String temp = new String();  
133 //              for(int j = 0; j < 3; ++j)  
134 //              {  
135 //                  temp += matrixValues[3 * i + j ] + "\t";  
136 //              }  
137 //              Log.e("TestTransformMatrixActivity", temp);  
138 //          }             
139               
140 //          // 4. 缩放  
141 //          matrix.setScale(2f, 2f);  
142 //          // 下面的代码是为了查看matrix中的元素  
143 //          float[] matrixValues = new float[9];  
144 //          matrix.getValues(matrixValues);  
145 //          for(int i = 0; i < 3; ++i)  
146 //          {  
147 //              String temp = new String();  
148 //              for(int j = 0; j < 3; ++j)  
149 //              {  
150 //                  temp += matrixValues[3 * i + j ] + "\t";  
151 //              }  
152 //              Log.e("TestTransformMatrixActivity", temp);  
153 //          }  
154 //            
155 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠  
156 //          matrix.postTranslate(view.getImageBitmap().getWidth(), view.getImageBitmap().getHeight());  
157 //          view.setImageMatrix(matrix);  
158 //            
159 //          // 下面的代码是为了查看matrix中的元素  
160 //          matrixValues = new float[9];  
161 //          matrix.getValues(matrixValues);  
162 //          for(int i = 0; i < 3; ++i)  
163 //          {  
164 //              String temp = new String();  
165 //              for(int j = 0; j < 3; ++j)  
166 //              {  
167 //                  temp += matrixValues[3 * i + j ] + "\t";  
168 //              }  
169 //              Log.e("TestTransformMatrixActivity", temp);  
170 //          }  
171   
172               
173 //          // 5. 错切 - 水平  
174 //          matrix.setSkew(0.5f, 0f);  
175 //          // 下面的代码是为了查看matrix中的元素  
176 //          float[] matrixValues = new float[9];  
177 //          matrix.getValues(matrixValues);  
178 //          for(int i = 0; i < 3; ++i)  
179 //          {  
180 //              String temp = new String();  
181 //              for(int j = 0; j < 3; ++j)  
182 //              {  
183 //                  temp += matrixValues[3 * i + j ] + "\t";  
184 //              }  
185 //              Log.e("TestTransformMatrixActivity", temp);  
186 //          }  
187 //            
188 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠           
189 //          matrix.postTranslate(view.getImageBitmap().getWidth(), 0f);  
190 //          view.setImageMatrix(matrix);  
191 //            
192 //          // 下面的代码是为了查看matrix中的元素  
193 //          matrixValues = new float[9];  
194 //          matrix.getValues(matrixValues);  
195 //          for(int i = 0; i < 3; ++i)  
196 //          {  
197 //              String temp = new String();  
198 //              for(int j = 0; j < 3; ++j)  
199 //              {  
200 //                  temp += matrixValues[3 * i + j ] + "\t";  
201 //              }  
202 //              Log.e("TestTransformMatrixActivity", temp);  
203 //          }  
204               
205 //          // 6. 错切 - 垂直  
206 //          matrix.setSkew(0f, 0.5f);  
207 //          // 下面的代码是为了查看matrix中的元素  
208 //          float[] matrixValues = new float[9];  
209 //          matrix.getValues(matrixValues);  
210 //          for(int i = 0; i < 3; ++i)  
211 //          {  
212 //              String temp = new String();  
213 //              for(int j = 0; j < 3; ++j)  
214 //              {  
215 //                  temp += matrixValues[3 * i + j ] + "\t";  
216 //              }  
217 //              Log.e("TestTransformMatrixActivity", temp);  
218 //          }  
219 //            
220 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠               
221 //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());  
222 //          view.setImageMatrix(matrix);  
223 //            
224 //          // 下面的代码是为了查看matrix中的元素  
225 //          matrixValues = new float[9];  
226 //          matrix.getValues(matrixValues);  
227 //          for(int i = 0; i < 3; ++i)  
228 //          {  
229 //              String temp = new String();  
230 //              for(int j = 0; j < 3; ++j)  
231 //              {  
232 //                  temp += matrixValues[3 * i + j ] + "\t";  
233 //              }  
234 //              Log.e("TestTransformMatrixActivity", temp);  
235 //          }             
236               
237 //          7. 错切 - 水平 + 垂直  
238 //          matrix.setSkew(0.5f, 0.5f);  
239 //          // 下面的代码是为了查看matrix中的元素  
240 //          float[] matrixValues = new float[9];  
241 //          matrix.getValues(matrixValues);  
242 //          for(int i = 0; i < 3; ++i)  
243 //          {  
244 //              String temp = new String();  
245 //              for(int j = 0; j < 3; ++j)  
246 //              {  
247 //                  temp += matrixValues[3 * i + j ] + "\t";  
248 //              }  
249 //              Log.e("TestTransformMatrixActivity", temp);  
250 //          }  
251 //            
252 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠               
253 //          matrix.postTranslate(0f, view.getImageBitmap().getHeight());  
254 //          view.setImageMatrix(matrix);  
255 //            
256 //          // 下面的代码是为了查看matrix中的元素  
257 //          matrixValues = new float[9];  
258 //          matrix.getValues(matrixValues);  
259 //          for(int i = 0; i < 3; ++i)  
260 //          {  
261 //              String temp = new String();  
262 //              for(int j = 0; j < 3; ++j)  
263 //              {  
264 //                  temp += matrixValues[3 * i + j ] + "\t";  
265 //              }  
266 //              Log.e("TestTransformMatrixActivity", temp);  
267 //          }  
268               
269 //          // 8. 对称 (水平对称)  
270 //          float matrix_values[] = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f};  
271 //          matrix.setValues(matrix_values);  
272 //          // 下面的代码是为了查看matrix中的元素  
273 //          float[] matrixValues = new float[9];  
274 //          matrix.getValues(matrixValues);  
275 //          for(int i = 0; i < 3; ++i)  
276 //          {  
277 //              String temp = new String();  
278 //              for(int j = 0; j < 3; ++j)  
279 //              {  
280 //                  temp += matrixValues[3 * i + j ] + "\t";  
281 //              }  
282 //              Log.e("TestTransformMatrixActivity", temp);  
283 //          }  
284 //            
285 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠   
286 //          matrix.postTranslate(0f, view.getImageBitmap().getHeight() * 2f);  
287 //          view.setImageMatrix(matrix);  
288 //            
289 //          // 下面的代码是为了查看matrix中的元素  
290 //          matrixValues = new float[9];  
291 //          matrix.getValues(matrixValues);  
292 //          for(int i = 0; i < 3; ++i)  
293 //          {  
294 //              String temp = new String();  
295 //              for(int j = 0; j < 3; ++j)  
296 //              {  
297 //                  temp += matrixValues[3 * i + j ] + "\t";  
298 //              }  
299 //              Log.e("TestTransformMatrixActivity", temp);  
300 //          }             
301               
302 //          // 9. 对称 - 垂直  
303 //          float matrix_values[] = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f};  
304 //          matrix.setValues(matrix_values);  
305 //          // 下面的代码是为了查看matrix中的元素  
306 //          float[] matrixValues = new float[9];  
307 //          matrix.getValues(matrixValues);  
308 //          for(int i = 0; i < 3; ++i)  
309 //          {  
310 //              String temp = new String();  
311 //              for(int j = 0; j < 3; ++j)  
312 //              {  
313 //                  temp += matrixValues[3 * i + j ] + "\t";  
314 //              }  
315 //              Log.e("TestTransformMatrixActivity", temp);  
316 //          }     
317 //            
318 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠   
319 //          matrix.postTranslate(view.getImageBitmap().getWidth() * 2f, 0f);  
320 //          view.setImageMatrix(matrix);  
321 //            
322 //          // 下面的代码是为了查看matrix中的元素  
323 //          matrixValues = new float[9];  
324 //          matrix.getValues(matrixValues);  
325 //          for(int i = 0; i < 3; ++i)  
326 //          {  
327 //              String temp = new String();  
328 //              for(int j = 0; j < 3; ++j)  
329 //              {  
330 //                  temp += matrixValues[3 * i + j ] + "\t";  
331 //              }  
332 //              Log.e("TestTransformMatrixActivity", temp);  
333 //          }  
334   
335               
336 //          // 10. 对称(对称轴为直线y = x)  
337 //          float matrix_values[] = {0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f};  
338 //          matrix.setValues(matrix_values);  
339 //          // 下面的代码是为了查看matrix中的元素  
340 //          float[] matrixValues = new float[9];  
341 //          matrix.getValues(matrixValues);  
342 //          for(int i = 0; i < 3; ++i)  
343 //          {  
344 //              String temp = new String();  
345 //              for(int j = 0; j < 3; ++j)  
346 //              {  
347 //                  temp += matrixValues[3 * i + j ] + "\t";  
348 //              }  
349 //              Log.e("TestTransformMatrixActivity", temp);  
350 //          }  
351 //            
352 //          // 做下面的平移变换,纯粹是为了让变换后的图像和原图像不重叠               
353 //          matrix.postTranslate(view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth(),   
354 //                  view.getImageBitmap().getHeight() + view.getImageBitmap().getWidth());  
355 //          view.setImageMatrix(matrix);  
356 //            
357 //          // 下面的代码是为了查看matrix中的元素  
358 //          matrixValues = new float[9];  
359 //          matrix.getValues(matrixValues);  
360 //          for(int i = 0; i < 3; ++i)  
361 //          {  
362 //              String temp = new String();  
363 //              for(int j = 0; j < 3; ++j)  
364 //              {  
365 //                  temp += matrixValues[3 * i + j ] + "\t";  
366 //              }  
367 //              Log.e("TestTransformMatrixActivity", temp);  
368 //          }  
369               
370             view.invalidate();  
371         }  
372         return true;  
373     }  
374 }  

上边给出上述代码中,种种变换的切实结果及其相应的连带变换矩阵

1.     平移

4858美高梅 64

输出的结果:

4858美高梅 65

请对照第3局地中的“壹 、平移变换”所讲的情景,考察上述矩阵的不错。

 

2.     旋转(围绕图像的大旨点)

4858美高梅 66

输出的结果:

4858美高梅 67

它实际是

matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f,
view.getImageBitmap().getHeight() / 2f);

matrix.postTranslate(view.getImageBitmap().getWidth()* 1.5f, 0f);

这两条语句综合效应的结果。依据第③片段中“贰 、旋转变换”里面关于围绕某点旋转的公式,

matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f,
view.getImageBitmap().getHeight() / 2f);

所产生的转移矩阵正是:

4858美高梅 68

而matrix.postTranslate(view.getImageBitmap().getWidth()* 1.5f,
0f);的情趣正是在上述矩阵的左手再乘以下边包车型客车矩阵:

4858美高梅 69

至于post是左乘那或多或少,大家在前面包车型客车论战部分已经提及过,后边大家还会尤其钻探那一个题目。

 

为此它实际上正是:

4858美高梅 70

出来计算上的精度误差,大家得以看出大家总结出来的结果,和程序直接出口的结果是一模一样的。

 

3.     旋转(围绕坐标原点旋转,在增进三回活动,效果同2)

4858美高梅 71

基于第③某些中“二 、旋转变换”里面关于围绕某点旋转的分解,简单知道:

matrix.setRotate(45f,view.getImageBitmap().getWidth() / 2f,
view.getImageBitmap().getHeight() / 2f);

等价于

matrix.setRotate(45f);

matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f
*view.getImageBitmap().getHeight() / 2f);

matrix.postTranslate((float)view.getImageBitmap().getWidth()/ 2f,
(float)view.getImageBitmap().getHeight() / 2f);

 

在那之中matrix.setRotate(45f)对应的矩阵是:

4858美高梅 72

matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f *
view.getImageBitmap().getHeight()/ 2f)对应的矩阵是:

4858美高梅 73

由于是preTranslate,是先乘,也正是右乘,即它应当出现在matrix.setRotate(45f)所对应矩阵的左边。

 

matrix.postTranslate((float)view.getImageBitmap().getWidth()/ 2f,
(float)view.getImageBitmap().getHeight() / 2f)对应的矩阵是:

4858美高梅 74

此次是因为是postTranslate,是后乘,也正是左乘,即它应当出现在matrix.setRotate(45f)所对应矩阵的左边。

 

就此综合起来,

matrix.setRotate(45f);

matrix.preTranslate(-1f* view.getImageBitmap().getWidth() / 2f, -1f
*view.getImageBitmap().getHeight() / 2f);

matrix.postTranslate((float)view.getImageBitmap().getWidth()/ 2f,
(float)view.getImageBitmap().getHeight() / 2f);

对应的矩阵便是:

4858美高梅 75

那和下部那么些矩阵(围绕图像中央顺时针旋转45度)其实是同等的:

4858美高梅 76

于是,此处变换后的图像和第22中学改换后的图像时一样的。

 

4.     缩放变换

4858美高梅 77

程序所出口的五个矩阵分别是:

4858美高梅 78

内部第二个矩阵,其实是底下八个矩阵相乘的结果:

4858美高梅 79 

世家能够相比第壹有的中的“三 、缩放变换”和“一 、平移变换”说法,自行验证结果。

 

5.     错切变换(水平错切)

4858美高梅 80

代码所出口的三个矩阵分别是:

4858美高梅 81

里头,第四个矩阵其实是底下八个矩阵相乘的结果:

 4858美高梅 82

世家能够比较第③部分中的“肆 、错切变换”和“① 、平移变换”的相干说法,自行验证结果。

 

6.     错切变换(垂直错切)

4858美高梅 83

代码所出口的七个矩阵分别是:

4858美高梅 84

其间,第二个矩阵其实是上边多个矩阵相乘的结果:

4858美高梅 85

我们能够对照第二局地中的“四 、错切变换”和“① 、平移变换”的连锁说法,自行验证结果。

 

7.     错切变换(水平+垂直错切)

4858美高梅 86

代码所出口的四个矩阵分别是:

4858美高梅 87

中间,后者是上面多个矩阵相乘的结果:

4858美高梅 88

大家能够相比第3部分中的“肆 、错切变换”和“① 、平移变换”的相干说法,自行验证结果。

 

8.     对称变换(水平对称)

4858美高梅 89

代码所出口的四个各矩阵分别是:

4858美高梅 90

当中,后者是下面五个矩阵相乘的结果:

4858美高梅 91 

世家能够相比较第二局地中的“五 、对称变换”和“壹 、平移变换”的连锁说法,自行验证结果。

 

9.     对称变换(垂直对称)

4858美高梅 92

代码所出口的五个矩阵分别是:

4858美高梅 93

内部,后者是底下八个矩阵相乘的结果:

4858美高梅 94 

世家能够对照第3部分中的“五 、对称变换”和“① 、平移变换”的相干说法,自行验证结果。

 

10.   对称变换(对称轴为直线y = x)

4858美高梅 95

代码所出口的三个矩阵分别是:

4858美高梅 96

里面,后者是底下三个矩阵相乘的结果:

4858美高梅 97 

大家能够对照第1局地中的“⑤ 、对称变换”和“一 、平移变换”的连锁说法,自行验证结果。

 

11.   关于先乘和后乘的标题

鉴于矩阵的乘法运算不满足沟通律,大家在头里已经多次提及先乘、后乘的难点,即先乘正是矩阵运算中右乘,后乘就是矩阵运算中的左乘。其实先乘、后乘的概念是对准变换操作的岁月顺序而言的,左乘、右乘是针对性矩阵运算的左右职分而言的。以率先片段“二 、旋转变换”中围绕某点旋转的气象为例:

4858美高梅 98 

越临近原图像中像素的矩阵,越先乘,越远离原图像中像素的矩阵,越后乘。事实上,图像处理时,矩阵的运算是从右侧往左侧方向拓展览演出算的。那就形成了越在左边的矩阵(右乘),越先运算(先乘),反之亦然。

 

自然,在其实中,假使首先钦定了3个matrix,比如大家先setRotate(4858美高梅 99),即钦点了上边变换矩阵中,中间的十分矩阵,那么继续的矩阵到底是pre照旧post运算,都以相对这么些个中矩阵而言的。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有