PDA

View Full Version : Calculating polygon lines



Tiberiu
09-26-2010, 10:56 AM
I have a polygon drawn with OpenGL line by line. However, I need to draw an extending line from the middle of each edge towrd the center of the polygon. As you can see in the picture below, the green and black lines are pointing in the right direction, but the white and blue ones are not.

http://img816.imageshack.us/img816/7402/linesl.jpg

What mathematical alogrithm should I use to correct this issue?

Here is the code:
//this draws an edge

//ortarr[j] is an array that stores each edge, x1 y1 and x2 y2 are the points of the edge, so x2 y2 correspond to the next edge's x1 and y2.

float slope = (ortarr[j].y2 - ortarr[j].y1) / (ortarr[j].x2 - ortarr[j].x1);//slope of edge
float angle = atan2(ortarr[j].y2 - ortarr[j].y1, ortarr[j].x2 - ortarr[j].x1);//angle of edge
float angle2 = atan(-1.0f / slope);//angle of the small line, negative reciprocal

//this draws the small extending line
x1 = mx + (cos(angle));//middle line coordinates
y1 = my + (sin(angle));
x2 = x1 + (cos(angle2) * 1.6f);//middle line extending coordinates, this is where it sometimes fails
y2 = y1 + (sin(angle2) * 1.6f);
DrawLine(coltmp, x1, y1, x2, y2, 3.0f);

david_f_knight
09-26-2010, 01:27 PM
I see two issues.

First, you have:

slope = (ortarr[j].y2 - ortarr[j].y1) / (ortarr[j].x2 - ortarr[j].x1);
angle2 = atan(-1.0f / slope);
That's not causing your problem in this case, but generally speaking, there's nothing stopping you from have a vertical edge, which will cause your calculation of slope to crash your program, and there's nothing from stopping you from having a horizontal edge, which has a slope of zero, and that will cause your calculation of angle2 to crash your program. The solution to your problem is to use trigonometric identities rather than algebraic identities to define your angles. That is, define angle2 as angle + pi / 2.0 . Never calculate slope, unless you provide different paths to handle things so you never divide by zero and never have absolute value of slope greater than one (calculate inverse slope instead if the absolute value of slope would be greater than one). (When slope, or inverse slope, approaches infinity, then the accuracy of your calculations drops. Angles don't suffer this problem. Trigonometry is your friend.)

Second, you have not shown us how you have defined ortarr[], your array of edge vertices. The order that you have defined the vertices stored in ortarr[] determines the direction of each edge, and the direction of each edge determines how you calculate angle2. If you reversed the order of your vertices in ortarr[] (I mean swap y1 with y2, and x1 with x2), you'd reverse the direction of each edge, and that would cause each edge bisector to be drawn on the other side of each edge, for example.

To solve your problem, you need to choose a winding convention, i.e., either clockwise or couterclockwise, and carefully and consistently define the vertices of all your edges consistent with that convention. Then, your code needs to be consistent with that convention, as well. That's the easy way.

Incidentally, if you are going to be drawing connected lines, then there is typically no need to store x1 and x2, and y1 and y2 for each edge. However, if you only store each vertex once, then you must define the vertices in the order that the edges are defined (or else introduce an index array).

Tiberiu
09-27-2010, 05:55 AM
Hello,

Thank you for your help, here are some clarifications:

I modified the code so only a vertex is stored, so now ortarr[] looks like this:
struct ortstr
{
float x1;
float y1;
}ortarr[999];

I removed slope and I calculate angle2 like this:
float angle2 = angle + PI /2.0f;

The winding rule was the most difficult since I have a database, but here is the quick solution:

calculate the are of the polygon, if it is negative, multiply by -1 the coordinates x2 and y2 that use atan2, here sg is sign, the value that contains eithe r aplus or a minus:
x2 = x1 + (cos(angle2) * 0.6f * fPixPerNM * sg);
y2 = y1 + (sin(angle2) * 0.6f * fPixPerNM * sg);

Thank you for your help!