Circle Drawing

From KBase

Jump to: navigation, search

Contents

[edit] Introduction

Azydream 님께서 http://azydream.tistory.com/51 에 PA_Lib 에 있는 원 그리기 함수를 소개해 주셨다. 처음에 이 함수를 보았을 때는 저걸로 어떻게 원을 그리지? 하는 생각이 문득 들었다. 그래서 과연 원을 그려줄 것인지 보려고 간단한 프로그램을 만들어 보았다.

[edit] Writing Test Application

원 소스에 있는 PA_DrawCircle() 은 고치지 않은 채로 결과를 Terminal 에서 확인할 수 있도록 했다.

[edit] Source Code

#include <stdio.h>
#include <stdlib.h>

#define CX_CANVAS 60
#define CY_CANVAS 60
#define DEFAULT_X 30
#define DEFAULT_Y 30
#define DEFAULT_R 10

static int count = 0;
static int occurrences[CY_CANVAS][CY_CANVAS];

void PA_DrawPixel(int x, int y, int color)
{
   printf("(%2d,%2d) ", x, y);
   if ((++count % 8) == 0) {
       printf("\n");
   }
   if (x >= 0 && x < CX_CANVAS &&
       y >= 0 && y < CY_CANVAS)
   {
       occurrences[y][x]++;
   }
}

void PA_DrawCircle(int xCenter, int yCenter, int radius, int color)
{
 int x = 0;
 int y = radius;
 int p = 3 - 2 * radius;

  while (x <= y){
     PA_DrawPixel(xCenter + x, yCenter + y, color);
     PA_DrawPixel(xCenter - x, yCenter + y, color);
     PA_DrawPixel(xCenter + x, yCenter - y, color);
     PA_DrawPixel(xCenter - x, yCenter - y, color);
     PA_DrawPixel(xCenter + y, yCenter + x, color);
     PA_DrawPixel(xCenter - y, yCenter + x, color);
     PA_DrawPixel(xCenter + y, yCenter - x, color);
     PA_DrawPixel(xCenter - y, yCenter - x, color);
     if (p < 0) p += 4 * x++ + 6;
     else p += 4 * (x++ - y--) + 10;
  }
}

void printOccurrences(int w, int h)
{
   for (int y = 0; y < w; y++) {
       for (int x = 0; x < h; x++) {
           if (occurrences[y][x]) {
               putchar('0' + occurrences[y][x]);
           } else {
               putchar(' ');
           }
       }
       printf("\n");
   }
}

int main(int argc, char *argv[])
{
   int r = DEFAULT_R;
   if (argc > 1) {
       r = atoi(argv[1]);
   }

   if (r <= 0 || (r >= CX_CANVAS / 2) || (r >= CY_CANVAS / 2)) {
       return 1;
   }

   PA_DrawCircle(r, r, r, 0);

   int maxx = 2 * r + 1;
   int maxy = 2 * r + 1;
   printOccurrences(maxx, maxy);

   return 0;
}

[edit] Explanation

  • main()
    • 반지름을 인자로 받아 원을 그린 뒤 출력한다
  • PA_DrawPixel()
    • PA_DrawCircle() 이 이 함수를 이용하므로, 가상으로 만들어 준다. 점을 찍는 위치를 순서대로 표시해 주고, 해당 첨이 몇 번 출력되는지 확인하기 위해 occurrence 라는 이름의 이차원 배열을 사용한다
  • printOccurrences()
    • 저장해 둔 occurrence 를 출력한다.

[edit] Output

/cygdrive/c/Temp $ ./a.exe
(10,20) (10,20) (10, 0) (10, 0) (20,10) ( 0,10) (20,10) ( 0,10)
(11,20) ( 9,20) (11, 0) ( 9, 0) (20,11) ( 0,11) (20, 9) ( 0, 9)
(12,20) ( 8,20) (12, 0) ( 8, 0) (20,12) ( 0,12) (20, 8) ( 0, 8)
(13,20) ( 7,20) (13, 0) ( 7, 0) (20,13) ( 0,13) (20, 7) ( 0, 7)
(14,19) ( 6,19) (14, 1) ( 6, 1) (19,14) ( 1,14) (19, 6) ( 1, 6)
(15,19) ( 5,19) (15, 1) ( 5, 1) (19,15) ( 1,15) (19, 5) ( 1, 5)
(16,18) ( 4,18) (16, 2) ( 4, 2) (18,16) ( 2,16) (18, 4) ( 2, 4)
(17,17) ( 3,17) (17, 3) ( 3, 3) (17,17) ( 3,17) (17, 3) ( 3, 3)
       1112111
     11       11
    1           1
   2             2
  1               1
 1                 1
 1                 1
1                   1
1                   1
1                   1
2                   2
1                   1
1                   1
1                   1
 1                 1
 1                 1
  1               1
   2             2
    1           1
     11       11
       1112111
/cygdrive/c/Temp $ ./a.exe 2
( 2, 4) ( 2, 4) ( 2, 0) ( 2, 0) ( 4, 2) ( 0, 2) ( 4, 2) ( 0, 2)
( 3, 4) ( 1, 4) ( 3, 0) ( 1, 0) ( 4, 3) ( 0, 3) ( 4, 1) ( 0, 1)
 121
1   1
2   2
1   1
 121
/cygdrive/c/Temp $ ./a.exe 3
( 3, 6) ( 3, 6) ( 3, 0) ( 3, 0) ( 6, 3) ( 0, 3) ( 6, 3) ( 0, 3)
( 4, 6) ( 2, 6) ( 4, 0) ( 2, 0) ( 6, 4) ( 0, 4) ( 6, 2) ( 0, 2)
( 5, 5) ( 1, 5) ( 5, 1) ( 1, 1) ( 5, 5) ( 1, 5) ( 5, 1) ( 1, 1)
  121
 2   2
1     1
2     2
1     1
 2   2
  121
/cygdrive/c/Temp $ ./a.exe 4
( 4, 8) ( 4, 8) ( 4, 0) ( 4, 0) ( 8, 4) ( 0, 4) ( 8, 4) ( 0, 4)
( 5, 8) ( 3, 8) ( 5, 0) ( 3, 0) ( 8, 5) ( 0, 5) ( 8, 3) ( 0, 3)
( 6, 7) ( 2, 7) ( 6, 1) ( 2, 1) ( 7, 6) ( 1, 6) ( 7, 2) ( 1, 2)
( 7, 7) ( 1, 7) ( 7, 1) ( 1, 1) ( 7, 7) ( 1, 7) ( 7, 1) ( 1, 1)
   121
 21   12
 1     1
1       1
2       2
1       1
 1     1
 21   12
   121
/cygdrive/c/Temp $ ./a.exe 5
( 5,10) ( 5,10) ( 5, 0) ( 5, 0) (10, 5) ( 0, 5) (10, 5) ( 0, 5)
( 6,10) ( 4,10) ( 6, 0) ( 4, 0) (10, 6) ( 0, 6) (10, 4) ( 0, 4)
( 7,10) ( 3,10) ( 7, 0) ( 3, 0) (10, 7) ( 0, 7) (10, 3) ( 0, 3)
( 8, 9) ( 2, 9) ( 8, 1) ( 2, 1) ( 9, 8) ( 1, 8) ( 9, 2) ( 1, 2)
   11211
  1     1
 1       1
1         1
1         1
2         2
1         1
1         1
 1       1
  1     1
   11211
/cygdrive/c/Temp $ ./a.exe 6
( 6,12) ( 6,12) ( 6, 0) ( 6, 0) (12, 6) ( 0, 6) (12, 6) ( 0, 6)
( 7,12) ( 5,12) ( 7, 0) ( 5, 0) (12, 7) ( 0, 7) (12, 5) ( 0, 5)
( 8,12) ( 4,12) ( 8, 0) ( 4, 0) (12, 8) ( 0, 8) (12, 4) ( 0, 4)
( 9,11) ( 3,11) ( 9, 1) ( 3, 1) (11, 9) ( 1, 9) (11, 3) ( 1, 3)
(10,10) ( 2,10) (10, 2) ( 2, 2) (10,10) ( 2,10) (10, 2) ( 2, 2)
    11211
   1     1
  2       2
 1         1
1           1
1           1
2           2
1           1
1           1
 1         1
  2       2
   1     1
    11211

[edit] Analysis

일단 신기하다 ^^ 좀 더 두고 보자. : )

[edit] Filling a Circle

안을 채우는 것을 간단히 고쳐 보았습니다. 점 여덟 개를 찍는 대신 각각을 가로 선으로 잇기만 하면 되며, 가로 선은 가장 싼 값(cost) 에 그릴 수 있습니다. Clipping 역시 선그리기에서 합니다.

