Ching
Original address: http://blog.csdn.net/qingdujun/article/details/40154077
In this paper, a complete example is presented to show the polygon effective edge table filling algorithm.
1) Create Caet class
Header file: AET.h
Aet.h:interface for the Caet class.////////////////////////////////////////////////////////////////////////#if! Defined (afx_aet_h__a7cad03f_c111_4b1f_90f2_88e39668c107__included_) #define Afx_aet_h__a7cad03f_c111_4b1f_90f2_ 88e39668c107__included_#if _msc_ver > 1000#pragma once#endif//_msc_ver > 1000//the effective edge table data structure is defined as follows: Class Caet { Public:caet (); virtual ~caet ();d ouble x;int ymax;double K; instead of 1/kcaet *pnext;}; #endif//!defined (AFX_AET_H__A7CAD03F_C111_4B1F_90F2_88E39668C107__INCLUDED_)
implementation file: AET.cpp
AET.cpp:implementation of the Caet class./////////////////////////////////////////////////////////////////////// /#include "stdafx.h" #include "FillPolygon.h" #include "AET.h" #ifdef _debug#undef this_filestatic Char this_file[]=__ file__, #define NEW debug_new#endif//////////////////////////////////////////////////////////////////////// Construction/destruction//////////////////////////////////////////////////////////////////////caet::caet () {} Caet::~caet () {}
2) Create Cbucket class
Header file: Bucket.h
Bucket.h:interface for the Cbucket class./////////////////////////////////////////////////////////////////////// /#if!defined (afx_bucket_h__f1ed22a9_3004_4c3a_8710_ad025bec063c__included_) #define Afx_bucket_h__f1ed22a9_3004_ 4c3a_8710_ad025bec063c__included_#if _msc_ver > 1000#pragma once#endif//_msc_ver > 1000#include "aet.h"// The data structure of the bucket is defined as follows: Class Cbucket {Public:cbucket (); virtual ~cbucket (); int scanline; Scan line Caet *p; The side table pointer on the bucket cbucket *pnext;}; #endif//!defined (AFX_BUCKET_H__F1ED22A9_3004_4C3A_8710_AD025BEC063C__INCLUDED_)
implementation file: Bucket.cpp
Bucket.cpp:implementation of the Cbucket class.///////////////////////////////////////////////////////////////// #include "stdafx.h" #include "FillPolygon.h" #include "Bucket.h" #ifdef _debug#undef this_filestatic Char This_ file[]=__file__, #define NEW debug_new#endif///////////////////////////////////////////////////////////////////// Construction/destruction//////////////////////////////////////////////////////////////////////cbucket:: Cbucket () {}cbucket::~cbucket () {}
3) Create Cfillpolygon class
Header file: FillPolygon.h
Fillpolygon.h:interface for the Cfillpolygon class.///////////////////////////////////////////////////////////// #if!defined (afx_fillpolygon_h__18c16134_aa95_46fe_b223_dd5cf4ecaec0__included_) #define Afx_ fillpolygon_h__18c16134_aa95_46fe_b223_dd5cf4ecaec0__included_#if _msc_ver > 1000#pragma once#endif//_MSC_VER > 1000#define number 7//closed polygon vertices, vertices stored in two-dimensional array Point[number] # include "AET.h" #include "Bucket.h"//effective edge table Polygon fill class Cfillpolygon {Public:cfillpolygon (); virtual ~cfillpolygon (); void Creatbucket (); Build bucket node void Createdge (); Constructed edge table void Insertedge (Caet *edge); Insert temporary side table caet* edgesort (); Sort the edge table void Polygonfill (CClientDC *dc, COLORREF RGB); Polygon fill void Showpolygon (CDC *PDC); Connect 7 vertices together protected:cpoint point[number]; Polygon Vertex COLORREF GetColor; Palette Cbucket *headb, *CURRENTB; The head node of the bucket and the current node Caet Edge[number], *heade, *currente, *T1, *t2;//the node of the effective Edge table}; #endif//!defined (afx_fillpolygon_h__18c16134_ Aa95_46fe_b223_DD5CF4ECAEC0__INCLUDED_)
implementation file: FillPolygon.cpp
FillPolygon.cpp:implementation of the Cfillpolygon class./////////////////////////////////////////////////////// #include "stdafx.h" #include "EdgeTable.h" #include "FillPolygon.h" #ifdef _debug#undef this_ filestatic char this_file[]=__file__; #define NEW Debug_new#endif#define ROUND (a) int (a+0.5)//Rounding/////////////////// construction/destruction///////////////////////////////// Cfillpolygon::cfillpolygon () {//Set 7 vertices of the polygon point[0]=cpoint (550,400);//p0 Point[1]=cpoint (350,600);//p1 point[2]=cpoint (250,350);//p2 point[3]=cpoint (350,50); P3 Point[4]=cpoint (500,250);//p4 point[5]=cpoint (600,50); P5 Point[6]=cpoint (800,450);//p6}cfillpolygon::~cfillpolygon () {}void cfillpolygon::creatbucket ()//Create empty bucket nodes, Edge Table {int I,scanmin,scanmax not connected; SCANMAX=SCANMIN=POINT[0].Y; for (i=1;i<number;i++)//determines the minimum and maximum value of the scan line {if (point[i].y<scanmin) {scanmin=point[i].y; The minimum value of the scan line} if (Point[i].y>scanmax) {scanmax=point[i].y; The maximum value of the scan line}} for (i=scanmin;i<=scanmax;i++)//Create a bucket node (similar to creating a single-linked list) {if (scanmin==i) Bucket head Node {headb=new cbucket; Establish the head node of the bucket currentb=headb; CURRENTB is the bucket current node pointer currentb->scanline=scanmin; else//Create a bucket with other nodes {Currentb->pnext=new cbucket;//create a new bucket junction Cu rrentb=currentb->pnext;//make CURRENTB point to the new bucket node currentb->scanline=i; }currentb->p=null; No linked edge list currentb->pnext=null; }} void Cfillpolygon::createdge ()//such as [P121 figure 4-28], construct the edge table (the edge table, equivalent to the "lowest" side of the edge table), while connecting the bucket table {for (int i=0;i<number;i++)//Access each A vertex {currentb=headb; Start the loop int j=i+1 from the head node of the bucket list; The second vertex of the edge, Point[i] and point[j] form the edge if (J==number) j= 0; Ensure that the closed if (POINT[J].Y>POINT[I].Y)//end point of the polygon is higher than the starting point {while (CURRENTB->SCANLINE!=POINT[I].Y)//in the bucket Find the side of the ymin {currentb=currentb->pnext;//move to the next bucket node} edge[i].x=point[i].x; The x intersection of the scan line and the Edge edge[i].ymax=point[j].y; Line highest point Y value edge[i].k=double ((point[j].x-point[i].x))/(POINT[J].Y-POINT[I].Y);//Represents 1/k EDGE[I].P Next=null; } if (POINT[J].Y<POINT[I].Y)//endpoint is lower than start {while (CURRENTB->SCANLINE!=POINT[J].Y) { currentb=currentb->pnext; } edge[i].x=point[j].x; EDGE[I].YMAX=POINT[I].Y; Edge[i].k=double ((point[i].x-point[j].x))/(POINT[I].Y-POINT[J].Y); Edge[i].pnext=null; }currente=currentb->p; Get the address of the link edge table on the bucket if (currentb->p==null)//The current bucket node has no link edge node {currente=&edge[i]; The starting address of the currentb->p=currente;//is connected directly to the corresponding bucket by the first edge node.}else{while (currente->pnext!=null)//If the current edge is connected with an edge node {currente=currente->pnext;//Moves the pointer to the last edge node of the current edge}currente ->pnext=&edge[i];//the current Edge up}} Currentb=null; Currente=null; } void Cfillpolygon::insertedge (Caet *edge)//Insert temporary side table {T1=heade; if (t1==null)//Benzi is empty, the edge table is set to Tempedge {T1=edge; HEADE=T1; } else {while (t1->pnext!=null)//Benzi is not empty, Tempedge is attached to the edge {t1=t1->pnext; } t1->pnext=edge; }} caet* Cfillpolygon::edgesort ()//To sort the side table (x| Ymin, representing the X-value at ymin) {T1=heade; if (t1==null) {return NULL; } if (T1->pnext==null)//If the edge table does not have a hyphen table {return NULL; The bucket node has only one edge and does not need to be sorted} else {if (T1->pnext->x<t1->x | | (t1->pnext->x==t1->x && t1->pnext->k<t1->k)) Edge table sorted by x,1/k value {t2=t1->pnext; t1->pnext=t2->pnext; t2->pnext=t1;Heade=t2; } T2=heade; t1=heade->pnext; while (T1->pnext!=null)//Continue 22 Compare the x,1/k value of the connected edge table, sort {if (T1->pnext->x<t1->x | | (t1->pnext->x==t1->x && t1->pnext->k<t1->k)) {t2->pnext=t1->pnext; t1->pnext=t1->pnext->pnext; t2->pnext->pnext=t1; t2=t2->pnext; } else {t2=t1; t1=t1->pnext; }}}return Heade;} void Cfillpolygon::showpolygon (CDC *PDC)//Connect 7 vertices {Pdc->polygon (point,7);//Draw polygon//output polygon vertex number pdc->textout ( 550,410, "P0"); Pdc->textout (350,600, "P1"); Pdc->textout (230,340, "P2"); Pdc->textout (350,30, "P3"); Pdc->textout (490,220, "P4"); Pdc->textout (600,30, "P5"); Pdc->textout (805,450, "P6");} void Cfillpolygon::P olygonfill (CClientDC *dc, COLORREF RGB)//Polygon fill {Caet *dele=null; CbucKet *delb=null; Heade=null; for (CURRENTB=HEADB; Currentb!=null; Currentb=currentb->pnext)//access all bucket nodes {for (currente=currentb->p; Currente!=null; Currente=currente->pnext)//access the side node before sorting in the bucket {//Create a temporary edge node Caet *tempedge=new Caet; tempedge->x=currente->x; tempedge->ymax=currente->ymax; tempedge->k=currente->k; tempedge->pnext=null; Insertedge (Tempedge); Insert the edge into the temporary Caet table} t1=edgesort (); Causes the edge table to be stored in the order of x,1/k increments (because Createdge is unordered when created) if (t1==null) {return; }//According to YMax discard the scanned edge node (local highest point and scan line coincident, then discard) while (Currentb->scanline>=t1->ymax)//Discard the node, CAET table pointer back (closed) {Del E=T1; t1=t1->pnext; Heade=t1;delete DelE; Free space dele=null; if (heade==null)//t1==null {return; }} if (T1->pnext!=null) {t2=t1; t1=t2->pnext; } while (T1!=null) {if (Currentb->scanline>=t1->ymax)//skips a node { t2->pnext=t1->pnext; t1->pnext=null; t1=t2->pnext; } else {t2=t1; t1=t2->pnext; }} BOOL Isfill=false; Set a bool variable Isfill, the initial value is false double xb,xe; The start and end of the scan line for (T1=heade; T1!=null; T1=t1->pnext)//fill in the interval of the scan line and polygon (isfill==false) {xb=t1->x; Isfill=true; Every access to a node, the Isfill value is reversed once} else//If the Isfill value is true, the interval from the X value of the current node to the end of the X value of the next node is populated {xe=t1->x-1; Left closed right open for (double x=xb;x<=xe;x++) dc->setpixel (ROUND (x), Currentb->scanline,rgb) ;//Fill statement Sleep (1); Delay 1ms, improve the visibility of the filling process isfill=false; }} for (T1=heade; T1!=null; T1=t1->pnext)//edge Coherence {t1->x=t1->x+t1->k; X=X+1/K}}//frees the edge table space while (heade!=null) {dele=heade; Heade=heade->pnext;delete DelE;} dele=null;//free bucket table space while (headb!=null) {delb=headb; Headb=headb->pnext;delete Delb;} Delb=null;}
4) Engineering Cedgetableview class
Header file: EdgeTableView.h
Edgetableview.h:interface of the Cedgetableview class/////////////////////////////////////////////////////////// #if!defined (afx_edgetableview_h__6908d229_1f3e_40e1_bb66_41e93ba625d9__included_) #define afx_edgetableview_h__6908d229_1f3e_40e1_bb66_41e93ba625d9__included_#if _msc_ver > 1000#pragma once#endif//_MSC _ver > 1000#include "FillPolygon.h" class Cedgetableview:public cview{protected://Create from serialization ONLYCEDG Etableview ();D eclare_dyncreate (Cedgetableview)//attributespublic:cedgetabledoc* getdocument ();// Operationspublic:private:CFillPolygon *pfill; Effective edge table Method polygon filling COLORREF RGB; Fill Color//overrides//ClassWizard generated virtual function overrides//{{afx_virtual (Cedgetableview) public:virtual void OnDraw (cdc* pDC); Overridden to draw this viewvirtual BOOL PreCreateWindow (createstruct& cs);p rotected://}}afx_virtual// Implementationpublic:virtual ~cedgetableview (); #ifdef _debugvirtual void AssertValid () const;virtual void Dump (cdumpcontext& DC) const; #endifprotected://Generated message map functionsprotected://{{afx_msg ( Cedgetableview) afx_msg void Onmenufill ();//}}afx_msgdeclare_message_map ()}; #ifndef _DEBUG//DEBUG version in Edgetableview.cppinline cedgetabledoc* cedgetableview::getdocument () {return (cedgetabledoc*) m_pDocument;} #endif///////////////////////////////////////////////////////////////////////////////{{afx_insert_location}}// Microsoft Visual C + + would insert additional declarations immediately before the previous line. #endif//!defined (Afx_edget ABLEVIEW_H__6908D229_1F3E_40E1_BB66_41E93BA625D9__INCLUDED_)
implementation file: EdgeTableView.cpp
EdgeTableView.cpp:implementation of the Cedgetableview class//#include "stdafx.h" #include "EdgeTable.h" #include " EdgeTableDoc.h "#include" EdgeTableView.h "#include" FillPolygon.h "#ifdef _debug#define new Debug_new#undef This_ Filestatic char this_file[] = __file__; #endif///////////////////////////////////////////////////////////////////// Cedgetableviewimplement_dyncreate (Cedgetableview, CView) begin_message_map (Cedgetableview, CView)//{{ Afx_msg_map (Cedgetableview) on_command (Idm_menu_fill, Onmenufill)//}}afx_msg_mapend_message_map ()/////////////// Cedgetableview construction/ Destructioncedgetableview::cedgetableview () {pfill = new Cfillpolygon; Initializes an object}cedgetableview::~cedgetableview () {delete Pfill;} BOOL Cedgetableview::P Recreatewindow (createstruct& cs) {//todo:modify the Window class or styles here by modifying// The createstruct csreturn CView::P Recreatewindow (CS);} ////////////////////////////////////Cedgetableview drawingvoid Cedgetableview::ondraw (cdc* PDC) { cedgetabledoc* PDoc = GetDocument (); Assert_valid (PDOC);//Connect 7 vertices together Pfill->showpolygon (PDC);} Cedgetableview Diagnostics#ifdef _debugvoid cedgetableview::assertvalid () Const{cview::assertvalid ();} void Cedgetableview::D UMP (cdumpcontext& DC) Const{cview::D UMP (DC);} cedgetabledoc* cedgetableview::getdocument ()//Non-debug version is Inline{assert (M_pdocument->iskindof (RUNTIME_ CLASS (Cedgetabledoc)); return (cedgetabledoc*) m_pdocument;} #endif//_debug///////////////////////////////////////////////////////////////////////////////CEdgeTableView Message handlersvoid Cedgetableview::onmenufill () {CCLIENTDC DC (this); CColorDialog CCD (RGB); if (CCD. DoModal () ==idok)//Call the palette to select the foreground color {RGB=CCD. GetColor (); } RedrawWindow (); Refresh screen Pfill->creatbucket (); Initialize Bucket PFilL->createdge (); Used to establish the edge table Pfill->polygonfill (&DC, RGB); Polygon Fill}
5) Operation effect
Original address: http://blog.csdn.net/qingdujun/article/details/40154077
References: 1) Basic Computer Graphics tutorial (Visual C + + Edition) (2nd edition) Konglingde
2) TMLJS1988,CSDN Blog, polygon effective edge table filling algorithm, http://blog.csdn.net/tmljs1988/article/details/5985914
Effective edge table filling algorithm for computer graphics (6)