计算机图形学课程设计综合实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

西南交通大学信息科学与技术学院计算机图形学实验(2014~2015学年第II学期)




学号:20122712 姓名:魏仁斌
专业:软件工程班级: 4
课程名称计算机图形学
班级软件4班学号___20122712 姓名___魏仁斌 _
试验日期2015.3.16实验成绩____ _ 实验名称实验 1 集成开发环境的认识和简单窗口程序移植与创建
1. 实验目的
熟悉windows编程和VC++编程环境
2. 实验设备与环境
硬件设备:
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理: windows提供了一系列的API函数
实验内容:用VC++创建工程,并且创建一个简单的窗口
实验设计步骤、设计过程或执行顺序
①可单击Windows桌面上的“开始”按钮,弹出开始菜单,点击→所有程序→Microsoft
Visual Studio 6.0→Microsoft Visual C++ 6.0,单击后进入开发环境。

②用鼠标单击 File 菜单中的 New 菜单项,在系统弹出的对话框中,有四大工作类型
供操作选择:Files、Projects、Workspaces、Other Documents,每种类型又包含
许多具体的文件类型。

③选择 Projects 标签,在 Project name 下的编辑框中输入应用工程的名称为实
验1。

在 Location 标签下的编辑框中,输入保存文件的位置,也可以用鼠标点击
旁边的“…”按钮来选择保存文件的目录。

④选择 Projects 标签下的 Win32 Application,点击OK按钮后,自动创建新的工
作空间。

⑤本例选择创建空白应用工程(An empty project),单击 Finsh按钮。

⑥点击“OK”按钮,建立空白的Win32应用工程。

⑦用鼠标单击File菜单中New菜单项,在系统弹出的对话框中,在Files标签下,选
择C++Source File,在右方的File编辑框中输入源程序文件的名称后单击“OK”。

⑧本例中的源程序文件名取为test1,扩展名为cpp,可在编辑窗口中输入具体的源程
序内容。

