Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11642
Последний выпуск: 19.06.2015

Алгоритм Брезенхема

При ограниченном разрешении точка приближаемой линии может находиться либо на самой линии, либо слева от нее либо справа. Расстояние на котором фактически установленная точка находиться от рисуемой линии, -- ошибка в рисовании линии. Переходя к каждой следующей точке, ошибка скажет какая точка будет хуже приближать кривую а какая лучше.

Принцип Брезенхема состоит в том, чтобы с каждой итерaцией двигаться на одну точку по той оси проекция на которую больше. По другой оси смешение на один пиксель происходит лишь тогда, когда линия отклонилась от текущей оси более чем на полпикселя (Рисунок 1).

Приведенные рассуждения рассматривают лишь суть, а не точный механизм работы алгоритма Брезенхема . Рассмотрим реализацию.

inline void Image::Octant0(int X0,int Y0,int DeltaX,int DeltaY,int XDirection) { 
  /* DeltaX -- поэкция на ось X 
     DeltaY -- проэкция на ось Y 
     XDirection -- направление движения 

  для данной функции |DeltaX|>DeltaY 
  следовательно основная ось X, a 
  вспомогaтельная Y 
  */ 
  int DYx2; 
  int DYx2MinusDXx2; 
  int ErrorTerm; 
  /* Установим начальную ошибку накопления и значения, 
     используемые во внутреннем цикле */ 

  DYx2=DY*2; 
  DYx2MinusDXx2= DYx2 - DX*2; 
  ErrorTerm = DYx2 - DX;// ошибка 

  /* ставим первую точку */ 
  setZPixel(X0,Y0,getZPixel(DeltaX),Color); 

  while(DeltaX--) { 
    if(ErrorTerm >=0) { 
  /* шагаем по вспомогательной оси 
     и подправляем ошибку накопления */ 
      Y0++; 
      ErrorTerm+=DeltaYx2MinusDeltaXx2; 
    } else { 
  /* добавляем ошибку накопления */ 
      ErrorTerm+= DeltaYx2; 
    } 
  /* двигаемся по основной оси */ 
    X0+= XDirection; 
  /* ставим точку */ 
    setZPixel(X0,Y0,getZPixel(DeltaX),Color); 
  } 
} 

Теперь о том как мы будем находить Z координаты для каждой точки рисуемой прямой. Очевидно они меняются по линейному закону y=k*x+b, где k,b подлежат определению. Их можно найти посмотрев на рисунок 3.



Для того чтобы рисовать линию необходимо определить в какой области (октанте) находится линия. На рис 2 показаны восемь октант. Очевидно четыре из них избыточны, нижние четыре октанты можно преобразовать в четыре верхнии, поменяв начальную точку линии с конечной. Т.е, поменять местами

(X0,Y0) (X1,Y1) если Y0>Y1

После этого надо определить в какой из четырех октант находится линия. Из этих четырех две октанты имеют в качестве основной имеют горизонтальную ось, а в качетве второстепенной вертикальную. У остальных основная ось вертикальная. Видно что оканты 0,3 отличаются только по направлению движения, тоже самое можно сказать об октантах 1,2. От сюда видно что рисование линии можно свести к двум функциям. Octant0 для 0,3 октант и Octant1 для 1,2. Точнее :

  
void Image::line(int X0,int Y0,float Z0,int X1,int Y1,float Z1,color C){ 
  int DeltaX,DeltaY; 
  Color=C;/* установим цвет */ 

  /* инициализируем закон изменения глубины */ 

  double dist = distance(X0, Y0, X1, Y1); 

  if (dist < 0.0001) { 
    setZPixel(X0, Y0, (Z0 < Z1 ? Z0 : Z1), C); 
    return; 
  } 

  k = (Z0 - Z1) / dist; 
  b = Z1; 

  /* уменьшим число условий наполовину 
     в результатe DeltaY всегда > 0 
     и можно работать с октантами 
     0-3 
  */ 

  if (Y0 > Y1 ) { 
    swap (Y0,Y1); 
    swap (X0,X1); 
  } 
  /* проэкция на ось X */ 
  DeltaX = X1 - X0; 
  /* проэкция на ось Y */ 
  DeltaY = Y1 - Y0; 

  if(DeltaX >0) { 
    /* рисуем с лева направо */ 
    if (DeltaX > DeltaY ) { 
      Octant0(X0,Y0, DeltaX,DeltaY,1); 
    } else { 
      Octant1(X0, Y0, DeltaX ,DeltaY,1); 
    } 
  } else { 
    /* с права налево */ 
    DeltaX = -DeltaX; 
    if( DeltaX > DeltaY) { 
      Octant0(X0,Y0, DeltaX, DeltaY,-1); 
    } else { 
      Octant1(X0,Y0, DeltaX, DeltaY,-1); 
    } 
  } 
} 

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
97K
02 июля 2016 года
Konstantin Lyakh
0 / / 02.07.2016
Мне нравитсяМне не нравится
2 июля 2016, 12:28:58
спасибо!!!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог