Link to home
Start Free TrialLog in
Avatar of InteractiveMind
InteractiveMindFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Calculate angle of line, relative to a vertical

Hi    :)

Okay, I have a graph, with (for example) the following two lines:

  a  =  (0, 0) to (0, 4)
  b  =  (0, 0) to (4, 4)

Line 'a' will always be vertical.

Now, I need to calculate the angle (clockwise) between these two lines (ultimately, I need either an equation or algorithm).

I came up with this:

   angle  =  tan^-1 ( 1 / m )
   where m = the gradient of line 'b'

But, this equation only applies when 'm' is positive. Whereas I require the equation to function correctly even when the m is negative.

I've tried using a combination of vector's and the Cosine rule, but I can't get it to work.

I know this is rather easy stuff (for you lot at least), but I just can't get it to work lol -- it's soo frustrating. Anyone got a solution please?

Thanks in advance,
>> IM
Avatar of GwynforWeb
GwynforWeb
Flag of Canada image

drawing these lines then clearly tan(theta) is clearly 1,  ie the angle is 45o



 
Avatar of InteractiveMind

ASKER

Yes, I came to that conclusion.. but I need an equation/algorithm which can calculate the angle between 'a' and another line (with any gradient)..

So, if 'b' = (0,0) to (3,-2)

the equation:

  tan(theta) = 1 / (m = -0.666666 )

doesn't work.

I need an equation that works for *all* possible vectors of 'b'.. including: b = (0,0) to (5,0)

Cheers,
Avatar of d-glitch
Forget about slopes and arctangents.  You have to deal with infinites and ambiguities.

Convert your b vector to polar coordinates:  (X, Y)  =  (r, theta)

That will give you an unambiguous angle, measured counterclockwise from the X-axis.

Then you can just do a subtraction.
I've tried using Vectors and the Cosine rule together, like so:

 Example
-----------

'a' and 'b' are both vectors  (expressed as column vectors)

a   =   0
~        5

b   =   -3
~        -2

The tail of vector 'a' is in contact with the tail of vector 'b'.

Now, I've decided to create a triangle, so that I can use the Cosine rule to calculate the angle.. So, I've got to add a third Vector, from the nose of vector 'a' to the nose of vector 'b':

c   =   b - a
~       ~   ~

From those vectors, we can calculate their lengths:

 a = 5
 ~

 b = 3^2 + 2^2 = 13
 ~

 c = b - a = 13 - 5 = 8
 ~   ~   ~

Without even moving onto the Cosine stuff, I can see that this is wrong; because vector 'c' has to be longer than vector 'a' and 'b' (because if you draw vectors 'a' and 'b', you can see that the angle 'ab' is greater than 90 degrees).

But even if I were to work with those figures, like below, it gives a result which is clearly incorrect:

  theta = cos^-1 ( ( 5^2 + 13^2 - 8^2) / 2(5)(13) ) = 0


I'm puzzled.

>> IM
Ah, let me just read your comment d-glitch...
Hmm.. I'm a little unclear..

 In: (X, Y)  =  (r, theta)

What does the 'r' represent? And could you please provide an example to demonstrate this?

Cheers :)
>> IM
A = (0, 4)  ==>   rA=4  
                          unit vector = (0, 1)   ==>    thetaA=90


B = (4, 4)  ==>  rB= sqrt(32)
                         unit vector (1/sqrt(2), 1/sqrt(2))    ==>  thetaB=45


The unit vector is always (X/mag, Y/mag)

          arccos( theta) = X/mag has two solutions.  
          arcsin(  theta) = Y/mag has ttwo solutions.

One of the solutions will work for both.      
Avatar of comnetz
comnetz

Your algorithm should check the value m, it must not be zero or infinite.
If m = zero, you know the angle is Pi/2,
If m = infinite, you know the angle is 0 or Pi
(if b= (0,Y(b)) where Y(b) is positive, then the angle is 0),
otherwise, you can use
angle = (Pi/2)*{[(m-abs(m)]/2m)} + arctan[abs(1/m)]
A vector can be expressed in Cartesian coordiantes (x, y)
or in polar coordinates (r, theta)  (magnitude, direction)

direction has to be a vector of length=1 (a unit vector)

[ cos(theta), sin(theta)] is the standard unit vector.  
It points in direction theta and it is one unit long since      cos^2 + sin^2 = 1

r is the magnitude of the vector    r = sqrt( x^2 + y^2)
> "r = sqrt( x^2 + y^2)"
what happens when x and y are negative? (r = sqrt( x^2 + y^2) = sqrt(-3^2 - 2^2) = sqrt(-13) = ?)
(-3, -2)  ==>      r = sqrt( -3^2 + -2^2) =  sqrt( 9 +4)  = sqrt( 13)

Magnitude is always guranteed to be positve.  That's the great thing about it.

You will find the direction of the unit vector between 180 a 270 degrees.
lol Ah yeah, of course! When I type it into my calculator, it says "Math Error" (...and that's what caused me to think so stupidly).

lol -- I'll get back to you all on this later.

Cheers,
>> IM
a  =  (0, 0) to (0, 4)
 b  =  (0, 0) to (4, 4)

the angle between to vectors is
arccos(a dot b / sqrt(a dot a * b dot b))
the dot product of two vectors is (ax*bx+ay*by)
a = (0-0,4-0)
b = (4-0,4-0)
a dot b = 4*0 + 4*4 = 16
a dot a = 0*0 + 4*4 = 16
b dot b = 4*4 + 4*4 = 32
16/sqrt(16*32) = 1/sqrt(2)
arccos(1/sqrt(2)) = pi/4


My former equation works for for 0-Pi.

angle = (Pi/2)*{[(m-abs(m)]/2m)} + arctan[abs(1/m)] + (Pi)*{[(X(b)-abs(X(b))]/2X(b))}

works for all angles around the circle where m is not zero or infinite.
If m = zero, the angle is Pi/2 or 3Pi/2 (Check X(b)).
If m = infinite, the angle is 0 or Pi (Check Y(b)).

You can use many methods,
any methods you use, you can not avoid checking some variables to check conditions.
Hi IM,
    angle = tan^-1(y/x) + (180 if y is negative)

Bye
---
Harish
InteractiveMind,
    You require the dirfference between the angles of each line.
    Req. Ang. =(tan^-1(by/bx) + (180 if by is negative))-(tan^-1(ay/ax) + (180 if ay is negative))
Thanks very much everyone.

the Java Math class doesn't seem to contain a an inverse tan method (/function). Is there a way that I can combine tan, and some other function to recreate the inverse tan function?

>> IM
I don't know Java. But I am sure, it will have something like

arctan(x) or atan(x)
Yes. I'll use that then... But is arctan the same as inverse tan? :o\
Oh right. I never knew that. lol :)

Strange. The link you posted about the Math Engine states that it contains the arctan() function, whereas according to my IDE, and the official API spec (http://java.sun.com/j2se/1.5.0/docs/api/), the Math class only contains an atan() function; (which obviously is the same thing - so it doesn't really matter; I just wonder why that links states otherwise).
Ah well.

Cheers, Harish.

I'll get back to you all.
>> IM
IM have you checked my algorithm? You can use directly
Req. Ang. =(arctan(by/bx) + (180° if by is negative)) - 90°

Note that the result of arctan may be in radians, in which case you will have to change that to degrees...
Req. Ang. =(arctan(by/bx)*180°/PI + (180° if by is negative)) - 90°
As  I have told already, I don't know Java :(
Cheers.
Okay, getting there.. I've tried this:

            double by = 4;
            double bx = 4;
           
            double bn = 0;
            if ( isNegative(by) )
                bn = 180;
           
            double angle = ( Math.toDegrees( Math.atan(by/bx) ) + bn) - 90;

Now, it should (at least, I want it to) set the 'angle' variable to 45.0; instead, it's setting it to -45.0.
Why is this?

BTW: I can do some C++ as well, so if you can do C++, and can demonstrate it in that, then I can 'translate' it into Java (although, for what we're doing here, Java is almost completely identical to C++).

Cheers,
>> IM
ASKER CERTIFIED SOLUTION
Avatar of Harisha M G
Harisha M G
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Fantastic.
Cheers, everyone! :)

>> IM
In C++....

#include <math.h>

main()
{
            double by = 4;
            double bx = 4;
           
            double bn = 0;
            if (by < 0)
                bn = 180;
           
            double angle = 90 - (atan(by/bx) * 180 / M_PI + bn);
}

You may have to check for the condition bx!=0
You have already accepted the answer !
Thanks :)
^_^
If you're working in Java, you should have an atan2(by,bx) function
This would eliminate problems when by or bx is zero, and properly handle negative bx or by over the full range of the circle.