<html>

<head><script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- MyFirstUnitAd -->
<ins class="adsbygoogle"
     style="display:inline-block;width:970px;height:250px"
     data-ad-client="ca-pub-5778386704669218"
     data-ad-slot="1503492166"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

<meta http-equiv="Content-Language" content="zh-cn">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Simple Polygon</title>
</head>

<body>



<p align="left"><font size="6" color="#FF0000"><span lang="en-ca"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </b></span>
</font><span lang="en-ca"><font size="6" color="#FF0000"><b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Simple Polygon</b></font></span></p>

<div align="left">
  <pre><b><font color="#ff0000" size="5">A. First Edition</font></b></pre>
</div>
<div align="left">
  <pre><b><font size="3">T<span lang="en-ca">he definition of simple polygon is a closed polygon consisted with a single polygonal chain which doesn't </span></font></b></pre>
</div>
<div align="left">
  <pre><b><font size="3"><span lang="en-ca">intersect with itself.</span></font></b></pre>
</div>
<div align="left">
  <pre>　</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">B</span>.<span lang="en-ca"><a name="problem"></a>The problem</span></font></b></pre>
</div>
<p ALIGN="LEFT"><span lang="en-ca"><b>At beginning it seems a trivial problem. 
However, before assignment 1 of comp6711 is issued I have no clue how to 
implement an algorithm. Suppose you are given a set of points, can you create a 
simple polygon from it? Is it simple? I feel not. </b></span></p>
<div align="left">
  <b><font color="#ff0000" size="5"><span lang="en-ca"><a name="explain"></a>C</span>.<span lang="en-ca">The
  </span></font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>idea of 
  program</b></font></span></div>
<div align="left">
  　</div>
<p><span lang="en-ca"><b>The algorithm is inspired by assignment from comp6711. 
It has a O(n*logn) time complexity. First we sort all points by its x value. 
Find the left-most and right-most point and use the line connected with them to 
separate all other points into &quot;upper&quot; part and &quot;lower&quot; part. Then for each 
point from left to right, if the point is at LHS of the testing line, connect it 
with upper point; If the point is at RHS of testing line, connect it with lower 
point.</b></span></p>
<div align="left">
  <pre><b><font color="#ff0000" size="5">D.<span lang="en-ca"><a name="Method"></a>The </span>major functions</font></b></pre>
</div>
<div align="left">
	<pre>　</pre>
</div>
<div align="left">
	<pre><span lang="en-ca"><font size="3"><b>In order to run in OpenGL, you need download &quot;glut32.dll&quot; and &quot;glu32.dll&quot; in your system folder. </b></font></span></pre>
</div>
<div align="left">
	<pre><span lang="en-ca"><font size="3"><b>i.e. <a href="file:///c:/windows/system32">c:\windows\system32</a></b></font></span></pre>
</div>
<div align="left">
	<pre><span lang="en-ca"><font size="3"><b>And to compile the code, you need to link with &quot;openGL32.lib, glut32.lib, glu32.lib&quot; in your vc6++.</b></font></span></pre>
</div>
<div align="left">
	<pre>　</pre>
</div>
<div align="left">
	<pre>　</pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">E</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>Further improvement</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>Unexpectedly I am running into an OPENGL problem which takes me most of time in this evening. You see the </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>algorithm is trivial and I almost re-use all utility functions from my previous <a href="convexHull-display.htm">trivial program</a>. However, the</b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>openGL problem puzzled me for almost whole night! When I use GL_LINE_LOOP to draw my polygon, the right-most </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>point and nearby is always dimmed and sometimes omitted unless I force openGL to refresh. It must be my </b></font></span></pre>
</div>
<div align="left">
  <pre><span lang="en-ca"><font size="3"><b>stupid bug, however, I cannot find it.</b></font></span></pre>
</div>
<div align="left">
  <pre><b><font color="#ff0000" size="5"><span lang="en-ca">F</span>.</font></b><span lang="en-ca"><font size="5" color="#FF0000"><b>File listing</b></font></span></pre>
</div>
<div align="left" style="width: 898; height: 86">
  <pre><font size="3"><b><span lang="en-ca">1. </span>C<span lang="en-ca">onvexHull.h</span></b></font></pre>
	<pre><span lang="en-ca"><font size="3"><b>2. ConvexHull.cpp</b></font></span></pre>
	<pre><span lang="en-ca"><font size="3"><b>3. main.cpp</b></font></span></pre>
  <pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: convexhull</span>.<span lang="en-ca">h</span></b></font></pre>
  <pre>#ifndef CONVEXHULL_H
#define CONVEXHULL_H

