이 ν¬μŠ€νŒ…μ€ 쿠팑 νŒŒνŠΈλ„ˆμŠ€ ν™œλ™μ˜ μΌν™˜μœΌλ‘œ, 이에 λ”°λ₯Έ μΌμ •μ•‘μ˜ 수수료λ₯Ό μ œκ³΅λ°›μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

λ°˜μ‘ν˜•

학ꡐ 과제둜 μ œμΆœν–ˆλ˜ μŠ€μΊ”λΌμΈ 폴리곀 ν•„ 및 λ°”μš΄λ”λ¦¬ 4-웨이 폴리곀 ν•„ ^.^

λ‹€κ°ν˜•μ±„μš°κΈ°!!


μ£Όμš” μ†ŒμŠ€ μ½”λ“œ


//━━━━━━━━━━━━━━━━━━━━━━━━┓
                         
//  ─━ μ œμž‘μž : ν˜Όλˆμ†μ˜ 지남차
//  ─━ λͺ©  적 : 학ꡐ 과제
//  ─━ κ³Ό  λͺ© : 컴퓨터 κ·Έλž˜ν”½μŠ€
//  ─━ μ£Ό  제 : λ‹€κ°ν˜• 색 μ±„μš°κΈ°.
//  ─━ λ°©  법 : Scanline fill & Flood Fill
//  ─━ λ‚   짜 : 2008. 10. 3 03:46 AM

//━━━━━━━━━━━━━━━━━━━━━━━━┛
#include <windows.h>
#include "defines.h"  //μ•ˆμ— 각쒅 ν—€λ”νŒŒμΌ 및 define듀이 μ“°μ—¬μ ΈμžˆμŒ.
#include "GLPoints.h" //(x,y)νŠœν”Œ

void scanLine(vector<CGLPoints>& vecGLPoints); //vertexλ­‰μΉ˜λ₯Ό 인자둜 λ°›μ•„ ScanlineFill

// μž¬κ·€ν•¨μˆ˜ μ΄μš©ν•œ version 1 (λ„ν˜•ν¬κΈ°κ°€ 컀지면 μ˜€λ²„ν”Œλ‘œμš° λ°œμƒ)

/*

void boundary_fill(int x, int y, BYTE* byBoundaryColor)
{

    cout << x << " " << y << endl;
    //ν˜„μž¬ν”½μ…€μ΄ ν…Œλ‘λ¦¬μƒ‰μ΄λž‘ κ°™μœΌλ©΄ 쀑단.
    BYTE byCurrerntColor[3];
    glReadPixels(x,WINSIZEY-y,1,1,GL_RGB,GL_UNSIGNED_BYTE,byCurrerntColor);
    if((byBoundaryColor[0] == byCurrerntColor[0]
        && byBoundaryColor[1] == byCurrerntColor[1]
        && byBoundaryColor[2] == byCurrerntColor[2] )|| x<=0||WINSIZEY<=y||WINSIZEX<=x||WINSIZEY<=WINSIZEY-y || matrix[x][WINSIZEY-y] == true )
    {
        return ;
    }
    else
    {
        matrix[x][WINSIZEY-y]=true;
        glColor3f(1.0, 1.0, 0.0);
        setPixel(x,WINSIZEY-y);

        boundary_fill(x+1, y, byBoundaryColor);
        boundary_fill(x, y-1, byBoundaryColor);

        boundary_fill(x-1, y, byBoundaryColor);
        boundary_fill(x, y+1, byBoundaryColor);

    }

}

*/



