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

下载本文档

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

文档简介

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

计算机图形学中的程序都是用C语言编写的,TurboC和VisualC++常见的两种C涪言开发环境,

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

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

一些高级语言都扩充了图形功能,这使得用户可以不需配备专门的图形软件,就能在计算机上进

行图形工作。TurboC2.0包含有460多个库函数,其中有70多个图形函数,这些函数包括了绘图、

处理图象及图素、屏幕及视图区控制、颜色及线型设置、状态查询和出错处理等,这使得TurboC具

有很强的图形功能。

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

IBMPC机的显示器可以在两种基本视频方式下工作:一种是文本方式;另一种是图形方式。

(1)文本方式

在文本方式下,屏幕上可以显示的最小单位是字符,字符在屏幕上以行、列排列,即我们通常见

到的情况。文本方式不同,屏幕上所显示字符的行数和列数也不一样,颜色也会有所区别。TurboC支

持6种不同的文本显示方式。

(2)图形方式

在图形方式下,屏幕上可以控制的最小单元称作像素(pixel),它是组成图形的基本元素,

一般叫作“点”。通常把屏幕上所包含像素的个数叫做分辨率。分辨率越高,显示的图形越细致、质

量越好,这是显而易见的。在图形方式卜,屏幕上每个像素的、显示位置用点坐标系来描述。在该坐标

系中,屏幕左上角为坐标系的原点,坐标值为(0,0);水平方向为X轴,自左向右;垂直方向

为Y轴,自上向下。见下图。

(0f0)XmaxX

Y

fmaxY

点坐标系中坐标值的范围决定于所用显示器的分辨率。分辨率不同,水平方向上和垂直方向上的

点数也不同,即其maxx、maxy的数值不同。就我们常用的VGA显示器来说,它通常所用的分辨

率为6405480,即它的maxx值为639,maxy的值为479。

2.图形函数及其用法

TurboC的图形函数均在一个头文件“graphics』”中定义。所以,凡是在程序中要调用这些

图形函数,都必须在源程序的开头写上文件包含命令:

#include<graphics.h>

(1)图形系统管理

在一般默认情况下,显示器处于文本方式下。在文本方式下,所有的图形函数均不能应用。因此

在调用图形函数绘图之前,必须先将显示器设置为图形模式,这就是通常所说的图形方式初始化。在

图形工作完毕之后,又要使显示器回到文本方式,以便进行程序文件等的编辑工作。

•图形方式初始化

图形方式初始化通过函数initgraph来实现,它的功能是通过从磁盘上装入一个图形驱动程序

来初始化图形系统,并将系统设置为图形模式。其调用格式为:initgraph(int*gdriver,int

*gmodc,char*path);

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

gdrivcr:是一个整型值,用来指定装入的驱动程序名。

gmode:是一个整型值,用来设置图形显示模式。path:是一个字符串,用来指明强动程序所在的

路径。

举例:假设使用VGA显示器,图形显示模式为VGAHI,即高分辨率图形模式,分辨率为640548()。

则初始化调用方式如下:

intgdriver=VGA,gmode=VGAHI;

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

・关闭图形模式

在运行图形程序结束后,应及时关闭图形模式,回到文本方式,以进行其他工作。关闭图形模式

用函数closegraph,其调用方法为:

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

(2)绘图函数

从理论上来说,用像素点儿乎可以画出任何图形,但毕竟是效率太低。为此,TurboC的BGI提

供了一些基本的绘图函数,以方便图形设计。所有绘图附数调用时的参数,其类型均为整型,因此填

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

putpixel函数:将指定的颜色写到由坐标x,y所确定的点。如pulpixel(x,y,GREEN);

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

Iineto函数:从当前点画线到指定点。如:lineto:x,y);

moveto函数:把当前点移到指定点(不画线)。如:noveto(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函数:设置背景颜色。如:setbkcolorICOLORNAME);

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

