# find the angle between two lines formed by three points in n-space

#### LMHmedchem

Hello,

I wasn't sure where to post this, so please feel free to move it. In some ways, I suspect this is a very elementary question for an expert, so I posted in on the pre-university side.

Here is an example in 2D of the problem I am looking at,

given three sets of coordinates, calculate the angle ABC.

Find the slope of AB and AC, m=y2-y1/x2-x1

mAB = 0.08-0.31/0.07-0.56
mAB = 0.46939
mAC = 0.86-0.31/0.49-0.56
mAC = -7.85714

Find the tangent of the angle, tan Ɵ = (mAB-mAC) / (1+mAB*mAC)

tan Ɵ = (0.46939- -7.85714)/(1+0.46939*-7.85714)
tan Ɵ = -3.09759

Find the arctan and convert to degrees,

arctan -3.09759 = -1.258526901 radians = -72.11 degrees

...you don't have to be a geometry expert to see that isn't right for the data in the plot as ABC is obviously >90.

Further, I need to do this in high dimensional space, so the equations I use need to be for cases other than x,y. I don't have access to Matlab, but I could program something in c++ with the Eigen library.

My understanding of this problem in higher dimensions is that the lines AB and AC are vectors. Assuming that the n-space is orthogonal (which it is in this case), the vectors AB and AC lie in a Euclidean plane and so I would need to derive the vectors AB and AC from the coordinates and then derive the angle between.

This website,
Online calculator. Angle between vectors.

calculates the angle between two vectors based on the start and end point coordinates of the vector (in 2D or 3D). This is the output of the solver for my points in 2D,

Calculate vector by initial and terminal points:
AB = {Bx - Ax; By - Ay} = {0.07 - 0.56; 0.08 - 0.31} = {-0.49; -0.23}
CD = {Dx - Cx; Dy - Cy} = {0.49 - 0.56; 0.86 - 0.31} = {-0.07; 0.55}

Calculate dot product:
AB · CD = ABx · CDx + ABy · CDy = (-0.49) · (-0.07) + (-0.23) · 0.55 = 0.0343 - 0.1265 = -4615000

Calculate magnitude of the vectors:
|AB| = √ABx2 + ABy2 = √(-0.49)2 + (-0.23)2 = √0.2401 + 0.0529 = √0.293 = √2930100
|CD| = √CDx2 + CDy2 = √(-0.07)2 + (0.55)2 = √0.0049 + 0.3025 = √0.3074 = √3074100

Calculate angle between vectors:
cos α = AB · CD / |AB||CD|
cos α = -461/5000 / √2930/100 · √3074/10 = -461√22517052251705 ≈ -0.3072169542860648

This method give yet a different answer which is also obviously not correct where I would estimate the angle to be ~100 degrees. The vector method is preferable in that I think I can see how to expand this to any dimension.

Can someone please let me know what I am doing wrong here?

LMHmedchem

Last edited:

#### chiro

MHF Helper
Hey LMHmedchem.

If you are using the inner product (i.e. cos(theta) = <A,B> / [|A||B|]) then you have to convert it to degrees since the answer will be in radians when you do the inverse.

So if you have cos(a) = x then you find arc-cosine(x) = a [where a is in between 0 and pi inclusive] and then in degrees you need to find degrees = radians*180/pi.

LMHmedchem

#### Plato

MHF Helper
Here is an example in 2D of the problem I am looking at,
View attachment 36039
given three sets of coordinates, calculate the angle ABC.
Given $A: (a_x,a_y),~B: (b_x,b_y),~\&~C: (c_x,c_y)$ then the $\angle BAC=\arccos \left( {\dfrac{{({b_x} - {a_x})\left( {{c_x} - {a_x}} \right) + ({b_y} - {a_y})\left( {{c_y} - {a_y}} \right)}}{{\sqrt {{{({b_x} - {a_x})}^2} + {{\left( {{b_y} - {a_y}} \right)}^2}} \cdot \sqrt {{{({c_x} - {a_x})}^2} + {{\left( {{c_y} - {a_y}} \right)}^2}} }}} \right)$

