图形学各种二维基础变换,原来线性代数还能这么用,太牛了

缩放变换

均匀缩放

  • 若想将一个图形缩小0.5倍

    image-20240708152453401

  • 若x乘上缩放值s等于x撇,y同理,则 x ′ = s x y ′ = s y \begin{aligned} & x^{\prime}=s x \\ & y^{\prime}=s y \end{aligned} x=sxy=sy,这样就表示了x缩小了s倍,y也是

  • 将其转为矩阵操作则是在前面乘上一个缩放矩阵 [ x ′ y ′ ] = [ s 0 0 s ] [ x y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{ll} s & 0 \\ 0 & s \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right] [xy]=[s00s][xy],根据矩阵乘法性质,其中的x撇和y撇最后乘出来就是上述的sx和sy。

  • 变换矩阵为 [ s 0 0 s ] \left[\begin{array}{ll} s & 0 \\ 0 & s \end{array}\right] [s00s]

非均匀缩放

  • x缩放0.5倍,y不变

image-20240708152837988

  • 和上述公式一样,只不过将对角矩阵的下面那个换一下就行 [ x ′ y ′ ] = [ s x 0 0 s y ] [ x y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{cc} s_x & 0 \\ 0 & s_y \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right] [xy]=[sx00sy][xy]
  • 其中sx为x轴的缩放倍数,sy为y轴。
  • 变换矩阵为 [ s x 0 0 s y ] \left[\begin{array}{cc} s_x & 0 \\ 0 & s_y \end{array}\right] [sx00sy]

镜像变换

  • 若要将x沿x轴镜像,则表达为 x ′ = − x y ′ = y \begin{aligned} & x^{\prime}=-x \\ & y^{\prime}=y \end{aligned} x=xy=y

image-20240708153231564

  • 其矩阵形式则为 [ x ′ y ′ ] = [ − 1 0 0 1 ] [ x y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{cc} -1 & 0 \\ 0 & 1 \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right] [xy]=[1001][xy]
  • 变换矩阵为 [ − 1 0 0 1 ] \left[\begin{array}{cc} -1 & 0 \\ 0 & 1 \end{array}\right] [1001]

剪切变换

  • x轴拉长,y轴不变

image-20240708153745046

  • 当y=0时,水平方向不变
  • 当y=1时,水平方向向右移动a个位置
  • 于是可推出,当y为1/2时,则移动后的x应该在原本的x+ay处,也就是x根据变换后为x+ay,y不变
  • 用矩阵表达则为 [ x ′ y ′ ] = [ 1 a 0 1 ] [ x y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{ll} 1 & a \\ 0 & 1 \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right] [xy]=[10a1][xy]
  • 变换矩阵为 [ 1 a 0 1 ] \left[\begin{array}{ll} 1 & a \\ 0 & 1 \end{array}\right] [10a1]

旋转变换

  • 若无特殊说明,若说A旋转45度,则表示为A绕原点逆时针旋转45度

image-20240708154814971

  • 则旋转矩阵为 R θ = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] \mathbf{R}_\theta=\left[\begin{array}{cc} \cos \theta & -\sin \theta \\ \sin \theta & \cos \theta \end{array}\right] Rθ=[cosθsinθsinθcosθ]
  • 也就是 [ x ′ y ′ ] = [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] [ x y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{cc} \cos \theta & -\sin \theta \\ \sin \theta & \cos \theta \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right] [xy]=[cosθsinθsinθcosθ][xy]
  • 若旋转角度为 − θ -\theta θ,则旋转矩阵为 R − θ = [ cos ⁡ θ sin ⁡ θ − sin ⁡ θ cos ⁡ θ ] \mathbf{R}_{-\theta}=\left[\begin{array}{cc} \cos \theta & \sin \theta \\ -\sin \theta & \cos \theta \end{array}\right] Rθ=[cosθsinθsinθcosθ],其中 cos ⁡ ( − θ ) = cos ⁡ ( θ ) , sin ⁡ ( − θ ) = − sin ⁡ ( θ ) \cos(-\theta)=\cos(\theta),\sin(-\theta)=-\sin(\theta) cos(θ)=cos(θ)sin(θ)=sin(θ)
  • 由此可观察得到, R − θ = R θ T \mathbf{R}_{-\theta}=\mathbf{R}_{\theta}^T Rθ=RθT,我们知道,旋转 θ \theta θ角度和旋转 − θ -\theta θ角度是互逆的,也就是 R − θ = R θ − 1 \mathbf{R}_{-\theta}=\mathbf{R}_{\theta}^{-1} Rθ=Rθ1,所以在这可以得到一个很有用的性质,即想求一个图形旋转 − θ -\theta θ角,我们只需要计算它旋转 θ \theta θ角度矩阵的转置即可。
  • 变换矩阵为 [ cos ⁡ θ − sin ⁡ θ sin ⁡ θ cos ⁡ θ ] \left[\begin{array}{cc} \cos \theta & -\sin \theta \\ \sin \theta & \cos \theta \end{array}\right] [cosθsinθsinθcosθ]

