Thuật toán tô màu dựa theo đường biên Khác với thuật toán tô màu dựa theo dòng quét, đường biên của vùng tô được xác định bởi tập các đỉnh của một đa giác, đường biên trong thuật toán đư
Trang 1aIntersectPt.NumPt = 0;
for(int i=FirstId; i<=LastId; i++)
{
if(EdgeList.aEdge[i].DeltaY>0)
{
aIntersectPt.xPt[aIntersectPt.NumPt]
= EdgeList.aEdge[i].xIntersect;
aIntersectPt.NumPt++;
}
}
SortOnX(aIntersectPt);
} //FindXIntersection
#define Round(x) int(x+0.5)
void FillLine(XINTERSECT aIntersectPt, int yScan) {
for(int i=0; i<aIntersectPt.NumPt; i+=2)
line(Round(aIntersectPt.xPt[i]), yScan,
Round(aIntersectPt.xPt[i+1]), yScan);
} // FillLine
void UpdateEdgeList(EDGELIST &EdgeList,int FirstId,int LastId)
{
for(int i=FirstId; i<=LastId; i++)
{
if(EdgeList.aEdge[i].DeltaY>0)
{
EdgeList.aEdge[i].DeltaY ;
Trang 2EdgeList.aEdge[i].xIntersect +=
EdgeList.aEdge[i].dxPerScan;
}
}
} //FillLine
void ScanLineFill(POLYGON P)
{
EDGELIST EdgeList;
XINTERSECT aIntersectPt;
int TopScan, BottomScan, FirstId, LastId;
MakeSortedEdge(P, EdgeList, TopScan, BottomScan); FirstId = LastId = 0;
for(int i=BottomScan; i<=TopScan; i++)
{
// Cap nhat lai danh sach cac canh
active - tuc la cac canh cat dong quet i UpdateActiveEdgeList(EdgeList, i,
FirstId, LastId);
// Tim cac hoanh do giao diem cua
dong quet voi cac canh cua da giac va sap xep lai cac hoanh do giao diem
truc tiep tren EdgeList
FindXIntersection(EdgeList,
aIntersectPt, FirstId, LastId);
FillLine(aIntersectPt, i);
UpdateEdgeList(EdgeList, FirstId,
LastId);
}
} //ScanLineFill
Trang 3Lưu đồ thuật toán tô màu theo dòng quét
3.2 Thuật toán tô màu dựa theo đường biên
Khác với thuật toán tô màu dựa theo dòng quét, đường biên của vùng tô được xác định bởi tập các đỉnh của một đa giác, đường biên trong thuật toán được mô tả bằng một giá trị duy nhất đó là màu
của tất cả các điểm thuộc về đường biên
Bắt đầu từ điểm nằm bên trong vùng tô, ta sẽ kiểm tra các điểm lân cận của nó đã được tô màu hay
có phải là điểm biên hay không, nếu không phải là điểm đã tô và không phải là điểm biên ta sẽ tô
màu nó Quá trình này được lặp lại cho tới khi nào không còn tô được điểm nào nữa thì dừng
Bằng cách này, toàn bộ các điểm thuộc vùng tô được kiểm tra và sẽ được tô hết
Trang 4Hình 2.24 – Thuật toán tô màu dựa theo đường biên
Có hai quan điểm về cách tô này, đó là dùng bốn điểm lân cận hay tám điểm lân cận đối với điểm
đang xét được tô bằng màu trắng (xem hình 2.25).
Hình 2.25 – 4 điểm lân cận (a) và 8 điểm lân cận (b)
Đoạn chương trình sau minh họa cài đặt thuật toán tô màu dựa theo đường biên sử dụng phương pháp tô 4 điểm lân cận
Cài đặt minh họa thuật toán tô màu dựa theo đường biên
void BoundaryFill(int x, int y, int FillColor, int BoundaryColor)
{
int CurrentColor;
CurrentColor = getpixel(x,y);
if((CurrentColor!=BoundaryColor)&&CurrentColor!= FillColor))
{
putpixel(x,y,FillColor);
BoundaryFill(x-1, y, FillColor, BoundaryColor);
BoundaryFill(x, y+1, FillColor, BoundaryColor);
Trang 5BoundaryFill(x+1, y, FillColor, BoundaryColor);
BoundaryFill(x, y-1, FillColor, BoundaryColor);
}
} // Boundary Fill
Nhận xét
Thuật toán này có thể sẽ không hoạt động chính xác khi có một số điểm nằm trong vùng tô có màu là màu cần tô của vùng (FillColor) Để khắc phục điều này, trước khi tô màu cần phải đảm bảo rằng toàn bộ các điểm thuộc về vùng
tô có màu khác màu tô
Nhận xét rằng trong cài đặt thuật toán ở trên, việc gọi thực hiện đệ quy thuật toán cho bốn điểm lân cận của điểm hiện hành không quan tâm tới một trong bốn điểm đó đã được xét ở bước trước hay chưa Ví dụ khi ta xét bốn điểm lân cận của điểm hiện hành (x,y), thì khi gọi thực hiện đệ quy với điểm hiện hành
là một trong bốn điểm lân cận trên, (x,y) vẫn được xem là điểm lân cận của chúng và lại được gọi thực hiện lại Ta sẽ đưa ra một cải tiến nhỏ để khắc phục điểm này, bằng cách mỗi lần xét điểm hiện hành (x,y) ta sẽ gọi 4 thủ tục riêng
để tô các điểm lân cận và trong 4 thủ tục này ta sẽ tránh gọi lại việc xét điểm (x,y)
void BoundaryFillEnhanced(int x, int y, int F_Color, int B_Color)
{
int CurrentColor;
CurrentColor = getpixel(x,y);
if((CurrentColor!=B_Color)&&CurrentColor!= F_Color))
{
putpixel(x,y,F_Color);
FillLeft(x-1, y, F_Color, B_Color);
FillTop(x, y+1, F_Color, B_Color);
FillRight(x+1, y, F_Color, B_Color);
FillBottom(x, y-1, F_Color, B_Color);
}