#include &lt;vector&gt;
#include &lt;GL/glut.h&gt;

using namespace std;

const int winPos_x=0, winPos_y=0;
const int winSize_width=600, winSize_height=600;
static const char* windowTitle=&quot;Convex Hull Demo&quot;;

const int MaxIntegerValue=winSize_width/2-30;

typedef GLfloat TColor[3];

static TColor red={1,0,0}, green={0,1,0}, blue={0,0,1};




struct TPoint
{
	float x;
	float y;
	void display();	
};

struct TPointContext
{
	TPoint* pointPtr;
	TColor pointColor;
};


float direction(TPoint* p, TPoint* q, TPoint* r);
float generateRandomValue();
void generatePoint(int pointNumber, TPoint*&amp; ptrArray);

class TPointSet
{
public:
	~TPointSet();
	TPointSet();
	int number;
	TPoint* ptrArray;
	void setArray(TPoint* inputArray, int inputNumber);

	void display();
};

class Convex
{
private:
	int number;
	int* indexArray;
	void sortPoint();
	vector&lt;int&gt; upVector;
	vector&lt;int&gt; downVector;
	void collectVertex(vector&lt;int&gt;&amp; intVector, bool upper);
	void addPoint(vector&lt;int&gt;&amp; intVector, int rIndex);
public:
	static TPoint* ptrArray;
	void generatePoint(int pointNumber);
	Convex();
	void display();
	void convexHull(TPointSet&amp; pointSet);
};


class TPolygon
{
private:
	int number;
	TPoint* leftMost;
	TPoint* rightMost;
	
public:
	TPoint* ptrArray;
	TPolygon();
	void createPolygon(int pointNumber, TPointSet&amp; pointSet);
	
};

#endif</pre>
  <pre>　</pre>
	<pre>　</pre>
	<pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: convexhull</span>.<span lang="en-ca">cpp</span></b></font></pre>
	<pre>#include &lt;iostream&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;
#include &quot;ConvexHull.h&quot;

using namespace std;

TPoint* Convex::ptrArray=NULL;

//GLenum drawingMode = GL_POINTS;



vector&lt;TPointContext&gt; separateVector;
vector&lt;TPointContext&gt; connectVector;

vector&lt;TPointContext&gt; polygonVector;
TPolygon polygon;

Convex convex;
TPointSet pointSet;

int compPoint(const void* elem1, const void* elem2)
{
	TPoint* ptr1, *ptr2;
	ptr1=(TPoint*)elem1;
	ptr2=(TPoint*)elem2;
	return ptr1-&gt;x-ptr2-&gt;x;
}

void TPolygon::createPolygon(int pointNumber, TPointSet&amp; pointSet)
{
	int start=0, end=pointNumber-1;
	number=pointNumber;
	::generatePoint(pointNumber, ptrArray);
	qsort(ptrArray, number, sizeof(TPoint), compPoint);
	leftMost=ptrArray;
	rightMost=ptrArray+number-1;
	pointSet.number=number;
	pointSet.ptrArray=new TPoint[number];
	
	for (int i=0; i&lt;number; i++)
	{
		if (direction(leftMost, rightMost, ptrArray+i)&lt;=0)
		{
			pointSet.ptrArray[start]=ptrArray[i];
			start++;
		}
		else
		{
			pointSet.ptrArray[end]=ptrArray[i];
			end--;
		}		
	}
}

TPolygon::TPolygon()
{
	//createPolygon();
}


int pointComp(const void* elem1, const void* elem2)
{
	TPoint *ptr1, *ptr2;
	float result;

	ptr1=Convex::ptrArray + *(const int*)(elem1);
	ptr2=Convex::ptrArray + *(const int*)(elem2);
	result= ptr1-&gt;x-ptr2-&gt;x;
	if (result&gt;0)
	{
		return 1;
	}
	else
	{
		if (result&lt;0)
		{
			return -1;
		}
		else
		{
			return 0;
		}
	}
}

float direction(TPoint* p, TPoint* q, TPoint* r)
{
	return q-&gt;x*r-&gt;y +p-&gt;x*q-&gt;y+p-&gt;y*r-&gt;x - p-&gt;y*q-&gt;x - q-&gt;y*r-&gt;x -p-&gt;x*r-&gt;y;
}

void TPoint::display()
{
	printf(&quot;[x=%f,y=%f]\n&quot;, x, y);
}

TPointSet::TPointSet()
{
	number=0;
	ptrArray=NULL;
}

void TPointSet::display()
{
	for (int i=0; i&lt;number; i++)
	{
		ptrArray[i].display();
	}
}


TPointSet::~TPointSet()
{
	if (number!=0)
	{
		delete[]ptrArray;
	}
}

