实验2
1、放缩与旋转
说明:关键得到变换矩阵,
放缩矩阵:
doubleb[3][3] = {
Sx,0, 0,
0,Sy, 0,
-xF* Sx + xF, -yF * Sy + yF, 1
};
旋转矩阵:
doubleb[3][3] = {
cos(theta),sin(theta), 0,
-sin(theta),cos(theta), 0,
xF- xF * cos(theta) + yF * sin(theta), yF - yF * cos(theta) - xF * sin(theta), 1
};
运行结果如图所示:
放缩:
旋转:
源程序:
#include <iostream>
#include <cmath>
#include "graphics.h"
using namespace std;
const int NUM = 3; // 多边形顶点个数
// 矩阵相乘:c = a * b
// 带回c
void MMul(double a[NUM][3], double b[3][3],double c[NUM][3])
{
for(int i = 0; i < NUM; ++i)
{
for(int j = 0; j < 3; ++j)
{
intelem = 0;
for(int k = 0; k < 3; ++k)
{
elem+= a[i][k] * b[k][j];
}
c[i][j]= elem;
}
}
}
void Zoom(double a[NUM][3])
{
doublexF;
doubleyF;
doubleSx;
doubleSy;
cout<< "请输入缩放比例:" << endl;
cin>> Sx;
Sy= Sx;
cout<< "请输入缩放参考点:\nx = ";
cin>> xF;
cout<< "y = ";
cin>> yF;
double b[3][3] = {
Sx,0, 0,
0,Sy, 0,
-xF* Sx + xF, -yF * Sy + yF, 1
};
doublec[NUM][3];
MMul(a,b, c);
intgdriver = DETECT;
intgmode = 0;
initgraph(&gdriver,&gmode, "");
moveto(a[NUM- 1][0], a[NUM - 1][1]);
for(int i = 0; i < NUM; ++i)
{
lineto(a[i][0],a[i][1]);
}
setcolor(YELLOW);
moveto(c[NUM- 1][0], c[NUM - 1][1]);
for(i = 0; i < NUM; ++i)
{
lineto(c[i][0],c[i][1]);
}
system("pause");
closegraph();
}
void Turn(double a[NUM][3])
{
doublexF = 200;
doubleyF = 30;
doubletheta = acos(-1) / 2;
cout<< "请输入旋转角度:" << endl;
cin>> theta;
cout<< "请输入旋转中心:\nx = ";
cin>> xF;
cout<< "y = ";
cin>> yF;
double b[3][3] = {
cos(theta),sin(theta), 0,
-sin(theta),cos(theta), 0,
xF- xF * cos(theta) + yF * sin(theta), yF - yF * cos(theta) - xF * sin(theta), 1
};
doublec[NUM][3];
MMul(a,b, c);
intgdriver = DETECT;
intgmode = 0;
initgraph(&gdriver,&gmode, "");
moveto(a[NUM- 1][0], a[NUM - 1][1]);
for(int i = 0; i < NUM; ++i)
{
lineto(a[i][0],a[i][1]);
}
setcolor(YELLOW);
moveto(c[NUM- 1][0], c[NUM - 1][1]);
for(i = 0; i < NUM; ++i)
{
lineto(c[i][0],c[i][1]);
}
system("pause");
closegraph();
}
int main(int argc, char **argv)
{
intp[8] = {10, 20, 150, 150, 200, 30, 10, 20};
doublea[NUM][3] = {
10,20, 1,
150,150, 1,
200,30, 1
};
// Zoom(a);
Turn(a);
return0;
}
2、裁减
用的是库函数setviewport得到视图窗口。源程序如下:
#include <stdio.h>
#include "graphics.h"
#define NUM 3
void Cut(int p[])
{
intgdriver = DETECT;
intgmode = 0;
initgraph(&gdriver,&gmode, "");
setviewport(10,20, 100, 100, 1);
drawpoly(1+ NUM, p);
getch();
clearviewport();
closegraph();
}
int main()
{
intp[2 * (NUM + 1)] = {10, 20, 150, 150, 200, 30, 10, 20};
Cut(p);
return0;
}
实验3
1、动画
显示图形的移动,运行结果如下,显示的是椭圆的向右移动:
源程序:
#include <iostream>
#include "graphics.h"
using namespace std;
int main(int argc,char**argv)
{
IMAGEimg;
initgraph(500,500);
ellipse(10,10, 90, 300);
getimage(&img,10, 10, 91, 301);
for(int i = 0; i <500 - (90 - 10); i++)
{
cleardevice();
putimage(i,10, &img);
Sleep(10);
}
system("pause");
closegraph();
return 0;
}
2、三维透视
显示一个正方体的一点透视投影图。关键是变换矩阵:
double b[DEMENSION][DEMENSION] = {
1,0, 0, 0,
0,1, 0, 0,
0,0, 0, 1 / d,
l,m, 0, 1 + n / d
};
运行结果:
原程序
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "graphics.h"
using namespace std;
const int NUM = 8; // 多面体顶点个数(这里是正方体)
const int DEMENSION = 4; // 维数(n+1维)
// 矩阵相乘:c = a * b, 带回c
void MMul(double a[NUM][DEMENSION], doubleb[DEMENSION][DEMENSION], double c[NUM][DEMENSION])
{
for(int i = 0; i < NUM; ++i)
{
for(int j = 0; j < DEMENSION; ++j)
{
doubleelem = 0;
for(int k = 0; k < DEMENSION; ++k)
{
elem+= a[i][k] * b[k][j];
}
c[i][j]= elem;
}
}
}
// 规范化齐次坐标
void Standard(double c[NUM][DEMENSION])
{
for(int i = 0; i < NUM; ++i)
{
for(int j = 0; j < DEMENSION - 1; ++j)
{
c[i][j]= c[i][j] / c[i][DEMENSION - 1];
}
c[i][DEMENSION- 1] = 1;
}
}
// 下面代码只能画正方体,12条边
void Draw3D(double array[NUM][DEMENSION])
{
//精度转换
intc[NUM][DEMENSION];
for(int i = 0; i < NUM; ++i)
{
for (int j = 0; j < DEMENSION; ++j)
{
c[i][j]= (int)array[i][j];
}
}
setlinestyle(PS_USERSTYLE,0xF0F0); // 与c[6]顶点相关联的三条边为虚线
line(c[5][0],c[5][1], c[6][0], c[6][1]);
line(c[6][0],c[6][1], c[7][0], c[7][1]);
line(c[2][0],c[2][1], c[6][0], c[6][1]);
setlinestyle(PS_SOLID);
line(c[0][0],c[0][1], c[1][0], c[1][1]);
line(c[1][0],c[1][1], c[2][0], c[2][1]);
line(c[2][0],c[2][1], c[3][0], c[3][1]);
line(c[3][0],c[3][1], c[0][0], c[0][1]);
line(c[4][0],c[4][1], c[5][0], c[5][1]);
line(c[7][0],c[7][1], c[4][0], c[4][1]);
line(c[0][0],c[0][1], c[4][0], c[4][1]);
line(c[1][0],c[1][1], c[5][0], c[5][1]);
line(c[3][0],c[3][1], c[7][0], c[7][1]);
setlinestyle(PS_SOLID);
}
void Reflect(double a[NUM][DEMENSION])
{
doubled; // 视点在z轴上的位置(z=-d处)
doublel, m, n; // 将三维形体平移到适当位置l, m, n
cout<< "请输入视点在z轴的位置:" << endl;
cin>> d;
cout<< "请输入要平移到的适当位置:" << endl;
cin>> l >> m >> n;
doubleb[DEMENSION][DEMENSION] = {
1,0, 0, 0,
0,1, 0, 0,
0,0, 0, 1 / d,
l,m, 0, 1 + n / d
};
doublec[NUM][DEMENSION];
MMul(a,b, c);
Standard(c);
intgdriver = DETECT;
intgmode = 0;
initgraph(&gdriver,&gmode, "");
setcolor(YELLOW);
// Draw3D(a);
Draw3D(c);
Sleep(10000);
system("pause");
closegraph();
}
int main(int argc, char **argv)
{
freopen("cin.txt","r", stdin);
//输入正方形各定点坐标
doublea[NUM][DEMENSION];
for(int i = 0; i < NUM; ++i)
{
for(int j = 0; j < DEMENSION; ++j)
{
cin>> a[i][j];
}
}
Reflect(a);
return0;
}
/*cin.txt:
0 0 0 1
300 0 0 1
300 300 0 1
0 300 0 1
0 0 300 1
300 0 300 1
300 300 300 1
0 300 300 1
250
80 160 200
*/