Affine Transformation是一种二维坐标到二维坐标之间的线性变换,保持二维图形的“平直性”和“平行性”。仿射变换可以通过一系列的原子变换的复合来实现,包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear)。

在做2D图形引擎时,仿射变换是非常重要的点,图形的旋转等各种表现都需要通过仿射变换来完成,比如在显示列表树中,父节点旋转了,那么子节点在计算显示时也要叠加上父节点的变换矩阵,这是叠加矩阵。还有计算2D空间内的点在经过仿射变换的图形中的位置、鼠标是否点在经过仿射变换过的矩形中,等等都是需要仿射变换来完成计算。

定义一个矩阵类Matrix包含属性如下:
| 参数 | 描述 |
| ----- |:----:|
| a | 水平缩放比例 |
| b | 垂直倾斜比例 |
| c | 水平倾斜比例 |
| d | 垂直缩放比例 |
| x | 水平偏移像素 |
| y | 垂直偏移像素 |

矩阵的默认值为Matrix(1,0,0,1,0,0),后面的变换以改变矩阵值的形式完成。通过H5中的canvas实现改变图形:

var c=document.getElementById("canvas");
var ctx=c.getContext("2d");ctx.fillStyle="yellow";
ctx.fillRect(0,0,250,100)var matrix = RM.Matrix.create(1,0,0,1,0,0);
ctx.setTransform(matrix.a,matrix.b,matrix.c,matrix.d,matrix.x,matrix.y);
ctx.fillStyle="red";
ctx.fillRect(0,0,250,100);

平移

平移变换是一种“刚体变换”,并不会改变图形的形状。

//(平移到点40,50)
matrix.translate( 40, 50 );

涉及到函数的平移公式code:

/**平移x,y像素*/
public translate( x:number, y:number ):RM.Matrix {this.x += x;this.y += y;return this;
}

缩放

缩放变换可以改变图形的宽高比例,横向缩放与纵向缩放。当值为负数反向缩放

//(x轴缩放0.5,y轴缩放0.5)
matrix.scale( 0.5, 0.5 );
或
//(x轴缩放-1,y轴缩放1)
matrix.scale( -1, 1 );

涉及到函数的缩放公式code:

/**缩放,x、y轴方向缩放*/
public scale( scaleX:number, scaleY:number ):RM.Matrix {this.a *= scaleX;this.b *= scaleY;this.c *= scaleX;this.d *= scaleY;this.x *= scaleX;this.y *= scaleY;return this;
}

旋转

目标图形围绕(x,y)点顺时针旋转value弧度

旋转矩阵为(cosA, sinA, -sinA, cosA, 0, 0)

//(顺时针旋转30角度)
matrix.rotate( 30 );

涉及到函数的旋转公式code:

/**旋转,单位是角度* 旋转矩阵( cosA, sinA, -sinA, cosA, 0, 0)* */
public rotate( angle:number ):RM.Matrix {angle = ( angle % 360 )angle = RM.GFunction.angle2radian( angle );//角度转弧度var cos:number = Math.cos( angle );var sin:number = Math.sin( angle );var ta:number = this.a;var tc:number = this.c;var tx:number = this.x;this.a = ta * cos - this.b * sin;this.b = ta * sin + this.b * cos;this.c = tc * cos - this.d * sin;this.d = tc * sin + this.d * cos;this.x = tx * cos - this.y * sin;this.y = tx * sin + this.y * cos;return this;
}

错切

错切变换指的是类似于四边形不稳定性那种性质,菱形形状。根据弧度顺时针倾斜。

错切矩阵为( 1, tanAy, tanAx, 1, 0, 0 )

//(x轴错切30角度)
matrix.skew( 30, 45 );

涉及到函数的错切公式code:

/**切变,单位是角度* 切变矩阵 ( 1, tanAy, tanAx, 1, 0, 0)* */
public skew( angleX:number, angleY:number ):RM.Matrix {angleX = ( angleX % 90 );angleY = ( angleY % 90 );angleX = RM.GFunction.angle2radian( angleX );//角度转弧度angleY = RM.GFunction.angle2radian( angleY );//角度转弧度var tanAx:number = Math.tan( angleX );var tanAy:number = Math.tan( angleY );var ta:number = this.a;var tc:number = this.c;var tx:number = this.x;this.a = ta + tanAx * this.b;this.b = ta * tanAy + this.b;this.c = tc + tanAx * this.d;this.d = tc * tanAy + this.d;this.x = tx + tanAx * this.y;this.y = tx * tanAy + this.y;return this;
}

属性叠加

当设置仿射变换的多个属性时,依据矩阵乘法的特性要遵循顺序(缩放->错切->旋转->平移)依次变换。

如果不按照以上顺序,产生的结果将会与预期大大不同。下图以先x轴缩放0.5、错切x轴-30y轴30、旋转10度、平移(10,20)

错切与旋转的区别:错切可以分别向两方向倾斜不同的角度;旋转是同时向两方向倾斜相同的角度。
那么,可以把错切与旋转合并,错切的默认x轴倾斜是正方向倾斜,也就是逆时针,改为与y轴倾斜相同的顺时针方向。
当旋转30度时,也就是x轴y轴同时顺时针倾斜30度。

如图所示,大矩形错切x轴y轴各30度,小矩形旋转30度,两者的结果是一致的。

//大矩形
matrix.rightTransform( 0,0,1,1,30,30,0 );
//小矩形
matrix.rightTransform( 0,0,1,1,0,0,30 );

属性叠加公式code:

/**转换矩阵操作,顺序为:缩放、切变、旋转、平移*/
public rightTransform(x:number, y:number, scaleX:number, scaleY:number, skewX:number, skewY:number, rotate:number):RM.Matrix {rotate = ( rotate % 360 );rotate = RM.GFunction.angle2radian(rotate);//旋转与切变一起算skewX = RM.GFunction.angle2radian(skewX) + rotate;skewY = RM.GFunction.angle2radian(skewY) + rotate;if (skewX || skewY) {//矩阵乘法(右置矩阵、后置矩阵)this.rightMultiply(Math.cos(skewY) * scaleX, Math.sin(skewY) * scaleX, -Math.sin(skewX) * scaleY, Math.cos(skewX) * scaleY, x, y);}else {this.rightMultiply(scaleX, 0, 0, scaleY, x, y);}
}

叠加矩阵

在显示对象树中,父节点旋转30度,那么它的子节点是否也要旋转到相对于父节点的位置呢?答案是肯定的,必须旋转到相对位置。这就涉及到矩阵乘法,例如矩阵A*矩阵B得到的就是叠加矩阵,但是一定要注意的是 A*B ≠ B*A

矩阵乘法满足结合律,但不满足交换律。

因为矩阵A*B=C,C的结果是由A的行与B的列相乘和的结果;而B*A=D,D的结果是由B的行与A的列相乘和的结果。显然,得到的结果C和D不一定相等

显然,大矩形为父节点,小矩形为大矩形的子节点,当大矩形旋转60度时,小矩形相对于父节点为0度,
然后小矩形再旋转60度,这是相对于父节点旋转了60度,相对于原点旋转了120度。大矩形以原点(0,0)点旋转,小矩形以大矩形内的坐标(0,0)点旋转。

parent.matrix = RM.Matrix.create(0,0,1,1,0,0,60);
//父节点的矩阵与子节点的矩阵相乘,便是子节点的真实矩阵
child.matrix = parent.matrix.rightTransform(0,0,1,1,0,0,60);

矩阵的运用

矩阵这东西在图形引擎中的运用是很多的,上面的例图就是使用自己写好的图形引擎,通过设置属性再渲染到canvas中的。一张坐标轴地图、一个虚线矩形、一个实线矩形完成演示。
矩阵的运用还是很多的,2D图形引擎中坐标点的判断,鼠标点击是否在图形上,脏矩形的范围,子节点上的坐标与原点坐标系的转换,等都是通过点与矩阵之间的二维空间转换而得到确切的值。

转载于:https://www.cnblogs.com/Richard-Core/p/matrix-affine-transform.html

