简单图形函数库设计与实现
一、要求:
设计和实现一个图形函数库,具有绘制直线段、任意圆弧、椭圆弧、多边形
区域的阴影填充和颜色填充等功能。(仅调用画点函数)
Windows API: setpixel(hdc,x,y,color)
二、设计与实现:
1. 在Visual C++ 6.0环境下设计与实现的。在Visusl C++ 6.0中创建一个
可以显示“Hello”的Win32的应用程序(Win32 Application);在
Project/Settings对话框中的Link选项卡中的Object/library modules
一栏中加入opengl32.lib, glu32.lib和glut32.lib。
步骤如下:
File——〉new——〉Projects——〉Win32 Application,在Projects name
一栏输入“ zj ”——〉选择A typical “Hello world” Application;
这样就得到了一个带窗口的应用程序框架。
2. 在建成的项目下,加入两个源文件draw.cpp和show.cpp。
draw.cpp文件用于书写简单的图形函数库,也即生成各种简单图形及颜
色填充的函数在此文件中。
show.cpp文件用于调用所设计的图形函数库中的各个函数,在窗口中输
出,以便观察所设计的函数是否正确。
3. 在LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
PARAM lParam) 中调用void show(HDC hdc)(此函数在show.cpp 中
L
定义)。如图:
4. 在draw.cpp中加入下列函数:
void line(HDC hdc,int x1,int y1,int x2,int y2);
画直线段函数,运用的是 Bresenham 算法。参数为直线段的两个端点坐
- 1 -
标(x1,y1),(x2,y2)。
void circle(HDC hdc,int r,int x0,int y0);
画圆函数,运用的是 “正负法” 算法,设计时采用的是把整个圆等分
成了4个部分,逐一画出,这样的画法使得画出的圆不是很圆滑,一个好
的方法是等分成4部分后,利用对称性画圆,即画第一象限的点时把对应
的第二、三、四象限的点通过对称变换一并画出。
void ellipse(HDC hdc,int x0,int y0,int a,int b);
画椭圆函数,运用的是 中点画椭圆算法 ,此算法是从相关的图形学教
材中找到的,本人觉得是个不错的算法。
void Flood_Fill_4(HDC hdc, int x,int y, COLORREF
old_color,COLORREF new_color);
区域颜色填充函数, 利用的是教材中的 Flood 算法。此算法有个很大
的缺点就是对图形进行填充时,经常出现堆栈溢出的情况,所以所填充
的图形不能太大,它的优点在很简单,只需明白递归的原理就行了。
5. 在show.cpp中加入函数void show(HDC hdc),此函数主要是进行draw.cpp
中的函数的调用。调用情况如下:
调用void line(HDC hdc,int x1,int y1,int x2,int y2);画直线段
调用void circle(HDC hdc,int r,int x0,int y0); 画圆
调用void ellipse(HDC hdc,int x0,int y0,int a,int b);画椭圆
调用void Flood_Fill_4(HDC hdc, int x,int y, COLORREF
old_color,COLORREF new_color);填充区域
附:
只提供draw.cpp与show.cpp中的源码(其它的是VC 6.0自动生成的框架)。
源程序:
draw.cpp如下:
#include "stdafx.h"
#include "resource.h"
#include "math.h"
#define Pi 3.14159265
void line(HDC hdc,int x1,int y1,int x2,int y2);
void circle(HDC hdc,int r,int x0,int y0);
void ellipse(HDC hdc,int x0,int y0,int a,int b);
void wholeellipse(HDC hdc,int x0,int y0,int x,int y);
void Flood_Fill_4(HDC hdc, int x,int y, COLORREF old_color,COLORREF new_color);
//画直线段
void line(HDC hdc,int x1,int y1,int x2,int y2)
- 2 -
{
int x,y,deltax,deltay,e;
////////////////////////////////////////////
if(x2>=x1){
if(y2>=y1){
deltax=x2-x1;
deltay=y2-y1;
e=-deltax;
x=x1;
y=y1;
for(int i=0;i<=deltax;i++){
SetPixel(hdc,x,y,RGB(0,0,0));
if(e>=0){
y=y+1;
e=e-2*deltax;
}
else{
x=x+1;
e=e+2*deltay;
}
}
}
else{
deltax=x2-x1;
y2=2*y1-y2;
deltay=y2-y1;
e=-deltax;
x=x1;
y=y1;
for(int i=0;i<=deltax;i++){
SetPixel(hdc,x,2*y1-y,RGB(0,0,0));
if(e>=0){
y=y+1;
e=e-2*deltax;
}
else{
x=x+1;
e=e+2*deltay;
}
}
}
}
- 3 -
else{
if(y2>=y1){
x2=2*x1-x2;
deltax=x2-x1;
deltay=y2-y1;
e=-deltax;
x=x1;
y=y1;
for(int i=0;i<=deltax;i++){
SetPixel(hdc,2*x1-x,y,RGB(0,0,0));
if(e>=0){
y=y+1;
e=e-2*deltax;
}
else{
x=x+1;
e=e+2*deltay;
}
}
}
else{
int temp;
temp=x1;
x1=x2;
x2=temp;
temp=y1;
y1=y2;
y2=temp;
deltax=x2-x1;
deltay=y2-y1;
e=-deltax;
x=x1;
y=y1;
for(int i=0;i<=deltax;i++){
SetPixel(hdc,x,y,RGB(0,0,0));
if(e>=0){
y=y+1;
e=e-2*deltax;
}
else{
x=x+1;
e=e+2*deltay;
- 4 -
}
}
}
}
}
//画圆
void circle(HDC hdc,int r,int x0,int y0)
{
int x,y,f;
x=x0;
y=y0+r;
f=0;
while(y >= y0){
//右下
SetPixel(hdc,x,y,RGB(0,0,0));
if(f>0){
f=f-2*(y-y0)+1;
y=y-1;
}
else{
f=f+2*(x-x0)+1;
x=x+1;
}
}
x=x0-r;
y=y0;
f=0;
while(x<=x0){
//左下
SetPixel(hdc,x,y,RGB(0,0,0));
if(f>0){
f=f+2*(x-x0)+1;
x=x+1;
}
else{
f=f+2*(y-y0)+1;
y=y+1;
}
}
x=x0;
y=y0-r;
f=0;
while(y<=y0){
//左上
SetPixel(hdc,x,y,RGB(0,0,0));
- 5 -
if(f>0){
f=f+2*(y-y0)+1;
y=y+1;
}
else{
f=f-2*(x-x0)+1;
x=x-1;
}
}
x=x0+r;
y=y0;
f=0;
while(x>=x0){
//右上
SetPixel(hdc,x,y,RGB(0,0,0));
if(f>0){
f=f-2*(x-x0)+1;
x=x-1;
}
else{
f=f-2*(y-y0)+1;
y=y-1;
}
}
}
//中点画椭圆算法
void ellipse(HDC hdc,int x0,int y0,int a,int b)
{
int a1=a*a, b1=b*b;
int a2=2*a1, b2=2*b1;
int x=0, y=b;
int d;
int dx=0, dy=a2*y;
d = (int) (b1 + a1 * (-b + 0.25) + 0.5);
wholeellipse(hdc,x0,y0,x,y);
while(dx
dy -= a2;
d += b1 + dx - dy;
y--;
}
wholeellipse(hdc,x0,y0,x,y);
}
d =(int) (b1*(x+0.5)*(x+0.5)+a1*(y-1)*(y-1)-a1*b1-0.5);
while(y>0)
{
y--;
dy -= a2;
if(d>0)
d += a1-dy;
else{
x++;
dx += b2;
d += a1-dy+dx;
}
wholeellipse(hdc,x0,y0,x,y);
}
}
void wholeellipse(HDC hdc,int x0,int y0,int x,int y)
{
SetPixelV(hdc,x0+x,y0+y, RGB(0,0,0));
SetPixelV(hdc,x0-x,y0+y, RGB(0,0,0));
SetPixelV(hdc,x0+x,y0-y, RGB(0,0,0));
SetPixelV(hdc,x0-x,y0-y, RGB(0,0,0));
}
//区域颜色填充,Flood算法
void Flood_Fill_4(HDC hdc, int x,int y, COLORREF old_color,COLORREF new_color)
{
if( GetPixel(hdc,x,y)==old_color){
SetPixel(hdc,x,y,new_color);
Flood_Fill_4(hdc,x,y+1,old_color,new_color);
Flood_Fill_4(hdc,x,y-1,old_color,new_color);
Flood_Fill_4(hdc,x-1,y,old_color,new_color);
Flood_Fill_4(hdc,x+1,y,old_color,new_color);
}
}
show.cpp如下:
- 7 -
#include "stdafx.h"
#include "resource.h"
void line(HDC hdc,int x1,int y1,int x2,int y2);
void circle(HDC hdc,int r,int x0,int y0);
void ellipse(HDC hdc,int x0,int y0,int a,int b);
void Flood_Fill_4(HDC hdc, int x,int y, COLORREF old_color,COLORREF new_color);
void show(HDC hdc)
{
////////////////////////////////////////////////////////////////
line(hdc,100,200,250,200);
line(hdc,100,200,350,500);
line(hdc,250,200,80,800);
Flood_Fill_4(hdc,150,250,RGB(255,255,255),RGB(195,195,195));//区域填充
////////////////////////////////////////////////////////////////
line(hdc,300,75,430,345);
line(hdc,450,150,650,0);
circle(hdc,20,345,220);
circle(hdc,19,430,215);
ellipse(hdc,400,220,85,55);
//画直线段1
//画直线段2
//画圆1
//画圆2
//画一个椭圆
Flood_Fill_4(hdc,345,220,RGB(255,255,255),RGB(195,195,195));//区域填充
Flood_Fill_4(hdc,430,215,RGB(255,255,255),RGB(215,215,220));//区域填充
Flood_Fill_4(hdc,400,220,RGB(255,255,255),RGB(100,220,175));//区域填充
}
- 8 -