If you insist on degrees, I will not help you. Only Neanderthals still use degrees.

LMHmedchem

#### LMHmedchem

If you are using the inner product (i.e. cos(theta) = <A,B> / [|A||B|]) then you have to convert it to degrees since the answer will be in radians when you do the inverse.

So if you have cos(a) = x then you find arc-cosine(x) = a [where a is in between 0 and pi inclusive] and then in degrees you need to find degrees = radians*180/pi.

Calculate vector by initial and terminal points:
AB = {Bx - Ax; By - Ay} = {0.07 - 0.56; 0.08 - 0.31} = {-0.49; -0.23}
CD = {Dx - Cx; Dy - Cy} = {0.49 - 0.56; 0.86 - 0.31} = {-0.07; 0.55}

Calculate dot product:
AB · CD = ABx · CDx + ABy · CDy = (-0.49) · (-0.07) + (-0.23) · 0.55 = 0.0343 - 0.1265 = -4615000

Calculate magnitude of the vectors:
|AB| = √ABx2 + ABy2 = √(-0.49)2 + (-0.23)2 = √0.2401 + 0.0529 = √0.293 = √2930100
|CD| = √CDx2 + CDy2 = √(-0.07)2 + (0.55)2 = √0.0049 + 0.3025 = √0.3074 = √3074100

Calculate angle between vectors:
cos α = AB · CD / |AB||CD|
cos α = -461/5000 / √2930/100 · √3074/10 = -461√22517052251705 ≈ -0.3072169542860648

Take arc cosine and convert to degrees:
arc-cosine α = arc-cosine -0.3072169542860648 = 1.883063498 radians = 107.89159099081 degrees

The answer of ~107 degrees looks much more plausible.

If I were to do the same operation in a high dimensional space like D50, what would the formula look like for converting the n-space points into vectors? Is it just,

AB = {Bx - Ax; By - Ay, Bz - Az, ...Bn - An}

I would hate to see the dot product and magnitude equations written out for 50D, but I assume I can generate those values with computer code. Am I right in assuming that the process is the same for any dimensions, meaning,
- generate vectors from start and end point coordinates
- take dot product
- calculate the magnitude
- solve for cosine α = AB · CD / |AB||CD|
- find arc-cosine of cosine α

It seems as if this is longer than it needs to be, but I am unsure of where to shorten it.

Thank you very much for your input,

LMHmedchem

#### LMHmedchem

If you insist on degrees, I will not help you. Only Neanderthals still use degrees.
I am working on a theorem where a certain case is true if the angle ABC is greater than 90 degrees. I am a bit worried about floating point as I am with anything done on a computer. Of curse, converting a value with an equation that involves pi is not exactly helping with that issue. I don't see any reason why I can't use 1.5708 radians, though I might want more precision than that.

Code:
$A: (a_x,a_y),~B: (b_x,b_y),~\&~C: (c_x,c_y)$ then the $\angle BAC=\arccos \left( {\dfrac{{({b_x} - {a_x})\left( {{c_x} - {a_x}} \right) + ({b_y} - {a_y})\left( {{c_y} - {a_y}} \right)}}{{\sqrt {{{({b_x} - {a_x})}^2} + {{\left( {{b_y} - {a_y}} \right)}^2}} \cdot \sqrt {{{({c_x} - {a_x})}^2} + {{\left( {{c_y} - {a_y}} \right)}^2}} }}} \right)$
I have never actually used this notation before, though I generally associate it with Matlab. Is there software that I can use to decode the above?

LMHmedchem

Last edited:

delete

#### Plato

MHF Helper
I have never actually used this notation before, though I generally associate it with Matlab. Is there software that I can use to decode the above[/B]
I think that you have completely miss-understood the process of learning. While CAS such as MatLab have been the greatest advanced in mathematics education(learning) in centuries, they are the most misunderstood. No one learns mathematics from using a CAS. Only if one first learns mathematics can one benefit from using MatLab to make computations simple.

Your post above proves that point. Learn the mathematics first then use MatLab to apply it.

#### LMHmedchem

I think that you have completely miss-understood the process of learning. While CAS such as MatLab have been the greatest advanced in mathematics education(learning) in centuries, they are the most misunderstood. No one learns mathematics from using a CAS. Only if one first learns mathematics can one benefit from using MatLab to make computations simple.
I am now nearly 50 years old and have been a scientist for most of my life. I can assure you that I understand the learning process better than most. It so happens that I often need to balance learning with the practicality of making progress in research that often involves ventures into disciplines that I don't know well. I need an algorithm for a project I am working on right now. I can't find a suitable algorithm that is currently available so I need to come up with my own. I have some ideas about how to proceed, but these ideas involve some linear algebra and trigonometry that I have not had in classes since the 1980s. My first need to actually find the angle between some n-space vectors, not because I want to learn how, but because I actually need to know what the angle is. This is the opposite case as is true for most math students who will value the theory and mental rigor and could generally care less about the answer. My next priority is to get this coded up in a language that will allow me to test if my hypothesis is supported or not. I have no objection to learning the theory and becoming a better mathematician, but I already work more than 80 hours most weeks and I have to triage what I spend my time on.

Your post above proves that point. Learn the mathematics first then use MatLab to apply it.
Yes, well it's going to be difficult to learn if the explanation is posted in a syntax that only someone with experience with MatLab can interpret. If I ask a question at an English language forum and the answer is written in ancient Sanskrit, am I to be scolded for asking for an interpretation in a language I understand?

The post by chiro was very useful because it was written in easy to understand language. I would like to go through the explanation that you posted, but as I stated in my original post, I don't have access to MatLab. If I am to be able to make any use of the explanation you provided, I need some means by which I can read the series of equations.

You would be very wrong to believe that I don't greatly appreciate the assistance I receive on forums such as this one. I would have never made the progress I have made with my research without the help of many who never asked anything in return. It is important to understand that a person is not necessarily wrong just because they are proceeding in a manner different than you would in the same situation.

I appreciate the advice just the same,

LMHmedchem

Last edited:

#### chiro

MHF Helper
The idea you have is right to get the angle.

I did your example though with the vectors you gave and got the following:

> x <- (-0.49*-0.07 - 0.23*0.55)/(sqrt(0.49^2 + 0.23^2)*sqrt(0.07^2+0.55^2))
> acos(x)*180/pi
[1] 107.8916
> x
[1] -0.307217

This is close to 108 degrees which is close to what you said.

The idea is sound and geometrically accurate.

Also - You can download Octave which is a free open source version of MATLAB and GuiOctave is a GUI component to make it more like MATLAB.

The program I used R is open source and comes with a console and is highly recommended for analytic work.

#### LMHmedchem

The idea you have is right to get the angle.

I did your example though with the vectors you gave and got the following:

> x <- (-0.49*-0.07 - 0.23*0.55)/(sqrt(0.49^2 + 0.23^2)*sqrt(0.07^2+0.55^2))
> acos(x)*180/pi
[1] 107.8916
> x
[1] -0.307217

This is close to 108 degrees which is close to what you said.

The idea is sound and geometrically accurate.
I alos get 107.89 degrees for the answer.

Thanks for going over this with me. I have it working in excel with a number of examples.

I have moved on to working with my actual data, which is in 46D. I am finding a few interesting things that I should have expected if I thought about it a bit more. The data is 47 input columns that have been orthagonalized to principle components. The first 46 PCA axes give 100% of the initial information, so I am not using the 47 axis.

I am evaluating the following,

BA: vector from point B in the data to A, the dataset centroid (arithmetic mean position of all points)
BC: vector from point B to some other point C
Angle ABC

Because of the PCA, the dataset centroid is at the origin. Every column of input averages to 0. Since the centroid, A, and origin are the same, the vector AB is the same as the point B, if that makes sense (the vector AB is the just coordinates of B). Since I am looking for the angle between the vector BA and BC, I need to reverse sign on AB to get BA. This just means,

