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),那么,绕旋转由三个步骤组成:
- 将该对象平移Δx=-xr,Δy=-yr。
- 按3.2.1进行旋转。
- 平移该对象Δx=xr,Δy=yr。
相当于平移至原点处旋转,然后再平移回来
3.3 变比
横纵坐标比例因子为Sx、Sy
x’=x*Sx
y’=y*Sy
作变比时,不仅对象的大小变化,而且,对象离原点的距离也发生了变化。
如果只希望变换对象的大小,而不希望变比对角离原点的距离,则可采用固定点变比(scaling relative to a fixed point)。若以a为固定点进行变比的方法
- 作平移Tx=-xa,Ty=-ya;
- 按上述原计划作变比;
- 作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();
}
}
}