Objetivo:
Utilice el algoritmo de recorte de polígonos de Sutherland-Hodgeman para recortar el polígono que se muestra en la figura.Se requiere dibujar los gráficos correspondientes para cada clip e indicar los vértices de entrada y salida. Compruébalo con el programa de recorte de polígonos de Sutherland-Hodgeman escrito por ti mismo
Principio experimental:
Recorta el polígono un borde de la ventana a la vez.
Considere un borde de la ventana y la línea de recorte formada por la línea de extensión que divide el plano en dos partes: el lado visible y el lado invisible. Puntos extremos S y P de cada lado del polígono. Solo hay cuatro relaciones posicionales entre ellos y la línea de recorte.
La figura 1 solo genera un vértice P;
Figura 2 salidas 0 vértices;
la figura 3 genera un punto de intersección I del segmento de línea SP y la línea de recorte;
la figura 4 genera un punto de intersección I y un punto final P del segmento de línea SP y la línea de recorte;
Tres: pasos experimentales y código fuente
关键代码:
//判断点在线段的内侧还是外侧
int Inside(Point p, Boundary b, Point wMin, Point wMax)
{
switch (b)
{
case Left:
if (p.x < wMin.x) return (false);
break;
case Top:
if (p.y > wMax.y) return (false);
break;
case Right:
if (p.x > wMax.x) return (false);
break;
case Bottom:
if (p.y < wMin.y) return (false);
break;
}
return true;
}
//判断两点在同侧还是异侧
int Cross(Point p1, Point p2, Boundary b, Point wMin, Point wMax)
{
if (Inside(p1, b, wMin, wMax) == Inside(p2, b, wMin, wMax))
return (false);
else
return true;
}
//求交点
Point Intersect(Point p1, Point p2, Boundary b, Point wMin, Point wMax)
{
Point iPt = { 0,0 };
float m = 0;
if (p1.x != p2.x) m = (p2.y - p1.y) / (p2.x - p1.x);
switch (b)
{
case Left:
iPt.x = wMin.x;
iPt.y = p2.y + (wMin.x - p2.x) * m;
break;
case Right:
iPt.x = wMax.x;
iPt.y = p2.y + (wMax.x - p2.x) * m;
break;
case Bottom:
iPt.y = wMin.y;
if (p1.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 (p1.x != p2.x) iPt.x = p2.x + (wMax.y - p2.y) / m;
else iPt.x = p2.x;
break;
}
return iPt;
}
//返回裁剪后的顶点个数
int edgeCliper(Boundary b, Point wMin, Point wMax, Point* pIn, int cnt, Point* pOut)
{
Point s;
int i, Outcnt = 0;
s = pIn[0];
for (i = 1; i <= cnt; i++)
{
if (!Inside(s, b, wMin, wMax) && Inside(pIn[i], b, wMin, wMax))
{
pOut[Outcnt] = Intersect(s, pIn[i], b, wMin, wMax);
Outcnt++;
pOut[Outcnt] = pIn[i];
Outcnt++;
}
else if (Inside(s, b, wMin, wMax) && Inside(pIn[i], b, wMin, wMax))
{
pOut[Outcnt] = pIn[i];
Outcnt++;
}
else if (Inside(s, b, wMin, wMax) && (!Inside(pIn[i], b, wMin, wMax)))
{
pOut[Outcnt] = Intersect(s, pIn[i], b, wMin, wMax);
Outcnt++;
}
s = pIn[i];
}
return (Outcnt);
}
void ClipPolygonSuthHodg(vector<VERTEX>& polygon)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
int i, cnt, Outcnt, b;
Point points[6] = { {400, 100}, {500, 400}, {800, 100}, {600, 800}, {100, 500},{400, 100} };
cnt = 5;
Point pOut[20], pIn[20];
Point wMin = { 200, 200 }, wMax = { 600, 600 };
for (i = 0; i < 4 * cnt; i++)
{
pIn[i].x = 0.0;
pIn[i].y = 0.0;
pOut[i].x = 0.0;
pOut[i].y = 0.0;
}
for (i = 0; i <= cnt; i++) pIn[i] = points[i];
glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glVertex2f(wMin.x, wMin.y);
glVertex2f(wMax.x, wMin.y);
glVertex2f(wMax.x, wMax.y);
glVertex2f(wMin.x, wMax.y);
glEnd();
glLineWidth(1.0);
glLineStipple(1, 0x0F0F);
glBegin(GL_LINE_LOOP);
for (i = 0; i < cnt; i++)
glVertex2f(pIn[i].x, pIn[i].y);
glEnd();
for (b = 0; b < 4; b++)
{
Outcnt = edgeCliper(Boundary(b), wMin, wMax, pIn, cnt, pOut);
for (int i = 0; i < Outcnt; i++)
for (i = 0; i < Outcnt; i++)
pIn[i] = pOut[i];
pIn[Outcnt] = pOut[0];
cnt = Outcnt;
}
glDisable(GL_LINE_STIPPLE);
glLineWidth(2.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
for (i = 0; i < cnt; i++)
glVertex2f(pOut[i].x, pOut[i].y);
glEnd();
glFlush();
}
Resultados Experimentales y Análisis
Gráficos originales:
Gráficos recortados
Análisis: Los gráficos recortados según el algoritmo del polígono se muestran en la línea roja de arriba, que es lo que queremos. Recortar cada borde una vez volverá a obtener una secuencia de vértices. Los cuatro bordes se cortan cuatro veces en total. La idea del algoritmo no es difícil, pero la implementación del algoritmo es más problemática y el cálculo del punto de intersección también es un poco difícil.