2020年计算机图形学实验指导书_第1页
2020年计算机图形学实验指导书_第2页
2020年计算机图形学实验指导书_第3页
2020年计算机图形学实验指导书_第4页
2020年计算机图形学实验指导书_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

文档仅供参考,不当之处,请联系改正。

[]第一章计算机图形学的软件开发环境

计算机图形学中的程序都是用C语言编写的,

TurboC和VisualC++常见的两种C语言开发环境,

TurboC是在Dos环境下开发,而VisualC++是在

Windows环境下开发。

1.1、在TurboC环境下开发应用程序

一些高级语言都扩充了图形功能,这使得用户能

够不需配备专门的图形软件,就能在计算机上进行图

形工作。TurboC2.0包含有460多个库函数,其中

有70多个图形函数,这些函数包括了绘图、处理图

象及图素、屏幕及视图区控制、颜色及线型设置、状

态查询和出错处理等,这使得TurboC具有很强的图

形功能。

1.图形显示器的工作方式

IBMPC机的显示器能够在两种基本视频方式下

工作:一种是文本方式;另一种是图形方式。

(1)文本方式

在文本方式下,屏幕上能够显示的最小单位是字

符,字符在屏幕上以行、列排列,即我们一般见到的

情况。文本方式不同,屏幕上所显示字符的行数和列

数也不一样,颜色也会有所区别。TurboC支持6种

不同的文本显示方式。

(2)图形方式

文档仅供参考,不当之处,请联系改正。

在图形方式下,屏幕上能够控制的最小单元称作

像素(pixel),它是组成图形的基本元素,一般

叫作“点”。一般把屏幕上所包含像素的个数叫做分

辨率。分辨率越高,显示的图形越细致、质量越好,

这是显而易见的。在图形方式下,屏幕上每个像素的

显示位置用点坐标系来描述。在该坐标系中,屏幕左

上角为坐标系的原点,坐标值为(0,0);水平

方向为X轴,自左向右;垂直方向为Y轴,自上向下。

见下图。

(0,0)XmaxX

Y

''maxY

点坐标系中坐标值的范围决定于所用显示器的

分辨率。分辨率不同,水平方向上和垂直方向上的点

数也不同,即其maxx、maxy的数值不同。就我们

常见的VGA显示器来说,它一般所用的分辨率为

6405480,即它的maxx值为639,maxy的值为

479o

文档仅供参考,不当之处,请联系改正。

2.图形函数及其用法

TurboC的图形函数均在一个头文件

"graphics,h"中定义。因此,凡是在程序中要调

用这些图形函数,都必须在源程序的开头写上文件包

含命令:

#include<graphics.h>

(1)图形系统管理

在一般默认情况下,显示器处于文本方式下。在

文本方式下,所有的图形函数均不能应用。因此在调

用图形函数绘图之前,必须先将显示器设置为图形模

式,这就是一般所说的图形方式初始化。在图形工作

完毕之后,又要使显示器回到文本方式,以便进行程

序文件等的编辑工作。

•图形方式初始化

图形方式初始化经过函数initgraph来实现,

它的功能是经过从磁盘上装入一个图形驱动程序来

初始化图形系统,并将系统设置为图形模式。其调用

格式为:initgraph(int*gdriver,int*gmode,char

*path);

调用该函数需用的三个参数含义为:

gdriver:是一个整型值,用来指定装入的驱动程

序名。

gmode:是一个整型值,用来设置图形显示模式。

文档仅供参考,不当之处,请联系改正。

path:是一个字符串,用来指明驱动程序所在的路

径。

举例:假设使用VGA显示器,图形显示模式为

VGAHI,即高分辨率图形模式,分辨率为6405480。

则初始化调用方式如下:

intgdriver=VGA,gmode=VGAHI;

initgraph(&gdriver,&gmode,"c:\\tc");

•关闭图形模式

在运行图形程序结束后,应及时关闭图形模式,

回到文本方式,以进行其它工作。关闭图形模式用函

数closegraph,其调用方法为:

closegraph();(该函数不需参数)

(2)绘图函数

从理论上来说,用像素点几乎能够画出任何图

形,但毕竟是效率太低。为此,TurboC的BGI提

供了一些基本的绘图函数,以方便图形设计。所有绘

图函数调用时的参数,其类型均为整型,因此填入参

数表的参数,应为整数或整型变量

putpixeI函数:将指定的颜色写到由坐标x,y所

确定的点。如putpixel(x,y,GREEN);

Iine函数:在指定两点之间画直线。如:line(xl,

yl,x2,y2);

Iineto函数:从当前点画线到指定点。如:lineto

文档仅供参考,不当之处,请联系改正。

moveto函数:把当前点移到指定点(不画线)。如:

moveto(x,y)

circle函数:指定圆心和半径画圆。如:circle

(xc,yc,r);

arc函数:画一段圆弧。要求指定圆弧所在圆的圆

心、半径,以及圆弧的起始角和终止角。

