当前位置:文档之家› 计算机图形学-图形的几何变换

计算机图形学-图形的几何变换

贵州大学实验报告学院:计算机科学与技术专业:软件工程班级:软件132 姓名常伟学号1308060226 实验地点一教704 实验时间2016.5.9 指导教师李智实验成绩实验项目名称试验四、图形的几何变换实验目的1.掌握矢量运算。

2.熟练使用齐次坐标。

3.掌握采用齐次坐标进行几何变换。

实验要求1.理解几何图形变换的原理,编程实现图形的几何变换。

2.编程界面友好,实现变换的所有方式,包括平移、缩放、旋转、对称、错切以及基本变换基础上的组合变换。

3.几何变换使用矩阵进行运算。

实验原理二维齐次坐标变换的矩阵的形式是⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡ihgfedcba这个矩阵的每一个元素都是有特殊含义的。

其中,⎥⎦⎤⎢⎣⎡edba可以对图形进行缩放、旋转、对称和错切等变换;⎥⎦⎤⎢⎣⎡fc是对图形进行平移变换;[]hg是对图形作投影变换;[]i 则是对图形进行缩放变换。

下面给出几个基本变换的矩阵运算。

1.平移变换⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡++=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡1),(111111''yxTyxyxttttttyxyxyxyx2.缩放变换⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡∙∙=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡1),(1111''yxssSysxsyxssyxyxyxyx3.旋转矩阵⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡+-=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡-=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡1)(1cossinsincos11cossinsincos1''yxRyxyxyxyxθθθθθθθθθ4.对称矩阵⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡++=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡1111''eydxbyaxyxedbayx对称变换其实只是a、b、d、e取0、1等特殊值产生的一些特殊效果。

5.错切变换⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡++=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡=⎥⎥⎥⎦⎤⎢⎢⎢⎣⎡111111''ydxbyxyxdbyx(1)当d=0时,图形的y坐标不变,x坐标随初值(x,y)及变换系数b作线性变化。

(2)当b=0时,图形的x坐标不变,y坐标随初值(x,y)及变换系数d作线性变化。

实验步骤1.设计图形界面。

本实验使用visual studio 2012 C#搭建窗口,设置相应的组件。

如下图。

如图所示,combox此时显示的字符是“平移”,在其下面显示的是关于平移的操作组件。

当选择combox的不同项时,其下面就显示对应的操作组件。

2.运行效果如下。

(1)平移从图中可见,原图形的颜色为黄绿色,平移后的图形为黑色。

(2)旋转(3)对称如图,这是原图形关于x轴对称后由对称后的图形关于原点对称得到的图形。

在界面中可看到一个text为“新变换”的checkbox,其作用是可以自由选择变换原图形或者变换变换后的图形。

(4)缩放有图可知,此时的x、y的缩放比例都是0.5,也就是原图形的x和y都关于原点缩小为原来的一半。

(5)错切此时y上的错切系数为0,即图形的y值不变,x的值随x上的错切系数变化。

(6)三角形的一顶点保持不变,另外两个顶点按缩放比例缩小,然后关于直线-2x+4y+3对称。

这是一个组合变换的问题,要使得三角形的一顶点保持不变,就要将该顶点移动到原点,缩放后再平移回去,然后再关于直线对称就行了。

组合变换时,先作用的变换矩阵在右端,后作用的变换矩阵在左端。

(7)四边形以原点为中心,以15°为间隔旋转。

在程序中设置一个旋转增量,每变换一次,就加上旋转增量,就可得到上图的结果。

实验数据由于代码篇幅过长,下面是代码的主要部分。

private void initMatrix() {temp = new double[3][];for (int i = 0; i < temp.Length; i++){temp[i] = new double[3];}resetTemp(ref temp);temp1 = new double[3][];for (int i = 0; i < temp1.Length; i++){temp1[i] = new double[3];}resetTemp(ref temp1);//初始化平移矩阵move = new double[3][];for (int i = 0; i < move.Length; i++){move[i] = new double[3];}for (int i = 0; i < move.Length; i++) {for (int j = 0; j < move[i].Length; j++) {if (i == j){move[i][j] = 1;}else {move[i][j] = 0;}}}//初始化缩放矩阵zoom = new double[3][];for (int i = 0; i < zoom.Length; i++){zoom[i] = new double[3];}for (int i = 0; i < zoom.Length; i++){for (int j = 0; j < zoom[i].Length; j++) {if (i == j){zoom[i][j] = 1;}else {zoom[i][j] = 0;}}}//初始化旋转矩阵rotate = new double[3][];for (int i = 0; i < rotate.Length; i++){rotate[i] = new double[3];}for (int i = 0; i < rotate.Length; i++){for (int j = 0; j < rotate[i].Length; j++) {if (i == j && i == 2){rotate[i][j] = 1;}else {rotate[i][j] = 0;}}}//初始化对称矩阵symmetry = new double[3][];for (int i = 0; i < symmetry.Length; i++){symmetry[i] = new double[3];}for (int i = 0; i < symmetry.Length; i++){for (int j = 0; j < symmetry[i].Length; j++) {if (i == j){symmetry[i][j] = 1;}else {symmetry[i][j] = 0;}}}//初始化错切矩阵shear = new double[3][];for (int i = 0; i < shear.Length; i++){shear[i] = new double[3];}for (int i = 0; i < shear.Length; i++){for (int j = 0; j < shear[i].Length; j++) {if (i == j){shear[i][j] = 1;}else {shear[i][j] = 0;}}}//初始化目标齐次坐标target = new double[3][];for (int i = 0; i < target.Length; i++){target[i] = new double[1];}for (int i = 0; i < target.Length; i++){for (int j = 0; j < target[i].Length; j++) {if (i == 2 && j == 0){target[i][j] = 1;}else {target[i][j] = 0;}}}//初始化结果齐次坐标result = new double[3][];for (int i = 0; i < result.Length; i++){result[i] = new double[1];}for (int i = 0; i < result.Length; i++){for (int j = 0; j < result[i].Length; j++){if (i == 2 && j == 0){result[i][j] = 1;}else{result[i][j] = 0;}}}}private void coordinate() {Brush brush = new SolidBrush(Color.Black);Pen pen = new Pen(brush,1);//获取x轴getGph().DrawLine(pen, new Point(0, panel1.Height / 2), newPoint(panel1.Width, panel1.Height / 2));getGph().DrawLine(pen, new Point(panel1.Width, panel1.Height / 2), new Point(panel1.Width-10, panel1.Height / 2-5));getGph().DrawLine(pen, new Point(panel1.Width, panel1.Height / 2), new Point(panel1.Width - 10, panel1.Height / 2 + 5));//获取y轴getGph().DrawLine(pen, new Point(panel1.Width / 2, 0), newPoint(panel1.Width / 2, panel1.Height));getGph().DrawLine(pen, new Point(panel1.Width / 2, 0), newPoint(panel1.Width / 2-5, 10));getGph().DrawLine(pen, new Point(panel1.Width / 2 , 0), newPoint(panel1.Width / 2+5,10 ));//获取xoygetGph().DrawString("O(0,0)", new Font("微软雅黑", 8), brush, new Point(panel1.Width/2-13, panel1.Height/2));getGph().DrawString("X", new Font("微软雅黑", 8), brush, newPoint(panel1.Width-15, panel1.Height / 2+5));getGph().DrawString("Y", new Font("微软雅黑", 8), brush, newPoint(panel1.Width/2+8,5));//原点坐标centerX = panel1.Width / 2;centerY = panel1.Height / 2;}private void GetPolygon(List<Point> point,Color color) {for (int i = 0; i <point.Count; i++) {Brush brush = new SolidBrush(color);Pen pen = new Pen(brush, 1);Point st = point[i];Point end = point[(i + 1) % point.Count];st.X += centerX;st.Y += centerY;end.X += centerX;end.Y += centerY;getGph().DrawLine(pen,st,end);Brush brushString = new SolidBrush(Color.Black);getGph().DrawString("("+ (st.X-centerX) + ","+ (centerY-st.Y) + ")", new Font("微软雅黑", 6), brushString, new Point(st.X, st.Y - 12));}}private void changePolygon(double[][] matrix) {List<Point> newPoint=new List<Point>();//用来暂时存储要变换的目标链表if (checkBox1.Checked){for (int i = 0; i < point.Count; i++){newPoint.Add(point[i]);}}else {if (chgPoint.Count == 0){for (int i = 0; i < point.Count; i++){newPoint.Add(point[i]);}}else {for (int i = 0; i < chgPoint.Count; i++) {newPoint.Add(chgPoint[i]);}}}chgPoint.RemoveAll(clear);//准备接收再次变换后的顶点for (int p = 0; p < newPoint.Count; p++){target[0][0] = newPoint[p].X;target[1][0] = newPoint[p].Y;for (int i = 0; i < matrix.Length; i++){for (int j = 0; j < matrix[i].Length; j++){for (int k = 0; k < target[0].Length; k++){result[i][k] += matrix[i][j] * target[j][k];}}}chgPoint.Add(new Point((int)result[0][0], (int)result[1][0]));resetResultMatrix();}GetPolygon(chgPoint, Color.Black);}private void transformation(ref double[][] result,ref double[][] first,ref double[][] second) {//计算矩阵相乘for (int i = 0; i < first.Length; i++){for (int j = 0; j < first[i].Length; j++){for (int k = 0; k < second[0].Length; k++){result[i][k] += first[i][j] * second[j][k];}}}}实验总结一开始做几何图形变换的时候,嫌使用矩阵麻烦,于是自己动手计算,在程序中使用计算后的公式来完成几何变换。

相关主题