线性变换

  • 经过上述变换公式,可以发现其任意一个坐标都可以通过乘上一个系数变成另一个坐标,即 x ′ = a x + b y y ′ = c x + d y \begin{aligned} & x^{\prime}=a x+b y \\ & y^{\prime}=c x+d y \end{aligned} x=ax+byy=cx+dy
  • 矩阵形式就是 [ x ′ y ′ ] = [ a b c d ] [ x y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{ll} a & b \\ c & d \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right] [xy]=[acbd][xy],也可写成 x ′ = M x \mathbf{x}^{\prime}=\mathbf{M} \mathbf{x} x=Mx
  • 则将这种变换取名为线性变换

平移变换

  • x轴移动tx,y轴移动ty

image-20240708161311429

  • 则在坐标上的表达为 x ′ = x + t x y ′ = y + t y \begin{aligned} & x^{\prime}=x+t_x \\ & y^{\prime}=y+t_y \end{aligned} x=x+txy=y+ty
  • 可是这种加法操作,并不能转换为二维矩阵的矩阵变换,也就是乘上一个矩阵从而使得xy移动到x撇y撇
  • 只能通过矩阵的加法来实现,也就是 [ x ′ y ′ ] = [ a b c d ] [ x y ] + [ t x t y ] \left[\begin{array}{l} x^{\prime} \\ y^{\prime} \end{array}\right]=\left[\begin{array}{ll} a & b \\ c & d \end{array}\right]\left[\begin{array}{l} x \\ y \end{array}\right]+\left[\begin{array}{l} t_x \\ t_y \end{array}\right] [xy]=[acbd][xy]+[txty],而这种形式的变换,被称为仿射变换
  • 若不想进行其他变换,也就是旋转啊、缩放啊等,则前面那个abcd矩阵设为单位矩阵

齐次坐标

  • 为了使得在进行平移变换的时候或者其他所有的变换都只用乘一个矩阵就完成变换,所以引入了齐次坐标
  • 也就是在原有维度的情况下添加了第三个坐标维度w,在原先是2d点的情况变为 ( x , y , 1 ) ⊤ (\mathbf{x}, \mathbf{y}, 1)^{\top} (x,y,1)
  • 原先是2d向量的情况现在变为 ( x , y , 0 ) ⊤ (\mathbf{x}, \mathbf{y}, 0)^{\top} (x,y,0)
  • 于是我们可以构建出一个矩阵,从而达成只乘一个矩阵就可完成平移变换 ( x ′ y ′ w ′ ) = ( 1 0 t x 0 1 t y 0 0 1 ) ⋅ ( x y 1 ) = ( x + t x y + t y 1 ) \left(\begin{array}{c} x^{\prime} \\ y^{\prime} \\ w^{\prime} \end{array}\right)=\left(\begin{array}{ccc} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{array}\right) \cdot\left(\begin{array}{l} x \\ y \\ 1 \end{array}\right)=\left(\begin{array}{c} x+t_x \\ y+t_y \\ 1 \end{array}\right) xyw = 100010txty1 xy1 = x+txy+ty1
  • 只看最右边的前两个值发现就是一个平移操作
  • 而为啥二维的点和二维的向量要区分开呢?也就是二维点增加的维度w为1,二维向量增加的维度w为0,主要是因为向量有一个性质,就是一个向量平移到了另一个位置,那它还是那个向量,并不会发生改变
  • 而看到上面的公式,若把矩阵右边乘上的向量里的1变为0,则乘完矩阵后的值还是(x, y, 0),这样才符合刚刚说的那个向量平移不变性的性质。
  • 同时,区分点和向量还有一个好处就是,向量加向量还是一个向量,例如两个向量相加,比如(x1, y1, 0) + (x2, y2, 0)后为(x1 + x2, y1 + y2, 0),这正好符合向量相加的原则
  • 并且当两个点相减的时候,可以理解为是从a点指向到了b点,那么这个a到b就是一个向量,也就是(x1, y1, 1) - (x2, y2, 1) = (x1 - x2, y1 - y2 , 0),这正好也符合两个点相减的意义
  • 同理可得一个点加上一个向量,就相当于该点移动了一个向量的位置到了另一个点,也就是(x1, y1, 1) + (x2, y2, 0) = (x1 + x2, y1 + y2, 1),这也正好表现为了一个点
  • 所以引入齐次坐标很方便
  • 而任何一个仿射变换都可以使用齐次坐标来转换为仅需乘上一个矩阵就可完成变换
  • ( x ′ y ′ ) = ( a b c d ) ⋅ ( x y ) + ( t x t y ) \binom{x^{\prime}}{y^{\prime}}=\left(\begin{array}{ll} a & b \\ c & d \end{array}\right) \cdot\binom{x}{y}+\binom{t_x}{t_y} (yx)=(acbd)(yx)+(tytx)可转换为 ( x ′ y ′ 1 ) = ( a b t x c d t y 0 0 1 ) ⋅ ( x y 1 ) \left(\begin{array}{l} x^{\prime} \\ y^{\prime} \\ 1 \end{array}\right)=\left(\begin{array}{llc} a & b & t_x \\ c & d & t_y \\ 0 & 0 & 1 \end{array}\right) \cdot\left(\begin{array}{l} x \\ y \\ 1 \end{array}\right) xy1 = ac0bd0txty1 xy1
  • 也就是现在处理任何一个变换,都可以仅乘一个矩阵就可以完成变换了
  • 而引入齐次坐标的上述所有变换矩阵,都可以用以下矩阵表示
  • 缩放变换: S ( s x , s y ) = ( s x 0 0 0 s y 0 0 0 1 ) \mathbf{S}\left(s_x, s_y\right)=\left(\begin{array}{ccc} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{array}\right) S(sx,sy)= sx000sy0001
  • 旋转变换: R ( α ) = ( cos ⁡ α − sin ⁡ α 0 sin ⁡ α cos ⁡ 4 α 0 0 0 1 ) \mathbf{R}(\alpha)=\left(\begin{array}{ccc} \cos \alpha & -\sin \alpha & 0 \\ \sin \alpha & \cos _4 \alpha & 0 \\ 0 & 0 & 1 \end{array}\right) R(α)= cosαsinα0sinαcos4α0001
  • 平移变换: T ( t x , t y ) = ( 1 0 t x 0 1 t y 0 0 1 ) \mathbf{T}\left(t_x, t_y\right)=\left(\begin{array}{ccc} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{array}\right) T(tx,ty)= 100010txty1
  • 可发现在二维仿射变换添加齐次坐标后的矩阵最后一行都是(0, 0, 1)。

逆变换

  • 若A点经过一个矩阵M变换成了B点,那么则B点经过一个矩阵 M − 1 M^{-1} M1可重新变换成A点,这个 M − 1 M^{-1} M1就是逆变换矩阵

    image-20240708165534391

变换矩阵的合并与分解

合并

  • 现在假设想将一个图形变换为另一个图形,如下图所示

