ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 과제#4 (Window To Viewport Transformation)
    정리필요2 2008. 9. 2. 15:43

    삼각형 신축, 회전

    지난 scanconversion 과제는 너무 어려웠으나...이번건 할만했다....

    2005mfc로 작성했으며 헤더파일에 선언한 클래스와 함수들은 생략했당~ 주된 흐름만 살포시 ...


    // 삼각형의 갯수와 좌표 정의
    void C과제4TransformationView::setTriangle(Triangle t1[], int countT)
    {
     int temp[][6] = { // 삼각형 6개 정의
      {10, 100, 100, 10, 150, 150},
      {320, 300, 400, 10, 580, 300},
      {280, 350, 10, 400, 300, 580},
      {610, 40, 650, 60, 620, 90},
      {450, 450, 600, 350, 600, 550},
      {650, 450, 800, 350, 800, 550}
     };
     for(int i=0; i<countT; i++)
     { // Triangle 객체로 넣는다.
      t1[i].x1 = temp[i][0];
      t1[i].y1 = temp[i][1];
      t1[i].x2 = temp[i][2];
      t1[i].y2 = temp[i][3];
      t1[i].x3 = temp[i][4];
      t1[i].y3 = temp[i][5];
     }
    }

    // 원본 삼각형의 좌표 출력
    void C과제4TransformationView::textout(Triangle t1[], int countT)
    {
     CClientDC dc(this);
     CString string1;
     for(int i=0; i<countT; i++)
     {
      string1.Format(_T("  %d , %d "), t1[i].x1, t1[i].y1);
      dc.TextOutW(t1[i].x1, t1[i].y1, string1);
      string1.Format(_T("  %d , %d "), t1[i].x2, t1[i].y2);
      dc.TextOutW(t1[i].x2, t1[i].y2, string1);
      string1.Format(_T("  %d , %d "), t1[i].x3, t1[i].y3);
      dc.TextOutW(t1[i].x3, t1[i].y3, string1);
     }

    }

    // 메인함수
    void C과제4TransformationView::Trans(void)
    {
     int countT = 6; // 그릴 삼각형 갯수
     COLORREF gcol = RGB(240, 240, 240), tcol = RGB(255, 0, 0);
     // 원본삼각형의 색과 가이드라인 색
     guidline(1000, 800, gcol);// 가이드라인 출력함수 호출

     Triangle *t1 = new Triangle[countT]; // 갯수만큼 공간 할당      
     setTriangle(t1, countT);    // 삼각형 정의함수 호출

     textout(t1, countT);     // 삼각형 좌표값 출력함수 호출

     for(int i=0; i<countT; i++)    
      drawTriangle(t1[i], tcol);   // 원본 삼각형 그리기
     
     // ROTATION - 원본 t1[0]을 60 ~ 300 도까지 t1[0]의 세번째 점을 기준으로 회전
     rotation(t1[0], 60, t1[0].x3, t1[0].y3);
     rotation(t1[0], 120, t1[0].x3, t1[0].y3);
     rotation(t1[0], 180, t1[0].x3, t1[0].y3);
     rotation(t1[0], 240, t1[0].x3, t1[0].y3);
     rotation(t1[0], 300, t1[0].x3, t1[0].y3);

     // ROTATION - 원본 t1[1]을 20 ~ 40 도까지 중심을 기준으로 회전
     rotationCenter(t1[1], 20);
     rotationCenter(t1[1], 30);
     rotationCenter(t1[1], 40);

     // SCAILING - 원본 t1[2]의 세번째점을 기준으로 X, Y 각 0.8, 0.6 배 축소
     scailing(t1[2], 0.8, 0.8, t1[2].x3 +100, t1[2].y3);
     scailing(t1[2], 0.6, 0.6, t1[2].x3 +200, t1[2].y3);

     //ROTATION - 원본 t1[3]을 점(720, 150) 기준으로 60~300도 회전
     rotation(t1[3], 60, 720, 150);
     rotation(t1[3], 120, 720, 150);
     rotation(t1[3], 180, 720, 150);
     rotation(t1[3], 240, 720, 150);
     rotation(t1[3], 300, 720, 150);

     //SCAILING - 원본 t1[4]의 첫번째 점을 기준으로 Y 값만 축소확대
     scailing(t1[4], 1.0, 1.5, t1[4].x1, t1[4].y1);
     scailing(t1[4], 1.0, 1.2, t1[4].x1, t1[4].y1);
     scailing(t1[4], 1.0, 0.8, t1[4].x1, t1[4].y1);
     scailing(t1[4], 1.0, 0.6, t1[4].x1, t1[4].y1);

     //SCAILING - 원본 t1[5]의 첫번째 점을 기준으로 X 값만 축소확대
     scailing(t1[5], 1.5, 1.0, t1[5].x1, t1[5].y1);
     scailing(t1[5], 0.8, 1.0, t1[5].x1, t1[5].y1);
     scailing(t1[5], 0.6, 1.0, t1[5].x1, t1[5].y1);
     scailing(t1[5], 1.2, 1.0, t1[5].x1, t1[5].y1);

    }

    // 삼각형 그리는 함수
    void C과제4TransformationView::drawTriangle(Triangle t1, COLORREF col)
    {
     drawLine(t1.x1, t1.y1, t1.x2, t1.y2, col); // 선그리는함수호출
     drawLine(t1.x2, t1.y2, t1.x3, t1.y3, col);
     drawLine(t1.x3, t1.y3, t1.x1, t1.y1, col);

    }

    // 삼각형 중심구하는 함수
    Point C과제4TransformationView::Center(Triangle t1)
    {
     Point cp;
     cp.x = (int)(((t1.x1 + t1.x2 + t1.x3) / 3) + 0.5);
     cp.y = (int)(((t1.y1 + t1.y2 + t1.y3) / 3) + 0.5);
     // x, y좌표 세개를 각각 더해 3으로 나눔, 반올림해줌.
     return cp;
    }

    // 신축함수 - 특정 위치 기준 축소확대
    void C과제4TransformationView::scailing(Triangle t1, double xs, double ys, int x0, int y0)
    {
     Triangle scail;
     scail = t1;
     // P' = T(x0, y0) * (S(sx, sy)) * T(-x0, -y0) * P = S(x0, y0, sx, sy)
     // 교제 170p 의 합성변환을 이용
     scail.x1 = (int)((xs * t1.x1) + (x0 * (1-xs)) + 0.5);
     scail.x2 = (int)((xs * t1.x2) + (x0 * (1-xs)) + 0.5);
     scail.x3 = (int)((xs * t1.x3) + (x0 * (1-xs)) + 0.5);
     scail.y1 = (int)((ys * t1.y1) + (y0 * (1-ys)) + 0.5);
     scail.y2 = (int)((ys * t1.y2) + (y0 * (1-ys)) + 0.5);
     scail.y3 = (int)((ys * t1.y3) + (y0 * (1-ys)) + 0.5);

     drawTriangle(scail, RGB(0, 255, 0)); // 삼각형 그리는 함수 호출
    }

    // 신축함수 - 중심기준 축소확대
    void C과제4TransformationView::scailingCenter(Triangle t1, double xs, double ys)
    {
     Point cp;
     cp = Center(t1); // 삼각형 중심구하는 함수 호출
     scailing(t1, xs, ys, cp.x, cp.y); // 중심점으로 신축함수 호출
    }

    // 회전 함수 - 임의의 점 기준
    void C과제4TransformationView::rotation(Triangle t1, int degree, int x0, int y0)
    {
     double angle = PI * degree / 180.0; // 각도를 라디안으로 바꿔줌

     Triangle rotate;
     // P' = T(x0, y0) * R(@) * T(-x0, -y0) * P = R(x0, y0, @) * P
     // 교제 171p 의 합성변환 그대로 이용
     rotate.x1 = (int)(t1.x1 * cos(angle) - t1.y1 * sin(angle) + (x0 * (1-cos(angle))) + y0 * sin(angle) + 0.5);
     rotate.x2 = (int)(t1.x2 * cos(angle) - t1.y2 * sin(angle) + (x0 * (1-cos(angle))) + y0 * sin(angle) + 0.5);
     rotate.x3 = (int)(t1.x3 * cos(angle) - t1.y3 * sin(angle) + (x0 * (1-cos(angle))) + y0 * sin(angle) + 0.5);
     rotate.y1 = (int)(t1.x1 * sin(angle) + t1.y1 * cos(angle) + (y0 * (1-cos(angle))) - x0 * sin(angle) + 0.5);
     rotate.y2 = (int)(t1.x2 * sin(angle) + t1.y2 * cos(angle) + (y0 * (1-cos(angle))) - x0 * sin(angle) + 0.5);
     rotate.y3 = (int)(t1.x3 * sin(angle) + t1.y3 * cos(angle) + (y0 * (1-cos(angle))) - x0 * sin(angle) + 0.5);
     
     drawTriangle(rotate, RGB(0, 0, 255)); // 삼각형 그리는 함수 호출
    }

    // 회전함수 - 중심기준
    void C과제4TransformationView::rotationCenter(Triangle t1, int degree)
    {
     Point cp;
     cp = Center(t1); // 중심구하는 함수 호출
     rotation(t1, degree, cp.x, cp.y); // 중심점으로 회전함수 호출
    }

    // 가이드라인 출력 함수
    void C과제4TransformationView::guidline(int width, int height, COLORREF col)
    {
     for(int i=10; i<=width; i+=10)
      drawLine(i, 0, i, height, col);

     for(int j=10; j<height; j+=10)
      drawLine(0, j, width, j, col);
    }

    // 선그리는 함수 (bresenham midpoint)
    void C과제4TransformationView::drawLine(int x1, int y1, int x2, int y2, COLORREF col)
    {
     CClientDC cdc(this);

     int  x, y;
     int  dx, dy;
     int  incx, incy;
     int  balance;


     // 증가방향이 + 경우 incx incy는 1,  - 일 경우 incx, incy는 -1
     if (x2 >= x1)
     {
      dx = x2 - x1; // 증가폭은 양수로
      incx = 1;
     }
     else
     {
      dx = x1 - x2;
      incx = -1;
     }

     if (y2 >= y1)
     {
      dy = y2 - y1;
      incy = 1;
     }
     else
     {
      dy = y1 - y2;
      incy = -1;
     }

     x = x1;
     y = y1;

     if (dx >= dy) // |m| < 1
     {
     
      dy <<= 1;   // dy * 2 (시프트연산)
      balance = dy - dx; // 2dy - dx 
      dx <<= 1;   // dx * 2 (시프트연산)

      while (x != x2)
      {
       cdc.SetPixel( x, y, col); // 점찍기
       if (balance >= 0)
       // balance = 2dy - dx >= 0 , 즉 dy >= 1/2dx
       // dy가 dx의 절반(midpoint)의 넘으면
       {
        y += incy; // y를 증가 NE를 선택
        balance -= dx; // dx빼준다
       }
       balance += dy; // dy 증가
       x += incx; //아니면 x만 증가 E를 선택
      }
     }
     else // |m| < 1 , 내용은 위와 정반대
     {
      dx <<= 1;   // dx * 2
      balance = dx - dy; // 2dx - dy
      dy <<= 1;   // dy *2

      while (y != y2)
      {
       cdc.SetPixel( x, y, col);
       if (balance >= 0)
       {
        x += incx;
        balance -= dy;
       }
       balance += dx;
       y += incy;
      }
     }


    }

Designed by Tistory.