컴퓨터 그래픽스 과제 # 3

학번 : 20021558	성명 : 경규성

<Scan Converting Polygon>

1. 소스코드

void CscanlineView::OnDraw(CDC* /*pDC*/)

{

CscanlineDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!pDoc)

return;

float dot[6] = {100, 100, 300, 500, 200, 500};

fill_triangle(dot);

// TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.

}

void CscanlineView::fill_triangle(float dot[])

{

int ymax = 399;

Triangle=3;

Edges = new Edge*[ymax];	// Edge List 선언

pts = new Point[Triangle];	// 점들 n 개 선언

for(int cnt1=0; cnt1 < Triangle; cnt1++)	// dot의 점들로 pts 초기화

{

pts[cnt1].x = (dot[(cnt1*2)]);

pts[cnt1].y = (dot[(cnt1*2)+1]);

}

//Polygon(Triangle, pts);

for(int cnt2=0; cnt2 < ymax; cnt2++)	//

{

Edges[cnt2] = new Edge;	// 에지 할당

Edges[cnt2]->next = NULL;

}

creatEL(Triangle, pts);

Active = new Edge;

Active->next = NULL; // AEL 초기화

/*

CClientDC dc(this);	// 삼각형의 좌표 출력. 지저분하여 안했다.

for(int test=0; test<Triangle; test++){

CString string1;

string1.Format(_T("  %d , %d "), (int)pts[test].x, (int)pts[test].y);

dc.TextOutW(pts[test].x, pts[test].y, string1);

}

*/

for(int scan=0; scan < ymax; scan++)

{

creatAEL(scan);

if(Active->next)

{

ResortAEL(scan); //실제로 scanfill이 일어나는 부분

UpdateAEL(scan);

ResortAEL();

}

}

}

void CscanlineView::creatEL(int n, Point pts[])

{

Edge* edge;

int yprev=0;

Point p1, p2;	// 임의의 두개의 점 설정

p1.x = pts[n-1].x;	// pts배열의 점들중 가장 마지막 [n-1]값 을 p1 으로

p1.y = pts[n-1].y;

for(int count=0; count<n; count++)

{

p2.x = pts[count].x;	//pts 배열 점들중 가장 처음 pts[0]~[n-1] 까지 p1 에 넣어서

p2.y = pts[count].y;

if(p1.y != p2.y && p1.x != p2.x)	// p1 과 p2 의 y값이 다르면

{

edge = new Edge; // 다른 점이므로 Edge를 만든다.

if(p1.y < p2.y)

makeEdge(p1, p2, edge, ynext(count)); // y값크기에 따라 다른 호출

else

makeEdge(p2, p1, edge, yprev);

}

yprev = p1.y;

p1.x = p2.x;

p1.y = p2.y;

}

}

int CscanlineView::ynext(int ycount) // 다음 Y값 계산

{

int jcount;

if(ycount+1 > Triangle-1)

jcount = 0;

else

jcount = ycount+1;

while(pts[ycount].y == pts[jcount].y)

{

if(jcount+1 > (Triangle-1))

jcount = 0;

else

jcount++;

}

return (pts[jcount].y);

}

void CscanlineView::makeEdge(Point low, Point high, Edge* edge, int ycomp)

{

edge->yupper = (int)low.y;	// 작은 y

edge->dxperscan = ((high.y - low.y)/(high.x - low.x));

edge->xinter = low.x;

if(high.y < ycomp)

edge->yupper = (high.y-1);

else

edge->yupper = high.y;

insertEdge(Edges[(int)low.y], edge);

}

void CscanlineView::insertEdge(Edge* list, Edge* edge)

{

Edge *ptr, *temp;

ptr = list; // ptr은 리스트의 시작

temp = ptr->next; // temp 는 ptr의 다음 노드, ptr - temp

while(temp!=NULL)

{

if(edge->xinter < temp->xinter)

temp=NULL;

else

{

ptr = temp; // 한노드 옴긴다

temp = temp->next;

}

}

edge->next = ptr->next;	// listnode에 뒤에 edge 삽입

ptr->next = edge;

}

void CscanlineView::creatAEL(int scan) // AEL 생성

{

Edge *temp, *ptr;

temp = Edges[scan]->next;

while(temp)

{

ptr = temp->next;

insertEdge(Active, temp);

temp = ptr;

}

}

void CscanlineView::ResortAEL(int scan) // AEL 재정렬

{

CClientDC cdc(this);

Edge *iedge, *jedge;

float icount;

iedge = Active->next;

while(iedge != NULL)

{

jedge = iedge->next;

for(icount = iedge->xinter; icount <= jedge->xinter-1; icount++)

cdc.SetPixel(icount, scan, icount);

iedge=jedge->next;

}

}

void CscanlineView::UpdateAEL(int scan) // AEL 리프래쉬

{

Edge *pedge, *ptr;

ptr = Active;

pedge = Active->next;

while(pedge)

{

if(scan >= pedge->yupper) // 스캔이 에지 끝에 도달하면

{

pedge = pedge->next; // 지난 에지는 지우고 pedge는 다음

deleteAfter(ptr);

}

else

{

pedge->xinter= pedge->xinter + pedge->dxperscan;

ptr = pedge;

pedge = pedge->next;

}

}

}

void CscanlineView::ResortAEL()

{

Edge *pedge, *ptr;

pedge = Active->next;

Active->next=NULL;

while(pedge)

{

ptr = pedge->next;

insertEdge(Active, pedge);

pedge = ptr;

}

}

void CscanlineView::deleteAfter(Edge* ptr)

{

Edge *pedge = ptr->next; //리스트에서 지난 에지 삭제

ptr->next = pedge->next;

delete pedge;

}

2. 실행화면

솔직히 EL, AEL 생성 관리는 되는데, 다음 에지로 넘어가면 그려지질 않았다.