메뉴
Circle Drawing (픽셀 단위 원 그리기)

2011. 3. 20. 12:01

알고리즘

(x - r)^2 + (y - r)^2 = r^2


알고리즘은 간단하다. 위와 같은 원의 공식을 사용한다.
원의 모양을 예측해 보면 (r, r)의 중심점을 가지는 반지름이 r인 원이 그려진다.
이 포스트에서는 반지름 이내의 범위의 어떤 좌표 (x, y)에 있는 점은 검은색 상자 (■)로 표시하고,
그렇지 않은 점은 빈 상자(□)로 표시할 생각이다.
간단히 생각해 보면 이중 반복문을 돌려서
삼항연산자든 if문이든 걸어서 범위 체크만 해주면 끝이라고 생각 할 수 있다.
하지만 실제로 그를 토대로 그려보면, 뭔가 좌우 대칭이 잘 맞지 않는다.




접근 방법

텍스트만 가지고 원을 그리려면, 픽셀 단위의 드로잉을 생각해야만 한다.
어떤 도장이 있다. 도장은 가로세로 1cm의 크기를 갖는 정사각형 모양을 찍어낸다.
이 도장을 가지고 반지름이 7cm인 원을 그린다고 생각하자.


원의 중심점에 빨간 도장을 찍어버리면, 원의 반지름을 표현하기 위해 8개의 도장을 찍게 된다.
원 전체를 그리게 되면 한 줄에 15개의 도장을 찍어야 한다.
반지름 7cm의 원을 그려야 하는데, 결론적으로는 지름 15cm인 원이 탄생하게 되는 것이다.
만약 반복문을 조금 고쳐서 어찌됐든 14cm가 되게 한다면, 어느 한 쪽은 잘려나가게 되고 비대칭적인 원이 탄생한다.

게다가, 동서남북에는 항상 1개의 도장이 찍히게 된다.
원의 형태는 나오지만 우리가 원하는 결과는 아니다.

이러한 결과는 우리가

r * r > (x - r)*(x - r) + (y - r)*(y - r)


같은 비교식을 사용했을때 얻게 된다.
따라서 우리는 어긋나버린 핀트를 조금 맞춰줄 필요가 있다. 방법은 간단하다.

 
픽셀을 각각 0.5cm씩 어긋난 위치에서 가져오는 것이다.
비교식은 다음과 같이 변화한다.

r * r > (x + 0.5 - r)*(x + 0.5 - r) + (y + 0.5 - r)*(y + 0.5 - r)


이제 14 x 14 개의 픽셀로 반지름 7의 원을 만드는것이 가능하다.




코드

#include <stdio.h>

void main() {
    int i,j,u;
    FILE *f;
    printf("<Circle Drawing>\nInput a integer number of radius of circle.> ");
    scanf_s("%d",&u,sizeof(int));
    fopen_s(&f,"circle.txt","w");
    for(i=0;i<u*2;i++){
        for(j=0;j<u*2;j++){
            (u*u > (i+0.5-u)*(i+0.5-u) + (j+0.5-u)*(j+0.5-u))? fprintf(f,"■") : fprintf(f,"□");
        }
        fprintf(f,"\n");
    }
    fclose(f);
}




결과

숫자를 입력받아서 circle.txt로 출력한다.
circle.txt에는 입력한 반지름의 크기를 가진 원이 그려져 있을 것이다.
메모장을 이용하는 경우, 원이 너무 크면 '자동 줄바꿈'을 해제해야 한다.
반지름을 21로 입력해서 얻은 결과는 아래와 같다.


□□□□□□□□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□
□□□□□□□□□□□□□■■■■■■■■■■■■■■■■□□□□□□□□□□□□□
□□□□□□□□□□□■■■■■■■■■■■■■■■■■■■■□□□□□□□□□□□
□□□□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□□□□
□□□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□□□
□□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□□
□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□
□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□
□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□
□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□
□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□
□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□
□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□
□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□
□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□
□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□
□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□
□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□
□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□
□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□
□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□
□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□
□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□
□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□
□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□
□□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□□
□□□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□□□
□□□□□□□□□■■■■■■■■■■■■■■■■■■■■■■■■□□□□□□□□□
□□□□□□□□□□□■■■■■■■■■■■■■■■■■■■■□□□□□□□□□□□
□□□□□□□□□□□□□■■■■■■■■■■■■■■■■□□□□□□□□□□□□□
□□□□□□□□□□□□□□□□■■■■■■■■■■□□□□□□□□□□□□□□□□




문제점

현재 프로그램은 반지름을 입력받기 때문에, 지름이 홀수인 원을 그려낼 수 없게 되어있다.
지름이 홀수인 원을 그리기 위해서는 어떻게 코딩을 해야할까?
간단히 몇 가지만 수정하면 된다.

#include <stdio.h>

void main() {
    int i,j,u;
    FILE *f;
    printf("<Circle Drawing>\nInput a integer number of diameter of circle.> ");
    scanf_s("%d",&u,sizeof(int));
    fopen_s(&f,"circle.txt","w");
    for(i=0;i<u;i++){
        for(j=0;j<u;j++){
            (u*u/4.0 > (i+0.5-u/2.0)*(i+0.5-u/2.0) + (j+0.5-u/2.0)*(j+0.5-u/2.0))? fprintf(f,"■") : fprintf(f,"□");
        }
        fprintf(f,"\n");
    }
    fclose(f);



생각해 봐야할 문제

타원을 그리려면 어떻게 해야할 것인가?
테두리만 있는 원을 그리려면 어떻게 해야 할 것인가?
직접 생각해 보기 바란다.




다운로드


위 프로그램을 다운 받아 실행하면, 명령 프롬프트가 뜨고 반지름을 입력하면 같은 폴더에 circle.txt가 생성된다.
지름을 입력받아 원을 그려주는 프로그램에 대해서는 스스로 해보기 바란다.