如:arc(xc,yc,angs,ange,r);

rectangle函数:指定矩形的两对角点画一个矩

形。如:rectangle(xl,yl,x2,y2);

drawpoly函数:画一条任意多边折线。如:

drawpoly(nps,xy);其中,nps为多边折线的

顶点数;xy为存放顶点坐标值的数组名。如果首尾

两点重合,则能够绘制一个任意多边形。

(3)图形属性控制

图形的属性指颜色和线型,颜色又有背景色和前

景色之分。背景色指的是屏幕的颜色,即底色;前景

色指的是绘图用的颜色。任何绘图函数都是在当前颜

色(背景色和前景色)和线型的状态下作图的。系统

的默认值为:背景色为黑色;前景色为白色;线型为

实线。

文档仅供参考,不当之处,请联系改正。

•setbkcolor函数:设置背景颜色。如:setbkcolor

(COLORNAME);

setcolor函数:设置前景颜色。(用法同上)

setIinestyIe函数:设置线型。如:setlinestyle

(LSTY,0,WIDTH);

(4)绘图程序简例

#include<graphics.h>

main()

|

/*DETECT的含义是自动检测当前显示器的类型,且选用最大可能的分辨率模式*/

intgd=DETECT,gm;initgraph(&gd,&gm,

“f:\\tc");

setbkcolor(LIGHTBLUE);

setcolor(RED);

circle(320,240,100);

/*getch()的含义是读入一个字符,但不回显在窗口中,加入这句语句的目的是防止显示的图像很快消失*/

getch();

closegraph();

)

1.2、在VisualC++环境下开发应用程序

一.Windows编程基础

VisualC++是可视化开发系统,一般而言,可视

化开发系统集成了一系列系统可用资源和开发工具:

文档仅供参考,不当之处,请联系改正。

程序调试工具包括源程序语法检查、可执行程序修改

和运行监视等;可选择并构成具体语句或源程序结构

的例程库及Help;资源管理器包括图形化窗口及组成

元素的多种对象的编辑器;应用程序Help和Setup

开发工具包,源程序编辑器和编译器;系统函数库和

系统函数开发工具。

在Windows的程序设计语言中,VC、VB、VJ都

是“面向对象”的程序设计语言。对象是Windows的

规范部件:窗口、菜单、按钮、对话框、程序模块都

是对象。编写Windows程序相当一部分工作是在创立

对象和为对象属性赋值。对象具有规范形态和操作模

式的特征。

在用vc进行编程时有两种方法:传统的编程方法

方法和交互式编程方法。传统的编程方法是采用直接

调用API的方法进行编程,API是Win系统与Win应

用程序间的标准程序接口,API为应用程序提供

Windows系统特殊函数及数据结构,而且Win应用程

序能够利用标准大量API函数调用系统功能。API函

数的功能包括:窗口管理函数实现窗口的创立、移动

和修改功能;系统服务函数:实现与操作系统有关的

多种功能;图形设备(GDI)函数:实现与设备无关的

图形操作功能。交互式编程方法是采用MFC的方法进

文档仅供参考,不当之处,请联系改正。

行编程。采用交互式方法时,可视化开发平台给出了

许多选用的对象,程序员可选择所需对象并确定其属

性,由此搭建起应用程序的“大框架”,并可根据需

要进一步编写必要的细节代码段,最后构成完整的应

用程序。

利用WindowsAPI函数编写Windows应用程序必须

首先了解以下内容:

(1)窗口的概念

(2)事件驱动的概念

⑶句柄

(4)消息

