}
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()));
}
}
Вообще, алгоритм Лианга-Барски эффективнее алгоритма Коэна-Сазерленда. Кавдое обновление параметров щ и щ требует только одного деления; точки пересечения линии с окном вычисляются только один раз, когда вычисляются конечные значения щ и щ. В то же время, алгоритм Коэна-Сазерленда может последователь-