图形变换


1、二维图形几何变换

基本变换:平移、旋转、变比

利用齐次坐标系来表示坐标值,以便用变换矩阵实现图形的变换

2、齐次坐标表示法

所谓齐次坐标表示法就是用n+1维向量表示一个n 维向量,即,倘若 n 维空间中点的位置向量为(p1,p2,…,pn),则将其表示为具有n+1个坐标分量的向量:(hp1,hp2, …,hpn,h)。

例如:

二维笛卡尔坐标系下点A(x1,y1)。用齐次坐标表示为:[x1,y1,1]或者[x1,y1,1]的逆。(此时h取1)

3、二维

3.1 平移

一句话:新点的横纵坐标等于旧坐标的横纵坐标加横纵坐标的变化量。即,(x’=x+Δx,y’=y+Δy)

3.2 旋转

3.2.1 绕原点旋转

旋转是以某个参考点为圆心, 将对象上的各点(x,y)围绕圆心转动一个逆时针角度0, 变为新的坐标(x′,y′)的变换。当参考点为原点(0,0)时,旋转的公式为:(设(x,y)直线角度为α)

x′=xcosθ-ysinθ

y′=ycosθ+xsinθ

3.2.2 绕非原点旋转

如果参考点不是原点,而是任意一点(xr,yr),那么,绕旋转由三个步骤组成:

  1. 将该对象平移Δx=-xr,Δy=-yr。
  2. 按3.2.1进行旋转。
  3. 平移该对象Δx=xr,Δy=yr。

相当于平移至原点处旋转,然后再平移回来

3.3 变比

横纵坐标比例因子为Sx、Sy

x’=x*Sx

y’=y*Sy

作变比时,不仅对象的大小变化,而且,对象离原点的距离也发生了变化。

如果只希望变换对象的大小,而不希望变比对角离原点的距离,则可采用固定点变比(scaling relative to a fixed point)。若以a为固定点进行变比的方法

  1. 作平移Tx=-xa,Ty=-ya;
  2. 按上述原计划作变比;
  3. 作1的逆变换,即作平移Tx=xa,Ty=ya。

当比例因子Sx或Sy小于0时,对象不仅变化大小,而且分别按x轴,或y的轴被反射。

4、三维

4.1 平移

公式为:

x’=x+ Tx
y’=y+ Ty
z’=z+ Tz

齐次坐标形式:

%变换矩阵为:
A=[1,  0,  0,  0;
   0,  1,  0,  0;
   0,  0,  1,  0;
   Tx, Ty, Tz, 1]
%新坐标为:
[x',y',1]=[x, y, 1]*A

4.2 缩放

公式为:

x’= Sx∙ x
y’= Sy∙ y
z’= Sz∙ z

齐次坐标形式:

%变换矩阵为:
B=[Sx,  0,   0,  0;
   0,   Sy,  0,  0;
   0,   0,   Sz, 0;
   0,   0,   0,  1]
%新坐标为:
[x',y',1]=[x, y, 1]*B

4.3 旋转

旋转分为三种基本旋转:
绕z轴旋转,绕x轴旋转,绕y轴旋转。

在下述旋转变换公式中,设旋转的参考点在所绕的轴上,绕轴转θ角,方向是从轴所指处往原点看的逆时针方向。

4.3.1 绕z轴旋转

绕z轴旋转的公式为:

​ x′=xcosθ-ysinθ
​ y′=xsinθ+ycosθ
​ z′=z

矩阵运算的表达为:

%变换矩阵为:
Mz=[cosα,  sinsα,   0,  0;
   -sinα,  cosα,    0,  0;
    0,      0,      1,  0;
    0,      0,      0,  1]
%新坐标为:
[x',y',z',1]=[x, y,z,1]*Mz

4.3.2 绕x轴旋转

绕x轴旋转的公式为:

​ x′=x
​ y′=ycosθ-zsinθ
​ z′=ysinθ+zcosθ

矩阵运算的表达为:

%变换矩阵为:
Mx=[1,    0,     0,   0;
    0,  cosα,  sinα,  0;
    0,  -sinα, cosα,  0;
    0,    0,    0,    1]
%新坐标为:
[x',y',z',1]=[x, y,z,1]*Mx

4.3.3 绕y轴旋转

绕y轴旋转的公式为:

​ x′=zsinθ+xcosθ
​ y′=y
​ z′=zcosθ-xsinθ

矩阵的运算表达式为:

%变换矩阵为:
My=[cosα,   0,  -sinα,  0;
     0,     1,   0,     0;
    sinα,   0,  cosα,   0;
     0,     0,   0,     1]
%新坐标为:
[x',y',z',1]=[x, y,z,1]*My

4.3.4 绕非坐标轴旋转

如果旋转所绕的轴不是坐标轴,而是一根任意轴,则变换过程变显得较复杂。首先,对物体作平移和绕轴旋转变换,使得所绕之轴与某一根标准坐标轴重合。然后,绕该标准坐标轴作所需角度的旋转。最后,通过逆变换使所绕之轴恢复到原来位置。这个过程须由7个基本变换的级联才能完成。

5、圆锥曲线几何变换

圆锥曲线的二次方程是

Ax2+Bxy+Cy2+Dx+Ey+F=0

其相应的矩阵表达式是:

5.1 平移变换

若对圆锥曲线平移变换,平移矩阵是:

A=[1,  0,  0;
   0,  1,  0;
   m,  n,  1;]

则平移后的圆锥曲线矩阵方程是:

XASA’X’=0

5.2 旋转变换

若对圆锥曲线相对坐标原点作旋转变换,旋转变换矩阵是 :

R=[cosα,  sinsα,   0;
   -sinα,  cosα,    0;
    0,      0,      1;]

则旋转后的圆锥曲线矩阵方程是:

XRSR’X’=0

若对圆锥曲线相对(m,n)点作旋转θ角变换,则旋转后的圆锥曲线是上述A、R变换的复合变换。

5.3 比例变换

若对圆锥曲线相对(m,n)点比例变换,比例变换矩阵为 :

N=[Sx,  0,   0;
   0,   Sy,  0;
   0,   0,   1;]

则变换后的圆锥曲线矩阵方程是:

XANSN’A’X’=0

6、C#代码实现

6.1 目的:

  • 将屏幕坐标转换为人们习惯的笛卡尔坐标系,即坐标原点在左下角
  • 画线、画字

6.2 效果

6.3 代码

6.3.1 结构

两个窗体:MainForm、Form1.

Form1用于用户输入,输入直线的起点、终点坐标。并将其传给MainForm

6.3.2 MainForm窗体代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Me
{
    public partial class MainForm : Form
    {
        public int x1, x2, y1, y2;  //画线坐标起点、终点
        public bool ifFresh = false;  //是否进行画线

        public MainForm()
        {
            InitializeComponent();
        }

        private void button_Exit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        //对坐标系进行变换
        public void translation(Graphics graphics)
        {
            Matrix MyMatrix = new Matrix();
            MyMatrix.Scale(1f, -1f);  //按屏幕坐标系,沿x轴进行镜像反转,把y轴反上去。
            MyMatrix.Translate(50f, 450, MatrixOrder.Append);  //平移。x平移50,y向下平移450。利用Append参数在原来基础上进行,也就是矩阵相乘
            graphics.MultiplyTransform(MyMatrix);  //进行变换
        }

        //对画出的文字进行变换
        private void TextTaanslation(Graphics graphics,int y)
        {
            Matrix matrix = new Matrix();
            matrix.Scale(1f,-1f);
            matrix.Translate(0f, 2*(y+12), MatrixOrder.Append);
            graphics.MultiplyTransform(matrix);
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            translation(e.Graphics);  //对坐标系进行变换
            e.Graphics.DrawLine(Pens.Black, 0, 0, 600, 0);  //画出x轴
            e.Graphics.DrawLine(Pens.Black, 0, 0, 0, 400);  //画出y轴
            if (ifFresh)
            {
                e.Graphics.DrawLine(Pens.Red, x1, y1, x2, y2);//画线

                //画字
                Font font1 = new Font("SimSun", 12, FontStyle.Regular);
                TextTaanslation(e.Graphics, y2);//对所画的文字进行变换。若不变换则为"倒影"
                e.Graphics.DrawString("大家好~我系渣渣昱……", font1, Brushes.Black, x2, y2);//画出文字
            }
        }
        private void button_DrawLine_Click(object sender, EventArgs e)
        {
            Form1 form1 = new Form1();
            form1.mainForm = this;
            form1.Show();
        }
    }
}

6.3.3 Form1窗体代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Me
{
    public partial class Form1 : Form
    {
        public MainForm mainForm;
        public Form1()
        {
            InitializeComponent();
        }

        private void button_OK_Click(object sender, EventArgs e)
        {
            mainForm.x1 = (int)numericUpDown_x1.Value;
            mainForm.y1 = (int)numericUpDown_y1.Value;
            mainForm.x2 = (int)numericUpDown_x2.Value;
            mainForm.y2 = (int)numericUpDown_y2.Value;

            mainForm.ifFresh = true;
            mainForm.Invalidate();
            this.Close();

        }
    }
}

文章作者: 李世昱
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 李世昱 !
评论
  目录