实验代码:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
char szTitle[]="This is a Simple Program for my Windows XP"; //title
int APIENTRY WinMain(HINSTANCE hInstance, //application program instance handle
HINSTANCE hPreInst, //the program instance previous handle
LPSTR lpszCmdLine, // Commandline parameter string
int nCmdShow) // the program beginning how to show window
{
HWND hWnd;
MSG msg;
WNDCLASS wcGRF;
if (!hPreInst)
{
//若hPeInst为零,则说明正运行的这个实例是程序的第一个实例,
//仅当运行第一个实例时,需要注册窗口类(对16位程序而言)
//注册窗口类如下:
wcGRF.lpszClassName =szTitle; //窗口类的类名
wcGRF.hInstance =hInstance; //定义该类的应用程序的句柄
wcGRF.lpfnWndProc =WndProc; //窗口函数
wcGRF.hCursor =LoadCursor(NULL,IDC_CROSS); //游标对象的句柄
wcGRF.hIcon =LoadIcon(NULL,IDI_APPLICATION); //图标对象的句柄
wcGRF.lpszMenuName =NULL; //标识菜单对象的字符串
wcGRF.hbrBackground =(HBRUSH)::GetStockObject(WHITE_BRUSH);
//used to clear handle
wcGRF.style =CS_HREDRAW|CS_VREDRAW; //windows style;
wcGRF.cbClsExtra =0; //类变量占据的存储空间
wcGRF.cbWndExtra =0; //实例变量占用的存储空间
if (!RegisterClass(&wcGRF)) //如注册失败则返回
return FALSE;
}
// 对每个实例创建一个窗口对象
hWnd=CreateWindow(szTitle, //类名,指定该窗口所属的类
szTitle, //窗口名,即在标题栏显示的文本
WS_OVERLAPPEDWINDOW,
//窗口风格,以下四个参数确定窗口初始位置及大小
30, //窗口左上角相对屏幕的X 坐标
30, //窗口左上角相对屏幕的Y 坐标
540, //窗口宽度
360, //窗口高度
NULL, //父窗口句柄
NULL, //菜单句柄
hInstance, //实例句柄
NULL); //额外参数
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
//消息循环
while (GetMessage(&msg,NULL,0,0)) //从应用程序队列中取出一条消息{
TranslateMessage(&msg); //翻译消息
DispatchMessage(&msg); //发送消息
}
return (msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg,WPARAM wParam,LPARAM
lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (messg)
{
case WM_PAINT :
hdc=BeginPaint(hWnd,&ps);
GetClientRect(hWnd,&rect);
DrawText(hdc, "Hello,This Program comes from Borland c++ 5.02 !", -1,&rect,DT_CENTER|DT_VCENTER);
EndPaint(hWnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return(0);
}
return DefWindowProc(hWnd,messg,wParam,lParam);
}
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:出现一个窗口显示一行文字。

实验结果的分类:无
实验中存在的问题:无
实验可以改进的方面和建议:无
课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期2015.3.23实验成绩____ _ 实验名称实验 1 键盘与鼠标的按键消息处理
1. 实验目的
熟悉集成开发环境和编辑操作,了解外围设备的工作原理,根据设
备特征和产生的消息信号处理消息,管理设备。

2. 实验设备与环境
硬件设备:
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理:
运行以上程序,可以随时获得某个字符的码值。

MessageBox 函数可以弹出一个显示信息的对话框,如果按下 BackSpace 键,将弹出"the char code is HEX:8 DEC:8"显示消息窗口。

表示该按键的 16 进制和十进制 ASCII 码值。

当用户在应用程序窗口上按下鼠标左键时,该程序将弹出一条消息,对收到的消息WM_LBUTTONDOWN 进行响应,体现了按下鼠标左键动作与WM_LBUTTONDOWN 消息的这种对应关系,另外程序还将在窗口内鼠标所按下的位置处写上一串提示文字。

当要在窗口上写字、绘图时,应用程序并不直接在这些设备上操作,而是在一个称为设备描述表(Device Contexts,简称 DC)的资源上操作的。

使用 DC,应用程序不用为图形的显示与打印输出分别单独处理了。

无论是打印还是显,都是在 DC 上操作,然后由 DC 映射到这些设备上。

使用 DC,不用担心程序在不同的硬件上执行的差异性,DC 能够装载合适的设备驱动程序,体现了应用程序的图形操作与底层设备的无关性。

GetDC 函数能够返回同窗口相关连的 DC 的句柄。

T extOut 函数在当前 DC 上指定的位置输出一个字符串,当按下鼠标左键时,消息WM_LBUTTONDOWN 的补充参数 lParam 中含有鼠标位置的 x,y 坐标,其中的低 16 位含有x 坐标,高 16 位含有 y 坐标,可以分别通过 LOWORD,HIWORD 宏获得。

实验内容:
在窗口内单击,显示一个字符串。

实验设计步骤、设计过程或执行顺序
①在键盘上进行按键操作,如果是可显示字符,在屏幕上输出对应的 ASCII 码;
②点击鼠标左键,在屏幕上的客户区窗口中鼠标点击的位置,输出一提示字符串。

实验代码:
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
char szTitle[]="This is a Simple Program for my Windows XP"; //title
int APIENTRY WinMain(HINSTANCE hInstance, //application program instance handle
HINSTANCE hPreInst, //the program instance previous handle
LPSTR lpszCmdLine, // Commandline parameter string
int nCmdShow) // the program beginning how to show window
{
HWND hWnd;
MSG msg;
WNDCLASS wcGRF;
if (!hPreInst)
{
//若hPeInst为零,则说明正运行的这个实例是程序的第一个实例,
//仅当运行第一个实例时,需要注册窗口类(对16位程序而言)
//注册窗口类如下:
wcGRF.lpszClassName =szTitle; //窗口类的类名
wcGRF.hInstance =hInstance; //定义该类的应用程序的句柄
wcGRF.lpfnWndProc =WndProc; //窗口函数
wcGRF.hCursor =LoadCursor(NULL,IDC_CROSS); //光标对象的句柄
wcGRF.hIcon =LoadIcon(NULL,IDI_APPLICATION); //光标对象的句柄
wcGRF.lpszMenuName =NULL; //标识菜单对象的字符串
wcGRF.hbrBackground =(HBRUSH)::GetStockObject(WHITE_BRUSH);
//used to clear handle
wcGRF.style =CS_HREDRAW|CS_VREDRAW; //windows style;
wcGRF.cbClsExtra =0; //类变量占据的存储空间
wcGRF.cbWndExtra =0; //实例变量占用的存储空间
if (!RegisterClass(&wcGRF)) //如注册失败则返回
return FALSE;
}
// 对每个实例创建一个窗口对象
hWnd=CreateWindow(szTitle, //类名,指定该窗口所属的类
szTitle, //窗口名,即在标题栏显示的文本
WS_OVERLAPPEDWINDOW,
//窗口风格,以下四个参数确定窗口初始位置及大小
30, //窗口左上角相对屏幕的X 坐标
30, //窗口左上角相对屏幕的Y 坐标
540, //窗口宽度
360, //窗口高度
NULL, //父窗口句柄
NULL, //菜单句柄
hInstance, //实例句柄
NULL); //额外参数
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
//消息循环
while (GetMessage(&msg,NULL,0,0)) //从应用程序队列中取出一条消息
{
TranslateMessage(&msg); //翻译消息
DispatchMessage(&msg); //发送消息
}
return (msg.wParam);
}
LRESULT CALLBACK WndProc( HWND hWnd,UINT Msg,WPARAM wParam, LPARAM
lParam)
{
HDC hDC;
switch(Msg)
{
case WM_CHAR:
char str[40];
sprintf(str,"the char code is HEX:%x DEC:%d",wParam,wParam);
MessageBox(hWnd,str," KeyBoard keypress Test",MB_OKCANCEL);
break;
case WM_LBUTTONDOWN:
MessageBox(hWnd,"mouse click"," Mouse Press ",MB_OK);
hDC=GetDC(hWnd);
TextOut(hDC,LOWORD(lParam),HIWORD(lParam),
" click mouse left ",strlen(" click mouse left "));
ReleaseDC(hWnd,hDC);
break;
case WM_CLOSE:
if(IDOK==MessageBox(NULL,"真的要要退出吗?",
" Window Close ",MB_OKCANCEL|MB_ICONQUESTION)) {
DestroyWindow(hWnd);
}
break;
case WM_PAINT:
PAINTSTRUCT ps;
hDC=BeginPaint(hWnd,&ps); //在WM_PAINT里必须用这个函数
TextOut(hDC,0,0," Mouse Left Button and Key Test",
strlen(" Mouse Left Button and Key Test"));
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd,Msg, wParam,lParam ));
}
return (0);
}
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:
响应鼠标左键键盘按键退出窗口
实验结果的分类:
1.当点击鼠标左键的时候,显示“mouse click”。

2. 当在键盘上按下一个按键时,显示“the char is HEX:** DEC:***”。

3. 当关闭窗口时,提示“真的要退出吗?”。

实验中存在的问题:不能显示组合键
实验可以改进的方面和建议:读取组合键的高低位。

课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期2015.3.30实验成绩____ _ 实验名称实验 2 设计一个指针式椭圆形实时显示时钟
1. 实验目的
掌握定时器的响应处理方式,掌握简单绘图函数的使用和应用程序
设计。

2. 实验设备与环境
硬件设备:
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理:
设当前需要显示的时间为Hour时Minute 分Second秒,则经过简单计
算就可得到各个指针实时显示夹角。

计算依据为:
时钟指针实时显示的夹角:AHour =(Hour +Minute/60 +Second/3600) * 2π/12; 分钟指针
实时显示的夹角:AMinute =(Minute+Second/60) * 2π/60; 秒钟指针实时显示的夹角:
ASecond =Second * 2π/60;
时钟的钟面用椭圆形显示,椭圆的中心位置可以确定在客户窗口的显示中心;绘制时、分、针时,用不同颜色的直线段显示,长度分别为椭圆半长轴的1/3、2/3、4/5;时钟表面的时间刻度,可用角度划分的方式均匀划分成12份,并用1~12的数字表示。

时间的获取方法:利用计时器的响应函数处理,每秒钟更新一次时钟画面,重画时钟的各个指针,各指针的位置可以通过显示夹角的计算得到,达到实时显示时钟的目标。

实验内容:利用消息映射与类中对应的成员函数,设计一个指针式椭圆形实时显示时钟。

实验设计步骤、设计过程或执行顺序
1.添加成员函数
2.修改函数OnTimer的代码
3.生成新的类
4.建立响应函数
实验代码:
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//获取客户区
RECT Rect;
GetClientRect(&Rect);
//计算椭圆中心位置
int CenterX = Rect.right/2;
int CenterY = Rect.bottom/2;
//取当前时间
CTime Time = CTime::GetCurrentTime();
CString str;
int i,x,y;
CSize size;
//创建一支黑色的笔,用来画椭圆
CPen Pen(PS_SOLID,5,RGB(0,0,0));
//先记下以前的画笔, 再设置当前画笔
CPen *OldPen = pDC->SelectObject(&Pen);
//绘制钟面椭圆
pDC->Ellipse(5,5,Rect.right-5,Rect.bottom-5);
double Radians;
//设置字体颜色为黑色
pDC->SetTextColor(RGB(255,0,0));
for(i = 1;i <= 12;i++){
//格式化钟点值
str.Format("%d",i);
size = pDC->GetTextExtent(str,str.GetLength());
Radians = (double)i*6.28/12.0;
//计算钟点放置的位置
x = CenterX - (size.cx/2) + (int)((double)(CenterX - 20)*
sin(Radians));
y = CenterY - (size.cy/2) - (int)((double)(CenterY - 20)*
cos(Radians));
//绘制钟点
pDC->TextOut(x,y,str);
}
//计算时钟指针的夹角
Radians = (double)Time.GetHour() + (double)Time.GetMinute()/60.0 + (double)Time.GetSecond()/3600.0;
Radians *= 6.28/12.0;
//创建时钟指针画笔
CPen HourPen(PS_SOLID,5,RGB(0,255,0));
pDC->SelectObject(&HourPen);
//绘制时钟指针
pDC->MoveTo(CenterX,CenterY);
pDC->LineTo(CenterX + (int)((double)(CenterX/3)*sin(Radians)), CenterY - (int)((double)(CenterY/3)*cos(Radians)));
//计算分钟指针的夹角
Radians = (double)Time.GetMinute()+(double)Time.GetSecond()/60.0; Radians *= 6.28/60.0;
//创建分钟指针画笔
CPen MinutePen(PS_SOLID,3,RGB(0,0,255));
pDC->SelectObject(&MinutePen);
//绘制分钟指针
pDC->MoveTo(CenterX,CenterY);
pDC->LineTo(CenterX + (int)((double)(CenterX*2)/3)*sin(Radians), CenterY - (int)((double)(CenterY*2/3)*cos(Radians)));
//计算秒钟指针的夹角
Radians = (double)Time.GetSecond();
Radians *= 6.28/60.0;
//创建秒钟指针画笔
CPen SecondPen(PS_SOLID,1,RGB(255,0,0));
pDC->SelectObject(&SecondPen);
//绘制秒钟指针
pDC->MoveTo(CenterX,CenterY);
pDC->LineTo(CenterX + (int)((double)(CenterX*4)/5)*sin(Radians), CenterY - (int)((double)(CenterY*4)/5*cos(Radians)));
pDC->LineTo(CenterX - (int)((double)(CenterX)/5)*sin(Radians), CenterY + (int)((double)(CenterY)/5*cos(Radians)));
pDC->SelectObject(OldPen);
}
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:出现一个窗口,显示的是一个时钟。

实验结果的分类:无
实验中存在的问题:指针没有延伸
实验可以改进的方面和建议:起始点把指针从圆心加上180度延长1/3的长度。

课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期2015.4.13实验成绩____ _ 实验名称实验 3 设屏幕可用显示模式和分辨率的获取与显示
1. 实验目的
了解显示器的工作原理,了解屏幕的可用显示模式和分辨率的关
系。

2. 实验设备与环境
硬件设备:
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理:
对于系统设备的显示特性信息的获取,Windows 系统有一个关键的API 函
数EnumDisplaySettings(),用来获得当前显示驱动所支持的所有显示模式。

调用方式为:EnumDisplaySettings(NULL,modenum,&devmode);
通过modenum的递增可以获取当前显示驱动所支持的所有显示模式。

再将获得的显示
模式的数据存入列表框,并在屏幕上显示出来。

系统定义和封装了DEVMODE 类型的数据结构,描述了获取显示器的各类属性值。

通常情况下用到的成员变量有:
devmode 是DEVMODE 类型的数据结构的指针。

dmSize:所用DEVMODE 数据结构的大小(以Bytes 为单位);
dmBitsPerPel :每象素所使用的显存位数(Bits);
dmPelsWidth :水平分辨率(点数);
dmPelsHeight Pixel height :垂直分辨率(点数);
dmDisplayFrequency :显示刷新率,以赫兹为单位;
dmFields:取DM_PELSWIDTH,DM_PELSHEIGHT,DM_BITSPERPEL,DM_DISPLAYFREQUENCY
等四种值之一或它们的组合;
通常情况下,不同的显示设备(如打印机)用到的DEVMODE 数据结构的内容不同,
比如设定打印机时,不会用到dmDisplayFrequency属性。

所以,在使用DEVMODE 数据结构时,应向系统说明具体用到的有效数据成员,dmFields的用处便在于此。

如果在程序中只用到dmPelsWidth(水平分辨率)和dmPelsHeight(垂直分辨率),那么该值应为
DM_PELSWIDTH|DM_PELSHEIGHT
实验内容:获取显示器的各种显示模式和对应的分辨率,并将这些数据显示在屏幕上,以利于用户观察。

实验设计步骤、设计过程或执行顺序
1.利用MFC AppWizard(EXE)向导生成一个基于对话框单文档的应用程序框架。