setIinestyIe函数:设置线型。如:set!inestyle(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

的规范部件:窗II、菜单、按钮、对话框、程序模块都是对象。编写Windows程序相当一部分工作是

在创建对象和为对象属性赋值。对象具有规范形态和操作模式的特征。

在用vc进行编程时有两种方法:传统的编程方法方法和交互式编程方法。传统的编程方法是采用

直接调用API的方法进行编程,API是Win系统与Win应用程序间的标准程序接口,API为应用程序

提供Windows系统特殊函数及数据结构,并且Win应用程序可以利用标准大量API函数调用系统功能。

API函数的功能包括:窗口管理函数实现窗口的创建、移动和修改功能;系统服务函数:实现与操作

系统有关的多种功能;图形设备(GDI)函数:实现与设备无关的图形操作功能。交互式编程方法是采

用MFC的方法进行编程。采用交互式方法时,可视化开发平台给出了许多选用的对象,程序员可选择

所需对象并确定其属性,由此搭建起应用程序的“大框架”,并可根据需要进一步编写必要的细节代

码段,最后构成完整的应用程序。

利用WindowsAPI函数编写Windows应用程序必须首先了解以下内容:

(1)窗口的概念

(2)事件驱动的概念

(3)句柄

(4)消息

⑴窗口

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

最大化按钮

控制菜单框文坤a)・他印a图电)MA,O)格式@工及s

幻灯片断,Q)9口”助qp

下拉菜单最小化按钮

HfilD

标题栏

••元.9MMM星Q2

由/公a、

・个I・,个・吊3d

工作区ttaxaoim.系统ui

・打・”•liM

垂直滚动条

水平滚动条

制处理消息,控制通知消息,滚动条通知消息,非用户区消息,MDI消息,DDE消息,应用程序自定

义的消息。

二、Windows应用程序常用消息

1.WM_LBUTTONDOWN:产生单击鼠标左键的消息。IParam:低字节包含当前光标的X坐标值高字节包

含当前光标的Y坐标值;wParam包含一整数值以标识鼠标键的按下状态;MKLBUTTON按下鼠标左

键,MKJIBUTTON按下鼠标中键,MK_RBUTTON按下鼠标右键.此外,相似的消息还有:

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

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

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

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

WM_RBUTTONDBLCLK:双击鼠标右键时产生

2.WM_KEYDOWN:按下•个非系统键时产生的消息。系统键是指实现系统操作的组合键,例如Alt与

某个功能键的组合以实现系统菜单操作等。wParam:按下键的虚拟键码,用以标识按下或释放的键(如

F1的虚拟键码在Windows」文件中定义为VKFl):IParam:记录了按键的重复次数、扫描码、转移

代码、先前键的状态等信息。

相似的消息还有WM_KEYUP,在放开非系统键时产生

3.WM_CHAR:按卜一个非系统键时产生的消息。WParam:为按键的ASCII码;IParam:与WM_KEYDOWN

的相同。

4.WM_CREATE:由CreateWindow函数发出的消息。wParam:未用;IParam:包含•个指向CREATESTRUCT

数据结构的指针。

5.WM_CL0SE:关闭窗口时产生的消息。wParam和IParam均未用。

6.WM_DESTROY:由DcstroyWiodow函数发出的消息。wParam和IParam均未用。

7.WM_QUIT:由PostQuilMessage函数发出的消息,退出应用程序时发出的消息。wParam:含退出代

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

8.WM.PAINT:以下情况时将产生WM_PAINT消息。用户区移动或显示,用户窗口改变大小,程序通过

滚动条滚动窗口,下拉式菜单关闭并需要恢复被覆盖的部分,Windows清除对话框等对象,并需要恢

复被覆盖的部分均产生WV_PAINT消息。

HWindows中的事件驱动程序设计

过程驱动程序设计和事件驱动程序设计的区别如下图:

沸驱动雄计算平均竭

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

1.应用程序的组成

•个完整的Windows应用程序通常由五种类型的文件组成。

LC语言源程序文件

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是多任务管理的,同一应用程序的多个窗口可能会同时存,*in系统对每个窗II的执行称为

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

⑵初始化