BA = {Ax-Bx; Ay-By; Az-Bz; An-Bn}
where B is the source point and A is the destination point

because the value of every element in A is 0.0 (A is the origin), we are just flipping the sign on every element of AB to get BA.

BC is created in the same way, but of course every element of C is not 0.0.

BC = {Cx-Bx; Cy-By; Cz-Bz; Cn-Bn}
where B is the source point and C is the destination point.

Do I have this correct in the direction of the vectors? If point B is the middle point in the angle I want both vectors to run away from B? As a matter of interest, if both vectors were set up with B as the destination point instead of the starting point, do you get the same angle?

The is an example from my current data,

Code:
[B][COLOR="#0000FF"]point A[/COLOR][/B] (centroid, origin)  {0.00000008, 0.00000001, 0.00000004, 0.00000002, -0.00000002, 0.00000009, -0.00000002, -0.00000005, 0.00000000, -0.00000004, 0.00000001, 0.00000006, 0.00000003, 0.00000001, -0.00000010, 0.00000002, 0.00000002, -0.00000003, 0.00000000, -0.00000002, -0.00000002, 0.00000002, 0.00000002, -0.00000005, -0.00000003, 0.00000000, -0.00000001, 0.00000002, -0.00000002, -0.00000001, -0.00000002, 0.00000001, 0.00000002, -0.00000003, 0.00000000, 0.00000002, -0.00000002, 0.00000000, 0.00000004, 0.00000000, -0.00000002, -0.00000001, -0.00000001, 0.00000003, 0.00000001, 0.00000002}
[B][COLOR="#0000FF"]point B[/COLOR][/B] (middle, vector AB) {0.175132, 0.348752, 1.24702, -0.544408, -0.73933, -0.0909104, 0.0485134, 0.278414, -0.058047, 0.355605, -0.900736, 0.461809, 0.0114412, 0.0842125, 0.102702, -0.390766, -0.15989, -0.621728, -0.350141, 0.134657, 0.246031, 0.0252494, -0.160878, -0.121506, 0.789493, -0.216505, 0.566662, 0.0708013, -0.0540743, 0.016411, -0.298636, 0.251557, 0.0613878, -0.286214, 0.0160241, -0.238378, -0.0476294, -0.0957132, 0.0379779, 0.150985, -0.189963, -0.0959136, -0.0553876, 0.0197653, 0.122549, 0.0130179}
[B][COLOR="#0000FF"]point C[/COLOR][/B] (vector AC)         {1.44436, -9.92098, 4.99388, 3.21483, -1.66346, 3.64611, -0.0439071, 5.17643, 4.04622, 6.83821, -2.37746, 1.80217, -1.58327, 2.0277, -1.09643, -3.37537, 2.40959, -2.62405, 1.11165, -2.93779, 0.624578, -0.408611, 0.394217, -0.11589, -0.260495, 0.772796, 0.365847, -0.448188, 0.183692, 0.185065, -0.217426, -0.263635, -0.042266, 0.388326, 0.751452, -0.259388, 0.0982389, 0.14734, -0.250635, 1.26168, -2.59434, -0.562643, -0.334437, 0.130835, 0.0722803, 0.117215}