(D窗口

一个应用程序的窗口一般包含下列成分:

编写一个Windows应用程序首先应创立一个或多个

窗口,随后应用程序的运行过程即是窗口内部、

窗口与窗口之间、窗口与系统之间进行数据处理与数

文档仅供参考,不当之处,请联系改正。

据交换的过程。

⑵事件驱动

Windows程序设计是针对事件或消息的处理进

行,消息是指描述事件发生的信息(如按下鼠标或键

盘)。Windows程序的执行顺序取决于事件发生的顺

序,程序的执行顺序是由顺序产生的消息驱动的,可

是消息的产生往往并不要求有次序之分。事件驱动编

程方法对于编写交互式程序很有用处,它避免了死板

的操作模式。

(3)句柄

句柄是一个4字节长的数值,用于标识应用程序

中不同的对象和同类对象中不同的实例,应用程

序经过句柄访问相应的对象信息。以下是常见句柄类

型及其说明:

HWND窗口句柄HDC设备

环境句柄

HBITMAP位图句柄HCURSOR光标

句柄

EICON图标句柄HFONT字体

句柄

HMENU菜单句柄HPEN回笔

句柄

HFILE文件句柄HBRUSH画刷

文档仅供参考,不当之处,请联系改正。

句柄

HINSTANCE当前实例句柄

(4)消息

Windows应用程序利用Windows消息(Message)与

应用程序及系统进行信息交换。消息由三部分组成,

①消息号:由事先定义好的消息名标识;

②字参数(wParam):用于提供消息的附加信息;

③长字参数(IParam):用于提供消息的附加信

息,附加信息与具体消息号的值有关

在Win中消息用结构体MSG表示:

typedefstructtagMSG

{HWNDhwnd;窗口句柄,为null,则可检索所有驻

留在消息队列中的消息

UINTmessage;消息值,由Windows,h头文件中的

宏定义来标识

WPARAMwPara叫包含有关消息的附加信息,不同

消息其值有所不同

LPARAMIParam;

DWORDtime;指定消息送至队列的时间

POINTpt;指定消息发送时屏幕光标的位置,其数

据类型殁幽也是一个结构体

}MSG;

文档仅供参考,不当之处,请联系改正。

typedefstructtagPOINT

{LONGx;

LONGy;

}POINT;

VC中存在几种系统定义的消息分类,不同的前缀符

号经常见于消息宏识别消息附属的分类,系统定义的

消息宏前缀如下:

BM表示按钮控制消息

CB表示组合框控制消息

DM表示默认下压式按钮控制消息

EM表示编辑控制消息

LB表示列表框控制消息

SBM表示滚动条控制消息

WM表示窗口消息

Windows编程常见消息包括:窗口管理消息,初始

化消息,输入消息,系统消息,剪贴板消息,控制处

理消息,控制通知消息,滚动条通知消息,非用户区

消息,MDI消息,DDE消息,应用程序自定义的消息。

二、Windows应用程序常见消息

1.WM.LBUTTONDOWN:产生单击鼠标左键的消息。

IParam:低字节包含当前光标的X坐标值高字节包

含当前光标的Y坐标值;wParam包含一整数值以标识

文档仅供参考,不当之处,请联系改正。

鼠标键的按下状态;MK_LBUTTON按下鼠标左

键,MK_MBUTTON按下鼠标中键,MK_RBUTTON按下

鼠标右键.另外,相似的消息还有:

WM_LBUTTONUP:放开鼠标左键时产生;

WM_RBUTTONDOWN:单击鼠标右键时产生;

WM_RBUTTONUP:放开鼠标右键时产生;

WM_LBUTTONDBLCLK:双击鼠标左键时产生;

WM_RBUTTONDBLCLK:双击鼠标右键时产生

2.WM_KEYDOWN:按下一个非系统键时产生的消息。

系统键是指实现系统操作的组合键,例如Alt与某个

功能键的组合以实现系统菜单操作等。wParam:按下

键的虚拟键码,用以标识按下或释放的键(如F1的

虚拟键码在Windows,h文件中定义为VK_F1);

IParam:记录了按键的重复次数、扫描码、转移代码、

先前键的状态等信息。

相似的消息还有WM.KEYUP,在放开非系统键时产

3.WM_CHAR:按下一个非系统键时产生的消息。

WParam:为按键的ASCH码;IParam:与WM_KEYDOWN

的相同。

文档仅供参考,不当之处,请联系改正。

4.WM_CREATE:由CreateWindow函数发出的消息。

wParam:未用;IParam:包含一个指向CREATESTRUCT

数据结构的指针。

5.WM_CLOSE:关闭窗口时产生的消息。wParam和

IParam均未用。

6.WM_DESTROY:由DestroyWiodow函数发出的消息。

wParam和IParam均未用。

7.WM_QUIT:由PostQuitMessage函数发出的消息,

退出应用程序时发出的消息。wParam:含退出代码,

标识程序退出运行时的有关信息;IParam:未用

8.WM_PAINT:以下情况时将产生WM_PAINT消息。用

户区移动或显示,用户窗口改变大小,程序经过滚动

条滚动窗口,下拉式菜单关闭并需要恢复被覆盖的部

分,Windows清除对话框等对象,并需要恢复被覆盖

的部分均产生WM_PAINT消息。

三Windows中的事件驱动程序设计

过程驱动程序设计和事件驱动程序设计的区别

如下图:

文档仅供参考,不当之处,请联系改正。

四'Windows应用程序组成及编程步骤

1.应用程序的组成

一个完整的Windows应用程序一般由五种类型的文件

组成。

1.C语言源程序文件

2.头文件

3.模块定义文件

文档仅供参考,不当之处,请联系改正。

4.资源描述文件

5.项目文件

2.源程序组成结构

WinMain和WndProc是Windows应用程序的主体,

Windows应用程序由这两个函数构成基本框架。入口

函数WinMain:1.是所有应用程序的入口,类似Main

函数,2.完成一系列的定义和初始化,并产生消息

循环。窗口函数WndProc包含各种数据类型、数据结

构与函数等。

(1)WinMain函数

WinMain函数的功能是注册窗口类,建立窗口及执

行必要的初始化。并进入消息循环,据接受的消息调

用相应的处理过程,当消息循环检索到WM_QUIT时终

止程序运行。WinMain函数由三个基本的组成部分:

函数说明、初始化和消息循环。

WinMain函数的说明如下:

intWINAPIWinMain

(HINSTANCEhThisInst,〃应用程序当前实例句

HINSTANCehPrevInst,〃应用程序其它实例句

LPSTRIpszCmdLine,//指向程序命令行参数

的指针

文档仅供参考,不当之处,请联系改正。

IntnCmdShow〃应用程序开始执行时窗口显

示方式的整数值标识

)

注意!Win是多任务管理的,同一应用程序的多个窗

口可能会同时存,Win系统对每个窗口的执行称为一

个实例,并用一个实例句柄来唯一标识

(2)初始化

初始化包括四个步骤。窗口类的定义:定义窗口的

形式与功能;窗口类的注册:窗口类必须先注册后使

用;创立窗口实例;显示窗口。

(a)窗口类定义

经过给窗口类数据结构WNDCLASS赋值完成,该数据

结构中包含窗口类的各种属性。窗口类定义常见以下

函数:

Loadicon:作用是在应用程序中加载一个窗口图

标。其原型为:

EICONLoadicon(HINSTANCEhlnstance,//hlnstance

图标资源所在的模块句柄,NULL则使用系统预

〃定义图标,

LPCTSTRIpIconName//

IpIconName图标资源名或系统预定义图标标识名。)

文档仅供参考,不当之处,请联系改正。

LoadCursor:作用是在应用程序中加载一个窗口光

标。其原型为:

HCURSORLoadCursor(HINSTANCEhlnstance,//

hlnst

ance

光标

资源

所在

的模

块句

柄,

NULL

则使

用系

〃统预

定义光标

LPCTSTRIpCursorName)//

IpCursorName光标资源名或系统预定义光标标识

〃名

GetStockObject:作用是获取系统提供的背景刷,

其原型为:

HBRUSHGetStockObject(intnBrush);//nBrush刷

文档仅供参考,不当之处,请联系改正。一

子的类型

(b)注册窗口类

Win系统本身提供部分预定义的窗口类,程序员也

能够自定义窗口类,窗口类必须先注册后使用。窗口

类的注册由函数RegisterClass()实现。

RegisterClass(&wndclass);//wndclass为窗口

类结构

RegisterClass函

数的返回为布尔

值,注

〃册成功则返回真

(C)创立窗口实例

创立一个窗口类的实例由函数CreateWindow()

实现,函数原型如下:

HWNDCreateWindow

(LPCTSTRIpszClassName,〃窗口类名

LPCTSTRIpszTitle,〃窗口标题名

DWORDdwStyle,〃创立窗口的样式

intx,y,〃窗口左上角坐标

intnWidth,nHeight,〃窗口宽度和度高

HWNDhwndParent,〃该窗口的父窗口句柄

HWENUhMenu,〃窗口主菜单句柄

文档仅供参考,不当之处,请联系改正。

HINSTANCEhlnstance,〃创立窗口的应用程序

当前句柄

LPVOIDIpParam〃指向一个传递给窗口的

参数值的指针

)

常用窗口样式

说明

WS_BORDER包犍一带边框的窗口

WS_CAPTION年犍一带标题栏的窗口

WS_VSCROLL包犍一带垂直滚动条的窗口

WS_MAXIMIZEBOX创犍一带最大化框的窗口

WS_MAXIMIZE包犍一最大尺寸的窗口

WS_MINIMIZEBOX毒犍一带最小化框的窗口

WS_MINIMIZE包犍一最小尺寸的窗口

WS_OVERLAPPED包犍一带边框和标J8的窗口

WS_OVERLAPPEDWINDOW包惚一带边框、标题栏、系皖单及最大、

最小化框的窗口

WS_POPUP卷犍一弹出式窗口

WS_POPUPWIND0W含犍一带边框和系纭单的弹出式窗口

WS_SYSMENU包犍一带系皖单的窗口

WS_HSCROLL包犍一带水平滚动条的菜单

(d)显示窗口

窗口类的显示由ShowWindow和UpdateWindow函数

实现。应用程序调用ShowWindow函数在屏幕上显示

窗口:

ShowWindow(hwnd,nCmdshow);//nCmdshow为窗口

显示形式标识

SW-HIDE隐豪窗口

SW_SHOWNORMAL显示并激活窗口

SW_SHOWMINIMIZE显示并最小化窗口

S\VSHOWMAXMIZE显示并最大化窗口

SW-SHOWNOACTIVE显示但不激活窗口

SM「RESTORE恢复窗口的原来位置及尺寸

显示窗口后,应用程序调用UpdateWindow更新并

文档仅供参考,不当之处,请联系改正。

绘制用户区,并发出WM_PAINT消息。

UpdateWindow(hwnd);

(3)消息循环

消息循环的过程如下图所示:

将消息传递给

窗口函数的相

Windows来

产生的消息

消息循环的常见格式如下:

MSGMsg;

while(GetMessage(&Msg,NULL,0,0))〃从消息队列

中读取一条消息,并将消息放在MSG结构中

{TranslateMessage(&Msg);//将消息的虚拟键转换

为字符信息

DispatchMessage(&Msg);}〃将消息传送到指定窗

口函数

其中函数GetMessage形式为:

GetMessage

IpMSG,〃指向MSG结构的指针

hwnd,

nMsgFilteMin,〃用于消息过滤的最小消息号值

nMsgFilterMax〃用于消息过滤的最大消息号值

文档仅供参考,不当之处,请联系改正。

)

返回零值,即检索到WM_QUIT消息,程序结束循环并

退出

2.窗口函数WinProc

WinProc定义了应用程序对接收到的不同消息的响

应,包含了对各种可能接收到的消息的处理过程。

WinProc函数由一个或多个switch语句组成。每一条

case语句对应一种消息,当应用程序接收到一个消息

时,相应的case语句被激活并执行相应的响应程序

模块。

窗口函数的一般形式如下:

LRESULTCALLBACKWndProc(HWNDhwnd,UINT

messgae,WPARAMwParam,LPARAMIParam)

{…

switch(message)//message为标识的消息

{case…

•••

break;

caseWM_DESTROY:

PostQuitMessage(0);

文档仅供参考,不当之处,请联系改正。

default:

return

DefWindowProc(hwnd,message,wParam,1Param);

)

return(0);

)

在消息处理程序段中一般都有对WM_DESTROY的处

理,该消息是关闭窗口时发出的。它向应用程序发出

WM_QUIT消息,请求退出处理函数:

voidPostQuitMessage(intnExitCode)

〃nExitCode为应用程序的退出,为未定义处理过程

//消

息提供缺省处理

3.数据类型

在Windows,h中定义了Windows应用程序中包含

种类繁多的数据类型

文档仅供参考,不当之处,请联系改正。