void TPointSet::setArray(TPoint* inputArray, int inputNumber)
{
	number=inputNumber;
	ptrArray=new TPoint[number];
	memcpy(ptrArray, inputArray, sizeof(TPoint)*number);
}

float generateRandomValue()
{
	float intPart, floatPart;
	intPart=rand()%MaxIntegerValue * (rand()%2==0?1 : (-1));
	floatPart=(float)rand()/(float)RAND_MAX;
	return intPart+floatPart;
}

void Convex::generatePoint(int pointNumber)
{
	number=pointNumber;
	::generatePoint(pointNumber, ptrArray);
}

void generatePoint(int pointNumber, TPoint*&amp; ptrArray)
{
	TPointContext pointContext;
	ptrArray=new TPoint[pointNumber];
	for (int i=0; i&lt;pointNumber; i++)
	{
		ptrArray[i].x=generateRandomValue();
		ptrArray[i].y=generateRandomValue();
		pointContext.pointPtr=ptrArray+i;
		memcpy(pointContext.pointColor, red, sizeof(TColor));
		separateVector.push_back(pointContext);
		//glutPostRedisplay();			
		glutSwapBuffers();
	}
	//glutPostRedisplay();	
}

//randomly generating points
Convex::Convex()
{
	number=0;
	ptrArray=NULL;	
}

void Convex::sortPoint()
{
	indexArray=new int[number];
	for (int i=0; i&lt;number; i++)
	{
		indexArray[i]=i;
	}
	qsort(indexArray, number, sizeof(int), pointComp);
}

void Convex::addPoint(vector&lt;int&gt;&amp; intVector, int rIndex)
{
	int currentSize;
	int pIndex, qIndex;
	while (intVector.size()&gt;=2)
	{
		currentSize=intVector.size();
		pIndex=intVector[currentSize-2];
		qIndex=intVector[currentSize-1];

		if (direction(ptrArray+pIndex, ptrArray+qIndex, ptrArray+rIndex)&gt;=0)
		{
			intVector.pop_back();
		}
		else
		{			
			break;
		}
	}
	intVector.push_back(rIndex);
}


void Convex::collectVertex(vector&lt;int&gt;&amp; intVector, bool upper)
{
	int index, offset, counter=number-2;

	intVector.clear();
	if (upper)
	{
		index=0;
		offset=1;
	}
	else
	{
		index=number-1;
		offset=-1;
	}

	intVector.push_back(indexArray[index]);
	index+=offset;
	intVector.push_back(indexArray[index]);
	
	while (counter&gt;0)
	{
		index+=offset;

		addPoint(intVector, indexArray[index]);
		counter--;
	}
}


void Convex::display()
{
	for (int i=0; i&lt;number; i++)
	{
		ptrArray[i].display();
	}
}

void Convex::convexHull(TPointSet&amp; pointSet)
{
	int i;
	int upSize, downSize;
	if (number&lt;3)
	{
		pointSet.setArray(ptrArray, number);
	}
	else
	{
		sortPoint();
		collectVertex(upVector, true);
		collectVertex(downVector, false);
		upSize=upVector.size();
		//we need to remove the first and last
		downSize=downVector.size()-2;
		pointSet.number=upSize+downSize;
		pointSet.ptrArray=new TPoint[pointSet.number];
		for (i=0; i&lt;pointSet.number; i++)
		{
			if (i&lt;upSize)
			{
				pointSet.ptrArray[i]=ptrArray[upVector[i]];
			}
			else
			{
				//starting from second, so add 1
				pointSet.ptrArray[i]=ptrArray[downVector[i-upSize+1]];
			}
		}
	}
}
</pre>
	<pre>　</pre>
	<pre><font size="3" color="#FF0000"><b><span lang="en-ca">file name: main</span>.<span lang="en-ca">cpp</span></b></font></pre>
	<pre>#include &quot;ConvexHull.h&quot;
#include &lt;GL/glut.h&gt;
#include &lt;ctime&gt;

using namespace std;

extern vector&lt;TPointContext&gt; separateVector;
extern vector&lt;TPointContext&gt; connectVector;

extern Convex convex;
extern TPolygon polygon;
extern TPointSet pointSet;


