CG实验2nd&3rd:二维几何变换、裁减、动画、三维透视

 

实验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
*/


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值