// 자체 μŠ€νƒμ„ μ΄μš©ν•œ version2 - λ„ν˜•μ˜ 크기가 컀도 잘 λ™μž‘ !! :)
void
boundary_fill(int x, int y, BYTE* byBoundaryColor)
{

  stack< CGLPoints > stackStoreCoords;

  stackStoreCoords.push(*(new CGLPoints(x,y)));
  cout << x << " " << y << endl;
  //ν˜„μž¬ν”½μ…€μ΄ ν…Œλ‘λ¦¬μƒ‰μ΄λž‘ κ°™μœΌλ©΄ 쀑단.
  BYTE byCurrerntColor[3];
  do
  {
    int nX = stackStoreCoords.top().GetX();
    int nY = stackStoreCoords.top().GetY();
    glReadPixels(nX
      ,WINSIZEY-(nY),1,1,GL_RGB,GL_UNSIGNED_BYTE,byCurrerntColor);
    if((byBoundaryColor[0] == byCurrerntColor[0]
      && byBoundaryColor[1] == byCurrerntColor[1]
      && byBoundaryColor[2] == byCurrerntColor[2] )
    )//  || nX<=0  \
      ||WINSIZEY<=nY  \
      ||WINSIZEX<=nX  \
      ||WINSIZEY<=WINSIZEY-nY  \
      || matrix[nX][WINSIZEY-nY] == true )
    {
      stackStoreCoords.pop();

    }
    else
    {
    //  matrix[nX][WINSIZEY-nY]=true;
      glColor3f(1.0, 1.0, 0.0);
      setPixel(nX,WINSIZEY-nY); //점을 찍고 μŠ€νƒμ—λ‹€ 4λ°©ν–₯을 μŒ“λŠ”λ‹€.
      stackStoreCoords.push(*(new CGLPoints(nX+1,nY)));
      stackStoreCoords.push(*(new CGLPoints(nX,nY-1)));
      stackStoreCoords.push(*(new CGLPoints(nX-1,nY)));
      stackStoreCoords.push(*(new CGLPoints(nX,nY+1)));
     
    }

  } while(!stackStoreCoords.empty()); //μŠ€νƒμ΄ λΉ„λ©΄ 루프λ₯Ό λΉ μ Έλ‚˜μ˜¨λ‹€.


}
//CGLPoints클래슀λ₯Ό yμ’Œν‘œ κΈ°μ€€μœΌλ‘œ μ •λ ¬ν• λ•Œ λΉ„κ΅ν•¨μˆ˜.
bool LessByY(CGLPoints pt1, CGLPoints pt2)
{
  return (pt1.GetY()<pt2.GetY());
}
//━━━━━━━━━━━━━━━━━━━━━━━━━
//      ─━   메인 μ‹œμž‘ ━─
//━━━━━━━━━━━━━━━━━━━━━━━━━
void main(int argc, char** argv)
{
 //μƒλž΅
}
//━━━━━━━━━━━━━━━━━━━━━━━━━
//      ─━   ν•¨μˆ˜λ“€ μ •μ˜ ━─
//━━━━━━━━━━━━━━━━━━━━━━━━━

//μ΄ˆκΈ°ν™”
void init(void)
{
 //μƒλž΅
 
}



//점 찍기
void setPixel(GLint x, GLint y)
{
   //μƒλž΅
}

//μ„  κΈ‹κΈ°
void setLine(GLint x, GLint y, GLint x2, GLint y2)
{
  //μƒλž΅
}


//λ‹€κ°ν˜• μ„ κΈ‹κΈ° (점듀을 인자둜 λ°›λŠ”λ‹€)
void setPolyLine(vector<CGLPoints>& vecGLPoints)
{
  int nNumOfvertice = vecGLPoints.size();
  int i;
  for(i = 1 ; i < nNumOfvertice ; i++)
  {
    setLine(vecGLPoints[i-1].GetX(), vecGLPoints[i-1].GetY(), vecGLPoints[i].GetX(), vecGLPoints[i].GetY());
  }
  setLine(vecGLPoints[nNumOfvertice-1].GetX(), vecGLPoints[nNumOfvertice-1].GetY(), vecGLPoints[0].GetX(), vecGLPoints[0].GetY());
}

