Последовательная реализация алгоритма отсечения многоугольников Сазерленда-Ходгмана демонстрируется в следующем наборе процедур. Входной набор вершин преобразуется в выходной путем применения процедур отсечения слева, справа, снизу и сверху.
typedef enum { Left, Right, Bottom, Top } Boundary; const GLint nClip = 4;
GLint inside (wcPt2D p, Boundary b, wcPt2D wMin, wcPt2D wMax)
{ switch (b) {
case Left: if (p.x < wMin.x) return (false); break;
case Right: if (p.x > wMax.x) return (false); break;
case Bottom: if (p.y < wMin.y) return (false); break;
case Top: if (p.y > wMax.y) return (false); break; }
return (true);
}
GLint cross (wcPt2D pi, wcPt2D p2, Boundary winEdge,
wcPt2D wMin, wcPt2D wMax)
{
if (inside (pi, winEdge, wMin, wMax) == inside (p2, winEdge, wMin, wMax)) return (false); else return (true);
}
wcPt2D intersect (wcPt2D pi, wcPt2D p2, Boundary winEdge,
wcPt2D wMin, wcPt2D wMax)
{
wcPt2D iPt;
GLfloat m;
if (pl.x != p2.x) m = (pl.y - p2.y) / (pl.x - p2.x); switch (winEdge) { case Left:
iPt.x = wMin.x;
iPt.y = p2.y + (wMin.x - p2.x) * inbreak; case Right:
iPt.x = wMax.x;
iPt.y = p2.y + (wMax.x - p2.x) * m; break; case Bottom:
iPt.y = wMin.y;
if (pl.x != p2.x) iPt.x = p2.x + (wMin.y - p2.y) / m; else iPt.x = p2.x; break; case Top:
iPt.y = wMax.y;
if (pl.x != p2.x) iPt.x = p2.x + (wMax.y - p2.y) / m;
else iPt.x = p2.x;
break;
}
return (iPt) ;
}
void clipPoint (wcPt2D р, Boundary winEdge, wcPt2D wMin, wcPt2D wMax, wcPt2D * pOut, int * cnt, wcPt2D * first[], wcPt2D * s)
<
wcPt2D iPt;
/* Если для данной границы отсечения не существует
* предыдущей точки, записывается текущая точка.
*/
if (!first[winEdge]) first[winEdge] = &p; else
/* Предыдущая точка существует. Если отрезок, соединяющий р
* и предыдущую точку, пересекает данную границу отсечения,
* находится точка пересечения. Если еще есть границы,
* отсечение по которым не выполнялось, провести отсечение
* по ним. Если границ отсечения больше нет, точки пересечения
* добавляются в выходной список.
*/
if (cross (р, s[winEdge], winEdge, wMin, wMax)) {
iPt = intersect (p, s[winEdge], winEdge, wMin, wMax); if (winEdge < Top)
clipPoint (iPt, b+1, wMin, wMax, pOut, cnt, first, s); else {
pOut[*cnt] = iPt; (*cnt)++;
}
}
/* Для данной границы отсечения записать р как новую
* точку.
*/
s[winEdge] = р;
/* Если точка внутренняя, перейти к следующей необработанной
* границе (если такие остались).