2. 添加全局变量:int modenum=0,done;DEVMODE lpdevmode;CString
stemp,lpdevstring[1028];
3.分别为编辑框、列表框添加成员变量UINT m_mode_num、CListBox m_list_dlg用于
数据交换;
4. 分别为编辑框、列表框添加成员变量UINT m_mode_num、CListBox m_list_dlg用于
数据交换;
5. 编译链接并运行程序
实验代码:
// MyTestScrxydlgDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MyTestScrxydlg.h"
#include "MyTestScrxydlgDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//全局变量
int modenum=0,done;
DEVMODE lpdevmode;
CString stemp,lpdevstring[1028];
/////////////////////////////////////////////////////////////////////////////
// CMyTestScrxydlgDlg dialog
CMyTestScrxydlgDlg::CMyTestScrxydlgDlg(CWnd* pParent /*=NULL*/) : CDialog(CMyTestScrxydlgDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMyTestScrxydlgDlg)
m_mode_num = 0;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 done=0;
modenum=0;
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMyTestScrxydlgDlg::DoDataExchange(CDataExchange* pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyTestScrxydlgDlg)
DDX_Control(pDX, IDC_LIST2, m__list_dlg);
DDX_Text(pDX, IDC_EDIT1, m_mode_num);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyTestScrxydlgDlg, CDialog) //{{AFX_MSG_MAP(CMyTestScrxydlgDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyTestScrxydlgDlg message handlers
BOOL CMyTestScrxydlgDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CMyTestScrxydlgDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMyTestScrxydlgDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMyTestScrxydlgDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CMyTestScrxydlgDlg::OnButton1()
{
// TODO: Add your control notification handler code here
done=0;
modenum=0;
do{
done=!(EnumDisplaySettings(NULL,modenum,&lpdevmode));
lpdevmode.dmSize =sizeof(DEVMODE);
lpdevmode.dmFields=DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
Sleep(30);
lpdevstring[modenum]="";
{
stemp.Format("%d",lpdevmode.dmBitsPerPel,10);
lpdevstring[modenum]=lpdevstring[modenum]+"BitsPerPixel:"+stemp;
stemp.Format("%d",lpdevmode.dmPelsWidth,10);
lpdevstring[modenum]=lpdevstring[modenum]+" WidthPixels:"+stemp;
stemp.Format("%d",lpdevmode.dmPelsHeight,10);
lpdevstring[modenum]=lpdevstring[modenum]+" HeightPixels:"+stemp;
m__list_dlg.AddString(lpdevstring[modenum]);
}
modenum++;
}while ((!done)&&(modenum<1028));
m_mode_num =modenum;
UpdateData(FALSE);
}
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:出现一个窗口,显示的是屏幕分辨率。

实验结果的分类:无
实验中存在的问题:无
实验可以改进的方面和建议:无
课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期 2015.4.20 实验成绩____ _ 实验名称实验 4 直线生成算法比较
1. 实验目的
在指定的输出设备(如光栅图形显示器)上利用点构造直线的算法与
原理,并利用Visual C++编程实现这些算法。

2. 实验设备与环境
硬件设备:
软件运行环境: windows XP
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理: 计算机上常见的显示器为光栅图形显示器,光栅图形显示器可以看作像
素的矩阵。

像素是组成图形的基本元素,一般称为“点”。

通过点亮一些像素,灭掉另一些像素,即在屏幕上产生图形。

实验内容:分别使用基本图形——直线的光栅扫描转换生成算DDA(数值微分),中点画线法,Bresenham算法画图,并且比较三者画图的效率。

实验设计步骤、设计过程或执行顺序
①用DDA画线法画图,并且保存其画图10000次所需要的时间,并且保存这个时间T1。

②用中点画线法画图,并且保存其画图10000次所需要的时间,并且保存这个时间T2。

③用Bresenham画线法画图,并且保存其画图10000次所需要的时间,并且保存这个
时间T3。

④在一个对话框中显示三者画图10000次分别所需要的时间。