//μŠ€μΊ”λΌμΈ λ°©μ‹μœΌλ‘œ λ‹€κ°ν˜• λ‚΄λΆ€ μΉ ν•˜κΈ°(점듀을 인자둜 λ°›λŠ”λ‹€)
void scanLine(vector<CGLPoints>& vecGLPoints)
{
  int i,j;
  int color;
  int minY, maxY;
 
  //Xμ’Œν‘œμš©
  //yμ’Œν‘œλ₯Ό 킀이며 xμ’Œν‘œλ₯Ό value둜 ν•˜λŠ” 맡
  vector<int>*  vecScanLineYCoord = new vector<int>[WINSIZEY];

  CGLPoints* temp = new CGLPoints(0,0);
  //λ‹€κ°ν˜•μ˜ y의 μ΅œλŒ€κ°’κ³Ό μ΅œμ†Œκ°’μ„ μ°ΎλŠ”λ‹€.
  temp = min_element(vecGLPoints.begin(),vecGLPoints.end(),LessByY); //μ΅œμ†Œκ°’
  minY = temp->GetY();
  temp = max_element(vecGLPoints.begin(),vecGLPoints.end(),LessByY); //μ΅œλŒ€κ°’
  maxY = temp->GetY();

  //μ΅œμ†Œμ΅œλŒ€κ°’ μ½˜μ†”μΆœλ ₯(ν…ŒμŠ€νŠΈμš©)
  cout << minY << " "<< maxY << endl;

  int nLenth = vecGLPoints.size(); //μ λ“€μ˜ 갯수
  for(i = 1 ; i <= nLenth ; i++)
  {
    //λ‘μ μ˜ 기울기λ₯Ό ꡬ함.
    float fSlope =  float(vecGLPoints[i-1].GetY() - vecGLPoints[i%nLenth].GetY()) 
            / float(vecGLPoints[i-1].GetX() - vecGLPoints[i%nLenth].GetX());
    //λ‘μ μ˜ μ§μ„ μ˜ λ°©μ •μ‹μ˜ y절편
    // y-y2 == (y2-y1)/(x2-x1) * (x-x2)  where x == 0
    float yInterCept = fSlope*(-vecGLPoints[i-1].GetX())+vecGLPoints[i-1].GetY();
    //for문을 μ˜¬λ°”λ‘œ 돌리기 μœ„ν•΄ 두 vertex의 yμ’Œν‘œ λŒ€μ†ŒλΉ„κ΅ν•œλ‹€.
    int minimum, maximum;
    if(vecGLPoints[i-1].GetY()<vecGLPoints[i%nLenth].GetY())
    {
      minimum = vecGLPoints[i-1].GetY();
      maximum = vecGLPoints[i%nLenth].GetY();
    }
    else
    {
      minimum = vecGLPoints[i%nLenth].GetY();
      maximum = vecGLPoints[i-1].GetY();
    }
    for(j = minimum ; j < maximum ; j++ )
    {
      // jλŠ” yμ’Œν‘œμ΄λ©° xμ’Œν‘œλŠ” yμ’Œν‘œμ— μ ˆνŽΈμ„ 뺀값을 (1/기울기)λ₯Ό κ³±ν•΄μ£Όλ©΄ λ‚˜μ˜¨λ‹€. (y = mx + b μ—μ„œλ„μΆœ)
      vecScanLineYCoord[j].push_back((j-yInterCept)*(1.0f/fSlope));
    }

  }



  //각 scanLine yμ’Œν‘œμ—μ— μ €μž₯된 xμ’Œν‘œλ“€μ„ μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬ν•œλ‹€.
  for(i = minY ; i <= maxY ; i++)
    sort(vecScanLineYCoord[i].begin(),vecScanLineYCoord[i].end());
 

  //μŠ€μΊ”λΌμΈμ˜ μ΅œμ†Œκ°’μ—μ„œ μ΅œλŒ€κ°’κΉŒμ§€
  for(i = minY ; i < maxY ; i++)
  {

    //μ •λ ¬λœ Xμ’Œν‘œλ“€μ˜ PAIR듀을 선을 κ·Έμ–΄ 폴리곀에 색을 μ±„μš΄λ‹€.
    int nSize = vecScanLineYCoord[i].size();
    for(j = 0 ; j < nSize ; j+=2)
    {

      //μ½˜μ†” ν…ŒμŠ€νŠΈ 좜λ ₯
//      cout << "scanLine Y :  " << i << "Xμ’Œν‘œ Pair : " \
        <<vecScanLineYCoord[i][j%nSize]  << " "<< vecScanLineYCoord[i][(j+1)%nSize] << endl;
      setLine(vecScanLineYCoord[i][j%nSize],i,vecScanLineYCoord[i][(j+1)%nSize],i);//μ„ κΈ‹κΈ°
    }
  }
}
void displayFunc(void)
{
  int i;
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f(1.0, 1.0, 0.0);
  //  (x,y)νŠœν”Œλ“€μ„ κ°€μ§ˆμˆ˜ μžˆλŠ” 벑터선언
  vector<CGLPoints> vecPtVertice;

  //λžœλ€λ„ν˜•
  srand(GetTickCount());
//  for(i = 0 ; i < 100 ; i++)
//    vecPtVertice.push_back(*(new CGLPoints(rand()%WINSIZEX, rand()%WINSIZEY)     ));


  //ν°λ„ν˜•
  vecPtVertice.push_back(*(new CGLPoints(100,400)));
  vecPtVertice.push_back(*(new CGLPoints(300,200)));
  vecPtVertice.push_back(*(new CGLPoints(500,100)));
  vecPtVertice.push_back(*(new CGLPoints(700,300)));
  vecPtVertice.push_back(*(new CGLPoints(500,500)));
  vecPtVertice.push_back(*(new CGLPoints(400,350)));
  vecPtVertice.push_back(*(new CGLPoints(300,600)));

  //μž‘μ€λ„ν˜•
/* 
  vecPtVertice.push_back(*(new CGLPoints(226, 143)));
  vecPtVertice.push_back(*(new CGLPoints(216, 174)));
  vecPtVertice.push_back(*(new CGLPoints(270, 184)));
  vecPtVertice.push_back(*(new CGLPoints(287, 139)));
  vecPtVertice.push_back(*(new CGLPoints(247, 132)));
*/

  //ν…Œλ‘λ¦¬
  setPolyLine(vecPtVertice);

  if(g_MouseState.rightButton == true)
    scanLine(vecPtVertice); //μŠ€μΊ”λΌμΈμœΌλ‘œ λ‹€κ°ν˜•μ„ μ±„μš΄λ‹€. (인자둜 verticeλ„˜κΉ€)

  //마우슀λ₯Ό ν΄λ¦­ν•˜λ©΄ ν•΄λ‹Ήμ˜μ—­λΆ€ν„° Boundary_fill μ‹œμž‘.
  if(g_MouseState.leftButton==true)
  {
    glColor3f(1.0, 1.0, 0.0);
    BYTE byBoundaryColor[3]={255,255,0};
    DWORD dwBegin  = GetTickCount();
    boundary_fill(g_MouseState.x,g_MouseState.y,byBoundaryColor);
    DWORD dwEnd    = GetTickCount();
    cout << "Boundary_FILL μ†Œμš”μ‹œκ°„ : " << float((dwEnd - dwBegin)/1000.0f) << endl;
  }
  glFlush();
 
}