期频说明

WORD16位无符号整数

LONG32位有符号整数

DWORD32位无符号整数

HANI>LE句柄

PINT32位无符号整数

BOOL布尔值

LPTSTR指向字符串的32位指针

LPCTSTR指向字符串常量的32位指针

4.一些重要的数据结构

MSG:包含一个消息的全部信息,是消息发送的格式

WINDCLASS:包含一个窗口类的全部信息及属性

POINT:定义了屏幕上或窗口中的一个点的X和Y坐

RECT:定义了一个矩形区域及其左上角和右下角的坐

五、应用程序

【例2-1]创立应用程序框架。本例的目的在于说明

创立Windows应用程序的方法及过程,程序的效果如

下图所示。

文档仅供参考,不当之处,请联系改正。

#include<windows.h>〃包含应用程序中所需的数据

类型和数据结构的定义

LRESULTCALLBACK

WndProc(HWND,UINT,WPARAM,LPARAM);〃窗

口函数说明

//.........以下初始化窗口类...............

intWINAPIWinMain(HINSTANCEhlnstance,

HINSTANCEhPrevInst,LPSTR

lpszCmdLine,intnCmdShow)

HWNDhwnd;

MSGMsg;

WNDCLASSwndclass;

文档仅供参考,不当之处,请联系改正。.

charIpszClassName[]="窗口";〃窗口类

charlpszTitle[]=nMy_Windowsn;〃窗口标

题名

〃窗口类的定义

wndclass.style=O;〃窗口类

型为缺省类型

wndclass.IpfnWndProc=WndProc;〃定义窗

口处理函数

wndclass.cbClsExtra=O;〃窗口类无

扩展

wndclass.cbWndExtra=O;〃窗口实

例无扩展

wndclass.hlnstance=hlnstaiice;〃当前实

例句柄

wndclass.hIcon=LoadIcon(NULL,IDI_APPLICAT

ION);〃窗口的最小化图标为缺省图标

wndclass.hCursor=LoadCursor(NULL,IDC_ARR

OW);〃窗口采用箭头光标

wndclass.hbrBackground=GetStockObject(WHIT

E_BRUSH);〃窗口背景为白色

wndclass.lpszMenuName=NULL;//窗口中无

文档仅供参考,不当之处,请联系改正。

菜单

wndclass.lpszCIassName=lpszClassName;//窗口类

名为“窗口”

//.........以下进行窗口类的注册……

if(!RegisterClass(&wndclass))〃如果注册失败则发

出警告

{MessageBeep(O);

returnFALSE;}

//..........创立窗口.............

hwnd=CreateWindow

(

IpszClassName,〃窗口类名

IpszTitle,〃窗口实例的标题名

WS_OVERLAPPEDWINDOW,〃窗口的风格

CW_USEDEFAULT,

CW_USEDEFAULT,〃窗口左上角坐标为缺省

CW.USEDEFAULT,

CW_USEDEFAULT„〃窗口的高和宽为缺省值

NULL,〃此窗口无父窗口

NULL,〃此窗口无主菜单

hlnstance,〃创立此窗口的应用程序的当前

文档仅供参考,不当之处,请联系改正。一

句柄

NULL〃不使用该值

);

