12 Program to implement Sutherland Hodgman Polygon Clipping in OpenGL

Program:

// Sutherland Hodgman Polygon Clipping Complete Code | implementation through openGL

#include <stdio.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <math.h>

typedef struct // structure that holds the information of points
{
	float x;
	float y;
} PT;

// global variables

int n;

int i, j;

PT p1, p2, p[20], pp[20];

void left() // left clipper
{
	i = 0;
	j = 0;

	for (i = 0; i < n; i++)
	{
		if (p[i].x < p1.x && p[i + 1].x >= p1.x) //Case-1:	outside to inside
		{
			if (p[i + 1].x - p[i].x != 0)
			{
				pp[j].y = (p[i + 1].y - p[i].y) / (p[i + 1].x - p[i].x) * (p1.x - p[i].x) + p[i].y; // save point of intersection
			}
			else
			{
				pp[j].y = p[i].y;
			}
			pp[j].x = p1.x;
			j++;
			pp[j].x = p[i + 1].x; // save that point that lie inside our clipping window // consult theory
			pp[j].y = p[i + 1].y;
			j++;
		}

		if (p[i].x >= p1.x && p[i + 1].x >= p1.x) //Case-2:	inside to inside
		{
			pp[j].y = p[i + 1].y; // only save second point that lie inside our clipping window // consult theory
			pp[j].x = p[i + 1].x;
			j++;
		}

		if (p[i].x >= p1.x && p[i + 1].x < p1.x) // Case-3:	inside to outside
		{
			if (p[i + 1].x - p[i].x != 0)
			{
				pp[j].y = (p[i + 1].y - p[i].y) / (p[i + 1].x - p[i].x) * (p1.x - p[i].x) + p[i].y; // only save point of intersection
			}
			else
			{
				pp[j].y = p[i].y;
			}
			pp[j].x = p1.x;
			j++;
		}
	}

	for (i = 0; i < j; i++)
	{
		p[i].x = pp[i].x;
		p[i].y = pp[i].y;
	}

	p[i].x = pp[0].x;
	p[i].y = pp[0].y;
	n = j;
}

void right() // right clipper
{
	i = 0;
	j = 0;

	for (i = 0; i < n; i++)
	{
		if (p[i].x > p2.x && p[i + 1].x <= p2.x) //Case-1:	outside to inside
		{
			if (p[i + 1].x - p[i].x != 0)
			{
				pp[j].y = (p[i + 1].y - p[i].y) / (p[i + 1].x - p[i].x) * (p2.x - p[i].x) + p[i].y; // save point of intersection
			}
			else
			{
				pp[j].y = p[i].y;
			}
			pp[j].x = p2.x;
			j++;
			pp[j].x = p[i + 1].x; // save that point that lie inside our clipping window // consult theory
			pp[j].y = p[i + 1].y;
			j++;
		}

		if (p[i].x <= p2.x && p[i + 1].x <= p2.x) // Case-2:	inside to inside
		{
			pp[j].y = p[i + 1].y; // only save second point that lie inside our clipping window // consult theory
			pp[j].x = p[i + 1].x;
			j++;
		}

		if (p[i].x <= p2.x && p[i + 1].x > p2.x) // Case-3:	inside to outside
		{
			if (p[i + 1].x - p[i].x != 0)
			{
				pp[j].y = (p[i + 1].y - p[i].y) / (p[i + 1].x - p[i].x) * (p2.x - p[i].x) + p[i].y; // only save point of intersection
			}
			else
			{
				pp[j].y = p[i].y;
			}
			pp[j].x = p2.x;
			j++;
		}
	}

	for (i = 0; i < j; i++)
	{
		p[i].x = pp[i].x;
		p[i].y = pp[i].y;
	}

	p[i].x = pp[0].x;
	p[i].y = pp[0].y;
}

void top() // top clipper
{
	i = 0;
	j = 0;

	for (i = 0; i < n; i++)
	{
		if (p[i].y > p2.y && p[i + 1].y <= p2.y) //Case-1:	outside to inside
		{
			if (p[i + 1].y - p[i].y != 0)
			{
				pp[j].x = (p[i + 1].x - p[i].x) / (p[i + 1].y - p[i].y) * (p2.y - p[i].y) + p[i].x; // save point of intersection
			}
			else
			{
				pp[j].x = p[i].x;
			}
			pp[j].y = p2.y;
			j++;
			pp[j].x = p[i + 1].x; // save that point that lie inside our clipping window // consult theory
			pp[j].y = p[i + 1].y;
			j++;
		}

		if (p[i].y <= p2.y && p[i + 1].y <= p2.y) // Case-2:	inside to inside
		{
			pp[j].y = p[i + 1].y; // only save second point that lie inside our clipping window // consult theory
			pp[j].x = p[i + 1].x;
			j++;
		}

		if (p[i].y <= p2.y && p[i + 1].y > p2.y) // Case-3:	inside to outside
		{
			if (p[i + 1].y - p[i].y != 0)
			{
				pp[j].x = (p[i + 1].x - p[i].x) / (p[i + 1].y - p[i].y) * (p2.y - p[i].y) + p[i].x; // only save point of intersection
			}
			else
			{
				pp[j].x = p[i].x;
			}
			pp[j].y = p2.y;
			j++;
		}
	}

	for (i = 0; i < j; i++)
	{
		p[i].x = pp[i].x;
		p[i].y = pp[i].y;
	}

	p[i].x = pp[0].x;
	p[i].y = pp[0].y;
	n = j;
}

void bottom() // bottom clipper
{
	i = 0;
	j = 0;

	for (i = 0; i < n; i++)
	{
		if (p[i].y < p1.y && p[i + 1].y >= p1.y) // Case-1:	outside to inside
		{
			if (p[i + 1].y - p[i].y != 0)
			{
				pp[j].x = (p[i + 1].x - p[i].x) / (p[i + 1].y - p[i].y) * (p1.y - p[i].y) + p[i].x; // save point of intersection
			}
			else
			{
				pp[j].x = p[i].x;
			}
			pp[j].y = p1.y;
			j++;
			pp[j].x = p[i + 1].x; // save that point that lie inside our clipping window // consult theory
			pp[j].y = p[i + 1].y;
			j++;
		}

		if (p[i].y >= p1.y && p[i + 1].y >= p1.y) // Case-2:	inside to inside
		{
			pp[j].x = p[i + 1].x; // only save second point that lie inside our clipping window // consult theory
			pp[j].y = p[i + 1].y;
			j++;
		}

		if (p[i].y >= p1.y && p[i + 1].y < p1.y) // Case-3:	inside to outside
		{
			if (p[i + 1].y - p[i].y != 0)
			{
				pp[j].x = (p[i + 1].x - p[i].x) / (p[i + 1].y - p[i].y) * (p1.y - p[i].y) + p[i].x; // only save point of intersection
			}
			else
			{
				pp[j].x = p[i].x;
			}
			pp[j].y = p1.y;
			j++;
		}
	}

	for (i = 0; i < j; i++)
	{
		p[i].x = pp[i].x;
		p[i].y = pp[i].y;
	}
	p[i].x = pp[0].x;
	p[i].y = pp[0].y;
	n = j;
}

void drawpolygon()
{
	glColor3f(1.0, 0.0, 0.0);
	for (i = 0; i < n - 1; i++)
	{
		glBegin(GL_LINES);
		glVertex2d(p[i].x, p[i].y);
		glVertex2d(p[i + 1].x, p[i + 1].y);
		glEnd();
	}
	glBegin(GL_LINES);
	glVertex2d(p[i].x, p[i].y);
	glVertex2d(p[0].x, p[0].y);
	glEnd();
}

void myMouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) // On output, please left click on polygon then and only then clipping performs
	{
		glClear(GL_COLOR_BUFFER_BIT);

		glBegin(GL_LINE_LOOP);
		glVertex2f(p1.x, p1.y);
		glVertex2f(p2.x, p1.y);
		glVertex2f(p2.x, p2.y);
		glVertex2f(p1.x, p2.y);
		glEnd();
		left();
		right();
		top();
		bottom();
		drawpolygon();
	}
	glFlush();
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.4, 1.0, 0.0);
	glBegin(GL_LINE_LOOP);
	glVertex2f(p1.x, p1.y);
	glVertex2f(p2.x, p1.y);
	glVertex2f(p2.x, p2.y);
	glVertex2f(p1.x, p2.y);
	glEnd();
	drawpolygon();
	glFlush();
}

void init(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0); // clear screen usually black
	gluOrtho2D(0, 500, 0, 500);
}

int main(int argc, char **argv)
{
	printf("Enter Window Coordinates:\n");
	printf("Please Enter two Points:\n"); // P1(x,y) is the bottom left point for clipping window
	printf("Enter P1(x,y):\n");
	scanf("%f", &p1.x); // if you don't know what value should be given: enter 200
	scanf("%f", &p1.y); // if you don't know what value should be given: enter 200

	printf("Enter P2(x,y):\n"); // P2(x,y) is the top right point for clipping window
	scanf("%f", &p2.x);			// if you don't know what value should be given: enter 400
	scanf("%f", &p2.y);			// if you don't know what value should be given: enter 400

	printf("\nEnter the no. of vertices:"); // if you don't know what value should be given: enter 3
	scanf("%d", &n);

	for (i = 0; i < n; i++)
	{
		printf("\nEnter V%d(x%d,y%d):\n", i + 1, i + 1, i + 1);
		scanf("%f", &p[i].x); // if you don't know what value should be given: enter V1(100,110), V2(340,210), V3(300,380)
		scanf("%f", &p[i].y);
	}

	p[i].x = p[0].x; // Assign last to first for connected everything
	p[i].y = p[0].y;

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize(640, 480);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("Sutherland Hodgman Polygon Clipping Algorithm ");
	init();

	glutDisplayFunc(display);
	glutMouseFunc(myMouse); // notice mouse movement and call user defined function
	glFlush();
	glutMainLoop();
	return 0;
}

Output:

Before Clip:
Sutherland Hodgman Polygon Clipping Before Clip

After Clip:
Sutherland Hodgman Polygon Clipping After Clip


Previous
Next Post »