void HandleMouseState(int button, int state, int x, int y)
{
//μƒλž΅
}

 

μ‹€ ν–‰ ν™” λ©΄

 

Boundary Fill을 이용

μž¬κ·€ν•¨μˆ˜λ₯Ό μ΄μš©ν•œ Boundary_fill

image
κ·Έλ¦Ό1) 이 정도 ν¬κΈ°λŠ” λ¬Έμ œμ—†λ‹€

 
κ·Έλ¦Ό2) ν”„λ‘œκ·Έλž¨μ΄ λ©Žμ–΄λ²„λ¦°λ‹€.

 

κ·ΈλŸ¬λ‚˜ 이 μž¬κ·€ν•¨μˆ˜μ˜ λ¬Έμ œμ μ€ 폴리곀의 크기가 μ‹œμŠ€ν…œ μŠ€νƒμ΄ μ €μž₯ν•  수 μžˆλŠ” μž„κ³„κ°’μ„ λ„˜μœΌλ©΄ Stack Overflowκ°€ λ‚˜μ„œ
더 이상 진행을 λͺ»ν•˜κ³  ν”„λ‘œκ·Έλž¨ μžμ²΄κ°€ 죽어버린닀.

 

κ·Έλž˜μ„œ 자체적인 μŠ€νƒμ„ κ΅¬ν˜„ν•΄μ•Όν•˜λŠ”λ° (νž™ λ©”λͺ¨λ¦¬λ₯Ό μ¨μ„œ ν•œκ³„κ°’μ΄ 훨씬 큼) STL의 stack을 썼닀.

 


