📄 polygon.h
字号:
/* ---------------------------------------------------------------------------------------------------
*
* Windows CE Graphics Libary v1.00.0000
*
*
* Written by James.
* Bug report : jiet@msn.com
* Copyright 2001
*/
// File: Polygon.h
// polygon-filling code.
//-----------------------------------------------------------------------------------------------------
// Update Information.
//-----------------------------------------------------------------------------------------------------
/*
* Created by James D. 2001.
* Date: 01/11/2001
*/
#include "CEGDefine.h"
#define CONVEX 0
#define NONCONVEX 1
#define COMPLEX 2
#define CONVEX_CODE_LINKED
/* Describes a series of points (used to store a list of vertices that
describe a polygon; each vertex connects to the two adjacent
vertices; the last vertex is assumed to connect to the first) */
typedef struct PtListHeader {
int Length; /* # of points */
POINT * PointPtr; /* pointer to list of points */
}PtListHeader;
typedef struct FloatPtListHeader {
int Length; /* # of points */
FLOATPOINT * PointPtr; /* pointer to list of points */
}FloatPtListHeader;
/* Describes the beginning and ending X coordinates of a single
horizontal line (used only by fast polygon fill code) */
struct HorLine {
int XStart; /* X coordinate of leftmost pixel in line */
int XEnd; /* X coordinate of rightmost pixel in line */
};
/* Describes a Length-long series of horizontal lines, all assumed to
be on contiguous scan lines starting at YStart and proceeding
downward (used to describe a scan-converted polygon to the
low-level hardware-dependent drawing code) (used only by fast
polygon fill code) */
struct HorLineList {
int Length; /* # of horizontal lines */
int YStart; /* Y coordinate of topmost line */
struct HorLine * HLinePtr; /* pointer to list of horz lines */
};
#define SWAP(a,b) {temp = a; a = b; b = temp;}
struct EdgeState {
struct EdgeState *NextEdge;
int X;
int StartY;
int WholePixelXMove;
int XDirection;
int ErrorTerm;
int ErrorTermAdjUp;
int ErrorTermAdjDown;
int Count;
};
/* Pointers to global edge table (GET) and active edge table (AET) */
static struct EdgeState *GETPtr, *AETPtr;
int FillPolygon(PtListHeader * VertexList, int PolygonShape, int XOffset, int YOffset, CCEDraw* pDraw);
int FillFloatPolygon(FloatPtListHeader * VertexList, int PolygonShape, int XOffset, int YOffset, CCEDraw* pDraw);
void DrawHorizontalLineSeg(int, int, int, CCEDraw* pDraw);
int FillConvexPolygon(PtListHeader *, int, int, CCEDraw* pDraw);
int FillConvexFloatPolygon(FloatPtListHeader *, int, int, CCEDraw* pDraw);
void BuildGET(PtListHeader *, struct EdgeState *,
int, int);
void BuildFloatGET(FloatPtListHeader *, struct EdgeState *,
int, int);
void MoveXSortedToAET(int);
void ScanOutAET(int, CCEDraw* pDraw);
void AdvanceAET(void);
void XSortAET(void);
void DrawHorizontalLineList(struct HorLineList *, CCEDraw* pDraw );
int FillPolygon(PtListHeader * VertexList, int PolygonShape, int XOffset, int YOffset, CCEDraw* pDraw)
{
struct EdgeState *EdgeTableBuffer;
int CurrentY;
#ifdef CONVEX_CODE_LINKED
/* Pass convex polygons through to fast convex polygon filler */
if (PolygonShape == CONVEX)
return(FillConvexPolygon(VertexList, XOffset, YOffset, pDraw));
#endif
/* It takes a minimum of 3 vertices to cause any pixels to be
drawn; reject polygons that are guaranteed to be invisible */
if (VertexList->Length < 3)
return(1);
/* Get enough memory to store the entire edge table */
if ((EdgeTableBuffer =
(struct EdgeState *) (malloc(sizeof(struct EdgeState) *
VertexList->Length))) == NULL)
return(0); /* couldn't get memory for the edge table */
/* Build the global edge table */
BuildGET(VertexList, EdgeTableBuffer, XOffset, YOffset);
/* Scan down through the polygon edges, one scan line at a time,
so long as at least one edge remains in either the GET or AET */
AETPtr = NULL; /* initialize the active edge table to empty */
if( GETPtr != NULL ) CurrentY = GETPtr->StartY; /* start at the top polygon vertex */
while ((GETPtr != NULL) || (AETPtr != NULL)) {
MoveXSortedToAET(CurrentY); /* update AET for this scan line */
ScanOutAET(CurrentY, pDraw); /* draw this scan line from AET */
AdvanceAET(); /* advance AET edges 1 scan line */
XSortAET(); /* resort on X */
CurrentY++; /* advance to the next scan line */
}
/* Release the memory we've allocated and we're done */
free(EdgeTableBuffer);
return(1);
}
int FillFloatPolygon(FloatPtListHeader * VertexList, int PolygonShape, int XOffset, int YOffset, CCEDraw* pDraw)
{
struct EdgeState *EdgeTableBuffer;
int CurrentY;
#ifdef CONVEX_CODE_LINKED
/* Pass convex polygons through to fast convex polygon filler */
if (PolygonShape == CONVEX)
return(FillConvexFloatPolygon(VertexList, XOffset, YOffset, pDraw));
#endif
/* It takes a minimum of 3 vertices to cause any pixels to be
drawn; reject polygons that are guaranteed to be invisible */
if (VertexList->Length < 3)
return(1);
/* Get enough memory to store the entire edge table */
if ((EdgeTableBuffer =
(struct EdgeState *) (malloc(sizeof(struct EdgeState) *
VertexList->Length))) == NULL)
return(0); /* couldn't get memory for the edge table */
/* Build the global edge table */
BuildFloatGET(VertexList, EdgeTableBuffer, XOffset, YOffset);
/* Scan down through the polygon edges, one scan line at a time,
so long as at least one edge remains in either the GET or AET */
AETPtr = NULL; /* initialize the active edge table to empty */
if( GETPtr != NULL ) CurrentY = GETPtr->StartY; /* start at the top polygon vertex */
while ((GETPtr != NULL) || (AETPtr != NULL)) {
MoveXSortedToAET(CurrentY); /* update AET for this scan line */
ScanOutAET(CurrentY, pDraw); /* draw this scan line from AET */
AdvanceAET(); /* advance AET edges 1 scan line */
XSortAET(); /* resort on X */
CurrentY++; /* advance to the next scan line */
}
/* Release the memory we've allocated and we're done */
free(EdgeTableBuffer);
return(1);
}
void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
int SkipFirst, struct HorLine **EdgePointPtr)
{
int DeltaX, Height, Width, AdvanceAmt, ErrorTerm, i;
int ErrorTermAdvance, XMajorAdvanceAmt;
struct HorLine *WorkingEdgePointPtr;
WorkingEdgePointPtr = *EdgePointPtr; /* avoid double dereference */
AdvanceAmt = ((DeltaX = X2 - X1) > 0) ? 1 : -1;
/* direction in which X moves (Y2 is
always > Y1, so Y always counts up) */
if ((Height = Y2 - Y1) <= 0) /* Y length of the edge */
return; /* guard against 0-length and horizontal edges */
/* Figure out whether the edge is vertical, diagonal, X-major
(mostly horizontal), or Y-major (mostly vertical) and handle
appropriately */
if ((Width = abs(DeltaX)) == 0) {
/* The edge is vertical; special-case by just storing the same
X coordinate for every scan line */
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePointPtr->XStart = X1;
else
WorkingEdgePointPtr->XEnd = X1;
}
} else if (Width == Height) {
/* The edge is diagonal; special-case by advancing the X
coordinate 1 pixel for each scan line */
if (SkipFirst) /* skip the first point if so indicated */
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePointPtr->XStart = X1;
else
WorkingEdgePointPtr->XEnd = X1;
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
}
} else if (Height > Width) {
/* Edge is closer to vertical than horizontal (Y-major) */
if (DeltaX >= 0)
ErrorTerm = 0; /* initial error term going left->right */
else
ErrorTerm = -Height + 1; /* going right->left */
if (SkipFirst) { /* skip the first point if so indicated */
/* Determine whether it's time for the X coord to advance */
if ((ErrorTerm += Width) > 0) {
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
ErrorTerm -= Height; /* advance ErrorTerm to next point */
}
}
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePointPtr->XStart = X1;
else
WorkingEdgePointPtr->XEnd = X1;
/* Determine whether it's time for the X coord to advance */
if ((ErrorTerm += Width) > 0) {
X1 += AdvanceAmt; /* move 1 pixel to the left or right */
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
}
}
} else {
/* Edge is closer to horizontal than vertical (X-major) */
/* Minimum distance to advance X each time */
XMajorAdvanceAmt = (Width / Height) * AdvanceAmt;
/* Error term advance for deciding when to advance X 1 extra */
ErrorTermAdvance = Width % Height;
if (DeltaX >= 0)
ErrorTerm = 0; /* initial error term going left->right */
else
ErrorTerm = -Height + 1; /* going right->left */
if (SkipFirst) { /* skip the first point if so indicated */
X1 += XMajorAdvanceAmt; /* move X minimum distance */
/* Determine whether it's time for X to advance one extra */
if ((ErrorTerm += ErrorTermAdvance) > 0) {
X1 += AdvanceAmt; /* move X one more */
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
}
}
/* Scan the edge for each scan line in turn */
for (i = Height - SkipFirst; i-- > 0; WorkingEdgePointPtr++) {
/* Store the X coordinate in the appropriate edge list */
if (SetXStart == 1)
WorkingEdgePointPtr->XStart = X1;
else
WorkingEdgePointPtr->XEnd = X1;
X1 += XMajorAdvanceAmt; /* move X minimum distance */
/* Determine whether it's time for X to advance one extra */
if ((ErrorTerm += ErrorTermAdvance) > 0) {
X1 += AdvanceAmt; /* move X one more */
ErrorTerm -= Height; /* advance ErrorTerm to correspond */
}
}
}
*EdgePointPtr = WorkingEdgePointPtr; /* advance caller's ptr */
}
void DrawHorizontalLineSeg(int Y, int LeftX, int RightX, CCEDraw* pDraw) {
int X;
pDraw->DrawHLine( LeftX, Y, RightX, Y, pDraw->m_pBrush->m_Color );
/* Draw each pixel in the horizontal line segment, starting with
the leftmost one */
//for (X = LeftX; X <= RightX; X++)
//pDraw->DrawPixel( X, Y, pDraw->m_pBrush->m_Color );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -