determine whether point lies inside triangle [closed] - math

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
The program needs to read the values of three coordinates
P1(x1,y1)
P2(x2,y2)
P3(x3,y3)
as well as another coordinate P(x,y) and determine whether this point is inside a triangle formed from the 3 point above.

The proper way to do this is by calculating the barycentric coordinates of the fourth point given the three points of your triangle. The formula to compute them is given at the end of the section "Converting to barycentric coordinates", but I hope to provide a less mathematics-intense explanation here.
Assume, for simplicity, that you have a struct, point, that has values x and y. You defined your points as:
point p1(x1, y1);
point p2(x2, y2);
point p3(x3, y3);
point p(x,y); // <-- You are checking if this point lies in the triangle.
Now, the barycentric coordinates, generally called alpha, beta, and gamma, are calculated as follows:
float alpha = ((p2.y - p3.y)*(p.x - p3.x) + (p3.x - p2.x)*(p.y - p3.y)) /
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float beta = ((p3.y - p1.y)*(p.x - p3.x) + (p1.x - p3.x)*(p.y - p3.y)) /
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
float gamma = 1.0f - alpha - beta;
If all of alpha, beta, and gamma are greater than 0, then the point p lies within the triangle made of points p1, p2, and p3.
The explanation behind this is that a point inside a triangle can be described using the points of the triangle, and three coefficients (one for each point, in the range [0,1]):
p = (alpha)*p1 + (beta)*p2 + (gamma)*p3
Rearranging this function gives you the formula to compute barycentric coordinates, but I feel like the steps to do so might be beyond the scope of the question. They are provided on the Wikipedia page that I linked up top.
It follows that each coefficient must be greater than 0 in order for the point p to lie within the area described by the three points.

Instead of P1, P2 and P3, lets assume the points as A,B and C.
A(10,30)
/ \
/ \
/ \
/ P \ P'
/ \
B (0,0) ----------- C(20,0)
Algorithm :
1) Calculate area of the given triangle, i.e., area of the triangle ABC in the above diagram.
Area A = [ x1(y2 - y3) + x2(y3 - y1) + x3(y1-y2)]/2
2) Calculate area of the triangle PAB. We can use the same formula for this. Let this area be A1.
3) Calculate area of the triangle PBC. Let this area be A2.
4) Calculate area of the triangle PAC. Let this area be A3.
5) If P lies inside the triangle, then A1 + A2 + A3 must be equal to A.
Given below is a program in C:
#include <stdio.h>
#include <stdlib.h>
/* A utility function to calculate area of triangle formed by (x1, y1),
(x2, y2) and (x3, y3) */
float area(int x1, int y1, int x2, int y2, int x3, int y3)
{
return abs((x1*(y2-y3) + x2*(y3-y1)+ x3*(y1-y2))/2.0);
}
/* A function to check whether point P(x, y) lies inside the triangle formed
by A(x1, y1), B(x2, y2) and C(x3, y3) */
bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
{
/* Calculate area of triangle ABC */
float A = area (x1, y1, x2, y2, x3, y3);
/* Calculate area of triangle PBC */
float A1 = area (x, y, x2, y2, x3, y3);
/* Calculate area of triangle PAC */
float A2 = area (x1, y1, x, y, x3, y3);
/* Calculate area of triangle PAB */
float A3 = area (x1, y1, x2, y2, x, y);
/* Check if sum of A1, A2 and A3 is same as A */
return (A == A1 + A2 + A3);
}
/* Driver program to test above function */
int main()
{
/* Let us check whether the point P(10, 15) lies inside the triangle
formed by A(0, 0), B(20, 0) and C(10, 30) */
if (isInside(0, 0, 20, 0, 10, 30, 10, 15))
printf ("Inside");
else
printf ("Not Inside");
return 0;
}
Time : O(1)
Space: O(1)

Take the average of the three given points. This new point P4 will always lie inside the triangle.
Now check if P and P4 lie on the same side of each of the three lines P1P2 P2P3 and P3P1. You can do this by checking the signs of the cross products (P -> P1) x (P -> P2) and (P4 -> P1) x (P4 -> P2) (where P->P1 is the vector from P to P1), and then the other two pairs.

Related

Position of a point in a circle

Hello again first part is working like a charm, thank you everyone.
But I've another question...
As I've no interface, is there a way to do the same thing with out not knowing the radius of the circle?
Should have refresh the page CodeMonkey solution is exactly what I was looking for...
Thank you again.
============================
First I'm not a developer, I'm a simple woodworker that left school far too early...
I'm trying to make one of my tool to work with an autonomous robot.
I made them communicate by reading a lot of tutorials.
But I have one problem I cant figure out.
Robot expect position of the tool as (X,Y) but tool's output is (A,B,C)
A is the distance from tool to north
B distance to east
C distance at 120 degree clockwise from east axe
the border is a circle, radius may change, and may or may not be something I know.
I've been on that for 1 month, and I can't find a way to transform those value into the position.
I made a test with 3 nails on a circle I draw on wood, and if I have the distance there is only one position possible, so I guess its possible.
But how?
Also, if someone as an answer I'd love pseudo code not code so I can practice.
If there is a tool to make a drawing I can use to make it clearer can you point it out to me?
Thank you.
hope it helps :
X, Y are coordinate from center, Da,Db, Dc are known.
Trying to make it more clear (sorry its so clear in my head).
X,Y are the coordinate of the point where is the tool (P).
Center is at 0,0
A is the point where vertical line cut the circle from P, with Da distance P to A;
B is the point where horizontal line cuts the circle fom P, with Db distance P to B.
C is the point where the line at 120 clockwise from horizontal cuts the circle from P, with Dc distance P to C.
Output from tool is an array of int (unit mm): A=123, B=114, C=89
Those are the only informations I have
thanks for all the ideas I'll try them at home later,
Hope it works :)
Basic geometry. I decided to give up having the circle at the origin. We don't know the center of the circle yet. What you do have, is three points on that circle. Let's try having the tool's position, given as P, as the new (0,0). This thus resolves to finding a circle given three points: (0, Da); (Db,0), and back off at 120° at Dc distance.
Pseudocode:
Calculate a line from A to B: we'll call it AB. Find AB's halfway point. Calculate a line perpendicular to AB, through that midpoint (e.g. the cross product of AB and a unit Z axis finds the perpendicular vector).
Calculate a line from B to C (or C to A works just as well): we'll call it BC. Find BC's halfway point. Calculate a line perpendicular to BC, through that midpoint.
Calculate where these two lines cross. This will be the origin of your circle.
Since P is at (0,0), the negative of your circle's origin will be your tool's coordinates relative to the circle's origin. You should be able to calculate anything you need relative to that, now.
Midpoint between two points: X=(X1+X2)/2. Y=(Y1+Y2)/2.
The circle's radius can be calculated using, e.g. point A and the circle's origin: R=sqrt(sqr((Ax-CirX)+sqr(Ay-CirY))
Distance from the edge: circle's radius - tool's distance from the circle's center via Pythagorean Theorem again.
Assume you know X and Y. R is the radius of the circle.
|(X, Y + Da)| = R
|(X + Db, Y)| = R
|(X - cos(pi/3) * Dc, Y - cos(pi/6) * Dc)| = R
Assuming we don't know the radius R. We can still say
|(X, Y + Da)|^2 = |(X + Db, Y)|^2
=> X^2 + (Y+Da)^2 = (X+Db)^2 + Y^2
=> 2YDa + Da^2 = 2XDb + Db^2 (I)
and denoting cos(pi/3)*Dc as c1 and cos(pi/6)*Dc as c2:
|(X, Y + Da)|^2 = |(X - c1, Y - c2)|^2
=> X^2 + Y^2 + 2YDa + Da^2 = X^2 - 2Xc1 + c1^2 + Y^2 - 2Yc2 + c2^2
=> 2YDa + Da^2 = - 2Xc1 + c1^2 - 2Yc2 + c2^2
=> Y = (-2Xc1 + c1^2 + c2^2 - Da^2) / 2(c2+Da) (II)
Putting (II) back in the equation (I) we get:
=> (-2Xc1 + c1^2 + c2^2 - Da^2) Da / (c2+Da) + Da^2 = 2XDb + Db^2
=> (-2Xc1 + c1^2 + c2^2 - Da^2) Da + Da^2 * (c2+Da) = 2XDb(c2+Da) + Db^2 * (c2+Da)
=> (-2Xc1 + c1^2 + c2^2) Da + Da^2 * c2 = 2XDb(c2+Da) + Db^2 * (c2+Da)
=> X = ((c1^2 + c2^2) Da + Da^2 * c2 - Db^2 * (c2+Da)) / (2Dbc2 + 2Db*Da + 2Dac1) (III)
Knowing X you can get Y by calculating (II).
You can also make some simplifications, e.g. c1^2 + c2^2 = Dc^2
Putting this into Python (almost Pseudocode):
import math
def GetXYR(Da, Db, Dc):
c1 = math.cos(math.pi/3) * Dc
c2 = math.cos(math.pi/6) * Dc
X = ((c1**2 + c2**2) * Da + Da**2 * c2 - Db * Db * (c2 + Da)) / (2 * Db * c2 + 2 * Db * Da + 2 * Da * c1)
Y = (-2*X*c1 + c1**2 + c2**2 - Da**2) / (2*(c2+Da))
R = math.sqrt(X**2 + (Y+Da)**2)
R2 = math.sqrt(Y**2 + (X+Db)**2)
R3 = math.sqrt((X - math.cos(math.pi/3) * Dc)**2 + (Y - math.cos(math.pi/6) * Dc)**2)
return (X, Y, R, R2, R3)
(X, Y, R, R2, R3) = GetXYR(123.0, 114.0, 89.0)
print((X, Y, R, R2, R3))
I get the result (X, Y, R, R2, R3) = (-8.129166703588021, -16.205081335032794, 107.1038654949096, 107.10386549490958, 107.1038654949096)
Which seems reasonable if both Da and Db are longer than Dc, then both coordinates are probably negative.
I calculated the Radius from three equations to cross check whether my calculation makes sense. It seems to fulfill all three equations we set up in the beginning.
Your problem is know a "circumscribed circle". You have a triangle define by 3 distances at given angles from your robot position, then you can construct the circumscribed circle from these three points (see Circumscribed circle from Wikipedia - section "Other properties"). So you know the diameter (if needed).
It is also known that the meeting point of perpendicular bisector of triangle sides is the center of the circumscribed circle.
Let's a=Da, b=Db. The we can write a system for points A and B at the circumference:
(x+b)^2 + y^2 = r^2
(y+a)^2 + x^2 = r^2
After transformations we have quadratic equation
y^2 * (4*b^2+4*a^2) + y * (4*a^3+4*a*b^2) + b^4-4*b^2*r^2+a^4+2*a^2*b^2 = 0
or
AA * y^2 + BB * y + CC = 0
where coefficients are
AA = (4*b^2+4*a^2)
BB = (4*a^3+4*a*b^2)
CC = b^4-4*b^2*r^2+a^4+2*a^2*b^2
So calculate AA, BB, CC coefficients, find solutions y1,y2 of quadratic eqiation, then get corresponding x1, x2 values using
x = (a^2 - b^2 + 2 * a * y) / (2 * b)
and choose real solution pair (where coordinate is inside the circle)
Quick checking:
a=1,b=1,r=1 gives coordinates 0,0, as expected (and false 1,-1 outside the circle)
a=3,b=4,r=5 gives coordinates (rough) 0.65, 1.96 at the picture, distances are about 3 and 4.
Delphi code (does not check all possible errors) outputs x: 0.5981 y: 1.9641
var
a, b, r, a2, b2: Double;
aa, bb, cc, dis, y1, y2, x1, x2: Double;
begin
a := 3;
b := 4;
r := 5;
a2 := a * a;
b2:= b * b;
aa := 4 * (b2 + a2);
bb := 4 * a * (a2 + b2);
cc := b2 * b2 - 4 * b2 * r * r + a2 * a2 + 2 * a2 * b2;
dis := bb * bb - 4 * aa * cc;
if Dis < 0 then begin
ShowMessage('no solutions');
Exit;
end;
y1 := (- bb - Sqrt(Dis)) / (2 * aa);
y2 := (- bb + Sqrt(Dis)) / (2 * aa);
x1 := (a2 - b2 + 2 * a * y1) / (2 * b);
x2 := (a2 - b2 + 2 * a * y2) / (2 * b);
if x1 * x1 + y1 * y1 <= r * r then
Memo1.Lines.Add(Format('x: %6.4f y: %6.4f', [x1, y1]))
else
if x2 * x2 + y2 * y2 <= r * r then
Memo1.Lines.Add(Format('x: %6.4f y: %6.4f', [x2, y2]));
From your diagram you have point P that you need it's X & Y coordinate. So we need to find Px and Py or (Px,Py). We know that Ax = Px and By = Py. We can use these for substitution if needed. We know that C & P create a line and all lines have slope in the form of y = mx + b. Where the slope is m and the y intercept is b. We don't know m or b at this point but they can be found. We know that the angle of between two vectors where the vectors are CP and PB gives an angle of 120°, but this does not put the angle in standard position since this is a CW rotation. When working with circles and trig functions along with linear equations of slope within them it is best to work in standard form. So if this line of y = mx + b where the points C & P belong to it the angle above the horizontal line that is parallel to the horizontal axis that is made by the points P & B will be 180° - 120° = 60° We also know that the cos angle between two vectors is also equal to the dot product of those vectors divided by the product of their magnitudes.
We don't have exact numbers yet but we can construct a formula: Since theta = 60° above the horizontal in the standard position we know that the slope m is also the tangent of that angle; so the slope of this line is tan(60°). So let's go back to our linear equation y = tan(60°)x + b. Since b is the y intercept we need to find what x is when y is equal to 0. Since we still have three undefined variables y, x, and b we can use the points on this line to help us here. We know that the points C & P are on this line. So this vector of y = tan(60°)x + b is constructed from (Px, Py) - (Cx, Cy). The vector is then (Px-Cx, Py-Cy) that has an angle of 60° above the horizontal that is parallel to the horizontal axis. We need to use another form of the linear equation that involves the points and the slope this time which happens to be y - y1 = m(x - x1) so this then becomes y - Py = tan(60°)(x - Px) well I did say earlier that we could substitute so let's go ahead and do that: y - By = tan(60°)(x - Ax) then y - By = tan(60°)x - tan(60°)Ax. And this becomes known if you know the actual coordinate points of A & B. The only thing here is that you have to convert your angle of 120° to standard form. It all depends on what your known and unknowns are. So if you need P and you have both A & B are known from your diagram the work is easy because the points you need for P will be P(Ax,By). And since you already said that you know Da, Db & Dc with their lengths then its just a matter of apply the correct trig functions with the proper angle and or using the Pythagorean Theorem to find the length of another leg of the triangle. It shouldn't be all that hard to find what P(x,y) is from the other points. You can use the trig functions, linear equations, the Pythagorean theorem, vector calculations etc. If you can find the equation of the line that points C & P knowing that P has A's x value and has B's y value and having the slope of that line that is defined by the tangent above the horizontal which is 180° - phi where phi is the angle you are giving that is CW rotation and theta would be the angle in standard position or above the horizontal you have a general form of y - By = tan(180° - phi)(x - Ax) and from this equation you can find any point on that line.
There are other methods such as using the existing points and the vectors that they create between each other and then generate an equilateral triangle using those points and then from that equilateral if you can generate one, you can use the perpendicular bisectors of that triangle to find the centroid of that triangle. That is another method that can be done. The only thing you may have to consider is the linear translation of the line from the origin. Thus you will have a shift in the line of (Ax - origin, By - origin) and to find one set the other to 0 and vise versa. There are many different methods to find it.
I just showed you several mathematical techniques that can help you to find a general equation based on your known(s) and unknown(s). It just a matter of recognizing which equations work in which scenario. Once you recognize the correct equations for the givens; the rest is fairly easy. I hope this helps you.
EDIT
I did forget to mention one thing; and that is the line of CP has a point on the edge of the circle defined by (cos(60°), sin(60°)) in the 1st quadrant. In the third quadrant you will have a point on this line and the circle defined by (-cos(60°), -sin(60°)) provided that this line goes through the origin (0,0) where there is no y nor x intercepts and if this is the case then the point on the circle at either end and the origin will be the radius of that circle.

How to check if an infinite line intersects a rectangular prism in 3d space?

If I have a line segment defined by two points p1, p2, and then a rectangular prism defined by (x,y,z) (lowest corner point) with length/width/height (l, w, h), how can I check if the line will intersect the prism? And also get the point of intersection if there is one?
Does anyone know?
Thanks
Seems that your prism is axis-aligned box (rectangular parallelepiped).
So use any algorithm intended for line clipping - for example, 3D-version of Liang-Barsky algorithm
In short - make parametric equation for line segment
X = X1 + t * (X2 - X1)
Y = Y1 + t * (Y2 - Y1)
Z = Z1 + t * (Z2 - Z1)
find parameters t for intersection with faces: substitute X = x or X = x + l in equation, find t, check if point with this t lies inside face rectangle

Given two points and two direction vectors, find the point where they intersect

EDIT: THIS IS NOT A DUPLICATE, please read the description of the problem
Just to be clear, these line segments does not have an end point. They start at a point and goes to infinity based on a direction vector. I've found solutions for finite line segments, but they do not apply in this particular case (I think).
So, the title is basically my entire question - I've got
point p1
point p2
direction vector n1 (a normalized vector)
direction vector n2 (a normalized vector)
The first line segment starts at p1 and points towards n1
The second line segment starts at p2 and points towards n2
I need two answers:
If they intersects and
What is the point of intersection
I've found these two answers, but I'm so bad at math that I could not adapt them to fit my problem, but it could help you guys, I hope.
How do you detect where two line segments intersect?
and
Given two points and two vectors, find point of intersection
Thanks a lot!
Edit: (BTW, I'm working at 2D Space, so you don't have to worry about the z axis, thanks)
So, I've used the info provided by this post:
Determining if two rays intersect
And the info provided by a friend to solve this problem.
The first post stated that, given two points (p1 and p2) and two direction vectors (n1 and n2), the following formula applies:
bool DoesRaysIntersects(Point p1, Point p2, Point n1, Point n2)
{
float u = (p1.y * n2.x + n2.y * p2.x - p2.y * n2.x - n2.y * p1.x) / (n1.x * n2.y - n1.y * n2.x);
float v = (p1.x + n1.x * u - p2.x) / n.x;
return u > 0 && v > 0;
}
if both u and v are greater than 0, it's because the two rays collide.
If they collide, we can use the equation of the line to provide the point of collision. I don't know if this is the best way to achieve it, but it worked for me:
First, we need the slope of each of the lines. With their slopes, we can calculate the y-intercept of each line. And with this two datas, we can calculate the point of collision:
Point GetPointOfIntersection(Point p1, Point p2, Point n1, Point n2)
{
Point p1End = p1 + n1; // another point in line p1->n1
Point p2End = p2 + n2; // another point in line p2->n2
float m1 = (p1End.y - p1.y) / (p1End.x - p1.x); // slope of line p1->n1
float m2 = (p2End.y - p2.y) / (p2End.x - p2.x); // slope of line p2->n2
float b1 = p1.y - m1 * p1.x; // y-intercept of line p1->n1
float b2 = p2.y - m2 * p2.x; // y-intercept of line p2->n2
float px = (b2 - b1) / (m1 - m2); // collision x
float py = m1 * px + b1; // collision y
return new Point(px, py); // return statement
}
Thanks everyone!

Knowing two points of a rectangle, how can I figure out the other two?

Hey there guys, I'm learning processing.js, and I've come across a mathematical problem, which I can't seem to solve with my limited geometry and trigonometry knowledge or by help of Wikipedia.
I need to draw a rectangle. To draw this rectangle, I need to know the coordinate points of each corner. All I know is x and y for the midpoints of the top and bottom of the box, and the length of all four sides.
There is no guarantee on the orientation of the box.
Any help? This seems like it should be easy, but it is really stumping me.
If this quadrilateral is a rectangle (all four angles are 90 degrees), then it can be solved. (if it could be any quadrilateral, then it is not solvable)
if the points are (x1,y1), and (x2, y2), and if the two points are not perfectly vertical (x1 = x2) or horizontal (y1 = y2), then the slope of one edge of the rectangle is
m1 = (y2-y1) / (x2-x1)
and the slope of the other edge is:
m2 = - 1 / m1
If you know the lengths of the sides, and the midpoints of two opposite sides, then the corrner points are easily determined by adding dx, dy to the midpoints: (if L is length of the sides that the midpoints are on)
dx = Sqrt( L^2 / (1 + m2^2) ) / 2
and
dy = m2 * dx
NOTE: if the points are vertically or horizontally aligned, this technique will not work, although the obvious solution for those degenerative cases is much simpler.
If you know your quadrilateral is a rectangle, then you can use some simple vector maths to find the coordinates of the corners. The knowns are:
(x1,y1) - the coordinate of the midpoint on the top line
(x2,y2) - the coordinate of the midpoint on the bottom line
l1 - the length of the top and bottom lines
l2 - the length of the other two lines
First, we find the vector between the two known points. This vector is parallel to the side lines:
(vx, vy) = (x2 - x1, y2 - y1)
We need to normalize this vector (i.e. make it length 1) so we can use it later as a basis to find our coordinates.
vlen = sqrt(vx*vx + vy*vy)
(v1x, v1y) = (vx / vlen, vy / vlen)
Next, we rotate this vector anticlockwise by 90 degrees. The rotated vector will be parallel to the top and bottom lines. 90 degree rotation turns out to just be swapping the coordinates and negating one of them. You can see this just by trying it out on paper. Or take at look at the equations for 2D rotations and substitute in 90 degrees.
(u1x, u1y) = (-v1y, v1x)
Now we have enough information to find the 'top-left' corner. We simply start at our point (x1, y1) and move back along that side by half the side length:
(p1x, p1y) = (x1 - u1x * l1 / 2, y1 - u1y * l1 / 2)
From here we can find the remaining points just by adding the appropriate multiples of our basis vectors. When implementing this you can obviously speed it up by only calculating each unique multiplication a single time:
(p2x, p2y) = (p1x + u1x * l1, p1y + u1y * l1)
(p3x, p3y) = (p1x + v1x * l2, p1y + v1y * l2)
(p4x, p4y) = (p3x + u1x * l1, p3y + u1y * l1)
function getFirstPoint(x1,y1,x2,y2,l1,l2)
distanceV = {x2 - x1, y2 - y1}
vlen = math.sqrt(distanceV[1]^2 + distanceV[2]^2)
normalized = {distanceV[1] / vlen, distanceV[2] / vlen}
rotated = {-normalized[2], normalized[1]}
p1 = {x1 - rotated[1] * l1 / 2, y1 - rotated[2] * l1 / 2}
p2 = {p1[1] + rotated[1] * l1, p1[2] + rotated[2] * l1}
p3 = {p1[1] + normalized[1] * l2, p1[2] + normalized[2] * l2}
p4 = {p3[1] + rotated[1] * l1, p3[2] + rotated[2] * l1}
points = { p1 , p2 , p3 , p4}
return p1
end
It's definitely a rectangle? Then you know the orientation of the short sides (they're parallel to the line between your points), and hence the orientation of the long sides.
You know the orientation and length of the long sides, and you know their midpoints, so it's straightforward to find the corners from there.
Implementation is left as an exercise to the reader.
This means that there will be two lines parallel to the line between the two points you have. Get the corners by translating the line you have 1/2 the length of the top side in each direction perpendicular to the line you have.
If you know the midpoint for the top, and the length of the top, then you know that the y will stay the same for both top corners, and the x will be the midpoint plus/minus the width of the rectangle. This will also be true for the bottom.
Once you have the four corners, there is no need to worry about the side lengths, as their points are the same as those used for the top and bottom.
midpoint
x,10 10,10 x,10
*--------------------------------------------*
width = 30
mx = midpoint x.
top left corner = (w/2) - mx or 15 - 10
top left corner coords = -5,10
mx = midpoint x.
top right corner = (w/2) + mx or 15 + 10
top left corner coords = 25,10
There's a difference between a "quadrilateral" and a "rectangle".
If you have the midpoint of the top and bottom, and the sides lengths, the rest is simple.
Given:
(x1, y1) -- (top_middle_x, top_middle_y) -- (x2, y1)
(x1, y2) -- (btm_middle_x, btm_middle_y) -- (x2, y2)
and top/bottom length along with right/left length.
x1 = top_middle_x - top/bottom_length / 2;
x2 = x1 + top/bottom_length;
y1 = top_middle_y
y2 = bottom_middle_y
Obviously, that's the simplest case and assuming that the line of (tmx, tmy) (bmx, bmy) is solely along the Y axis.
We'll call that line the "mid line".
The next trick is to take the mid line, and calculate it's rotational offset off the Y axis.
Now, my trig is super rusty.
dx = tmx - bmx, dy = tmy - bmy.
So, the tangent of the angle is dy / dx. The arctangent(dy / dx) is the angle of the line.
From that you can get your orientation.
(mind, there's some games with quadrants, and signs, and stuff to get this right -- but this is the gist of it.)
Once you have the orientation, you can "rotate" the line back to the Y axis. Look up 2D graphics for the math, it's straight forward.
That gets you your normal orientation. Then calculate the rectangles points, in this new normal form, and finally, rotate them back.
Viola. Rectangle.
Other things you can do is "rotate" a line that's half the length of the "top" line to where it's 90 deg of the mid line. So, say you have a mid line that's 45 degrees. You would start this line at tmx, tmy, and rotate this line 135 degrees (90 + 45). That point would be your "top left" corner. Rotate it -45 (45 - 90) to get the "top right" point. Then do something similar with the lower points.
Calculate the angle of the line joining the two midpoints using an arc-tangent function applied to the vector you get between them.
Subtract 90 degrees from that angle to get the direction of the top edge
Starting from the top-center point, move relative (1/2 top width x sin(angle), 1/2 top width x cos(angle)) - that gets the top right corner point.
Continue around the rectangle using the sin and cos of the angles and widths as appropriate
As a test: Check you made it back to the starting point
/* rcx = center x rectangle, rcy = center y rectangle, rw = width rectangle, rh = height rectangle, rr = rotation in radian from the rectangle (around it's center point) */
function toRectObjectFromCenter(rcx, rcy, rw, rh, rr){
var a = {
x: rcx+(Math.sin((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2)),
y: rcy-(Math.cos((rr-degToRad(90))+Math.asin(rh/(Math.sqrt(rh*rh+rw*rw)))) * (Math.sqrt(rh*rh+rw*rw)/2))
};
var b = {
x: a.x+Math.cos(rr)*rw,
y: a.y+Math.sin(rr)*rw
};
var c = {
x: b.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
y: b.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
};
var d = {
x: a.x+Math.cos(degToRad(radToDeg(rr)+90))*rh,
y: a.y+Math.sin(degToRad(radToDeg(rr)+90))*rh
};
return {a:a,b:b,c:c,d:d};
}

turn a line into a rectangle

I have a method that draws a line between two points. This works pretty well, but now I want to make this line into a rectangle.
How can I get the points on the left and right side of each of the line points to make it into a rectangle that I can draw?
It is almost as though I need to somehow figure out how to get perpendicular lines programatically....
I'm guessing you basically want fat lines? Lets assume the line is specified by two points (x0, y0) and (x1, y1) we then have:
float dx = x1 - x0; //delta x
float dy = y1 - y0; //delta y
float linelength = sqrtf(dx * dx + dy * dy);
dx /= linelength;
dy /= linelength;
//Ok, (dx, dy) is now a unit vector pointing in the direction of the line
//A perpendicular vector is given by (-dy, dx)
const float thickness = 5.0f; //Some number
const float px = 0.5f * thickness * (-dy); //perpendicular vector with lenght thickness * 0.5
const float py = 0.5f * thickness * dx;
glBegin(GL_QUADS);
glVertex2f(x0 + px, y0 + py);
glVertex2f(x1 + px, y1 + py);
glVertex2f(x1 - px, y1 - py);
glVertex2f(x0 - px, y0 - py);
glEnd();
Since you're using OpenGL ES I guess you'll have to convert the immediate mode rendering (glBegin, glEnd, etc) to glDrawElements. You'll also have to convert the quad into two triangles.
One final thing, I'm a little tired and uncertain if the resulting quad is counterclockwise or clockwise so turn of backface culling when you try this out (glDisable(GL_CULL)).
Since you've asked this question with OpenGL taged I'll assume that you wish for a solution that is close to OpenGL.
As you know you have two points that make up a line. Lets call them x1,y1 and x2, y2
Lets also assume that x1, y1 is the top left point and x2, y2 is the bottom right.
Your 4 points to plot will be [you need to perserve order to make a rectangle with GL_LINES)
Height:y1-y1
Width: x2-x1
(x1, y1)
(x1+width, y1)
(x2, y2)
(x2-width, y2)
drawRect(x,y,w,h)
tl = (x,y)
tr = (x+w, y)
br = (x+w, y+h)
bl = (x, y+h)

Resources