//.........显示窗口...............

ShowWindow(hwnd,nCmdShow);

//.........绘制用户区..............

UpdateWindow(hwnd);

//...........消息循环...............

while(GetMessage(&Msg,NULL,0,0))

(

TranslateMessage(&Msg);

DispatchMessage(&Msg);

)

returnMsg.wParam;〃消息循环结束即程序终止时

将信息返回系统

)

〃窗口函数

LRESULTCALLBACKWndProc

(HWNDhwnd,

UINTmessage,

WPARAMwParam,

LPARAMIParam

文档仅供参考,不当之处,请联系改正。

)

switch(message)

{caseWM_DESTROY:

PostQuitMessage(O);

default:〃缺省时采用系统消息缺省处理函数

return

DefWindowProc(hwnd,message,wParamJParam);

)

return(O);

)

六、绘图函数

在Windows平台下,常见的绘图函数有:

SetPixel:在x,y点画上相应的颜色。例如:

SetPixel(hdc,x,y,crColor),crColor的类型是

COLORREF,COLORREF是一个32位的无符号整数,代

表一种颜色,常见RGB宏来生成颜色。

#defineRGB(r,g,b)((COLORREF)(((BYTE)(r)|\

((WORD)((BYTE)(g))«8))|\

((DWORD)((BYTE)(b))«16)))

文档仅供参考,不当之处,请联系改正。

MoveToEx:把当前点移动到指定点,如

MoveToEx(hdc,xBeg,yBeg,NULL);

LineTo:从当前点画线到指定点,如

LineTo(hdc,xEnd,yEnd);

当要画图时,应在WM_PAINT消息下编写程序:

•••

switch(message)

(

caseWM_PAINT

hdc=BeginPaint(hwnd,&ps);

GetClientRect(hwnd,&rect);

…〃在此添加绘图函数

EndPaint(hwnd,&ps);

return0;

caseWM_DESTROY:

PostQuitMessage(O);

default:〃缺省时采用系统消息缺省处理函数

return

DefWindowProc(hwnd,message,wParamJParam);

)

文档仅供参考,不当之处,请联系改正。

第二章计算机图形学的实验

2.1直线的生成

(-)直线的DDA算法

1、实验目的

(1)熟悉TurboC或在VisualC++开发环境,掌握在

TurboC或在VisualC++环境下进行图形程序设计的

基本方法。

⑵掌握直线的DDA算法

2、实验内容

根据输入的直线的端点坐标画出相应的直线。

3、独立图形运行程序的建立

TurboC对于用initgraph。函数直接进行的图形初

始化程序,

在编译和链接

文档仅供参考,不当之处,请联系改正。

时并没有将相应的驱动程序(*.BGI)装入到执行程序,

当程序进行到intitgraph()

语句时,

再从该函数中第三个形式参数char*path中所规定

的路径中去找相应的

驱动程序。若没有驱动程序,则在C:\TC中去找,

如C:\TC中仍没有或TC不存在,

将会出现错误:

BGIError:Graphics

notinitialized(use'initgraph')

因此,为了使用方便,

应该建立一个不需要驱动程序就能独立运行的可执

图形程序,TurboC中规定用下述步骤(这里以EGA、

VGA显示器为例):

1.在C:\TC子目录下输入命令:BGIOBJEGAVGA

此命令将驱动程序EGAVGA.BGI转换成EGAVGA.OBJ的

目标文件。

2.

在C:\TC子目录下输入命令:TLIB

文档仅供参考,不当之处,请联系改正。

LIB\GRAPHICS.LIB+EGAVGA

此命令的意思是将EGAVGA.OBJ的目标模块装到

GRAPHICS.LIB库文件中。

3.

在程序中initgraph。函数调用之前加上一句:

registerbgidriver(EGAVGA_driver):

该函数告诉连接程序在连接时把EGAVGA的驱动程序

装入到用户的执行程序中。

经过上面处理,编译链接后的执行程序可在任何

目录或其它兼容机上运行。

假设已作了前两个步骤,若再向例6中加

registerbgidriver()函数则变成:

例7:

#include<stdio.h>

#include<graphics.h>

intmain()

文档仅供参考,不当之处,请联系改正。

intgdriver=DETECT,gmode;

registerbgidriver(EGAVGA_driver):/*建立独立

图形运行程序*/

initgraph(gdriver,

gmode,"c:\\tc");

bar3d(50,50,250,150,20,1);

getch();

closegraph();

return0;

)

上例编译链接后产生的执行程序可独立运行。

4、参考程序

这里只给出了实现DDA算法的一个子函数,当上

文档仅供参考,不当之处,请联系改正。

机调试时需根据所选用的编程环境自己来成整个程

序。

#include<gra

phics.h>

#include<ma

th.h>

#include<co

nio.h>

voidLine(int

xO,intyOJnt

x1,inty1,int

value)

