0
101 Jan 04, 2009 at 00:16

Hi.

My name is aNewHobby. I am not a mathamatician, or a student, or anything like that. What I am is a colledge drop out and a zoo keeper, who has a strange hobby that some of my mates think is very wierd. I make freeware homebrew computer games. Anyway. I am currently working on a project during my spare time at the moment and have come up against a mathamatical problem i just can not solve.

I have no one to turn to, I have tried asking on maths forums but no one seams to be able to help. I was hoping you may be able to point me in the correct direction to find someone who might be interested in solving my problem for me? I have tried for weeks now and read book after book, but I haven’t really done maths for like 15 years so it is a hard slog for me.

Anyway… here is the problem… I really hope you may be able to solve to for me or at least put me in touch with someone who may help me.. For like I said I am just unable to do it and do not know where I am suppose to go for Math help.

So thanks in advance if you decide to help, and if not thanks for your time. If you know a way better way of doing thins.. then please let me know.

aNewHobby

The Problem
(please look at attached images as I explain)

I have a computer screen represented in X,Y grid coordinates. 0,0 (x,y) is the very top left of the screen and 1280,800 is the very bottom right of the screen. (this is a range as well anything outside this is no good as it will not render on screen)
I have two points with known X,Y values on this screen. (Lets call them A and B) So I know the values of Xa,Ya and Xb,Yb.

What I am trying to do if find the X,Y cords of an ARC that passes though A and B.

Now I know that without a third point this is not possible so let me go on….

The LINE that connects A and B is the base of a isosceles triangle. And we know the values of the equal angels.

So to Recap, What do we know?

1) The X,Y values of A
2) The X,Y values of B
3) The value of the 2 angles marked D

So What do we need to do?

1) Use the X,Y Vales of A and B to work out the distance between those points.- Lets call that S
2) Using S and the values of D we can work out the X,Y cords of H.
3) Using the X,Y cords of A,B and H we work out the X,Y cords of any Point along the line of the arc that moves through all three points.

Some other things.

In the game the situations will always be like in the drawing. as in A is always on the RIGHT and B is always on the left.
A and B will always be slightly different from each other. A and B should nvr share and X or Y value.

(dunno if that help? maybe it makes it more simple?)

What exactly am i asking for?

I am looking for some formulas that

1) I can plug in the A,B (x,y cords) and D (angle values) into and return the X,Y of the point we are callign H
2) A Formular that uses the A,B and H x,y values to return a New X,Y value that sits on the arce that moves between all points. (Say Xp,Yp)
3) A way to move though the entire possible points on this arc.

OK.. here is my lame Math…. remember I have been looking up websites to learn wtf COS is and stuff like that… I have no math training and suck at all this, it is probably totally gibberish to you but I wanted to show you that I have been trying.

My Steps
1) I have assumed a value called H. This is the X,Y Location point of the top of a isos triangle, whose base line makes up the line from A-B.

2) I have “invented” a value for the degrees of the = angles that of the isos triangle. I figure by changing this angle I can make the arc more or less rounded.

3) I use the ANGLE D and the Length of the LINE A - > B to find the height of H.

4) Then using A,B and H. I can then plot the points of all the X,Y cords along the ARC.

This is My method… and here is my lame math… that doesn’t seam to work.

Ok, working out the location of H from the angles D

1) work out distance between A and B, let’s call this Di1:

Di1 = sqrt((Xb - Xa)\^2 + (Yb - Ya)\^2)

2) work out midpoint of AB line, let’s call this M

(Xm , Ym) = ((Xb + Xa) / 2 , (Yb + Ya) / 2)

3) work out gradient of line AB, let’s call this g1

g1 = (Yb - Ya) / (Xb - Xa)

4) work out gradient of line perpendicular to AB, let’s call this g2

g2 = -1 / g1 (note: this value won’t exist if g1 = 0, need a special case, see below)

5) work out angle between line perpendicular to AB and horizontal, let’s call this phi

phi = atan(g2), if g2 exists (I.e. if g1 is not 0)
= 90 degrees = Pi/2 radians, if g1 is 0

6) get distance between midpoint (M) and H, let’s call this D2