[edit] Source Code

#include <stdio.h>
#include <stdlib.h>

#define CX_CANVAS 24
#define CY_CANVAS 24
#define DEFAULT_X 10
#define DEFAULT_Y 10
#define DEFAULT_R 10

static int occurrences[CY_CANVAS][CY_CANVAS];

void PA_DrawPixel(int x, int y, int color)
{
    if (x >= 0 && x < CX_CANVAS &&
        y >= 0 && y < CY_CANVAS)
    {
        occurrences[y][x]++;
    }
}

void PA_DrawHorzLine(int x1, int x2, int y, int color)
{
    if (y < 0 || y >= CY_CANVAS || x1 >= CX_CANVAS || x2 < 0)
        return;

    if (x1 < 0) x1 = 0;
    if (x2 >= CX_CANVAS) x2 = CX_CANVAS - 1;

    for (int x = x1; x <= x2; x++) {
        occurrences[y][x]++;
    }
}

void PA_DrawCircle(int xCenter, int yCenter, int radius, int color)
{
  int x = 0;
  int y = radius;
  int p = 3 - 2 * radius;

   while (x <= y){
      PA_DrawHorzLine(xCenter - x, xCenter + x, yCenter + y, color);
      PA_DrawHorzLine(xCenter - x, xCenter + x, yCenter - y, color);
      PA_DrawHorzLine(xCenter - y, xCenter + y, yCenter + x, color);
      PA_DrawHorzLine(xCenter - y, xCenter + y, yCenter - x, color);
      if (p < 0) p += 4 * x++ + 6;
      else p += 4 * (x++ - y--) + 10;
   }
}

void printOccurrences(int w, int h)
{
    for (int y = 0; y < w; y++) {
        for (int x = 0; x < h; x++) {
            if (occurrences[y][x]) {
                putchar('0' + occurrences[y][x]);
            } else {
                putchar(' ');
            }
        }
        printf("\n");
    }
}

int main(int argc, char *argv[])
{
    int r = DEFAULT_R;
    if (argc > 1) {
        r = atoi(argv[1]);
    }

    // if (r <= 0 || (r >= CX_CANVAS / 2) || (r >= CY_CANVAS / 2)) {
    //  return 1;
    // }

    PA_DrawCircle(r, r, r, 0);

    int maxx = 2 * r + 1;
    int maxy = 2 * r + 1;
    if (maxx > CX_CANVAS)
        maxx = CX_CANVAS;
    if (maxy > CY_CANVAS)
        maxy = CY_CANVAS;
    printOccurrences(maxx, maxy);

    return 0;
}

[edit] Output

소스에서 Canvas 크기를 24로 해 두었기 때문에, 반지름을 15 로 하면 clipping 이 일어나는 것을 볼 수 있다.

/cygdrive/c/Temp$ ./a.exe 2
 121
11111
22222
11111
 121
/cygdrive/c/Temp$ ./a.exe 3
  121
 22222
1111111
2222222
1111111
 22222
  121
/cygdrive/c/Temp$ ./a.exe 4
   121
 2333332
 1111111
111111111
222222222
111111111
 1111111
 2333332
   121
/cygdrive/c/Temp$ ./a.exe 10
       1234321
     12222222221
    1111111111111
   222222222222222
  11111111111111111
 1111111111111111111
 1111111111111111111
111111111111111111111
111111111111111111111
111111111111111111111
222222222222222222222
111111111111111111111
111111111111111111111
111111111111111111111
 1111111111111111111
 1111111111111111111
  11111111111111111
   222222222222222
    1111111111111
     12222222221
       1234321
/cygdrive/c/Temp$ ./a.exe 15
            1234321
         1233333333321
       12222222222222221
      111111111111111111
     1111111111111111111
    11111111111111111111
   111111111111111111111
  1111111111111111111111
  1111111111111111111111
 11111111111111111111111
 11111111111111111111111
 11111111111111111111111
111111111111111111111111
111111111111111111111111
111111111111111111111111
222222222222222222222222
111111111111111111111111
111111111111111111111111
111111111111111111111111
 11111111111111111111111
 11111111111111111111111
 11111111111111111111111
  1111111111111111111111
  1111111111111111111111

custom research papers

Personal tools
Wiki Help (mediawiki.org)