[B][COLOR="#0000FF"]vector BA[/COLOR][/B] {-0.17513192, -0.34875199, -1.24701996, 0.54440802, 0.73932998, 0.09091049, -0.04851342, -0.27841405, 0.05804700, -0.35560504, 0.90073601, -0.46180894, -0.01144117, -0.08421249, -0.10270210, 0.39076602, 0.15989002, 0.62172797, 0.35014100, -0.13465702, -0.24603102, -0.02524938, 0.16087802, 0.12150595, -0.78949303, 0.21650500, -0.56666201, -0.07080128, 0.05407428, -0.01641101, 0.29863598, -0.25155699, -0.06138778, 0.28621397, -0.01602410, 0.23837802, 0.04762938, 0.09571320, -0.03797786, -0.15098500, 0.18996298, 0.09591359, 0.05538759, -0.01976527, -0.12254899, -0.01301788
[B][COLOR="#0000FF"]|BA|[/COLOR][/B] = 2.4520
[B][COLOR="#0000FF"]vector BC[/COLOR][/B] {1.269228, -10.269732, 3.74686, 3.759238, -0.92413, 3.7370204, -0.0924205, 4.898016, 4.104267, 6.482605, -1.476724, 1.340361, -1.5947112, 1.9434875, -1.199132, -2.984604, 2.56948, -2.002322, 1.461791, -3.072447, 0.378547, -0.4338604, 0.555095, 0.005616, -1.049988, 0.989301, -0.200815, -0.5189893, 0.2377663, 0.168654, 0.08121, -0.515192, -0.1036538, 0.67454, 0.7354279, -0.02101, 0.1458683, 0.2430532, -0.2886129, 1.110695, -2.404377, -0.4667294, -0.2790494, 0.1110697, -0.0502687, 0.1041971
[B][COLOR="#0000FF"]|BC|[/COLOR][/B] = 16.9606

[B][COLOR="#0000FF"]BA•BC[/COLOR][/B] = -5.175244692

[B][COLOR="#0000FF"]cos [SIZE=3]α[/SIZE][/COLOR][/B] = BA•BC/|BA|*|BC| = -0.124442112

[B][COLOR="#0000FF"]arc-cos [SIZE=3]α[/SIZE][/COLOR][/B] = 1.6956

[B][COLOR="#0000FF"]arc-cos [SIZE=3]α[/SIZE]*180/pi[/COLOR][/B] = 97.15 degrees
I apologize for not doing a better job with significant figures. I should have formatted my excel page a bit more to control that. You may note that the element values for the centroid and not 0.0 exactly. They were created using the same equation as was used to generate BC and there is floating point variance in the averages of the columns so you don't get exactly 0.0. I am tempted to just use 0.0 but the variance is far enough out that it should affect the calculations, especially if I do this in double. It's hard to say.

This methodology seems reasonable at this point and won't be difficult to program. If you have R set up to do this, could you possibly check my math on this example and let me know if you get the same angle? If it all checks out, I will write a program and post it tomorrow.

You can download Octave which is a free open source version of MATLAB and GuiOctave is a GUI component to make it more like MATLAB.
Thanks for the heads up on this. I should have guessed there was a freeware version out there. Allot of the posts I find on stackexchange use MatLab script in their explanations. It seems to have become the standard alternative syntax for algebra. It makes allot of sense to have developed a linear syntax that can be displayed on computer without special equation writing software. I'm sure that folks who are familiar with it can now read it just as well as traditional Cartesian or linear algebra. I'm pretty clueless looking at it, so it would be nice to have an application that would help me to see what is going on. It would be nice to see if the explanation by Plato is the same as what I am already using or if it's an alternative method.

The program I used R is open source and comes with a console and is highly recommended for analytic work.
I use R some, but I find the script language a bit of an obstacle. It's on the list of things I wish I had more time to learn properly. I often find that in the course of research I need an algorithm that doesn't quite exist as a coded application, so I often end up writing my own. These are generally not all the different then commonly available algorithms, but the small differences can be important.

Lately I have been using a neat data mining program called Tanagra.
TANAGRA - A free data mining software for research and education

It has an easy to use interface and lets you set up custom workflows with a graphic interface and then save those workflows for later use. You can do multi-step operations like import data, rotate to principle components, run a feature selection algorithm, bootstrap the training data, and create a model just by dragging and dropping the different tool elements in the gui. If you like the work flow, you can save it to leave later but just selecting a different input file. It also does lots of statistics and such. I use it more than I use JMP or SAS now because it is much easier to use. I doesn't replicate the features of an application like MatLab, but it does many of the calculations I would otherwise do in R so I thought I would mention it.

Thanks again,

LMHmedchem

Last edited: