//////////////////////////////////////// //////////////////////////////////////// //////////////////
// Function: Fill the Polygon
//
// Parameter: lppoints: pointer to the vertex coordinate array. The array type is point, and the polygon are closed and connected sequentially.
// Ncount: Number of vertices
// Ncolor: The filled color is black by default.
// PDC: Device handle pointer
//
// Return: No Return Value
//
// Description: it can be a polygon with overlapping edges.
//
// Create (modify): Cao Hai
//////////////////////////////////////// //////////////////////////////////////// //////////////////
Void fillpolygon (lppoint lppoints, int ncount, CDC * PDC, int ncolor/* = 0 */)
{
// Check the validity of parameters
Assert_valid (PDC );
Assert (lppoints );
Assert (ncount> 2 );
Assert (ncolor> = 0 );
// Edge Structure Data Type
Typedef struct edge {
Int Ymax; // The maximum y coordinate of an edge
Float X; // X coordinate of the intersection with the current scanned line
Float DX; // the reciprocal of the slope of the straight line where the edge is located
Struct edge * pnext; // point to the next edge
} Edge, * lpedge;
Int I = 0, j = 0, K = 0;
Int Y0 = 0, Y1 = 0; // The maximum and minimum Y coordinates of the scanning line
Lpedge Paet = NULL; // activates the edge header pointer
Lpedge * PET = NULL; // edge header pointer
Paet = new edge; // initialize the header pointer. The first element is not required.
Paet-> pnext = NULL;
// Obtain the scanning line boundary in the Y direction
Y0 = Y1 = lppoints [0]. Y;
For (I = 1; I <ncount; I ++)
{
If (lppoints [I]. Y <y0)
Y0 = lppoints [I]. Y;
Else if (lppoints [I]. Y> Y1)
Y1 = lppoints [I]. Y;
}
If (y0> = Y1) return;
// Initialize the edge table. The first element is not required.
PET = new lpedge [y1-y0 + 1];
For (I = 0; I <= y1-y0; I ++)
{
Pet [I] = new edge;
Pet [I]-> pnext = NULL;
}
For (I = 0; I <ncount; I ++)
{
J = (I + 1) % ncount; // next point of the edge
If (lppoints [I]. y! = Lppoints [J]. Y) // If the edge is not horizontal, add it to the edge table.
{
Lpedge peg; // pointer to this edge
Lpedge ppeg; // pointer to the edge pointer
// Construct an edge
Peg = new edge;
K = (lppoints [I]. Y> lppoints [J]. Y )? I: J;
Peg-> Ymax = lppoints [K]. Y; // maximum y coordinate of the edge
K = (k = J )? I: J;
Peg-> X = (float) lppoints [K]. X; // coordinates of the side and the scanning line focus X
If (lppoints [I]. y! = Lppoints [J]. Y)
Peg-> dx = (float) (lppoints [I]. x-lppoints [J]. x)/(lppoints [I]. y-lppoints [J]. y); // reciprocal of the edge slope
Peg-> pnext = NULL;
// Insert edge
Ppeg = pet [lppoints [K]. y-y0];
While (ppeg-> pnext)
Ppeg = ppeg-> pnext;
Ppeg-> pnext = peg;
} // End if
} // End for I
// Scan
For (I = y0; I <= Y1; I ++)
{
Lpedge peg0 = pet [i-y0]-> pnext;
Lpedge peg1 = pet [i-y0];
If (peg0) // Add a new edge
{
While (peg1-> pnext)
Peg1 = peg1-> pnext;
Peg1-> pnext = Paet-> pnext;
Paet-> pnext = peg0;
}
// Sort Paet in ascending order of X
Peg0 = Paet;
While (peg0-> pnext)
{
Lpedge pegmax = peg0;
Lpedge peg1 = peg0;
Lpedge PEGI = NULL;
While (peg1-> pnext)
{
If (peg1-> pnext-> x> pegmax-> pnext-> X)
Pegmax = peg1;
Peg1 = peg1-> pnext;
}
PEGI = pegmax-> pnext;
Pegmax-> pnext = PEGI-> pnext;
PEGI-> pnext = Paet-> pnext;
Paet-> pnext = PEGI;
If (peg0 = Paet)
Peg0 = PEGI;
}
// Traverse the active edge table and draw lines
Peg0 = Paet;
While (peg0-> pnext)
{
If (peg0-> pnext)
{
Drawline (INT) peg0-> pnext-> X, I, (INT) peg0-> pnext-> X, I, PDC, ncolor );
Peg0 = peg0-> pnext;
}
Else
Break;
}
// Delete the Ymax = I node from the active edge table and increase the X value of each node to DX
Peg0 = Paet;
While (peg0-> pnext)
{
If (peg0-> pnext-> Ymax <I + 2)
{
Peg1 = peg0-> pnext;
Peg0-> pnext = peg0-> pnext; // Delete
Delete peg1;
Continue;
}
Peg0-> pnext-> X + = peg0-> pnext-> DX; // increase the X value of each node by DX
Peg0 = peg0-> pnext;
}
}
// Delete an edge table
For (I = 0; I <y1-y0; I ++)
If (PET [I])
Delete pet [I];
If (Paet)
Delete Paet;
If (PET)
Delete [] PET;
}