}

else

if (codel & winBottomBitCode) {

/* Нужно обновить pl.x только для невертикальных линий. */ if (р2.х != pl.x)

pl.x += (winMin.у - pl.y) / m; pl.y = winMin.y;

}

else

if (codel & winTopBitCode) { if (p2.x != pl.x)

pl.x += (winMax.у - pl.y) / m; pl.y = winMax.у;

}

}

}

if (plotLine)

lineBres (round (pl.x), round (pl.y), round (p2.x),

round (p2.y));

}

ОТСЕЧЕНИЯ ЛИНИИ ЛИАНГА-БАРСКИ

Были разработаны и более быстрые алгоритмы отсечения линий, в которых перед расчетом точек пересечения производится больше проверок. Одна из первых работ в этом направлении принадлежит Сайресу (Cyrus) и Бэку (Beck), и она основана на анализе параметрических уравнений прямой. Позднее Лианг (Liang) и Барский (Barsky) независимо разработали даже еще более быструю форму параметрического алгоритма отсечения линий.

class wcPt2D { private:

GLfloat x, у; public:

/* По умолчанию точка инициализируется как (0.0, 0.0). */ wcPt3D ( ) { х = у = 0.0;

}

setCoords (GLfloat xCoord, GLfloat yCoord) { x - xCoord; у = yCoord;

}

GLfloat getx ( ) const { return x;

}

GLfloat gety ( ) const { return y;

}

};

inline GLint round (const GLfloat a) { return GLint (a + 0.5);

}

GLint clipTest (GLfloat p, GLfloat q, GLfloat * ul,

GLfloat * u2){

GLfloat r;

GLint returnValue = true; if (p < 0.0) { r = q / p; if (r > *u2)

returnValue = false; else

if (r > *ul)

*ul = r; }

else

if (р > 0.0) { г = q / р;

if (г < *ul)

returnValue = false; else if (r < *u2)

*u2 = r;

}

else

/* В этом случае p = 0, и линия параллельна границе отсечения. */

if (q < 0.0)

/* Линия вне границы отсечения. */ returnValue = false; return (returnValue);

}

void lineClipLiangBarsk (wcPt2D winMin, wcPt2D winMax,

wcPt2D pi, wcPt2D p2)

{

GLfloat ul = 0.0, u2 = 1.0, dx = p2.getx ( ) - pl.getx ( ), dy;

if (clipTest (-dx, pl.getx ( ) - winMin.getx ( ), &ul, &u2))

if (clipTest (dx, winMax.getx ( ) - pl.getx ( ), &ul, &u2))

{

dy = p2.gety ( ) - pi.gety ( );

if (clipTest (-dy, pi.gety () - winMin.gety (), &ul, &u2)) if (clipTest (dy, winMax.gety () - pi.gety (), Sul, &u2)) {

if (u2 < 1.0) {

p2.setCoords (pl.getx ( ) + u2 * dx, pi.gety ( ) +

u2 * dy);

}

if (ul > 0.0) {

pl.setCoords (pl.getx ( ) + ul * dx, pi.gety ( ) +

ul * dy);

}

lineBres (round (pl.getx ( )), round (pi.gety ( )),

round (p2.getx ( )), round (p2.gety()));

}

}

Вообще, алгоритм Лианга-Барски эффективнее алгоритма Коэна-Сазерленда. Кавдое обновление параметров щ и щ требует только одного деления; точки пересечения линии с окном вычисляются только один раз, когда вычисляются конечные значения щ и щ. В то же время, алгоритм Коэна-Сазерленда может последователь-


⇐ вернуться назад | | далее ⇒