2016-02-21 9 views
0

Я изучаю компьютерную графику и натолкнулся на алгоритм отсечения линии Коэна-Сазерленда. Где у нас есть сегмент линии, определяемый точками P1 и P2, и мы пытаемся выяснить, будет ли он обрезаться внутри отсекающего прямоугольника (обычно определяемого шириной и высотой экрана, а верхний левый - [0, 0])Зачем нам нужно округлять при вычислении x-перехвата горизонтальной линии в алгоритме отсечения Коэна-Сазерленда?

алгоритм прост, мы просто проверяем каждую точку, чтобы увидеть, если х точки и у находятся вне границ:

if (y1 < min_clip_y) 
     p1_code |= CLIP_NORTH; 
else if (y1 > max_clip_y) 
     p1_code |= CLIP_SOUTH; 

if (x1 < min_clip_x) 
     p1_code |= CLIP_WEST; 
else if (x1 > max_clip_x) 
     p1_code |= CLIP_EAST; 

// Same deal with x2, y2 

если оба p1_code и p2_code не равны нулю, мы отвергаем линию, если они оба равны нулю, мы принимаем его, в противном случае мы продолжаем тестирование, чтобы найти точку пересечения клипа с краем прямоугольника прямоугольника пересечения:

switch(p1_code) 
{ 
    case CLIP_NORTH: 
    { 
     yc1 = min_clip_y; 
     xc1 = x1 + 0.5f + (min_clip_y - y1) * (x2-x1)/(y2-y1); 
    } break; 

    // other cases... 
} 

Я прочитал это из книги. Я понимаю, как мы выводим уравнение х-перехвата, я просто не понимаю, почему мы добавляем 0.5f для округления до следующего целого числа. Зачем нам крутиться?

Спасибо!

ответ

0

Многие тексты компьютерной графики имеют такие ошибки. C-S был изобретен ~ 50 лет назад, когда число с плавающей запятой было значительно медленнее, чем целочисленная математика, поэтому нормой было использование целочисленных арифметических или целых инструкций для эмуляции неподвижной точки. В результате возникают странные повторные реализации старого кода, которые пересаживают старую неподвижную точку с плавающей точкой. По-видимому, это один из них.

Как вы подозреваете, вы хотите сделать все вычисление с плавающей точкой, а затем округлить до ближайшего пикселя, если это абсолютно необходимо в конце. Но с современными графическими процессорами вы можете даже пропустить это, так как сглаживание линии будет делать правильно с координатами с плавающей запятой.

На самом деле, странно, что графические тексты по-прежнему имеют отсечение линий так заметно, поскольку современная графика - это гораздо больше о полигонах. Есть множество хороших алгоритмов треугольника и многоугольника, которые имеют более практическое значение, чем отсечение линии. Слишком много авторов учебников являются рабами инструментов их ученичества.

+0

Спасибо за ответ. Книга, которую я отношусь относительно старой, да, но она единственная в своем роде, по крайней мере, я не видел много книг, похожих на нее. Это Андре Ламоте, через создание средства визуализации программного обеспечения, но сначала вы создаете каркасный движок, в котором вы рисуете линии и треугольники через Bresenham и, следовательно, отсекаете линию. То, чего я не получаю, - это то, почему округляется до следующего целого, а не от текущего? т. е. если результат был «2,3», почему круглые до 3, а не до 2? – vexe

+0

@vexe У вас это неправильно. (int) (x + 0,5) имеет эффект округления до ближайшего int, потому что преобразование в int делает усечение. (2,3 + 0,5) усечено 2, а не 3. Я хочу сказать, что это глупое место для преобразования в целое. Это делает алгоритм значительно менее точным. Сделайте обрезку полностью в поплавках, затем округлите до пиксельных координат. – Gene

+0

«Сделайте обрезку полностью в поплавках, затем округлите до координат пикселей». Вы имеете в виду, что входные координаты находятся в поплавке, а затем округляют их в конце? «У вас это неправильно» - ОК 2.3 был плохим примером. Take 2.7, int (2.7) == 2, int (2.7 + 0.5) == 3, я думаю, глядя, что я знаю ответ сейчас, потому что 2.7 ближе к 3, чем к 2, поэтому причина, по которой мы должны приближаться целочисленное значение для фактического значения с плавающей запятой. – vexe