计算机图形学综合实验设计
——用 C 语言实现画图板的功能
学 院:信息管理学院
专 业:计算机科学与技术
姓 名:赵 某某
学号:****08030132
计算机图形学综合实验设计
————画图板
Windows 系统自带的画图板简单灵巧,为用户的小型图形开发工作带来了很多便利。本
实验完全利用 C 语言开发了一个画图板,该画图板具有画图、调整图形大小与方位、保存
与打开文件等基本图能。
一.设计目的
利用 C 语言完成了一个 Windows 应用程序的开发——画图板,该画图板能实现基本的
图形操作功能。通过本次实验,应该了解怎么将像素写入文件、怎么从文件中读取像素;了
解直线、矩形、圆和 Bezier 曲线等图形的绘制原理、旋转原理、移动院里和缩放原理等。
二.功能描述
本实验利用 C 语言编程实现的画图板,具有基本的画图功能、图形操作功能和文件保
存打开功能等。
1)图形绘制功能
(1)绘制直线:能绘制任意角度的直线,能实现直线的旋转、伸长、缩短和上下左右
移动。
(2)绘制矩形:能绘制任意大小(画布范围内)的矩形,能实现矩形的放大、缩小和
上下左右移动。
(3)绘制圆形:能绘制任意半径大小(画布范围内)的圆形,能实现圆形的放大和缩
小。
(4)绘制 Bezier 曲线:能根据屏幕上的点(单击鼠标后产生的点)绘制出 Bezier 曲线。
2)文件处理功能
(1)保存:能保存画布中的所有图形到指定的文件。
(2)加载:能打开指定的文件,将其内容加载到画布中。
3)用户帮助功能
显示用户使用指南,包括各种图形的绘制方法和操作方法等。
三. 总体设计
1. 系统模块图
本系统包括 4 个模块,分别是图形绘制模块、鼠标控制模块、功能控制模块和保存加载
模块.
(1)图形绘制模块。该模块包括图形的绘制和操作功能,主要有绘制直线、移动直线、
缩放和旋转直线;绘制矩形、移动和缩放矩形;绘制和缩放圆形;绘制 Bezier 曲线。
(2)鼠标控制模块。该模块主要实现鼠标状态的获取、鼠标位置的设置,以及鼠标
的绘制等。
(3)功能控制模块。该模块实现的功能包括输出中文、填充像素和显示用户帮助。
(4)保存加载模块。该模块将像素保存到指定文件和从指定文件中读取像素到画
布。
2.数据结构设计
● int Rx,Ry,R:分别表示所画圆形的圆心的横坐标、纵坐标,以及圆的半径。
● int TOPx,TOPy,BOTTOMx,BOTTOMy:分别表示所画矩形的左上角的横坐标、纵坐标,
以及右下角的横坐标、纵坐标。
● int Centx,Centy:表示直线或者矩形旋转中心点的横坐标和纵坐标。
● int lineStartx,lineStarty,lineEndx,lineEndy:分别表示直线的起点横坐标、纵
坐标,以及终点的横坐标、纵坐标。
● int linePoint_x[20],linePoint_y[20]:这两个数组用于在画 Bezier 曲线时存储
所选点的横坐标和纵坐标。
3.函数功能描述
1) outChinese()
函数原型: void outChinese(char*mat,int x,int y,int color)
本程序中虽然有中文显示,但是显示的中文不多,所以就没有加载中文字库,而是生
成字模信息来建立一个小型字库,以此来减轻程序“负担” 。
outChinese()函数根据点阵信息显示中文,其中 mat 为字模指针,matisize 为点阵
大小,x 和 y 表示起始坐标,color 表示显示的颜色。
2) fill()
函数原型: void fill(int startx,int starty,int endy, int color)
Fill()函数用于以指定的颜色填充指定的区域。其中 startx、starty 表示填充区域
的左上角横、纵坐标,endx、endy 表示填充区域的右下角的横、纵坐标,color 表示填充
的颜色。该函数调用系统画图函数 putpixel()来实现。
3) showHelp()
函数原型:void showHelp()
showHelp()函数用于显示用户使用指南。用户使用指南包括各种图行的绘制方法和调
整方法等。
4) save()
函数原型:void save()
Save()函数用于保存画布中的图形。用户首先输入保存文件的文件名,然后将画布中
的像素写入文件,保存文件是以“.dat”结尾的。保存完毕将提示用户。
5)
函数原型: void load()
load()函数用于打开已有的图形。用户首先输入打开文件的文件名,然后将文件中的
像素输入到画布中。打开完毕将提示用户。如果打开过程中出现错误,如没有找到指定的文
件等,也将显示错误信息。
6) mouseStatus()
函数原型: int mouseStatus(int*x,int*y)
mouseStatus()函数用于获取鼠标的状态,包括鼠标指针所处的横坐标、纵坐标,以
及鼠标的按键情况。中断的入口参数 AH 为 03H,出口参数 BH 表示鼠标按键状态,位 0 为 1
表示按下左键,位 1 为 1 表示按下右键,位 2 为 1 表示按下中键;CX 表示水平位置,DX 表
示垂直位置。函数中传递的指针参数 x、y 分别用来接收鼠标指针的水平位置和垂直位置。
7)setMousePos()
函数原型:int setMosePos(int x,int y)
setMousePos()函数用来设置鼠标的位置。X、y 分别表示预设置的横坐标和纵坐标。
这里中断的入口参数 AH 为 1,分别把 x 和 y 赋给寄存器 CX 和 DX。
8)DrawMouse()
函数原型:voidDrawMouse(float x,float y)
DrawMouse()函数用于绘制鼠标。X、y 分别表示鼠标指针所处的位置。
9)DrawLine()
函数原型:void DrawLine()
DrawLine()函数用于绘制直线。单击鼠标左键,捕获鼠标指针位置,并以此为起点开
始画直线,拖动鼠标,松开鼠标结束绘制。然后可以通过键盘来调整直线的位置、大小等。
10) DrawRectangle()
函数原型:void DrawRectangle()
DrawRectangle()函数用于绘制矩形。其绘制方法与直线的绘制方法一致。
11)LineToCircle()
函数原型:void LineToCircle(int x0,int y0,int r)
LineToCircle()函数实现的是直线法生成圆。x0、y0 表示圆心,r 表示半径。直线法
生成圆的相关知识读者可查阅图形学资料。
12)DrawCircle()
函数原型:void DrawCircle()
DrawCircle()函数实现的是画圆功能,该函数是调用 LineToCircle()函数来实现的。
13)factorial()
函数原型:void factorial(int n)
factorial()函数用于求阶乘,n 表示需要求阶乘的函数。求阶乘的方法很多,本程
序中使用的是比较原始的方法,即从 n 依次乘到 1,也可以用递归来实现,读者可以自行设
计。
14)berFunction()
函数原型:float berFunction(int I,int n,double t)
berFunction() 函 数 是 伯 恩 斯 坦 基 函 数 的 计 算 , 该 函 数 调 用 了 前 面 的 阶 乘 函 数
factorial().
15)DrawBezier()
函数原型:void DrawBezier()
DrawBezier() 函数实现画 Bezier 曲线,该函数调用了 berFunction()函数。Bezier
曲线的绘制涉及到数学知识,读者可查阅相关资料。
4.程序实现
4.1 预处理
程序预处理包括头文件的加载、常量的定义和全局变量的定义,以及点阵字模的定义。
#include
#include
#include
#include
#include
#include
#include
#include
/*定义常量*/
/*向上翻页移键*/
#define PAGEUP 0x4900
/*向下翻页移键*/
#define PAGEDOWN 0x5100
/*Escape 键*/
#define ESC 0x011b
/*左移键*/
#define LEFT 0x4b00
/*右移键*/
#define RIGHT 0x4d00
/*下移键*/
#define DOWN 0x5000
/*上移键*/
#define UP 0x4800
/*空格键*/
#define SPACE 0x3920
#define
#define
#define
#define
0
NO_PRESSED
LEFT_PRESSED
1
RIGHT_PRESSED 2
pi
3.1415926
/*定义全局变量*/
int Rx,Ry,R;
int TOPx,TOPy,BOTTOMx,BOTTOMy;
int Centx,Centy;
int lineStartx,lineStarty,lineEndx,lineEndy;
int linePoint_x[20],linePoint_y[20];
/*这里的字模数组均由“点阵字模工具”生成,你可以用你自己需要的点阵信息来
替换示例中的字模信息,注意字模大小要一致,否则显示会出问题。*/
char zhi16K[]={
/* 以下是 '直' 的 16 点阵楷体_GB2312 字模,32 byte */
0x01,0x00,0x01,0x00,0x01,0xF0,0x1E,0x00,
0x02,0x00,0x07,0xC0,0x08,0x40,0x0F,0x40,
0x08,0x40,0x0F,0x40,0x08,0x40,0x0F,0x40,
0x08,0x40,0x0F,0xFC,0x70,0x00,0x00,0x00,
};
char xian16K[]={
/* 以下是 '线' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x80,0x00,0x90,0x08,0x88,0x10,0x80,
0x24,0xF0,0x45,0x80,0x78,0xB0,0x11,0xC0,
0x2C,0x88,0x70,0x50,0x04,0x60,0x18,0xA4,
0x63,0x14,0x00,0x0C,0x00,0x04,0x00,0x00,
};
char ju16K[]={
/* 以下是 '矩' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x00,0x08,0x00,0x08,0x78,0x10,0x80,
0x1E,0x80,0x28,0xF8,0x48,0x88,0x0E,0x88,
0xF8,0xF0,0x08,0x80,0x14,0x80,0x12,0x9E,
0x20,0xE0,0x40,0x00,0x00,0x00,0x00,0x00,
};
char xing16K[]={
/* 以下是 '形' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x00,0x07,0x88,0x3A,0x08,0x12,0x10,
0x12,0x20,0x17,0x48,0xFA,0x10,0x12,0x20,
0x12,0xC8,0x12,0x08,0x22,0x10,0x42,0x20,
0x00,0x40,0x00,0x80,0x03,0x00,0x00,0x00,
};
char yuan16K[]={
/* 以下是 '圆' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0xF8,0x3F,0x08,0x23,0x88,0x24,0x88,
0x27,0x08,0x21,0xC8,0x2E,0x48,0x29,0x48,
0x29,0x48,0x22,0x88,0x24,0x48,0x28,0x08,
0x3F,0xE8,0x00,0x10,0x00,0x00,0x00,0x00,
};
char qing16K[]={
/* 以下是 '清' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x80,0x00,0xE0,0x33,0x80,0x10,0xE0,
0x03,0x80,0x40,0xFC,0x2F,0x00,0x01,0xE0,
0x12,0x20,0x13,0xA0,0x22,0x20,0x63,0xA0,
0x42,0x20,0x02,0x60,0x00,0x20,0x00,0x00,
};
char ping16K[]={
/* 以下是 '屏' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0xF0,0x0F,0x30,0x08,0x60,0x0F,0x80,
0x0A,0x20,0x09,0x40,0x08,0xF8,0x17,0x20,
0x11,0x3E,0x2F,0xE0,0x21,0x20,0x42,0x20,
0x82,0x20,0x04,0x20,0x08,0x20,0x00,0x00,
};
char bao16K[]={
/* 以下是 '保' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x00,0x09,0xF0,0x0A,0x10,0x12,0x10,
0x13,0xE0,0x30,0x80,0x50,0xFC,0x9F,0x80,
0x11,0xC0,0x12,0xA0,0x14,0x98,0x18,0x8E,
0x10,0x80,0x10,0x80,0x00,0x00,0x00,0x00,
};
char cun16K[]={
/* 以下是 '存' 的 16 点阵楷体_GB2312 字模,32 byte */
0x01,0x00,0x01,0x00,0x01,0xF0,0x1E,0x00,
0x02,0x70,0x05,0x90,0x08,0x20,0x08,0x40,
0x18,0x7E,0x2B,0xA0,0xC8,0x20,0x08,0x20,
0x08,0x20,0x08,0xA0,0x00,0x40,0x00,0x00,
};
char jia16K[]={
/* 以下是 '加' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
0x0F,0x00,0x79,0x3C,0x09,0x44,0x11,0x44,
0x11,0x44,0x22,0x44,0x22,0x78,0x4A,0x00,
0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
char zai16K[]={
/* 以下是 '载' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x80,0x08,0xA0,0x08,0x90,0x0E,0x80,
0x38,0xF0,0x0F,0x80,0x78,0x50,0x0E,0x50,
0x34,0x20,0x1E,0x20,0x34,0x50,0x0E,0x92,
0x75,0x0A,0x04,0x06,0x04,0x02,0x00,0x00,
};
char bang16K[]={
/* 以下是 '帮' 的 16 点阵楷体_GB2312 字模,32 byte */
0x04,0x00,0x07,0x38,0x1C,0x48,0x06,0x50,
0x1C,0x50,0x07,0x48,0x78,0x58,0x11,0x40,
0x21,0xF0,0x4F,0x10,0x09,0x10,0x09,0x50,
0x09,0x20,0x01,0x00,0x01,0x00,0x00,0x00,
};
char zhu16K[]={
/* 以下是 '助' 的 16 点阵楷体_GB2312 字模,32 byte */
0x00,0x00,0x00,0x20,0x0C,0x20,0x34,0x20,
0x24,0x20,0x34,0x38,0x25,0xC8,0x34,0x48,
0x24,0x48,0x26,0x88,0x38,0x88,0xE1,0x28,
0x02,0x10,0x04,0x00,0x00,0x00,0x00,0x00,
};
4.2 控制模块
功能控制模块主要实现根据点阵信息显示中文功能、填充屏幕功能和显示用户指南功能,
分别由函数 outChinese()、fill()和 showHelp()来实现。
(1)
(2)
(3)
void outChinese(char*mat,int matsize,int x,int y,int color),根据
定义的点阵字模数组显示中文。
void fill(int startx,int starty,int endx,int endy,int color),在
指定的区域用指定的颜色来填充。
void showHelp(),显示用户使用指南,包括直线、矩形、圆形和 Bezier
曲线的绘制方法。
/*根据点阵信息显示中文函数* /
void outChinese(char *mat,int matsize,int x,int y,int color)
{
`
int i,j,k,n;
n=(matsize -1)/8+1
for(j=0;j>k))
/*测试为 1 的位则显示*/
putpixel(x + i * 8 + k, y + j, color);
}
/*填充函数*/
void fill(int startx,int starty,int endx,int endy,int color)
{
int i,j;
for(i=startx;i<=endx;i++)
for(j=starty;j<=endy;j++)
/*在指定位置以指定颜色画一像素*/
putpixel(i,j,color);
}
/*显示用户帮助函数*/
void showHelp()
{
setcolor(14);
outtextxy(45,50,"Line:");
setcolor(WHITE);
outtextxy(45,50,"
outtextxy(45,65,"
outtextxy(45,80,"
1 Press left button to start until to line end.");
2 Use UP,DOWN,LEFT,RIGHT keys to move it.");
3 Use PAGEUP key to enlarge it, and PAGEDOWN key to
shrink it.");
outtextxy(45,95,"
4 Use SPACE key to rotate it.");
setcolor(14);