扫描线画法.docx
- 文档编号:7296113
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:17
- 大小:19.67KB
扫描线画法.docx
《扫描线画法.docx》由会员分享,可在线阅读,更多相关《扫描线画法.docx(17页珍藏版)》请在冰豆网上搜索。
扫描线画法
//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->xStart 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;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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 扫描 画法
![提示](https://static.bdocx.com/images/bang_tan.gif)