-
과제#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 *2while (y != y2)
{
cdc.SetPixel( x, y, col);
if (balance >= 0)
{
x += incx;
balance -= dy;
}
balance += dx;
y += incy;
}
}
}