计算机图形学实验二——二维图形几何变换及裁剪
Posted 大灬白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机图形学实验二——二维图形几何变换及裁剪相关的知识,希望对你有一定的参考价值。
【实验名称】 二维图形几何变换及裁剪
【实验目的】
1. 通过实验,进一步理解和掌握二维几何图形的基本变换及复合变换的原理;
2. 理解和掌握cohen-sutherland裁剪算法的基本思想。
【实验原理】
1.平移变换、旋转变换、比例变换、对称变换的变换矩阵;
绕任意点旋转、相对任意点缩放的变换矩阵;
相对于任意参考点(xF,yF)的二维几何变换,基本思路是,将图形经过平移,使参考点与原点重合,此时相对于参考点的变换变成相对于原点的基本几何变换,最后再平移,使参考点回到原来的位置。
(1)相对于(xF,yF)点的比例变换,变换矩阵如下:
(2) 相对于(xF,yF)点的旋转变换,变换矩阵如下:
2.Cohen-Sutherland端点编码算法
(1)若线段P1P2两端点的四位编码均为0,则两端点均在窗口内,该线段完全可见,显示该线段,算法结束;
(2) 若线段P1P2两端点的四位编码按位“与”结果为非0,则该线段完全不可见,算法结束。
(3)若线段两端点的四位编码按位“与”结果为0, 找到P1P2在窗口外的一个端点P1(或P2),用窗口相应的边与P1P2的交点取代该端点P1(或P2), 返回(1)步。
【实验内容】
1.显示一个飞机:(飞机各顶点的坐标存放在数组中)
(1)按比例缩小或放大.缩放比例由键盘输入,缩放的参考点由用户确定;
#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
//f[20][2]中存放的是飞机的关键点
Int f[15][2] =
{285,70,310,100,310,185,430,240,440,260,310,225,310,355,345,400,225,400,260,355,260,225,130,260,140,240,260,185,260,100};
int b;
float k;
int n = 15;
int a[15][2];
void DDALine( int x0,int y0,int x1,int y1 )
{
//DDA画直线算法
int dx,dy,epsl,k;
float x,y,xIncre,yIncre;
dx = x1 - x0;
dy = y1 - y0;
x = x0;
y = y0;
if( abs(dx) > abs(dy) )
epsl = abs(dx);
else
epsl = abs(dy);
xIncre = (float)dx / (float)epsl;
yIncre = (float)dy / (float)epsl;
for( k = 0; k <= epsl; k++ )
{
putpixel((int)(x+0.5),(int)(y+0.5),GREEN);
x += xIncre;
y += yIncre;
}
}
void Draw()
{
int i,j,p,q;
int gdriver = DETECT,gmode;
printf("请输入参考点(X,Y):\\n");
scanf("%d %d",&p,&q);
printf( "请输入放大倍数(缩小0.5倍也是可以的):" );
scanf( "%f",&k );
for( i = 0; i < n; i++ )
{
//a[i][0]中存的是x
//a[i][1]中存的是y
a[i][0] = ((f[i][0] - p) * k) + p;
a[i][1] = ((f[i][1] - q) * k) + q;
}
initgraph( 960,540 );
for( j = 0; j < 1000; j++ )
for( i = 0; i < 1000; i++ )
putpixel( i,j,WHITE );//首先生成一个960*540大小的窗口,并置成白色
for( i = 0; i < n - 1; i++ )
//DDA画直线,首先将飞机的点顺时针按序连成线
DDALine( a[i][0],a[i][1],a[i+1][0],a[i+1][1] );
DDALine( a[0][0],a[0][1],a[n-1][0],a[n-1][1] );
}
void change()
{
int i,j,k,s,dx,dy,temp;
int x0,y0,x1,y1,x2,y2;
for( i = 0; i < n; i++ )
{
if( i == n - 1 )
{
x0 = a[i][0];
y0 = a[i][1];
x1 = a[0][0];
y1 = a[0][1];
}
else
{
x0 = a[i][0];
y0 = a[i][1];
x1 = a[i+1][0];
y1 = a[i+1][1];
}
dx = x0 - x1;
dy = y0 - y1;
if( y0 > y1 )
{
temp = x0;
x0 = x1;
x1 = temp;
temp = y0;
y0 = y1;
y1 = temp;
}
for( j = y0; j < y1; j++ )
{
s = int( (j - y0) * dx / dy ) + x0;//求交点坐标
for( k = s; k < 1000; k++ )
{
if( getpixel( k,j ) == WHITE )
putpixel( k,j,BLACK);
else if( getpixel(k,j) == BLACK)
putpixel( k,j,WHITE );
else
putpixel( k,j,GREEN);
}
}
}
}
int main()
{
Draw();
change();
getch();
return 0;
}
运行截图:
(2)旋转.由键盘输入旋转角度和旋转中心;
#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
//f[20][2]中存放的是飞机的关键点
int f[15][2] =
{285,70,310,100,310,185,430,240,440,260,310,225,310,355,345,400,225,400,260,355,260,225,130,260,140,240,260,185,260,100};
int b;
float k;
int n = 15;
int a[15][2];
void DDALine( int x0,int y0,int x1,int y1 )
{
//DDA画直线算法
int dx,dy,epsl,k;
float x,y,xIncre,yIncre;
dx = x1 - x0;
dy = y1 - y0;
x = x0;
y = y0;
if( abs(dx) > abs(dy) )
epsl = abs(dx);
else
epsl = abs(dy);
xIncre = (float)dx / (float)epsl;
yIncre = (float)dy / (float)epsl;
for( k = 0; k <= epsl; k++ )
{
putpixel((int)(x+0.5),(int)(y+0.5),GREEN);
x += xIncre;
y += yIncre;
}
}
void Rotate()
{
int i,j,d,p,q;
int gdriver = DETECT,gmode;
printf("请输入旋转度数:");
scanf("%d",&d);
printf("\\n请输入旋转中心:");
scanf("%d %d",&p,&q);
for( i = 0; i < n; i++ )
{
//a[i][0]中存的是x
//a[i][1]中存的是y
a[i][0] = (f[i][0] - p) * cos(d*1.0) - (f[i][1] - q) * sin(d*1.0) + p;
a[i][1] = (f[i][0] - p) * sin(d*1.0) + (f[i][1] - q) * cos(d*1.0) + q;
}
initgraph( 960,540 );
for( j = 0; j < 1000; j++ )
for( i = 0; i < 1000; i++ )
putpixel( i,j,WHITE );//首先生成一个960*540大小的窗口,并置成白色
for( i = 0; i < n - 1; i++ )
//DDA画直线,首先将飞机的点顺时针按序连成线
DDALine( a[i][0],a[i][1],a[i+1][0],a[i+1][1] );
DDALine( a[0][0],a[0][1],a[n-1][0],a[n-1][1] );
}
void change()
{
int i,j,k,s,dx,dy,temp;
int x0,y0,x1,y1,x2,y2;
for( i = 0; i < n; i++ )
{
if( i == n - 1 )
{
x0 = a[i][0];
y0 = a[i][1];
x1 = a[0][0];
y1 = a[0][1];
}
else
{
x0 = a[i][0];
y0 = a[i][1];
x1 = a[i+1][0];
y1 = a[i+1][1];
}
dx = x0 - x1;
dy = y0 - y1;
if( y0 > y1 )
{
temp = x0;
x0 = x1;
x1 = temp;
temp = y0;
y0 = y1;
y1 = temp;
}
for( j = y0; j < y1; j++ )
{
s = int( (j - y0) * dx / dy ) + x0;//求交点坐标
for( k = s; k < 1000; k++ )
{
if( getpixel( k,j ) == WHITE )
putpixel( k,j,BLACK);
else if( getpixel(k,j) == BLACK)
putpixel( k,j,WHITE );
else
putpixel( k,j,GREEN);
}
}
}
}
int main()
{
Rotate();
change();
getch();
return 0;
}
运行截图:
2.编码实现Cohen-Sutherland端点编码算法(用矩形窗口裁剪一条直线段)
(选做)关于任意一条水平线(或垂直线)对称
(选做) 任意画出一个多边形,由用户确定一个矩形裁剪窗口的位置和大小,保留窗口里的图形,抹去其余部分;
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#define LEFT 1//0001
#define RIGHT 2//0010
#define BOTTOM 4//0100
#define TOP 8//1000
int XL = 100,XR = 400,YB =300,YT = 100;
int encode(int x,int y)
{
int c=0;
if(x<XL) c=c|LEFT;
else if(x>XR) c=c|RIGHT;
if(y>YB) c=c|BOTTOM;
else if(y<YT) c=c|TOP;
return c;
}
// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点)
void DisplayLine(int x1, int y1, int x2, int y2, int color)
{
int x = x1, y = y1;
int a = y1 - y2, b = x2 - x1;//a,b分别为x和y的增量
//考虑四种情况,分别计算增量
int cx = (b >= 0 ? 1 : (b = -b, -1));
int cy = (a <= 0 ? 1 : (a = -a, -1));
putpixel(x, y, color);
int d, d1, d2;
if (-a <= b以上是关于计算机图形学实验二——二维图形几何变换及裁剪的主要内容,如果未能解决你的问题,请参考以下文章