画直线部分的实验代码:
// DDA算法生成直线
void CTestView:: OnDdaline()
{
CDC* pDC=GetDC();//获得设备指针
int xa=100,ya=300,xb=300,yb=200,c=RGB(255,0,0);//定义直线的两端点,直线颜色
int x,y;
float xl,yl,dx, dy, k;
dx=(float)(xb-xa), dy=(float)(yb-ya);
k=dy/dx, y=ya;
if(abs(k)<1)
{yl=ya;
for (x=xa;x<=xb;x++)
{pDC->SetPixel (x,int(yl+0.5),c);
yl=yl+k;}
}
if(abs(k)>=1)
{xl=xa;
for (y=ya;y<=yb;y++)
{pDC->SetPixel (int(xl+0.5),y,c);
xl=xl+1/k;}
}
ReleaseDC(pDC);
}
//中点算法生成直线
void CTestView::OnMidpointline()
{
CDC* pDC=GetDC();
int xa=300, ya=200, xb=450, yb=300,c=RGB(0,255,0); float a, b, d1, d2, d, x, y;
a=ya-yb, b=xb-xa, d=2*a+b;
d1=2*a, d2=2* (a+b);
x=xa, y=ya;
pDC->SetPixel(x, y, c);
while (x<xb)
{ if (d<0) {x++, y++, d+=d2; }
else {x++, d+=d1;}
pDC->SetPixel(x, y, c);
}
ReleaseDC(pDC);
}
//Bresenham算法生成直线
void CTestView::OnBresenhamline()
{
CDC* pDC=GetDC();
int x1=100, y1=200, x2=350, y2=100,c=RGB(0,0,255); int i,s1,s2,interchange;
float x,y,deltax,deltay,f,temp;
x=x1;
y=y1;
deltax=abs(x2-x1);
deltay=abs(y2-y1);
if(x2-x1>=0) s1=1; else s1=-1;
if(y2-y1>=0) s2=1; else s2=-1;
if(deltay>deltax)
{
temp=deltax;
deltax=deltay;
deltay=temp;
interchange=1;
}
else interchange=0;
f=2*deltay-deltax;
pDC->SetPixel(x,y,c);
for(i=1;i<=deltax; i++) {
if(f>=0)
{
if(interchange==1) x+=s1; else y+=s2;
pDC->SetPixel(x,y,c);
f=f-2*deltax;
}
else
{
if(interchange==1) y+=s2; else x+=s1;
f=f+2*deltay;
}
}
}
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:画图窗口,显示画图所需时间。

实验结果的分类:三种方法的时间
实验中存在的问题:无
实验可以改进的方面和建议:无
课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期2015.4.27 实验成绩____ _
实验名称实验 4 生成圆
1. 实验目的
用中点画圆法和圆的Bresenham算法生成圆,并且比较两者的效率
2. 实验设备与环境
硬件设备:
软件运行环境: windows XP
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理:
中点画圆算法就是每部单位间隔取样并且计算离圆最近的位置。

在继续之前,我这里补充一
个关于圆对称性的知识点,通过在圆中计算考虑使用对称性计算开销可以减小到原来的1/8。

对称性质原理:
(1)圆是满足x轴对称的,这样只需要计算原来的1/2点的位置;
(2)圆是满足y轴对称的,这样只需要计算原来的1/2点的位置;
(3)圆是满足y = x or y = -x轴对称的,这样只需要计算原来的1/2点的位置;
通过上面三个性质分析得知,对于元的计算只需要分析其中1/8的点即可。

Bresenham算法原理:过各行各列象素中心构造一组虚拟网格线。

按直线从起点到终点的顺序计算直线与各垂直网格线的交点,然后确定该列象素中与此交点最近的象素。

该算法的巧妙之处在于采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列的所求象素。

实验内容:使用中点画圆法和Bresenham画圆法生成圆,并且比较两者画圆的效率。

实验设计步骤、设计过程或执行顺序
①创建应用程序框架,以建立的单文档程序框架为基础。

②编辑菜单资源
③添加消息处理函数。

④在一个对话框中显示三者画图10000次分别所需要的时间。

中点画圆法代码:
void CTestView::OnMidpointcircle() //中点算法绘制圆
{
// TODO: Add your command handler code here
CDC* pDC=GetDC();
int xc=300, yc=300, r=50, c=0;
int x,y;
float d;
x=0; y=r; d=1.25-r;
pDC->SetPixel ((xc+x),(yc+y),c);
pDC->SetPixel ((xc-x),(yc+y),c);
pDC->SetPixel ((xc+x),(yc-y),c);
pDC->SetPixel ((xc-x),(yc-y),c);
pDC->SetPixel ((xc+y),(yc+x),c);
pDC->SetPixel ((xc-y),(yc+x),c);
pDC->SetPixel ((xc+y),(yc-x),c);
pDC->SetPixel ((xc-y),(yc-x),c);
while(x<=y)
{ if(d<0) d+=2*x+3;
else { d+=2*(x-y)+5; y--;}
x++;
pDC->SetPixel ((xc+x),(yc+y),c);
pDC->SetPixel ((xc-x),(yc+y),c);
pDC->SetPixel ((xc+x),(yc-y),c);
pDC->SetPixel ((xc-x),(yc-y),c);
pDC->SetPixel ((xc+y),(yc+x),c);
pDC->SetPixel ((xc-y),(yc+x),c);
pDC->SetPixel ((xc+y),(yc-x),c);
pDC->SetPixel ((xc-y),(yc-x),c);
}
}
Bresenham画圆法代码:
void CTestView::OnBresenhamcircle() //// Bresenham算法绘制圆{
CDC* pDC=GetDC();
int xc=100, yc=100, radius=50, c=0;
int x=0,y=radius,p=3-2*radius;
while(x<y)
{
pDC->SetPixel(xc+x, yc+y, c);
pDC->SetPixel(xc-x, yc+y, c);
pDC->SetPixel(xc+x, yc-y, c);
pDC->SetPixel(xc-x, yc-y, c);
pDC->SetPixel(xc+y, yc+x, c);
pDC->SetPixel(xc-y, yc+x, c);
pDC->SetPixel(xc+y, yc-x, c);
pDC->SetPixel(xc-y, yc-x, c);
if (p<0)
p=p+4*x+6;
else
{
p=p+4*(x-y)+10;
y-=1;
}
x+=1;
}
if(x==y)
pDC->SetPixel(xc+x, yc+y, c);
pDC->SetPixel(xc-x, yc+y, c);
pDC->SetPixel(xc+x, yc-y, c);
pDC->SetPixel(xc-x, yc-y, c);
pDC->SetPixel(xc+y, yc+x, c);
pDC->SetPixel(xc-y, yc+x, c);
pDC->SetPixel(xc+y, yc-x, c);
pDC->SetPixel(xc-y, yc-x, c); }
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:画图窗口,显示画图所需时间。

实验结果的分类:两种方法的时间
实验中存在的问题:无
实验可以改进的方面和建议:无
课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期2015.4.27 实验成绩____ _
实验名称实验 5 多边形区域填充算法
1. 实验目的
画出两个图形,并且用简单种子填充算法和扫描线算法对不同的图形
进行填充
2. 实验设备与环境
硬件设备:
软件运行环境: windows XP
软件设计工具: Microsoft Visual C++ 6.0
3. 实验设计说明
基本工作原理:
简单种子填充算法的原理:
域填充指先将区域的一点赋予指定的颜色,然后将该颜色扩展到整个区域的过程。


域填充算法要求区域是连通的。

上面讨论的多边形填充算法是按扫描线顺序进行的。

种子填充算法则是假设在多边形内
有一像素已知,由此出发利用连通性填充区域内的所有像素。

一般采用多次递归方式。

扫描线算法的原理:
算法的基本过程如下:给定种子点(x,y),首先填充种子点所在扫描线上给定区域的
一个区段,然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,并依次保存下来。

反复这个过程,直到填充结束。

实验内容:分别用种子填充算法和扫描线填充算法对不同区域进行填充,并且分析比较两
者的效率。

实验设计步骤、设计过程或执行顺序
①创建应用程序框架,以上述单文档程序框架为基础,创建应用程序界面的菜单项。

②编辑菜单资源。

③利用ClassWizard(建立类向导)为应用程序添加与菜单项相关的消息处理函数,
ClassName栏中选择CTestView,建立如消息映射函数,ClassWizard会自动
完成有关的函数声明。

④添加程序结构代码。

实验代码:
1.建立边表结构
typedef struct //建立边表结构
{
int num, ymin,ymax;
float xmin,xmax,dx;
} Edge;
class CTestView : public CView
{
protected: // create from serialization only
M
public:
Cpoint ptset[7];
CPoint spt[8],s_point;
Edge edge[7],edge1[7],newedge[1];
M
}
2.绘制要填充的多边形
void CTestView::OnDraw(CDC* pDC)//绘制要填充的多边形
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CPen newpen(PS_SOLID,1,RGB(255,0,0));
CPen *old=pDC->SelectObject(&newpen);
pDC->TextOut(20,20,"双击鼠标左键,出现多边形,点击功能菜单项实现区域填充"); pDC->TextOut(20,50," 需用鼠标右键单击多边形内一点,作为种子点进行填充, "); pDC->SelectObject(old);
}
3.扫描线算法进行多边形区域填充
void CTestView:: OnPolyFillByScan() //扫描线算法进行多边形区域填充
{
CDC* pDC=GetDC();
CPen newpen(PS_SOLID,1,RGB(0,255,0));
CPen *old=pDC->SelectObject(&newpen);
int j,k,s=0;
int p[5]; //每根扫描线交点
int pmin,pmax;
for(int i=0;i<7;i++)//建立边表
{ edge[i].dx=(float)(spt[i+1].x-spt[i].
x)/(spt[i+1].y-spt[i].y);
if(spt[i].y<=spt[i+1].y){
edge[i].num=i;
edge[i].ymin=spt[i].y;
edge[i].ymax=spt[i+1].y;
edge[i].xmin=(float)spt[i].x;
edge[i].xmax=(float)spt[i+1].x;
pmax=spt[i+1].y;
pmin=spt[i].y;
}
else{
edge[i].num=i;
edge[i].ymin=spt[i+1].y;
edge[i].ymax=spt[i].y;
edge[i].xmax=(float)spt[i].x;
edge[i].xmin=(float)spt[i+1].x;
pmax=spt[i].y;
pmin=spt[i+1].y;
}
}
for(int r=1;r<7;r++) //边排序edge(y递增,x默认)
{
for(int q=0;q<7-r;q++)
{
if(edge[q].ymin<edge[q+1].ymin)
{
newedge[0]=edge[q]; edge[q]=edge[q+1];
edge[q+1]=newedge[0];
}
}
}
pmax=edge[0].ymax;
pmin=edge[0].ymin;
for(int scan=pmax-1;scan>pmin+1;scan--)
{
int b=0;
k=s;
for(j=k;j<7;j++)
{
if((scan>edge[j].ymin)&&(scan<=edge[j].ymax))//判断与线段相交{
if(scan==edge[j].ymax)
{
if(spt[edge[j].num+1].y<edge[j].ymax)
{
b++;
p[b]=(int)edge[j].xmax;
} else
if(spt[edge[j].num-1].y<edge[j].ymax)
{
b++;
p[b]=(int)edge[j].xmax;
}
}
if((scan>edge[j].ymin)&&(scan<edge[j].ymax))
{
b++;
p[b]=(int)(edge[j].xmax+edge[j].dx*(scan-edge[j].ymax));
}
}
if(scan<=edge[j].ymin)
s=j;
}
if(b>1)
{
for(int u=1;u<b;u++)
{
pDC->MoveTo(p[u]+1,scan);
u++;
pDC->LineTo(p[u]-1,scan);
}
}
}
pDC->SelectObject(old);
}
4.种子填充算法进行多边形区域填充void CTestView:: OnSeedfill()
//种子填充算法进行多边形区域填充{
CWindowDC dc (this);
int fill=RGB(0,255,0);
int boundary=RGB(255,0,0);
CPoint p0,pt=s_point;
int x,y,pmin,pmax;
//求多边形的最大最小值
for(int m=1;m<7;m++)
{
for(int n=0;n<=7-m;n++)
{
if(spt[n].y<spt[n+1].y)
{
p0=spt[n]; spt[n]=spt[n+1];
spt[n+1]=p0;
}
}
}
pmax=spt[0].y,pmin=spt[6].y;
x=s_point.x;
y=s_point.y;
for(;y<pmax+1;y++)
{
int current=dc.GetPixel(x,y);
while((current!=boundary)&&(current!=fill)) {
dc.SetPixel(x,y,fill);
x++;
current=dc.GetPixel(x,y);
}
x=s_point.x;
x--;
current=dc.GetPixel(x,y);
while((current!=boundary)&&(current!=fill)) {
dc.SetPixel(x,y,fill);
x--;
current=dc.GetPixel(x,y);
}
x=s_point.x;
}
x=s_point.x;
y=s_point.y-1;
for(;y>pmin+1;y--)
{
int current=dc.GetPixel(x,y);
while((current!=boundary)&&(current!=fill)) {
dc.SetPixel(x,y,fill);
x++;
current=dc.GetPixel(x,y);
}
x=s_point.x;
x--;
current=dc.GetPixel(x,y);
while((current!=boundary)&&(current!=fill)) {
dc.SetPixel(x,y,fill);
x--;
current=dc.GetPixel(x,y);
}
x=s_point.x;
}
}
实验结果记录:
4. 实验结果的分析和描述
实验结果的主要组成部分:画图窗口。

实验结果的分类:种子填充算法填充图像和扫描线填充算法填充图像。

实验中存在的问题:无。

实验可以改进的方面和建议:无
课程名称计算机图形学
班级软件4班学号___20122712_ 姓名____魏仁斌 _
试验日期 2015.5.11 实验成绩____ _ 实验名称实验6 二维图形变换
1. 实验目的
编程实现二维图形的变换
2. 实验设备与环境
硬件设备:
软件运行环境: Windows XP
软件设计工具: Microsoft Visual C++ 6.0 3. 实验设计说明
基本工作原理: 由于二维图形是由点或直线段组成的,其中,直线段可由其端点坐标定
义,因此,二维图形的几何变换可以归结为对点或对直线段端点的变换。

实验内容:
①绘制原始二维图形
②实现原始图形的平移变换
③实现原始图形的旋转变换,包括绕X轴、Y轴、Z轴变换
④实现错切变换,包括X、Y、Z轴的错切
实验设计步骤、设计过程或执行顺序
(1)创建单文档应用程序工程框架.。

相关文档
最新文档