κ·Έλ¦Ό3> 자체적인 μŠ€νƒμ„ μ΄μš©ν•œ 비ꡐ적 큰 μ‚¬μ΄μ¦ˆμ˜ λ„ν˜• μƒ‰μ±„μš°κΈ°.

Scanline μ΄μš©ν•˜μ—¬ μ±„μš°κΈ°.

같은 λ„ν˜•μœΌλ‘œ μ‹€ν—˜ν–ˆμ„λ•Œ λ˜‘κ°™μ΄ μ±„μ›Œμ‘Œλ‹€.
차이점이라면 μˆ˜ν–‰μ†λ„λŠ” 0μ΄ˆμ— κ°€κΉκ²Œ 훨씬 λΉ λ₯΄κ²Œ μ±„μ›Œμ‘Œλ‹€.

점 백개λ₯Ό 랜덀으둜 찍어 μ˜¬λ°”λ₯΄κ²Œ μˆ˜ν–‰ν•˜λŠ”μ§€ ν…ŒμŠ€νŠΈ ν–ˆλ‹€.

λ„ν˜•μ˜ λ‚΄λΆ€ μ™ΈλΆ€λ₯Ό 잘 κ΅¬λΆ„ν•˜μ—¬ μ˜¬λ°”λ₯΄κ²Œ 색칠이 λ˜μ—ˆλ‹€.

 

 

 

Discussion


λ˜‘κ°™μ€ λ„ν˜•μ„ λ‹€λ₯Έ 두 λ°©μ‹μœΌλ‘œ μ±„μ› μ„λ•Œ μˆ˜ν–‰μ‹œκ°„

 
두 방식은 μ†Œμš”μ‹œκ°„μ—μ„œ μ—„μ²­λ‚œ 차이가 λ‚œλ‹€.

 

Scanline_fill 같은 κ²½μš°λŠ” μ§μ„ μ˜ 방정식을 μ΄μš©ν•œ coherence νŠΉμ§•μ„ μ΄μš©ν•΄μ„œ 거의 0μ΄ˆμ— κ°€κΉκ²Œ λ‚˜μ™”μ§€λ§Œ
Boundary_fill 같은 κ²½μš°λŠ” ν”½μ…€ν•˜λ‚˜μ”© μ°μ„λ•Œ λ§ˆλ‹€ glReadPixelsλ₯Ό ν˜ΈμΆœν•˜κΈ° λ•Œλ¬Έμ— 그에 λ”°λ₯Έ μ˜€λ²„ν—€λ“œ 및 ν•œμ  ν•œμ  처리λ₯Ό ν•˜κΈ° λ•Œλ¬Έμ— 21~24μ΄ˆμ— κ°€κΉŒμš΄ μ‹œκ°„μ΄ κ±Έλ Έλ‹€.(싀행화면에 μžˆλŠ” 큰 λ„ν˜•μ˜ 경우)

κ΅¬ν˜„μ‹œ μ–΄λ €μ› λ˜ 점은 glReadPixels의 y인자λ₯Ό 창의 Yν¬κΈ°μ—μ„œ λΊ€ 값을 λ„£μ–΄μ€˜μ•Ό μ˜¬λ°”λ₯΄κ²Œ μž‘λ™ν•˜λŠ” κ²ƒμ΄μ—ˆλ‹€.
이 것 λ•Œλ¬Έμ— 수 κ΅¬ν˜„μƒ 수 λ§Žμ€ μ‹œν–‰μ°©μ˜€λ₯Ό κ²ͺμ—ˆλ‹€.
OPENGLμ—μ„œλŠ” 맨 μ•„λž˜κ°€ yμ’Œν‘œ 0인 반면 μœˆλ„μš°μƒμ—μ„œ μ‹€μ œλ‘œ λ””μŠ€ν”Œλ ˆμ΄ 될 λ•ŒλŠ” 맨 μœ—μͺ½μ΄ 0으둜 μ°ν˜”λ‹€.

