원을 알아보았으니까 이번에는 타원을 알아봐야 갰지요. 역시 정수 계산만으로 타원을 그리는 방법입니다만 이렇게 실수를 사용하지 않고 타원을 그린다는 자체가 참 신기하기만 합니다.

한가지 아래의 코드는 제가 아주 오래전에 어디서 구한 코드입니다. 그런데 아쉽게도 코드를 구해놓고 정작 출처를 잊어버렸네요. 제 기억으로는 아래의 코드는 브레슨햄의 알고리듬을 이용한 것은 아닙니다. 그러나 나눗셈이 있더라도 루프 밖에 있고, 작업이 많은 루프 안에서는 역시 정수 덧셈과 뺄셈만 있습니다.

구현한 함수는 ellipse() 로,

  void ellipse( int x_center, int y_center, int x_width, int y_height)

x_center, y_center 는 타원의 중심을 가리킵니다. x_width 와 y_height 는 타원의 폭과 높이를 지정하면 됩니다.

*** 혹 이글을 보시고 출처를 알고 계시거나 브레슨햄의 타원 코드를 가지고 계신 분이 계신다면 http://forum.falinux.com게시판에 알려 주신다면 매우 감사하겠습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>        // abs

#include <unistd.h>        // open/close
#include <fcntl.h>         // O_RDWR
#include <sys/ioctl.h>     // ioctl
#include <sys/mman.h>      // mmap PROT_
#include <linux/fb.h>

int   screen_width;
int   screen_height;
unsigned short *fb_mapped;


void  dot( int x, int y)
{
   unsigned short *ptr;

   if ( 0 <= x && 0 <= y && x < screen_width && y < screen_height)
   {
      ptr   = fb_mapped + screen_width * y + x;
     *ptr  = 0xffff;
   }
}

void ellipse( int x_center, int y_center, int x_width, int y_height)
{
   int      x_coor, y_coor;
   long     width, height;
   long     xone_squ, xtwo_squ;
   long     yone_squ, ytwo_squ;
   long     delta, dx, dy;


   x_coor   = 0;
   y_coor   = y_height;
   width    = x_width;
   height   = y_height;
   xone_squ = width * width;
   xtwo_squ = xone_squ << 1;
   yone_squ = height * height;
   ytwo_squ = yone_squ << 1;



   delta    = yone_squ - xone_squ *height + (xone_squ >> 2);
   dx       = 0;
   dy       = xtwo_squ * height;

   while( dx < dy )
   {
      dot( x_center+x_coor, y_center+y_coor);
      dot( x_center-x_coor, y_center+y_coor);
      dot( x_center+x_coor, y_center-y_coor);
      dot( x_center-x_coor, y_center-y_coor);

      if( delta > 0 )
      {
         y_coor--;
         dy    -= xtwo_squ;
         delta -= dy;
      }
      x_coor++;
      dx       += ytwo_squ;
      delta    += yone_squ + dx;
   }

   delta += ( 3*(xone_squ - yone_squ)/2 - (dx+dy)/2 );

   while( y_coor >= 0 )
   {
      dot( x_center+x_coor, y_center+y_coor);
      dot( x_center-x_coor, y_center+y_coor);
      dot( x_center+x_coor, y_center-y_coor);
      dot( x_center-x_coor, y_center-y_coor);
      if( delta < 0 )
      {
         x_coor++;
         dx      += ytwo_squ;
         delta   += dx;
      }
      y_coor--;
      dy      -= xtwo_squ;
      delta   += xone_squ - dy;
   }
}

int   main( int argc, char **argv)
{
   int      fb_fd;
   struct   fb_var_screeninfo  fbvar;
   struct   fb_fix_screeninfo  fbfix;
   int      bytes_per_line;
   int      mem_size;
   int      ndx;

   fb_fd = open( "/dev/fb", O_RDWR);
   ioctl( fb_fd, FBIOGET_VSCREENINFO, &fbvar);
   ioctl( fb_fd, FBIOGET_FSCREENINFO, &fbfix);

   screen_width   = fbvar.xres;                    // 스크린의 픽셀 폭
   screen_height  = fbvar.yres;                    // 스크린의 픽셀 높이
   bytes_per_line = fbfix.line_length;             // 한개 라인 당 바이트 개수

   mem_size       = bytes_per_line * screen_height;

   fb_mapped      = ( unsigned short *)mmap( 0,
                                          mem_size,
                                          PROT_READ|PROT_WRITE,
                                          MAP_SHARED,
                                          fb_fd,
                                          0);

   for ( ndx = 20; ndx < 200; ndx+=20)
   {
      ellipse( 250, 250, ndx, 200);
      ellipse( 250, 250, 200, ndx);
   }

   for ( ndx = 10; ndx < 100; ndx+=10)
   {
      ellipse( 500, 400, ndx, 100);
      ellipse( 500, 400, 100, ndx);
   }

   munmap( fb_mapped, mem_size);
   close( fb_fd);

   return 0;
}

실행을 하면 아래와 같이 출력됩니다.

태그 : *그래픽 *타원 *ellipse