初始化包括四个步骤。窗口类的定义:定义窗口的形式与功能;窗口类的注册:窗口类必须先注册

后使用;创建窗口实例;显示窗口。

(a)窗口类定义

通过给窗口类数据结构WNDCLASS赋值完成,该数据结构中包含窗口类的各种属性。窗口类定义常用

以下函数:

Loadicon:作用是在应用程序中加载一个窗口图标。其原型为:

HICONLoadicon(HINSTANCEhlnstance,//hlnstance图标资源所在的模块句柄,NULL则使用系统预

〃定义图标,

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

LoadCursor:作用是在应用程序中加载一个窗I」光标。其原型为:

HCURSORLoadCursor(HINSTANCEhlnstance,//hlnstance光标资源所在的模块句柄,NULL则使用系

〃统预定义光标

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

〃名

GctStockObject:作用是获取系统提供的背景刷,其原型为:

HBRUSHGetStockObject(intnBrush)://nBrush刷子的类型

(b)注册窗口类

Win系统本身提供部分预定义的窗口类,程序员也可以自定义窗口类,窗口类必须先注册后使用。

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

RegisterClass(&wndclass);//wndclass为窗口类结构RegisterClass函数的返回为布尔值,注

〃册成功则返回真

(C)创建窗口实例

创建一个窗口类的'实例由函数CreateWindow()实现,函数原型如下:

HWNDCroateWindow

(LPCTSTRIpszClassName,〃窗口类名

LPCTSTRIpszTitle,〃窗口标题名

DWORDdwStyle,〃创建窗口的样式

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

intnWidth,nlleight.〃窗口宽度和度高

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

HWENUhMcnu,〃窗口主菜单句柄

HINSTANCEhlnstance,〃创建窗口的应用程序当前句柄

LPVOIDIpParam〃指向一个传递给窗口的参数值的指针

)

常用窗口样式

few说明

WS_BORDER创信一带边框的窗口

WSCAPTION包犍一用标题栏的窗口

WS_VSCROLL创犍一带垂直濠动条的窗口

WS_MAXIMIZEBOX包健一带最大化框的窗口

WS_MAXIMIZE色犍一最大尺寸的窗口

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

WS_MINIMIZE创康一最小尺寸的窗口

WS_OVERLAPPED您犍一带边框和标题的窗口

WS_OVERLAPPEDWINDOW自犍一带边框、标题栏、系统菜单及最大、

最小化糖的窗口

WS_POPUP包犍一弹出式窗口

WS_POPUPWINDOW包犍一带边框和系统菜单的弹出式窗口

WS_SYSMENU打犍一带系统菜单的曾口

WS_HSCROLL创屣一带水平滚动条的菜单

(d)显示窗口

窗口类的显示由ShowWindow和UpdateWindow函数实现。应用程序调用ShowWindow函数在屏幕上

显不窗口:

ShowWindow(hwnd,nCmdshow);//nCmdshow为窗口显示形式标识

sw_HIDE隐意窗口

sw_SHOWNORMAL显示并激活窗口

sw_SHOWMINIMIZE显示并最小化窗口

sw_SHOWMAXMIZE显示并最大化窗口

sw_«HOWNOACTIVE显示但不激活窗口

sw.RESTORE恢复窗口的原来位置及尺寸

显示窗口后,应用程序调用UpdateWindow更新并绘制用户区,并发出WM/AINT消息。

UpdatcWindow(hwnd);

(3)消息循环

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

将消息传递给

窗口函数的相

Windo”不将

产生的消息

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

MSGMsg;

while(GetMessage(&Msg,NULL,0,0))〃从消息队列中读取一条消息,并将消息放在MSG结构中

{TranslateMcssage(&Msg);//将消息的虚拟键转换为字符信息

DispeitchMessage(&Msg);"/将消息传送到指定窗口函数

其中函数GetMessage形式为:

GetMessage

IpMSG,〃指向MSG结构的指针

hwnd,

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

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

)

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

2.窗口函数WinProc

WinProc定义了应用程序对接收到的不同消息的响应,包含了对各种可能接收到的消息的处理过程。

WinProc函数由一个或多个switch语句组成。每一条case语句对应一种消息,当应用程序接收到一

个消息时,相应的case语句被激活并执行相应的响应程序模块。

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

LRESULTCALLBACKWndProc(HWNDhwnd,LINTmessgae,WPARAMwParam,LPARAMIParam)

{…

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

{case•••

•••

break;

caseWMDESTROY:

PostQuitMessage(0);

default:

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

)

return(0);

}

在消息处理程序段中一般都有对WM_DESTROY的处理,该消息是关闭窗口时发出的。它向应用程序发

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

voidPostQuitMcssage(intnExitCode)〃nExitCodc为应用程序的退出,为未定义处理过程的

〃消息提供缺省处理

3.数据类型

在Windows』中定义了Windows应用程序中包含种类繁多的数据类型

则频说明

WORD16位无符号整数

LONG32位有符号整数

DWORD32位无符号整数

HANDLE句柄

VINT32位无符号整数

BOOL布尔值

LPTSTR指向字符串的32位指针

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

4.一些重要的数据结构

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

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

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

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

五、应用程序

【例2-1】创建应用程序框架。本例的FI的在于说明创建Windows应用程序的方法及过程,程序的效

果如下图所示。

#include<windows.h>//包含应用程序中所需的数据类型和数据结构的定义

LRESULTCALLBACKWndProc(HWND.UINT,WPARAM,LPARAM);〃窗口函数说明

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

intWINAPIWinMain(HINSTANCEhlnstance,

H1NSTANCEhPrcvInst,LPSTRIpszCmdLnCmdShow)

HWNDhwnd;

MSGMsg;

WNDCLASSwndclass;

charIpszClassName」="窗口";〃窗口类名

charlpszTitle[]="My_Windo\vs";〃窗口标题名

〃窗口类的定义

wndclass.style=O;〃窗口类型为缺省类型

wndclass.lpfnWndProc=WndProc;〃定义窗口处理函数

wndclass.cbClsExtra=O;〃窗口类无扩展

wndclass.cbWndExtra=O;〃窗口实例无扩展

wndclass.hlnstance=hlnslance;〃当前实例句柄

wndclass.hIcon=LoadIcon(NULLJDI_APPLICATION);〃窗口的最小化图标为缺省图标

wndclass.hCursor二LoadCursor(NULL,IDC_ARROW);〃窗口采用箭头光标

wndclass.hbrBackground=GetStockObject(WHITE_BRUSH);//窗口背景为白色

wndclass.lpszMcnuNamc=NULL;//窗II中无菜单

wndclass.lpszClassName=lpszClassName;〃窗口类名为"窗口"

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

if(!RegisierClass(&wndclass))〃如果注册失败则发出警告

{MessageBeep(O);

returnFALSE;}

//-----------创建窗口

hwnd=CrcateWindow

IpszClassName,〃窗口类名

IpszTitle,〃窗口实例的标题名

WS_OVERLAPPEDWINDOW,〃窗口的风格

C\V_USEDEFAULT,

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

CWJJSEDEFAULT,

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

NULL,〃此窗口无父窗口

NULL,〃此窗口无主菜单

hlnstance,〃创建此窗口的应用程序的当前句柄

NULL//不使用该值

);

//----------显示窗口-

ShovvWindow(hwnd,nCmdShow);

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

UpdateWindow(hwnd);

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

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

{

TranslatcMcssagc(&Msg);

DispatchMessage(&Msg);

I

returnMsg.wParam;〃消息循环结束即程序终止时将信息返回系统

I

〃窗口函数

LRESULTCALLBACKWndProc

(HWNDhwnd,

UINTmessage,

WPARAMwPaiam,

LPARAMIParam

switch(message)

{caseWM_DESTROY:

PostQuitMessage(O);

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

returnDef'Windo\vProc(hwnd,message,wParani,IParam);

relurn(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,xBcg,yBcg,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:

PostQuitMessageiO);

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

returnDefWindowProc(hwnd.message,wParamJParam);

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

2.1直线的生成

(-)直线的DDA算法

1、实验目的

(1)熟悉TurboC或在VisualC++开发环境,掌握在TurboC或在VisualC++环境下正行图形程序设

计的基本方法。

(2)掌握直线的DDA算法

2、实验内容

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

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

TurboC对于用initgraphO函数直接进行的图形初始化程序,

在编译和链接

时并没有将相应的驱动程序装入到执行程序,当程序进行到intitgraphO

语句时,

再从该函数中第三个形式参数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子目录下输入命令:TLIBLIB\GRAPHICS.LIB+EGAVGA

此命令的意思是将EGAVGA.OBJ的目标模块装到GRAPHICS.LIB库文件中。

3.

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

registei'bgidriver(EGAVGA_driver):

该函数告诉连接程序在连接时把EGAVGA的驱动程序装入到用户的执行程序中。

经过上面处理,编译链接后的执行程序可在任何目录或其它兼容机上运行。

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

registerbgidriver()函数则变成:

例7:

#include<stdio.h>

#include<graphics.h>

intmain()

(

intgdrivor=DETECT,gmodc;

registerbgidriver(EGAVGA_driver):/*建立独立图形运行程序*/

initgraph(gdriver,

gmode,〃c:\\tc");

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

getch();

closegraph();

return0;

)

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

4、参考程序

这里只给出了实现DDA算法的一个子函数,当上机调试时需根据所选用的编程环境自己来成整个

程序。

#include<graphics.h>

#include<math.h>

#include<conio.h>

voidLine(intxO,intyO,intx1,irty1,intvalue)

{intx;

floatdx,dy,m,y;

dx=x1-x0;

dy=y1-yO;

m=dy/dx;

y=yo;

for(x=xO;x<=x1;x++)

{putpixel(x,(int)(y+0.5),value);

y=y+m;

if(getch()==17)exit();

)

)

voidmain()

{inii,driver,mode;

driver=DETECT;

registerbgidriver(EGAVGA_driver);

initgraph(&driver,&mode,"..\\bgi");

printf("pressanykeytocontinueexcpet'ctrl+Q'to

quitAn");

Line(100,100,500,400,15);

closegraph();

)

(二)直线的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;/*的直线变换至ij1a,4a*/

x2=tmp;

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

y1=y2;

dx=-dy;

dy=-dy;

)

p=2*dy-dx;

constl=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;/*直线变换至U2b,1b*/

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

tmp-y1;

yi=y2;

dx="dy;

dy=-dy;

)

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

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

const2=2*(dx-dy);

x=x1;

y=yi;

set_pixel(x,y,c);

while(y<y2){

y++;

if(P<0)

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;

floatxjnt;

intdelta_y;

floaatx_changejDer_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();

)

)

voidputjn_sid9sjist(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++;

putjn_sidesjist(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];

yi=y[k];xi=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.xjnt;x.xjm=y.xjnt;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].xjnt<

sides[entry-1].xjnt))

{

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

entry-

)

)

voidprocess_x_intersections(scan,firsts,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,xjnt_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].xjnt+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].xjnt-=sides[k].

x_change_per_scan;

)

)

)

2.3直线的裁剪

1、实验目的

(1)熟悉TurboC或在VisualC++开发环境,掌握在TurboC或在VisualC++环境下正行图形程序设

计的基本方法.

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

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,code1[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,xwmin,xwmax,ywmin,

yw_max);

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

yw_max);

if(accept(code1,code2))

{

done=1;

display=1;

break;

)

else

if(reject(codel,code2)i

{

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=(float)(y2-yl)/(float)(x2-x1);

if(codel[0])

(

x1+=(yw_min-y1)/m;

y1=yw_min;

)

elseif(codel[1])

(

x1-=(y1-yw_maxi/m;

y1=yw_max;

)"

elseif(codel[2])

(

y1-=(x1-xw_min)*m;

x1=xwmin;

)

elseif(code[3])

温馨提示

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

评论

0/150

提交评论