image-20240708170417203

  • 则明显有一个方法,就是利用平移变换和旋转变换

  • 但是这里如果先利用平移再旋转,则会出现下图情况

    image-20240708170545289

  • 可以发现第一个图形并没有变换到我们想要的位置上

  • 而如果我们先旋转,再平移,则可以发现可以完美变换到我们想要的位置

    image-20240708170653389

  • 这说明变换的顺序是非常重要的,也就是 R 45 ⋅ T ( 1 , 0 ) ≠ T ( 1 , 0 ) ⋅ R 45 R_{45} \cdot T_{(1,0)} \neq T_{(1,0)} \cdot R_{45} R45T(1,0)=T(1,0)R45

  • 也就是我们要先将向量和旋转矩阵相乘,再进行平移变换,即 T ( 1 , 0 ) ⋅ R 45 [ x y 1 ] = [ 1 0 1 0 1 0 0 0 1 ] [ cos ⁡ 4 5 ∘ − sin ⁡ 4 5 ∘ 0 sin ⁡ 4 5 ∘ cos ⁡ 4 5 ∘ 0 0 0 1 ] [ x y 1 ] T_{(1,0)} \cdot R_{45}\left[\begin{array}{l} x \\ y \\ 1 \end{array}\right]=\left[\begin{array}{lll} 1 & 0 & 1 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{array}\right]\left[\begin{array}{ccc} \cos 45^{\circ} & -\sin 45^{\circ} & 0 \\ \sin 45^{\circ} & \cos 45^{\circ} & 0 \\ 0 & 0 & 1 \end{array}\right]\left[\begin{array}{l} x \\ y \\ 1 \end{array}\right] T(1,0)R45 xy1 = 100010101 cos45sin450sin45cos450001 xy1

  • 然后我们计算顺序则是要从右到左进行运算

  • 而又由于矩阵有结合律,也就是(A*B)*C = A*(B*C),那么我们可以先将前面几个变换矩阵先乘为一个矩阵,再用该矩阵去乘上向量,从而使得这个矩阵可以表示前面所有的变换操作,即 A n ( … A 2 ( A 1 ( x ) ) ) = A n ⋯ A 2 ⋅ A 1 ⋅ ( x y 1 ) A_n\left(\ldots A_2\left(A_1(\mathbf{x})\right)\right)=\mathbf{A}_n \cdots \mathbf{A}_2 \cdot \mathbf{A}_1 \cdot\left(\begin{array}{l} x \\ y \\ 1 \end{array}\right) An(A2(A1(x)))=AnA2A1 xy1

  • 因为这些变换矩阵都是3*3的,所以当他们乘完之后的最后的矩阵也肯定还是3*3的,也就是说最后乘完的这个矩阵可以表示出非常复杂的变换

分解

  • 一般情况下我们说旋转默认都是按照原点逆时针开始旋转,但是假设我现在想要按照当前图形的左下角进行旋转,应该怎么办呢。

  • 例如要将如下图像的最左侧图形变换到最右侧

    image-20240708210504934

  • 如果直接就旋转变换,由于旋转是默认对着原点旋转的,所以就很难变成最右边的图形,那么我们就可以将步骤分解,先把图形移动到原点,然后再旋转变换,再移动回原位即可。

  • 矩阵形式表达即 T ( c ) ⋅ R ( α ) ⋅ T ( − c ) \mathbf{T}(\mathbf{c}) \cdot \mathbf{R}(\alpha) \cdot \mathbf{T}(-\mathbf{c}) T(c)R(α)T(c)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/42269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UML中用例之间的可视化表示

用例除了与参与者有关联关系外,用例之间也存在着一定的关系,如泛化关系、包含关系、扩展关系等。 4.2.1 包含关系 包含关系指的是两个用例之间的关系,其中一个用例(称为基本用例,Base Use Case)的行为包…

温度传感器的常见故障及处理方法

温度传感器作为现代工业、科研及日常生活中不可或缺的重要元件,其稳定性和准确性直接影响到设备的运行效率和安全。然而,由于各种因素的影响,温度传感器在使用过程中常会遇到一些故障。本文将针对这些常见故障进行分析,并提出相应…

如果你想手写Linux系统

哈喽,我是子牙老师。今天咱们聊聊这个话题吧,Linux作为当今科技世界的地基,我们越来越接近真理了,有木有? 这个文章的角度,你可能全网都很难找到第二篇如此系统讲透这个问题的文章 你可能想问&#xff1a…

LabVIEW电滞回线测试系统

铁电材料的性能评估依赖于电滞回线的测量,这直接关系到材料的应用效果和寿命。传统的电滞回线测量方法操作复杂且设备成本高。开发了一种基于LabVIEW的电滞回线测试系统,解决传统方法的不足,降低成本,提高操作便捷性和数据分析的自…

spring boot 3.x版本中集成spring security 6.x版本进行实现动态权限控制解决方案

一、背景 最近在进行项目从jdk8和spring boot 2.7.x版本技术架构向jdk17和spring boot 3.3.x版本的代码迁移,在迁移过程中,发现spring boot 3.3.x版本依赖的spring security版本已经升级6.x版本了,语法上和spring security 5.x版本有很多地方…

Mysql中存储引擎简介、修改、查询、选择

场景 数据库存储引擎 数据库存储引擎是数据库底层软件组件,数据库管理系统(DBMS )使用数据引擎进行创建、查询、更新和删除数据的操作。 不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎还可以…