{intx;

float

dx,dy,m,y;

dx=x1-x0;

dy=y1-y0;

m=dy/dx;

文档仅供参考,不当之处,请联系改正。

y=yo;

for(x=xO;x<=

x1;x++)

{putpixel(x,(i

nt)(y+0.5),valu

e);

y=y+m;

if(getch()==1

7)exit();

}

}

voidmain()

{int

i,driver,mode;

driver=DETE

CT;

文档仅供参考,不当之处,请联系改正。

registerbgidr

iver(EGAVGA_

driver);

initgraph(&d

river,&mode,M..

Wbgi-);

printf(Mpress

anykeyto

continue

excpefctrl+Q't

oquit.\nM);

Line(100,100

,500,400,15);

closegraphQ

(二)直线的Breshenham算法

1、实验目的

(1)熟悉TurboC或在VisualC++开发环境,掌握在

TurboC或在VisualC++环境下进行图形程序设计的

文档仅供参考,不当之处,请联系改正。

基本方法。

(2)掌握直线的Breshenham算法

2、实验内容

根据输入的直线的端点坐标画出相应的直线。

3、参考程序

这里只给出了实现Breshenham算法的一个子函数,

当上机调试时需根据所选用的编程环境自己来成整

个程序。

voidline(x1,y1,x2,y2,c)

intx1,y1,x2,y2,c;

(

intdx;

intdy;

intx;

inty;

intp;

intconstl;

intconst2;

intinc;

inttmp;

dx=x2-x1;

dy=y2-y1;

if(dx*dy>=0)/*准备x或y的单位递变值。*/

inc=1;

else

inc=-1;

if(abs(dx)>abs(dy)){

if(dx<0){

tmp=x1;/*将2a,3a象限方向*/

x1=x2;/*的直线变换到1a,4a*/

x2=tmp;

tmp=y1;/*象限方向去7

yi=y2;

dx=-dy;

dy=-dy;

}

p=2*dy-dx;

文档仅供参考,不当之处,请联系改正。

const1=2*dy;/*注意此时误差的*/

const2=2*(dy-dy);/*变化参数取值.*/

x=x1;

y=yi;

set_pixel(x,y,c);

while(x<x2){

x++;

if(P<0)

p+=const1;

else{

y+=inc;

p+=const2;

}

set_piexl(x,y,c);

}

}

else{

if(dy<0){

tmp=x1;/*将3b,4b象限方向的

*/

x1=x2;/*直线变换到2b,1b*/

x2=tmp;/*象限方向去.*/

tmp=y1;

yi=y2;

dx=-dy;

dy=-dy;

}

p=2*dx-dy;/*注意此时误差的7

const1=2*dx;/*变化参数取值.

*/

const2=2*(dx-dy);

x=x1;

y=yi;

set_pixel(x,y,c);

while(y<y2){

y++;

if(pvO)

p+=const1;

else{

x+=inc;

p+=const2;

set_pixel(x,y,

c);

}

文档仅供参考,不当之处,请联系改正。一

}

)

2.2区域填充

1、实验目的

(1)熟悉TurboC或在VisualC++开发环境,掌握在

TurboC或在VisualC++环境下进行图形程序设计的

基本方法。

(2)掌握多边形的扫描线算法

2、实验内容

根据输入的多边形的顶点的坐标对输入多边形进

行填色。

3、参考程序

这里只给出了实现扫描线填色算法的子函数,当上

机调试时需根据所选用的编程环境自己来成整个程

序。

typedefstruct{

inty_top;

floatx_int;

intdelta_y;

floaatx_change_per_scan;

}EACH_ENTRY;

EACH_ENTRYSIDES[MAX_POINT];

intx[MAX_POINT],y[MAX_POINT];

intside_count,first_s,last_s,scan,bottomscan,x_int_count,r;

fill_area(count,x,y)

intcount,x[],y[];

(

sort_on_bigger_y(count);

first_s=1;

last_s=1;

for(scan=sides[1].y_top;scan>bottomscan?;scan--)

update_first_and_last(count,scan);

文档仅供参考,不当之处,请联系改正。

process_x_intersections(scan,first_s,last_s);

drawjines(scan,x_int_count,first_s);

update-_sides_list();

}

}

voidput_in_sides_list(entry,x1,y1,x2,y2,next_y);

intentry,x1,y1,x2,y2,next_y;

(

intmaxy;

floatx2_temp,x_change_temp;

x_change_temp=(float)(x2-x1)/(float)(y2-y1);

x2_temp=x2;/*以下为退缩一点操作.*/

if((y2>y1)&&(y2<next_y)){

y2--;

x2_temp-=x_change_temp;

)

else{

if((y2<y1)&&(y2>next_y)){

y2++;

x2_temp+=x_change_temp;

}

}

/*以下为插入活性表操作.*/

maxy=(y1>y2)?y1:y2;

while((entry>1)&&(maxy>sides[entry-1].y_top))

(

sides[entry]=sides[entry?];

entry-

}

sides[entry].y_top=maxy;

sides[entry].delta_y=abs(y2-y1)+1;

if(yi>y2)

sides[entry].xjnt=x1;

else{

sides[entry].x_int=x2_temp;

sides[entry].

x_change_per_scan=x_change_temp;

}

voidsort_on_bigger_y(n)

intn;

(

intk,x1,y1;

side_count=0;

yi=y[n];

文档仅供参考,不当之处,请联系改正。

x1=x[n];

bottomscan=y[n];

for(k=1;k<n+1;k++)

(

if(yi!=y[k]){

side_count++;

put_in_sides_list(side_count,x1,y1,

x[k],y[k]);

}

else{

move((short)xl,(short)yl);

line((short)x[k],(short)yl,status);

}

if(y[k]<bottomscan)bottomscan=y[k];

y1=y[k];x1=x[k];

}

}

voidupdate_first_and_last(count,scan)

intcount,scan;

(

while((sides[last_s+1].y_top>=scan)&&(last_s

<count))last_s++;

while(sides[first_s].delta_y==0)first_s++;

}

voidswap(x,y)

EACH_ENTRYx,y;

(

inti_temp;

floatf_temp;

i_temp=x.y_top;x.y_top=y.y_top;y.y_top=i_temp;

f_temp=x.x_int;x.x_int=y.x_int;y.x_int=f_temp;

i_temp=x.delta_y;x.delta=y.delta_y;y.delta_y=i_temp;

f_temp=x.x_change_per_scan;x.

x_change_per_scan=y.x_change_per_scan;y.x.

change_per_scan=f_temp;

}

voidsort_on_x(entry,first_s)

intentry,first_s;

(

while((entry>first_s)&&(sides[entry].xjntv

sides[entry-1].xjnt))

文档仅供参考,不当之处,请联系改正。

swap(sides[entry],sides[entry-1]);

entry-

}

}

voidprocess_x_intersections(scan,first_s,last_s)

intscan,first_s,last_s;

(

intk;

x_int_cout=0;

for(k=first_s;k<last_s+1;k++)

(

if(sides[k].delta_y>0){

x_int_count++;

sort_on_x(k,first_s);

}

}

}

voiddraw_lines(scan,x_int_count,index)

intscan,x_int_count,index;

(

intk,x,x1,x2;

for(k=1;k<(int)(x_int_count/2+1.5);k++)

(

while(sides[index].delta_y==0)index++;

x1=(int)(sides[index].x_int+0.5);

index++;

while(sides[index].delta_y==0)index++;

x2=(int)(sides[index].xjnt+0.5);

move((short)x1,(short)scan);

Iine((short)x2,(short)scan,status);

index++;

}

}

voidupdate_sides_list()

(

intk;

for(k=first_s;k<last_s+1;k++)

(

if(sides[k].delta_y>0)

sides[k].delta_y-

文档仅供参考,不当之处,请联系改正。

sides[k].x_int-=sides[k].

x_change_per_scan;

}

}

}

2.3直线的裁剪

1、实验目的

(1)熟悉TurboC或在VisualC++开发环境,掌握在

TurboC或在VisualC++环境下进行图形程序设计的

基本方法。

(2)掌握Cohen-Suther1and直线裁剪算法

2、实验内容

输入多边形顶点的坐标和待裁剪的直线的端点坐

标,由多边形对直线进行裁剪。

3^参考程序

这里只给出了实现Cohen-Sutherland直线裁剪算

法的子函数,当上机调试时需根据所选用的编程环境

自己来成整个程序。

clip_a_line(x1,y1,x2,y2,xw_min,xw_max,yw_min,yw_max)

intx1,x2,y1,y2;xw_min,xw_max,yw_min,yw_max;

(

inti,codel[4],code2[4],done,display;

floatm;

intx11,x22,y11,y22,mark;

done=0;

display=0;

while(done==0)

(

x11=x1;x22=x2;y11=y1;y22=y2;

encode(x1,y1,codel,xw_min,xw_max,yw_min,

yw_max);

文档仅供参考,不当之处,请联系改正。

encode(x2,y2,code2,xw_min,xw_max,yw_min,

ywmax);

if(accept(code1,code2))

(

done=1;

display=1;

break;

}

else

if(reject(codel,code2))

(

done=1;

break;

}

mark=swap_if_needed(code1,code2);

if(mark==1)

(

x1=x22;

x2=x11;

y1=y22;

y2=y11;

}

if(x2==x1)m=-1;

else

m=(fIoat)(y2-y1)/(float)(x2-x1);

if(codel[0])

(

x1+=(yw_min-y1)/m;

y1=yw_min;

}

elseif(code1[1])

(

x1-=(y1-yw_max)/m;

y1=yw_max;

}

elseif(code1[2])

(

y1-=(x1-xw_min)*m;

x1=xw_min;

}

elseif(code[3])

(

y1+=(xw_max-x1)*m;

x1=xw_max;

文档仅供参考,不当之处,请联系改正。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论