Реализация двухмерного алгоритма отсечения прямых Коэна-Сазерленда представлена в следующих процедурах. Расширение этого алгоритма на трехмерную ситуацию очевидно, а более подробно трехмерное наблюдение рассматривается в следующей главе.
class wcPt2D { public:
GLfloat x, у;
};
inline GLint round (const GLfloat a)
{ return GLint (a + 0.5); }
/* Для каждой внешней области прямоугольного отсекающего окна
* определяется четырехбитовый код. */
const GLint winLeftBitCode = 0x1;
const GLint winRightBitCode - 0x2; const GLint winBottomBitCode = 0x4; const GLint winTopBitCode = 0x8;
/* Битовый код области также присваивается каждой конечной
* точке входного отрезка согласно его расположению
* относительно четырех краев входного прямоугольного
* отсекающего окна.
* Конечная точка с кодом области 0000 находится внутри
* отсекающего окна, в противном случае она находится вне хотя
* бы одной отсекающей границы. Если применение операции ИЛИ
* к двум кодам конечных точек дает значение 'false', вся
* линия, определенная этими двумя конечными точками
* записывается (принимается). Если применение операции И к
* двум кодам конечных точек дает значение 'true', линия лежит
* полностью вне отсекающего окна, и она исключается из
* дальнейшей обработки (отклоняется). */
inline GLint inside (GLint code) { return GLint (!code); } inline GLint reject (GLint codel, GLint code2)
{ return GLint (codel & code2); } inline GLint accept (GLint codel, GLint code2)
{ return GLint (!(codel | code2)); }
GLubyte encode (wcPt2D pt, wcPt2D winMin, wcPt2D winMax)
{
GLubyte code = 0x00; if (pt.x < winMin.x)
code = code I winLeftBitCode; if (pt.x > winMax.x)
code = code I winRightBitCode; if (pt.y < winMin.у)
code = code I winBottomBitCode; if (pt.y > winMax.у)
code = code | winTopBitCode; return (code);
}
void swapPts (wcPt2D * pi, wcPt2D * p2)
(
wcPt2D tmp;
tmp = *pl; *pl = *p2; *p2 = tmp;
}
void swapCodes (GLubyte * cl, GLubyte * c2)
{
GLubyte tmp;
tmp = *cl; *cl - *c2; *c2 = tmp;
}
void lineClipCohSuth (wcPt2D winMin, wcPt2D winMax,
wcPt2D pi, wcPt2D p2)
t
GLubyte codel, code2;
GLint done = false, plotLine = false;
GLfloat m; while (!done) {
codel = encode (pi, winMin, winMax); code2 = encode (p2, winMin, winMax); if (accept (codel, code2)) { done = true; plotLine = true;
}
else
if (reject (codel, code2)) done = true; else {
/* Пометить конечную точку вне окна на экране как pi. */ if (inside (codel)) ( swapPts (&pl, &p2); swapCodes (Scodel, &code2);
}
/* Использовать тангенс угла наклона m */
/* для расчета пересечения линии со стороной. */ if (р2.х != pl.x)
m = (р2.у - pi.у) / (р2.х - pl.x); if (codel & winLeftBitCode) {
pl.y += (winMin.х - pl.x) * m; pl.x = winMin.x;
}
else
if (codel & winRightBitCode) { pl.y += (winMax.x - pl.x) * m; pl.x = winMax.x;