Di2 = Di1 * tan(D) / 2

7) get coordinates for C

(Xc , Yc) = (Xm + Di2 * cos(phi), Ym + Di2 * sin(phi))

note, you’ll get a semi circle when D are 45 degrees.

OKKKKKaaaayyyyyy

Now how to get the points on the ARC itself….

1) Work out the centrepoint of the arc (let’s call this point C) - this is the point that is the same distance from points A,B and H.

Xc = [(Yb - Yh)(Xa\^2 + Ya\^2) + (Yh - Ya)(Xb\^2 + Yb\^2) + (Ya - Yb)(Xh\^2 + Yh\^2)]

2*[Xa*Yb + Xb*Yh + Xh*Ya - Ya*Xb - Yb*Xh - Yh*Xa]

Yc = [(Xb - Xh)(Ya\^2 + Xa\^2) + (Xh - Xa)(Yb\^2 + Xb\^2) + (Xa - Xb)(Yh\^2 + Xh\^2)]

2*[Ya*Xb + Yb*Xh + Yh*Xa - Xa*Yb - Xb*Yh - Xh*Ya]

2) Work out the radius of the arc, this can be done by calculating the distance between C and A (or C and H, or C and B).

r = sqrt((Xb- Xc)\^2 + (Yb - Yc)\^2)

3) Work out the the start and finish angles around the arc. The easiest way to do this is using a function called ATAN2 if you are using C or something similar.

Start angle = angle between horizontal and the line joining C and A = atan2(Yb - Yc, Xb - Xc)
Finish angle = angle between horizontal and the line joining C and B = atan2(Ya - Yc, Xa - Xc)

4) any angle between the start angle and finish angle will give you a point along the arc, so you can use code like the following pseudo code to generate these points:

for each angle theta between the start angle and finish angle do the following
calculate the x coordinate as Xp = Xc + r * cos(theta)
calculate the y coordinate as Yp = Yc + r * sin(theta)
output the point on the arc as (Xp,Yp)

#### 10 Replies

0
165 Jan 04, 2009 at 01:41

Well, the H point can be found as follows. It is simplest to do this by making use of the concept of a vector. In case you haven’t encountered vectors before, you can visualize them as an arrow. Like an arrow, a vector has a specific length and a specific direction. Like points, vectors have X and Y coordinates. The X, Y values for a vector are simply the difference between the X, Y values of the ending and starting points of the arrow.

For instance, if “U” is the vector from A to B, we would have:

Ux = Bx - Ax
Uy = By - Ay

where the coordinates of A are (Ax, Ay) and so on.

Now, one of the many things we can do with a vector is rotate it. This keeps the arrow the same length but changes its direction. Without going into detail, if you want to rotate a vector U by an angle D, the formula is:

U’x = cos(D) * Ux - sin(D) * Uy
U’y = sin(D) * Ux + cos(D) * Uy

Here U’ (pronounced “U prime”) is the rotated version of U. For these purposes you don’t need to worry too much about what the sin and cos functions “actually do” - you can just plug in the numbers and go. :)

Now one thing to note is that this formula rotates the vector counterclockwise. If you want to rotate it clockwise, you have to use a negative value for the angle. Also keep in mind that in most programming languages, sin and cos take their argument in radians, not degrees, so you’ll have to convert.

Another thing we can do with a vector is scale it; this changes the length of the vector, but leaves its direction the same. Scaling is very simple; you just multiply the X, Y values of the vector by a scaling factor.

Combining rotation and scaling, we can find the H point. First we have to start with the vector B - A. Then rotate it clockwise by D (therefore use the above formula with -D), which gets it pointing in the right direction. Then we have to scale it by the quantity 1 / (2 * cos(D)). I can explain how I got that expression if you want, but I don’t want to overload you with too much information just yet. :) Finally, we add our rotated and scaled vector to the point A, and that will give us the coordinates of the point H.

So, to put it all together, the formula for H is:

Hx = (cos(-D) * (Bx - Ax) - sin(-D) * (By - Ay)) / (2 * cos(D)) + Ax
Hy = (sin(-D) * (Bx - Ax) + cos(-D) * (By - Ay)) / (2 * cos(D)) + Ay

I hope you can see how I got this by putting together all the pieces - first, subtracting B and A to get a vector, then rotating it, then scaling it, and finally adding it back to A to get H.

You seem like you have a handle on the second part of the problem, so I hope that will be enough to get you going.

0
101 Jan 04, 2009 at 01:57

applause for such a good explanation!

0
101 Jan 04, 2009 at 03:33

Thanks for thins reply… give me a sec to work though it….

WOW… this code works perfectly and wats more i understand you explination!!! (apart form one bit that you didn’t explain)

Anyway thanks a lot…. So now I have A,B and H should I use the math I posted to work out the rest of the points on the arc, or should I be waitinf for a part 2 post from you as your math for the finding H was way way way more elegant than mine.

Thanks again.

0
101 Jan 04, 2009 at 07:32

Ok, I am stuck again… I seam unable to get the Center Point of the Arc to work out… as i think i need it… the Math I am using is

Xc = ((Yb - Yh)(Xa\^2 + Ya\^2) + (Yh - Ya)(Xb\^2 + Yb\^2) + (Ya - Yb)(Xh\^2 + Yh\^2)) / (2*(Xa*Yb + Xb*Yh + Xh*Ya - Ya*Xb - Yb*Xh - Yh*Xa))

But it dosn’t seam to be giving me a result that i can use. This is math from my first attempt… but from your explination of teh scalign of teh vector… can’t I use the vector itself to plot all the points of the curve instead of just the H point?

0
165 Jan 04, 2009 at 08:32

Actually, there is a nice elegant way to find the center too. There is an old geometric construction for the circle passing through three points. This is to construct a triangle from the three points, then draw a line perpendicular to each edge of the triangle, through the edge’s midpoint. These three perpendicular lines will all converge at one point, which is the center of the circle. (See here for diagrams.)

In our case since the triangle is isosceles we can do it even more simply, as we only need to calculate one perpendicular bisector and we can calculate the length of it using trigonometry.

Start with the vector H - A, then rotate it by 90 degrees counterclockwise, then scale it by 1 / (2 * tan(D)). Then add it to the midpoint between A and H, which is just (A + H) / 2. That should give the center of the circle.

This works because ABH is an isosceles triangle and therefore, if I use F to denote the midpoint between A and H, the triangle FCH is a right triangle and the angle at FCH (the angle at C between F and H) equals D. Then, the ratio between the distance HF (which we know) and the distance FC (which we are trying to find) is 1 / tan(D), since tan(D) is “opposite over adjacent”, HF is the “opposite” and FC is the “adjacent”. Now HF is just half the distance AH, so I scale the AH vector (which is H - A) by 1 / (2 * tan(D)), and that makes it have the same length as FC.

(Incidentally, the 1 / (2 * cos(D)) factor in my previous post was arrived at in much the same way. The triangle formed by A, H, and the midpoint of AB is a right triangle with a known angle D at one corner. Here the adjacent side is known and we want the hypotenuse AH, so I used cosine, which is “adjacent over hypotenuse”.)

0
101 Jan 04, 2009 at 16:03

@Reedbeta

For instance, if “U” is the vector from A to B, we would have:

Ux = Bx - Ax
Uy = By - Ay

where the coordinates of A are (Ax, Ay) and so on.

Now, one of the many things we can do with a vector is rotate it. This keeps the arrow the same length but changes its direction. Without going into detail, if you want to rotate a vector U by an angle D, the formula is:

U’x = cos(D) * Ux - sin(D) * Uy
U’y = sin(D) * Ux + cos(D) * Uy

@Reedbeta

Start with the vector H - A, then rotate it by 90 degrees counterclockwise, then scale it by 1 / (2 * tan(D)). Then add it to the midpoint between A and H, which is just (A + H) / 2. That should give the center of the circle.

Ok.. teach… lets see … .. ..

C = CenterPoint;

If “V” is the vector from H to A, we would have:

Vx = Hx - Ax
Vy = Hy - Ay
R = 90 degrees = 1.57079633 radians

V’x = cos(R) * Vx - sin(R) * Vy
V’y = sin(R) * Vx + cos(R) * Vy

Um so…… Rotate by 90 Counter Clockwise is

C1x = (cos(R) * (Hx - Ax) - sin(R) * (Hy - Ay)
C1y = (sin(R) * (Hy - Ay) - cos(R) * (Hx - Ax)

Scale

C2x = C1x / (2 * tan(D))
C2y = C1y / (2 * tan(D))

• 1/2 distence a/h

Cx = C2x + ((A + H) / 2)
Cy = C2y + ((A + H) / 2)

So all together…

Cx = (cos(R) * (Hx - Ax) - sin(R) * (Hy - Ay)) / (2 * tan(D)) + ((Ax + Hx) / 2)
Cy = (sin(R) * (Hy - Ay) - cos(R) * (Hx - Ax)) / (2 * tan(D)) + ((Ay + Hy) / 2)

?? Am i making sense?

lol

0
165 Jan 04, 2009 at 19:16

Yep, looks good except that you accidentally changed the sign of the cos(R) in the equation for Cy - it should be positive, not negative.

Also, since R is 90 degrees you can simplify this a bit further, using the fact that
sin(90 degrees) = 1
cos(90 degrees) = 0

0
101 Jan 04, 2009 at 23:58

@Reedbeta

Yep, looks good except that you accidentally changed the sign of the cos(R) in the equation for Cy - it should be positive, not negative

Yea i can not get this to work correctly…

Cx = (cos(R) * (Hx - Ax) - sin(R) * (Hy - Ay)) / (2 * tan(D)) + ((Ax + Hx) / 2)
Cy = (sin(R) * (Hy - Ay) + cos(R) * (Hx - Ax)) / (2 * tan(D)) + ((Ay + Hy) / 2)

Is that the right code? As it places the center point somwhere wierd.

<

After some effort i got 2nd code to do the same thing.. but still curious as to why the one yu gave me dose not work.

#include "scripts\base.inc"

on "LeftClick"
{
var x1 = Xb;
var y1 = Yb;

var x2 = Xa;
var y2 = Ya;

var x3 = Xh;
var y3 = Yh;

var temp;
var m12;
var m23;
var det;
var center_x;
var center_y;

temp = Math.Pow(x2, 2) + Math.Pow(y2, 2);

m12 = ( Math.Pow(x1, 2) + Math.Pow(y1, 2) - temp ) / 2.0;
m23 = ( temp - Math.Pow(x3, 2) - Math.Pow(y3, 2) ) / 2.0;

det = (x1 - x2) * (y2 - y3) - (x2 - x3) * (y1 - y2);

if (Math.Abs(det) < 0.000001)
{
Xc = 0;
Yc = 0;
Game.Msg("Jerrot says NO! The points are in a line, how dare you to fool me!");

}
else
{
det = 1 / det;
Xc = ( m12 * (y2-y3) - m23 * (y1-y2) ) * det;
Yc = ( (x1 - x2) * m23 - (x2 - x3) * m12) * det;
Game.Msg("center x: " + ToInt(Xc));
Game.Msg("center y: " + ToInt(Yc));
Game.Msg("Xh = " +Xh +" Yh = " +Yh);
}

}

0
165 Jan 05, 2009 at 00:25

Ahh, you’ve also interchanged x and y in part of the equation for Cy - it should be:

Cx = (cos(R) * (Hx - Ax) - sin(R) * (Hy - Ay)) / (2 * tan(D)) + ((Ax + Hx) / 2)
Cy = (sin(R) * (Hx - Ax) + cos(R) * (Hy - Ay)) / (2 * tan(D)) + ((Ay + Hy) / 2)

0
101 Jan 06, 2009 at 04:08

Well I got this all working…

If your interested here is the Demo of the math code I used to test the functions. It looks a little raw, but it is only a math test.. Still its shows the math working..

Math Test

@Reedbeta

I would just like to thank you for your great help and advise in this thread. Your a star mate. This function is all done and working great. I have incorporated it into my game and the arc makes it looks SOOOOO much better when you throw and item at something, rather than a strait line.

So thanks again.

Anyway.. Thanks a ton for your help

PS - If anyone else wants to do this same thign here is the code… excuse my lame self taught coding :P