void displayCallback()
{
	int separateNumber, connectNumber, i;
	glClearColor(1,1,0,1);
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//separateNumber=separateVector.size();
	separateNumber=0;
	connectNumber=connectVector.size();
	//connectNumber=0;

	glPointSize(10.0);
	glLineWidth(5);
	if (separateNumber&gt;0)
	{
		glBegin(GL_POINTS);
		for (i=0; i&lt;separateNumber; i++)
		{
			glVertex2f(separateVector[i].pointPtr-&gt;x, separateVector[i].pointPtr-&gt;y);
			glColor3fv(separateVector[i].pointColor);
			//printf(&quot;x=%f, y=%f\n&quot;, separateVector[i].pointPtr-&gt;x, separateVector[i].pointPtr-&gt;y);
		}
		glEnd();
	}
	if (connectNumber&gt;0)
	{
		
		glBegin(GL_LINE_LOOP);
		for (i=0; i&lt;connectNumber; i++)
		{
			glVertex2f(connectVector[i].pointPtr-&gt;x, connectVector[i].pointPtr-&gt;y);
			//printf(&quot;x=%f, y=%f\n&quot;, connectVector[i].pointPtr-&gt;x, 
			//	connectVector[i].pointPtr-&gt;y);
			glColor3fv(connectVector[i].pointColor);
		}
		glEnd();
	
		glBegin(GL_POINTS);
		for (i=0; i&lt;connectNumber; i++)
		{
			glVertex2f(connectVector[i].pointPtr-&gt;x, connectVector[i].pointPtr-&gt;y);
			glColor3fv(connectVector[i].pointColor);
			//printf(&quot;x=%f, y=%f\n&quot;, separateVector[i].pointPtr-&gt;x, separateVector[i].pointPtr-&gt;y);
		}
		glEnd();
	
	}


	glutSwapBuffers();
	//glutPostRedisplay();
}

void keyboardCallback(unsigned char key, int x, int y)
{
	int i;
	TPointContext pointContext;
	//float coord[4];
	switch (key)
	{
	case 27:
		exit(0);
		break;
	case 's':
		convex.generatePoint(10);
		break;
	case 'c':
		convex.convexHull(pointSet);
		for (i=0; i&lt;pointSet.number; i++)
		{
			memcpy(pointContext.pointColor, green, sizeof(TColor));
			pointContext.pointPtr=pointSet.ptrArray+i;
			connectVector.push_back(pointContext);
			glutPostRedisplay();
		}
		break;
	case 't':
		//glutStrokeCharacter(GLUT_STROKE_ROMAN, 's');
		glColor3fv(blue);
		glPointSize(1.0);
		glutBitmapCharacter(GLUT_BITMAP_9_BY_15 , 1);
		/*
		glGetFloatv(GL_CURRENT_RASTER_POSITION, coord);
		for (i=0; i&lt;4; i++)
		{
			printf(&quot;[%f],&quot;, coord[i]);
		}
		*/
		break;
	case 'p':
		polygon.createPolygon(11, pointSet);
		for (i=0; i&lt;pointSet.number; i++)
		{
			memcpy(pointContext.pointColor, blue, sizeof(TColor));
			pointContext.pointPtr=pointSet.ptrArray+i;
			connectVector.push_back(pointContext);
			//glutPostRedisplay();
		}
		break;

	}
	glutPostRedisplay();
}

void reshapeCallback(int width, int height)
{
	glutPostRedisplay();
}


void init()
{
	gluOrtho2D((float)winSize_width/2.0, (float)winSize_width/-2.0, 
		(float)winSize_height/-2.0, (float)winSize_height/2.0);
}





int main(int argc, char** argv)
{
	srand(time(0));
	glutInit(&amp;argc, argv);
	glutInitWindowPosition(winPos_x, winPos_y);
	glutInitWindowSize(winSize_width, winSize_height);	
	glutInitDisplayMode(GLUT_RGBA|GLUT_ALPHA|GLUT_DOUBLE);
	glutCreateWindow(windowTitle);
	glutDisplayFunc(displayCallback);
	glutKeyboardFunc(keyboardCallback);
	glutReshapeFunc(reshapeCallback);

	init();





	//printf(&quot;before convex hull\n&quot;);
	//convex.display();

	//convex.convexHull(pointSet);
	//printf(&quot;after convex hull\n&quot;);
	//pointSet.display();
	//glutPostRedisplay();
	//glutShowWindow();

	glutMainLoop();

	return 0;
}</pre>
</div>

<pre><span lang="en-ca">			</span></pre>

<pre><span lang="en-ca">				</span> <a href="game24.htm"><img src="picture/back.gif" style="border: medium none" alt="back.gif (341 bytes)" width="32" height="35"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="index.htm"><img src="picture/up.gif" style="border: medium none" alt="up.gif (335 bytes)" width="35" height="32"></a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="picture/next.gif" style="border: medium none" alt="next.gif (337 bytes)" width="32" height="35"> </pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<pre></pre>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;                                   
&nbsp;&nbsp;&nbsp;</p>

</body>

</html>