Scanline_fill κ΅¬ν˜„ μ‹œ ,두 점의 μ§μ„ μ˜ 방정식을 이용 y-y1 = (y2-y1)/(x2-x1)(x-x1)
두 점 μ‚¬μ΄μ—μ„œ μŠ€μΊ”λΌμΈκ°’μ„ 1증가 ν˜Ήμ€ κ°μ†Œ μ‹œν‚¬λ•Œ x값을 μΆ”μ •ν›„ κ·Έ xκ°’μ˜ yμΈλ±μŠ€μ— x의 λ°Έλ₯˜λ₯Ό λ„£μ–΄μ£Όκ³ 
λ‹€λ₯Έμ λ“€μ— λŒ€ν•΄μ„œλ„ 이와 같이 λ°˜λ³΅ν›„ μŠ€μΊ”λΌμΈμ˜ νŠΉμ • vectorλ₯Ό sortν•œν›„ pairλ₯Ό 이루게 ν•˜μ—¬ 선을 κ·Έμ–΄μ£Όμ—ˆλ‹€.

μ›λž˜ μ’€ 더 직관적인 방법인 μ•„λž˜μ—μ„œ λΆ€ν„° ν”½μ…€ν•˜λ‚˜ν•˜λ‚˜ κ²€μ‚¬ν•˜λ©° 점을 λ§Œλ‚˜λ©΄ 그리기 μ‹œμž‘ν•˜κ³  λ‹€μ‹œ λ§Œλ‚˜λ©΄ 그리기λ₯Ό μ€‘λ‹¨ν•˜λŠ” μ‹μœΌλ‘œ ν• λ €κ³  ν–ˆμœΌλ‚˜ μ‹œκ°„λ„ 많이 걸리고 μ˜ˆμ™Έμ‚¬ν•­μ΄ λ„ˆλ¬΄ 많이 λ‚˜μ™€μ„œ "직관적"이긴 ν•˜μ§€λ§Œ κ΅¬ν˜„μ‹œμ—λŠ”
coherence λ₯Ό μ΄μš©ν•œ 방법보닀 더 λ§Žμ€ μˆ˜κ³ λ‘œμ›€μ΄ ν•„μš”ν–ˆλ‹€. (μ‹€μ œλ‘œ OPENGL을 μ΄μš©ν•˜μ—¬ 선을 그으면 xμ’Œν‘œμ— 각도에 따라 2κ°œμ΄μƒμ˜ 점이 μ°νžˆλŠ” κ²½μš°κ°€ μžˆκΈ°λ•Œλ¬Έμ— μ±…μ—μ„œ λ‚˜μ˜¨ μ˜ˆμ™Έμ‚¬ν•­ 외에도 생각할 거리가 λ§Žλ‹€.)

Boundary fill 이 λ„ν˜•ν¬κΈ°μ— 따라 μ‹œκ°„μ΄ 달리 μ†Œμš”λ˜κΈ΄ ν•˜μ§€λ§Œ μœ„μ˜ μ‹€ν—˜μ—μ„œ 23μ΄ˆμ―”μŒ κ±Έλ¦¬λŠ”κ²ƒμ„ 보고 μ•½κ°„ 의문점이 λ“œλŠ”κ²ƒμ΄ , 포톡 Graphic νˆ΄μ—μ„œλ„ Boundary_fill μ΄λ‚˜ μˆ™μ œμ—” λ‚˜μ˜€μ§€ μ•Šμ€ Flood_fill 같은 방법 λ˜ν•œ μ‚¬μš©ν• ν…λ°
μ–΄λ–»κ²Œ κ·Έλ ‡κ²Œ 짧은 μˆœκ°„μ— λ‹€κ°ν˜•μ„ μΉ ν•  수 μžˆλŠ”μ§€ κΆκΈˆν•΄μ‘Œλ‹€.

이번 과제λ₯Ό 톡해 λ³΄λ„ˆμŠ€λ‘œ STLμ—μ„œ μ œκ³΅ν•˜λŠ” vector 및 stack에 λŒ€ν•΄μ„œ  μ’€ 더 μΉœμˆ™ν•΄μ§ˆ 수 μžˆμ—ˆκ³  μƒˆμ‚Ό μƒμš©κ·Έλž˜ν”½νˆ΄μ˜ μœ„λŒ€ν•¨μ„ 느끼게 λ˜μ—ˆλ‹€.

λ°˜μ‘ν˜•

+ Recent posts