通过Matrix进行二维图形仿射变换相关推荐

  1. 二维图形的变换(矩阵形式)

    变化图形就是变化图形的几何关系,即改变顶点的坐标,同时保持图形的原拓扑关系不变(即用结点.弧段和多边形所表示的实体之间的邻接.关联.包含和连通关系不变.如:点与点的邻接关系.点与面的包含关系.线与面的 ...

  2. 计算机图形学 学习笔记(七):二维图形变换:平移,比例,旋转,坐标变换等

    接上文 计算机图形学 学习笔记(六):消隐算法:Z-buffer,区间扫描线,Warnock,光栅图形学小结 在图形学中,有两大基本工具:向量分析,图形变换.本文将重点讲解向量和二维图形的变换. 5. ...

  3. 【OpenGL ES】二维图形绘制

    目录 OpenGL ES 学习--2D 着色器语言基础知识 绘制纯色背景 JAVA版本 C++版本 绘制圆点.直线.三角形 JAVA版本 C++版本 绘制彩色三角形 JAVA版本 C++版本 绘制纯色 ...

  4. 计算机图形学:二维图形的几何变换(算法原理及代码实现)

    一.实现方案 对于一个二维图形作平移.旋转.放缩变换,可以转换为在二维坐标系中图形的所有点分别可以对应到在x,y轴方向分别平移tx,ty(平移).绕一点旋转固定的角(旋转).在x,y轴方向分别放缩sx ...

  5. 计算机图形学-二维图形变换 笔记总结与代码实战

    文章目录 1.向量基础知识 2.图形坐标系 3.二维图形变换原理 4.二维图形几何变换 5.窗口视区变换 基本二维几何变换代码 二维复合变换实战-五星红旗绘制 1.向量基础知识 为什么向量如此重要:在 ...

  6. autocad2007二维图画法_cad怎样绘制简单的二维图形

    CAD绘制二维图形非常的简单,大家经常用它来画图,下面是学习啦小编带来关于cad怎样绘制简单的二维图形的内容,希望可以让大家有所收获! cad绘制简单二维图形的方法 1.绘图菜单绘图菜单是绘制图形最基 ...

  7. 如何使用MATLAB绘制不同类型的二维图形

    如何使用MATLAB绘制不同类型的二维图形 听语音 | 浏览:360 | 更新:2014-11-30 18:10 | 标签:matlab 1 2 3 4 5 分步阅读 如何用MATLAB绘制各种二维图 ...

  8. 二维绕任意点旋转_二维图形复合线性变换程序设计:三角形绕任意点旋转2wfhbh...

    第七讲:二维图形复合线性变换程序设计: 例题:三角形绕任意点旋转. 组合变换为: ( 1 )平移变换 ( 2 )旋转变换 ( 3 )平移变换 #include #include #define PAI ...

  9. matlab 如何画二维图形,Matlab 学习 画图篇 一 二维图形

    matlab给绘制二维图形提供了很多的函数,把一些绘制二维图形的基本函数做成一张表,如下图所示: 我就按照表的顺序一一记录一些个函数的简略用法. 首先是 1.plot函数 plot函数有很多重载方法, ...

最新文章

  1. webstorm设置点击(单击)左侧项目资源管理器里面的文件,自动在右侧打开源代码文件
  2. 4种事务特性,5种隔离级别,7种传播行为
  3. C语言实验——矩阵转置_JAVA
  4. P4316 绿豆蛙的归宿 期望dp + DAG
  5. 【美文保存】nosql数据库对比以及如何巧妙利用redis来提高效率?
  6. [014]模板-模板实参推导
  7. android手机和荣耀哪个版本好,【求测评】荣耀v40轻奢版与荣耀X10哪款更好?图文爆料分析...
  8. 【转】专利申请前的技术交底书是什么?怎么写?
  9. 轻松访问Google Chrome浏览器中的浏览历史记录
  10. 【Unity3D】使用 FBX 格式的外部模型 ② ( FBX 模型与默认 3D 模型的区别 | FBX 模型贴图查找路径 | FBX 模型可设置多个材质 )
  11. STM32F103ZET6 驱动 OLED
  12. 无人驾驶—激光雷达与相机
  13. 爬虫----js逆向某宝h5的sign参数
  14. 交流充电桩电路图_一种新能源汽车交流充电桩控制电路的制作方法
  15. Ubuntu20.04使用中科大镜像源安装更新nginx
  16. 计算机考研数学试卷,考研数学一般有几种试卷?
  17. ROS从入门到精通2-1:机器人3D可视化工具——Rviz
  18. 信用卡最低还款与分期付款有什么区别呢?
  19. 关于第一次使用keil5软件注释为什么变成了?(保姆级教程)
  20. Ubuntu18.04系统下,gcc编译过程分析、命令参数介绍及ELF文件格式学习

热门文章

  1. 营销网站SEO优化:前方优化难点出没!
  2. python读取进程内存_Python读取Linux内存进程错误(/ proc / $pid / mem...
  3. 计算机多媒体理论知识,计算机多媒体技术07311.doc
  4. antd 动态添加表单_ZooTeam 拍了拍你,来看看如何设计动态化表单
  5. 读服务器文件,读取服务器文件
  6. win7无法打开计算机共享文件,win7不能共享文件的解决方法
  7. tcp linux 报文内容,linux – tcpdump – 只是逐行输出数据包内容
  8. Ciruy英雄谭 Chapter 2 Web浏览器如何将数据委托出去(一)
  9. Linux上的free命令详解
  10. IxRmhOECiP