扫描线画法.docx

上传人:b****6 文档编号:7296113 上传时间:2023-01-22 格式:DOCX 页数:17 大小:19.67KB
下载 相关 举报
扫描线画法.docx_第1页
第1页 / 共17页
扫描线画法.docx_第2页
第2页 / 共17页
扫描线画法.docx_第3页
第3页 / 共17页
扫描线画法.docx_第4页
第4页 / 共17页
扫描线画法.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

扫描线画法.docx

《扫描线画法.docx》由会员分享,可在线阅读,更多相关《扫描线画法.docx(17页珍藏版)》请在冰豆网上搜索。

扫描线画法.docx

扫描线画法

//forstu.cpp:

定义应用程序的入口点。

//

#include"stdafx.h"

#include"stdio.h"

#include"forstu.h"

#defineMAX_LOADSTRING100

#defineWINDOW_HEIGHT600

#defineMAX_POINT256

#defineCOLOR255

 

typedefenumtdrawtype{

LINE_DDA=1,

LINE_BR,

CIRCLE_BR,

AET

}drawtype;

typedefstructtEdge{

intyMax;

floatxStart,dx;

structtEdge*next;

}Edge;

typedefstructtdcPt{

intx;

inty;

}dcPt;

//全局变量:

HINSTANCEhInst;//当前实例

TCHARszTitle[MAX_LOADSTRING];//标题栏文本

TCHARszWindowClass[MAX_LOADSTRING];//主窗口类名

 

//当前绘制类型

drawtypecurtype;

//用于AET的变量

FILE*fp;

dcPtvertexs[256];

inti,cnt,x;

 

//二维图形栅格化生成算法

voidddaline(HDChdc,intx1,inty1,intx2,inty2);

intsign(floatx);

voidbresenhamline(HDChdc,intx1,inty1,intx2,inty2);

voidbresenhamcircle(HDChdc,intxc,intyc,intr);

voidcyclepoint(HDChdc,intx,inty,intxc,intyc);

//下面的函数用于AET算法

voidinsertEdge(Edge*list,Edge*edge);

intyNext(intk,intcnt,dcPt*pts);

voidmakeEdgeRec(dcPtlower,dcPtupper,intyComp,Edge*edge,Edge*edges[]);

voidbuildEdgeList(intcnt,dcPt*pts,Edge*edges[]);

voidbuildActiveList(intscan,Edge*active,Edge*edges[]);

voidfillScan(HDChdc,intscan,Edge*active);

voiddeleteAfter(Edge*q);

voidupdateActiveList(intscan,Edge*active);

voidresortActiveList(Edge*active);

voidscanFill(HDChdc,intcnt,dcPt*pts);

//此代码模块中包含的函数的前向声明:

ATOMMyRegisterClass(HINSTANCEhInstance);

BOOLInitInstance(HINSTANCE,int);

LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);

LRESULTCALLBACKAbout(HWND,UINT,WPARAM,LPARAM);

intAPIENTRY_tWinMain(HINSTANCEhInstance,

HINSTANCEhPrevInstance,

LPTSTRlpCmdLine,

intnCmdShow)

{

//TODO:

在此放置代码。

MSGmsg;

HACCELhAccelTable;

//初始化全局字符串

LoadString(hInstance,IDS_APP_TITLE,szTitle,MAX_LOADSTRING);

LoadString(hInstance,IDC_FORSTU,szWindowClass,MAX_LOADSTRING);

MyRegisterClass(hInstance);

//执行应用程序初始化:

if(!

InitInstance(hInstance,nCmdShow))

{

returnFALSE;

}

hAccelTable=LoadAccelerators(hInstance,(LPCTSTR)IDC_FORSTU);

//主消息循环:

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

{

if(!

TranslateAccelerator(msg.hwnd,hAccelTable,&msg))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

return(int)msg.wParam;

}

 

//

//函数:

MyRegisterClass()

//

//目的:

注册窗口类。

//

//注释:

//

//仅当希望在已添加到Windows95的

//“RegisterClassEx”函数之前此代码与Win32系统兼容时,

//才需要此函数及其用法。

调用此函数

//十分重要,这样应用程序就可以获得关联的

//“格式正确的”小图标。

//

ATOMMyRegisterClass(HINSTANCEhInstance)

{

WNDCLASSEXwcex;

wcex.cbSize=sizeof(WNDCLASSEX);

wcex.style=CS_HREDRAW|CS_VREDRAW;

wcex.lpfnWndProc=(WNDPROC)WndProc;

wcex.cbClsExtra=0;

wcex.cbWndExtra=0;

wcex.hInstance=hInstance;

wcex.hIcon=LoadIcon(hInstance,(LPCTSTR)IDI_FORSTU);

wcex.hCursor=LoadCursor(NULL,IDC_ARROW);

wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);

wcex.lpszMenuName=(LPCTSTR)IDC_FORSTU;

wcex.lpszClassName=szWindowClass;

wcex.hIconSm=LoadIcon(wcex.hInstance,(LPCTSTR)IDI_SMALL);

returnRegisterClassEx(&wcex);

}

//

//函数:

InitInstance(HANDLE,int)

//

//目的:

保存实例句柄并创建主窗口

//

//注释:

//

//在此函数中,我们在全局变量中保存实例句柄并

//创建和显示主程序窗口。

//

BOOLInitInstance(HINSTANCEhInstance,intnCmdShow)

{

HWNDhWnd;

hInst=hInstance;//将实例句柄存储在全局变量中

hWnd=CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);

if(!

hWnd)

{

returnFALSE;

}

ShowWindow(hWnd,nCmdShow);

UpdateWindow(hWnd);

returnTRUE;

}

//

//函数:

WndProc(HWND,unsigned,WORD,LONG)

//

//目的:

处理主窗口的消息。

//

//WM_COMMAND-处理应用程序菜单

//WM_PAINT-绘制主窗口

//WM_DESTROY-发送退出消息并返回

//

//

LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)

{

intwmId,wmEvent;

PAINTSTRUCTps;

HDChdc;

//用于AET的变量

FILE*fp;

dcPtvertexs[256];

inti,cnt;

switch(message)

{

caseWM_COMMAND:

wmId=LOWORD(wParam);

wmEvent=HIWORD(wParam);

//分析菜单选择:

switch(wmId)

{

caseIDM_ABOUT:

DialogBox(hInst,(LPCTSTR)IDD_ABOUTBOX,hWnd,(DLGPROC)About);

break;

caseIDM_EXIT:

DestroyWindow(hWnd);

break;

caseID_BR:

curtype=LINE_BR;

InvalidateRect(hWnd,NULL,TRUE);

UpdateWindow(hWnd);

break;

caseID_DDA:

curtype=LINE_DDA;

InvalidateRect(hWnd,NULL,TRUE);

UpdateWindow(hWnd);

break;

caseID_CIRCLE_BR:

curtype=CIRCLE_BR;

InvalidateRect(hWnd,NULL,TRUE);

UpdateWindow(hWnd);

break;

caseID_AET:

curtype=AET;

InvalidateRect(hWnd,NULL,TRUE);

UpdateWindow(hWnd);

break;

default:

returnDefWindowProc(hWnd,message,wParam,lParam);

}

break;

caseWM_PAINT:

hdc=BeginPaint(hWnd,&ps);

//TODO:

在此添加任意绘图代码...

switch(curtype)

{

caseLINE_DDA:

ddaline(hdc,50,70,100,150);//红色直线

break;

caseLINE_BR:

bresenhamline(hdc,50,70,200,150);//兰色直线

break;

caseCIRCLE_BR:

bresenhamcircle(hdc,350,250,100);

break;

caseAET:

fp=fopen("polygon1.ply","rt");

fscanf(fp,"%d%d",&(vertexs[0].x),&(vertexs[0].y));

i=0;

do{

i++;

fscanf(fp,"%d%d",&(vertexs[i].x),&(vertexs[i].y));

}while((vertexs[0].x!

=vertexs[i].x||vertexs[0].y!

=vertexs[i].y)&&!

feof(fp));

fclose(fp);

cnt=i;

scanFill(hdc,cnt,vertexs);

break;

default:

break;

}

EndPaint(hWnd,&ps);

break;

caseWM_DESTROY:

PostQuitMessage(0);

break;

default:

returnDefWindowProc(hWnd,message,wParam,lParam);

}

return0;

}

//“关于”框的消息处理程序。

LRESULTCALLBACKAbout(HWNDhDlg,UINTmessage,WPARAMwParam,LPARAMlParam)

{

switch(message)

{

caseWM_INITDIALOG:

returnTRUE;

caseWM_COMMAND:

if(LOWORD(wParam)==IDOK||LOWORD(wParam)==IDCANCEL)

{

EndDialog(hDlg,LOWORD(wParam));

returnTRUE;

}

break;

}

returnFALSE;

}

 

//-----------------------直线的DDA算法------------------------------------------------------

voidddaline(HDChdc,intx1,inty1,intx2,inty2)

{

intlength,i;

floatdx,dy,x,y;

length=max(abs(x2-x1),abs(y2-y1));

dx=(float)(x2-x1)/length;

dy=(float)(y2-y1)/length;

if(dx==0){for(i=y1;i<=y2;i++)SetPixel(hdc,x1,i,RGB(COLOR,0,0));}

elseif(dy==0){for(i=x1;i<=x2;i++)SetPixel(hdc,i,y1,RGB(COLOR,0,0));}

else

{

x=(float)(x1+0.5*sign(dx));

y=(float)(y1+0.5*sign(dy));

for(i=1;i<=length;i++)

{

SetPixel(hdc,int(x),int(y),RGB(COLOR,0,0));

x=x+dx;

y=y+dy;

}

}

}

 

intsign(floatx)

{

if(x>0)return1;

elseif(x<0)return-1;

elsereturn0;

}

//--------------------------直线的Bresenham算法---------------------------------------------------

voidbresenhamline(HDChdc,intx1,inty1,intx2,inty2)

{

intx,y,dx,dy,i;

floatm,e;

x=x1;y=y1;

dx=x2-x1;dy=y2-y1;

if(dx==0){for(i=y1;i<=y2;i++)SetPixel(hdc,x1,i,RGB(COLOR,0,0));}

elseif(dy==0){for(i=x1;i<=x2;i++)SetPixel(hdc,i,y1,RGB(COLOR,0,0));}

else

{m=(float)dy/(float)dx;

e=float(m-0.5);

for(i=1;i<=dx;i++)

{

SetPixel(hdc,x,y,RGB(0,0,COLOR));

if(e>=0){y=y+1;e=e-1;}

x=x+1;e=e+m;

}

}

}

//------------------------------Bresenham的中点画圆法-----------------------------------------------

voidbresenhamcircle(HDChdc,intxc,intyc,intr)

{

intx,y,d;

x=0;y=r;

d=3-2*r;

while(x

{

cyclepoint(hdc,x,y,xc,yc);

if(d>=0){d=d+4*(x-y)+10;y--;}

elsed=d+4*x+6;

x++;

}

if(x==y)cyclepoint(hdc,x,y,xc,yc);

}

voidcyclepoint(HDChdc,intx,inty,intxc,intyc)

{

SetPixel(hdc,x+xc,y+yc,RGB(COLOR,0,0));

SetPixel(hdc,y+xc,x+yc,RGB(COLOR,COLOR,0));

SetPixel(hdc,x+xc,-y+yc,RGB(COLOR,0,COLOR));

SetPixel(hdc,y+xc,-x+yc,RGB(0,COLOR,COLOR));

SetPixel(hdc,-x+xc,-y+yc,RGB(0,COLOR,0));

SetPixel(hdc,-y+xc,-x+yc,RGB(0,0,COLOR));

SetPixel(hdc,-y+xc,x+yc,RGB(COLOR,0,0));

SetPixel(hdc,-x+xc,y+yc,RGB(0,0,COLOR));

}

 

/*按照y值升序进行插入排序*/

voidinsertEdge(Edge*list,Edge*edge)

{

Edge*p,*q=list;

p=q->next;

while(p!

=NULL){

if(edge->xStartxStart)

p=NULL;

else{

q=p;

p=p->next;

}

}

edge->next=q->next;

q->next=edge;

}

/*返回给定边下一条非水平边的y值*/

intyNext(intk,intcnt,dcPt*pts)

{

intj;

if((k+1)>(cnt-1))

j=0;

else

j=k+1;

while(pts[k].y==pts[j].y)

if((j+1)>(cnt-1))

j=0;

else

j++;

return(pts[j].y);

}

/*生成各个边对应的结点信息并插入到边表中*/

voidmakeEdgeRec(dcPtlower,dcPtupper,intyComp,

Edge*edge,Edge*edges[])

{

edge->dx=(float)(upper.x-lower.x)

/(upper.y-lower.y);

edge->xStart=lower.x;

/*对特殊交点个数的处理,其中包括了0、1、2个交点对应的特殊情况。

*/

if(upper.y

edge->yMax=upper.y-1;

else

edge->yMax=upper.y;

/*将该边对应的结点加入边表中*/

insertEdge(edges[lower.y],edge);

}

/*建立初始边表*/

voidbuildEdgeList(intcnt,dcPt*pts,Edge*edges[])

{

Edge*edge;

dcPtv1,v2;

inti,yPrev=pts[cnt-2].y;

v1.x=pts[cnt-1].x;

v1.y=pts[cnt-1].y;

for(i=0;i

v2=pts[i];

if(v1.y!

=v2.y){/*非水平边*/

edge=(Edge*)malloc(sizeof(Edge));

if(v1.y

makeEdgeRec(v1,v2,yNext(i,cnt,pts),

edge,edges);

else/*该边y方向按照多边形边前进方向从大到小*/

makeEdgeRec(v2,v1,yPrev,edge,edges);

}

yPrev=v1.y;

v1=v2;

}

}

/*从边表中取出给定扫描线对应的链表,插入活性边表中*/

voidbuildActiveList(intscan,Edge*active,

Edge*edges[])

{

Edge*p,*q;

p=edges[scan]->next;

while(p){

q=p->next;

insertEdge(active,p);

p=q;

}

}

 

/*单条扫描线对应的填充操作*/

voidfillScan(HDChdc,intscan,Edge*active)

{

Edge*p1,*p2;

inti;

p1=active->next;

while(p1){

p2=p1->next;

for(i=p1->xStart;ixStart;i++)

SetPixel(hdc,(int)i,scan,RGB(255,0,0));

p1=p2->next;

}

}

/*删除单项链表中节点q指向的下一个边节点*/

voiddeleteAfter(Edge*q)

{

Edge*p=q->next;

q->next=p->next;

free(p);

}

/*更新活性边表:

将达到yMax的边对应的结点从活性边表中删除,然后将各个边对应的x起点加上增量1/k*/

v

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1