Advertisement

Strange problem with polygons...

Started by April 13, 2003 07:58 PM
5 comments, last by ShmeeBegek 21 years, 10 months ago
I am using the area of a polygon to decide weather a point is within it or not, I do this by finding the area of the polygon using a triangle fan and then adding up the area of a triangle fan around the point to the vertices of the polygon, but for some reason when I test it one side is missing and I get strange outputs (they do not come close to the polygon area). Sadly after days of debugging I have to post it here. note: the GL commands and printf were both inserted for dubugging...
  

#include "polygon.h"
#include <math.h>

#include <gl/glut.h>

long triangle_area(long V[6])
{
	int i;
	long mostleft=V[0],mostright=V[0],mosthigh=V[1],mostlow=V[1];

	// Pick Left

	for(i=1;i<3;i++)
	{
		if(V[i*2] < mostleft)
			mostleft=V[i*2];
	}

	// Pick Right

	for(i=1;i<3;i++)
	{
		if(V[i*2] > mostright)
			mostright=V[i*2];
	}

	// Pick High

	for(i=1;i<3;i++)
	{
		if(V[(i*2)+1] < mosthigh)
			mosthigh=V[(i*2)+1];
	}

	// Pick Low

	for(i=1;i<3;i++)
	{
		if(V[(i*2)+1] > mostlow)
			mostlow=V[(i*2)+1];
	}

	return ((mostright-mostleft)*(mostlow-mosthigh))/2;
}

long polygon_area(int nvert,in_vertex *V)
{
	// Add the area of a triangle fan around point 0

	int i;
	long list[6];
	long area=0;

	if(nvert<3)
		return 0;

	list[0]=V[0].X;
	list[1]=V[0].Y;

	for(i=2;i<nvert;i++)
	{
		list[2]=V[i-1].X;
		list[3]=V[i-1].Y;
		list[4]=V[i].X;
		list[5]=V[i].Y;
		area+=triangle_area(list);
	}

	return area;
}

bool isInPolygon(in_poly *polygon,long offx,long offy,long X,long Y)
{
	// Add the area of a triangle fan around the point

	long cur_area=0;
	int i,l=0,c=0;
	long list[6];
	if(!polygon)
		return 0;
	if(polygon->numVertices < 3)
		return 0;
	if(!polygon->vertices)
		return 0;

	list[0]=X-offx;
	list[1]=Y-offy;
	for(i=1;i<=polygon->numVertices;i++)
	{
		glColor3f(0.6f,0.5f+(0.25f/polygon->numVertices)*(i-1),0.5f);
		l=c;
		c=i;
		if(c==(polygon->numVertices))
			c=0;

		// Triangle is from p to current to last

		list[2]=polygon->vertices[c].X;
		list[3]=polygon->vertices[c].Y;
		list[4]=polygon->vertices[l].X;
		list[5]=polygon->vertices[1].Y;

		glBegin(GL_TRIANGLES);
		
		glVertex2i(list[0],list[1]);
		glVertex2i(list[2],list[3]);
		glVertex2i(list[4],list[5]);
		glEnd();
		cur_area+=triangle_area(list);
	}
	printf("%i,%i\r\n",cur_area,polygon_area(polygon->numVertices,polygon->vertices));
	return cur_area==polygon_area(polygon->numVertices,polygon->vertices);
}
  
Thanks ~SPH
AIM ME: aGaBoOgAmOnGeR
Very interesting idea. Although, I bet that it is not going to be the most efficient way to do this. Sorry, but I''m not too familiar with OGL, so I am not really sure what your code is doing. Maybe it''s not looping through all the way (i.e., you aren''t including a triangle strip between the point, the end vertex, and the start vertex). Make sure that you are doing this.

Brendan
Brendan"Mathematics is the Queen of the Sciences, and Arithmetic the Queen of Mathematics" -Gauss
Advertisement

Nah nothing that simple, but as I noted the GL and printf lines are only for debug, rest is pure syntax.

Its not the most eficient way no, but since this is a quikkie project with less than 10 polies on the screen at a time, its okay for my code to be written faster for a bit of a preformance loss.

I am using this as a work around so I do not have to write a whole time consuming BSP renderer and such for a simple 2d game.

Thanks, ~SPH
AIM ME: aGaBoOgAmOnGeR

I''ve figured it out... its my "triangle_area" function. So now I need help figuring out how to find the area of an arbitrary triangle, sorry about this but I have thought about it on my own and I''m coming up blank (1/2 * bh is not working obviously).

Thanks, ~SPH
AIM ME: aGaBoOgAmOnGeR
Are you checking the coordinate base x Height? are you taking the distance from each point to each other point for the side lengths?
Disclaimer: "I am in no way qualified to present advice on any topic concerning anything and can not be held responsible for any damages that my advice may incurr (due to neither my negligence nor yours)"
I noticed the problem in your triangle area function as well. I believe I have a solution, but it''s probably not the most efficient/elegant.

The problem with your solution is that you weren''t taking the appropriate base or height of your triangle. For the sake of discussion, let''s have a triangle with vertices A, B, and C. The base should lie on one side of your triangle, let''s just pick the line AB, or in vector math, |A-B|. Now that that''s over with, onto the slightly harder part, the height. Really what we need to find is a new line that runs from point C to a line that runs through points A and B, and the magnitude of that line is the height of the triangle. A basic geometric fact is that the shortest distance from a point to a line is along a line perpendicular to the first, and if we call the point at which these two lines meet B'', the new triangle AB''C is a right triangle, and the line B''C is the height of our original triangle. Since we now have a right triangle, we can use a little trig to get at the height. The height is |C-A|sin(c) where c is the angle opposite point C in the triangle, and |C-A| is the vector magnitude of the hypoteneuse(sp?). Since we know |C-A| all we need is c. To find this, it takes a little vector math. Basically, c = arccos((B-A)*(C-A))/(|B-A||C-A|)) where the numerator is the dot product, and the denominator is just the magnitudes of these vectors multiplied together. So there you have it (if I haven''t made any mistakes, which I probably did). Please someone correct me if I''m wrong.

Recap:
base = |B-A|
height = |C-A|sin(c) where c = arccos((B-A)*(C-A))/(|B-A||C-A|))


I hope this helps.

Elijah
--"The greatest pleasure in life is in doing what people say you cannot do." -- Walter Bageholt
Advertisement
I will also point you to the forum, which has a link to point-in-polygon test approaches:

Forum FAQ


Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net

This topic is closed to new replies.

Advertisement