Алгоритъмът за рисуване на кръг на Bresenham

Алгоритъмът за рисуване на кръг на Bresenham

Не е лесно да се покаже непрекъсната гладка дъга на екрана на компютъра, тъй като екранът на нашия компютър е направен от пиксели, организирани в матрична форма. Така че, за да начертаем кръг на компютърен екран, винаги трябва да избираме най-близките пиксели от отпечатания пиксел, така че те да могат да образуват дъга. Има два алгоритъма за това:

  1. Алгоритъм за рисуване на кръг в средата
  2. Алгоритъм за чертане на кръг на Брезенхам

Вече обсъдихме Алгоритъм за рисуване на кръг в средата в предишната ни публикация. В тази публикация ще обсъдим алгоритъма за чертане на кръг на Bresenham. 

И двата алгоритъма използват ключовата характеристика на кръга, че е силно симетричен. Така че за целия кръг от 360 градуса ще го разделим на 8 части, всеки октант от 45 градуса. За да направим това, ще използваме кръговия алгоритъм на Bresenham за изчисляване на местоположението на пикселите в първия октант от 45 градуса. Предполага се, че центърът на кръга е в началото. Така че за всеки пиксел (x y), който изчислява, рисуваме пиксел във всеки от 8-те октанта на кръга, както е показано по-долу: 

За един пиксел (xy) всички възможни пиксели в 8 октантаЗа един пиксел (xy) всички възможни пиксели в 8 октанта


Сега ще видим как да изчислим следващото пикселно местоположение от предишно известно пикселно местоположение (x y). В алгоритъма на Bresenham във всяка точка (x y) имаме две възможности или да изберем следващия пиксел на изток, т.е. (x+1 y), или на югоизток, т.е. (x+1 y-1).
 

кръг 2


И това може да бъде решено чрез използване на параметъра за решение d като: 
 

  • Ако d > 0, тогава (x+1 y-1) трябва да бъде избран като следващ пиксел, тъй като ще бъде по-близо до дъгата.
  • иначе (x+1 y) трябва да бъде избран като следващ пиксел.


Сега, за да начертаем кръга за даден радиус 'r' и център (xc yc). Ще започнем от (0 r) и ще се движим в първия квадрант до x=y (т.е. 45 градуса). Трябва да започнем от изброеното първоначално условие: 
 

 d = 3 - (2 * r)   
x = 0
y = r

Сега за всеки пиксел ще извършим следните операции:  

  1. Задайте начални стойности на (xc yc) и (x y).
  2. Задайте параметъра за решение d на d = 3 – (2 * r).
  3. Извикайте функцията drawCircle(int xc int yc int x int y).
  4. Повторете следните стъпки, докато x <= y:
    • Ако d < 0 set d = d + (4 * x) + 6.
    • В противен случай задайте d = d + 4 * (x – y) + 10 и намалете y с 1.
    • Увеличете стойността на x.
    • Извикайте функцията drawCircle(int xc int yc int x int y).

функция drawCircle():  

CPP
   // function to draw all other 7 pixels   // present at symmetric position   drawCircle  (  int     xc       int     yc       int     x       int     y  )   {      putpixel  (  xc  +  x       yc  +  y       RED  );      putpixel  (  xc  -  x       yc  +  y       RED  );      putpixel  (  xc  +  x       yc  -  y       RED  );      putpixel  (  xc  -  x       yc  -  y       RED  );      putpixel  (  xc  +  y       yc  +  x       RED  );      putpixel  (  xc  -  y       yc  +  x       RED  );      putpixel  (  xc  +  y       yc  -  x       RED  );      putpixel  (  xc  -  y       yc  -  x       RED  );   }   

По-долу е C реализация на горния подход. 

CPP
   // C-program for circle drawing   // using Bresenham’s Algorithm   // in computer-graphics   #include         #include         #include         // Function to put pixels   // at subsequence points   void     drawCircle  (  int     xc       int     yc       int     x       int     y  ){      putpixel  (  xc  +  x       yc  +  y       RED  );      putpixel  (  xc  -  x       yc  +  y       RED  );      putpixel  (  xc  +  x       yc  -  y       RED  );      putpixel  (  xc  -  x       yc  -  y       RED  );      putpixel  (  xc  +  y       yc  +  x       RED  );      putpixel  (  xc  -  y       yc  +  x       RED  );      putpixel  (  xc  +  y       yc  -  x       RED  );      putpixel  (  xc  -  y       yc  -  x       RED  );   }   // Function for circle-generation   // using Bresenham's algorithm   void     circleBres  (  int     xc       int     yc       int     r  ){      int     x     =     0       y     =     r  ;      int     d     =     3     -     2     *     r  ;      drawCircle  (  xc       yc       x       y  );      while     (  y     >=     x  ){          // check for decision parameter      // and correspondingly       // update d y      if     (  d     >     0  )     {      y  --  ;         d     =     d     +     4     *     (  x     -     y  )     +     10  ;      }      else      d     =     d     +     4     *     x     +     6  ;      // Increment x after updating decision parameter      x  ++  ;          // Draw the circle using the new coordinates      drawCircle  (  xc       yc       x       y  );      delay  (  50  );      }   }   int     main  ()   {      int     xc     =     50       yc     =     50       r     =     30  ;      int     gd     =     DETECT       gm  ;      initgraph  (  &  gd       &  gm       ''  );     // initialize graph      circleBres  (  xc       yc       r  );     // function call      return     0  ;   }   

Изход: 
 

заобикаляне


Предимства  

  • Това е прост алгоритъм.
  • Може да се приложи лесно
  • Изцяло се основава на уравнението на кръга, т.е. x 2 +y 2 =r 2

Недостатъци  

  • Има проблем с точността при генериране на точки.
  • Този алгоритъм не е подходящ за сложни и високо графични изображения.
Създаване на тест