【C++报错已解决】Invalid Use of ‘this’ Pointer

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 引言 一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一:修正‘this’指针使用2…

React+TS前台项目实战(二十六)-- 高性能可配置Echarts图表组件封装

文章目录 前言CommonChart组件1. 功能分析2. 代码详细注释3. 使用到的全局hook代码4. 使用方式5. 效果展示 总结 前言 Echarts图表在项目中经常用到,然而,重复编写初始化,更新,以及清除实例等动作对于开发人员来说是一种浪费时间…

LVS-DR负载均衡

LVS-DR负载均衡 LVS—DR工作模式 原理 客户端访问调度器的VIP地址,在路由器上应该设置VIP跟调度器的一对一的映射关系,调度器根据调度算法将该请求“调度“到后端真实服务器,真实服务器处理完毕后直接将处理后的应答报文发送给路由器&#xf…

EDI安全:如何在2024年保护您的数据免受安全和隐私威胁

电子数据交换(EDI)支持使用标准化格式在组织之间自动交换业务文档。这种数字化转型彻底改变了业务通信,消除了对纸质交易的需求并加速了交易。然而,随着越来越依赖 EDI 来传输发票、采购订单和发货通知等敏感数据,EDI …

【跨境分享】中国商家如何卷到国外?电商独立站和电商平台的优势对比

为什么要选择独立站而不是电商平台 对于跨境电商经营者而言,采取多平台、多站点的运营策略是至关重要的战略布局。这一做法不仅有助于分散风险,避免将所有投资集中于单一市场,从而降低“所有鸡蛋置于同一篮子”的隐患,而且有利于拓…

【友邦保险-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…

华为od相关信息分享

2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C合集) 问 1.什么是华为od? 答:OD全称是Outsourcing Dispacth,即外包派遣,是华为和外企德科…

Kafka日志处理:深入了解偏移量查找与切分文件

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! Hello, 大家好!我是你们的技术小伙伴小米,今天要和大家分享一些关于Kafka日志处理的深入知识。我们将讨论如何查看偏移量为23的消息,以及Kafka日志分…

重载、覆盖(重写)、重定义(同名隐藏)的区别 (超详解)

📚 重载(Overloading)、覆盖(Overriding)、重定义(Hiding)是面向对象编程中常见的概念,它们分别用于描述不同情况下函数或方法的行为。 目录 重载(Overloading&#xff…

ST7789 linux4.x驱动

文章目录 ST7789 linux4.x驱动设备树配置驱动程序编译驱动测试驱动 ST7789 linux4.x驱动 设备树配置 pinctrl_ecspi2_cs_1: ecspi2_cs_grp-1 {fsl,pins <MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x40017059>; };pinctrl_ecspi2_1: escpi2grp {fsl,pins <MX6UL_PAD_CSI_…

RocketMQ快速入门:主从、集群模式原理及搭建实操(十一)

目录 0. 引言1. 前备知识1.1 namesrv集群模式1.2 broker集群模式1.2 broker主从复制原理 2. 集群部署2.1 环境准备2.2 配置讲解2.3 一主多从模式部署2.4 多主无从模式部署2.5 多主多从模式部署 3. 总结 0. 引言 在学习完rocketmq的基础知识后&#xff0c;我们进入rocketmq高可…

和Bug较劲的第n天:[Error: Unable to open snapshot file: No such file or directory]

问题描述 最近做了一个小demo&#xff0c;基于parcel的&#xff0c;在迁移仓库的时候发生了一个报错 [Error: Unable to open snapshot file: No such file or directory] 原因分析&#xff1a; 在迁移仓库的时候&#xff0c;我将项目放入了一个以中文命名的文件夹里&#xf…

模电基础 - 信号的运算和处理

目录 一. 简介 二. 加法 三. 减法 四. 乘法 五. 除法 六. 总结 一. 简介 在模电基础中&#xff0c;信号的运算和处理是非常重要的内容。 信号的运算包括加法、减法、乘法、除法等。通过使用集成运放&#xff0c;可以很容易地实现这些运算。例如&#xff0c;利用反相输入…

算法的几种常见形式

算法&#xff08;Algorithm&#xff09; 算法&#xff08;Algorithm&#xff09;是指解决问题或完成任务的一系列明确的步骤或规则。在计算机科学中&#xff0c;算法是程序的核心部分&#xff0c;它定义了如何执行特定的任务或解决特定的问题。算法可以用多种方式来表示和实现…