

Title  Find the angle between two line segments 
Keywords  angle, line segments 
Categories  Algorithms, Graphics 


The GetAngle function uses vector mathematics including dot products and cross products. Before you can understand the function, it helps to understand a little vector algebra.
A vector consists of a series of components giving a direction and a distance. You can think of the vector as an arrow: it has direction and length.
In 2 dimensions, you can write a vector as <x, y> where x and y give the vector's X and Y components. For example, the vector <2, 0> is a vector of length 2 parallel to the X axis and pointing to the right (in the positive X direction).
You can find the vector between two points by subtracting the coordinates of the points. The vector from point (x1, y1) to point (x2, y2) is:
V = <x2  x1, y2  y1>
The length of a vector <x, y> is written <x, y> . Using the Pythagorean Theorem it is easy to show that:
<x, y> = Sqr(x * x + y * y)
The dot product of two vectors A = <x1, y1> and B = <x2, y2> is written A · B and has the value:
A · B = A * B * Cos(theta)
where theta is the angle between the two vectors. You can easily calculate the dot product using this equation:
A · B = x1 * x2 + y1 * y2
The following code calculates the dot product of two vectors. The function takes as parameters the coordinates of three points A, B, and C, and finds the dot product of the vectors AB and BC.


' Return the dot product AB · BC.
' Note that AB · BC = AB * BC * Cos(theta).
Private Function DotProduct( _
ByVal Ax As Single, ByVal Ay As Single, _
ByVal Bx As Single, ByVal By As Single, _
ByVal Cx As Single, ByVal Cy As Single _
) As Single
Dim BAx As Single
Dim BAy As Single
Dim BCx As Single
Dim BCy As Single
' Get the vectors' coordinates.
BAx = Ax  Bx
BAy = Ay  By
BCx = Cx  Bx
BCy = Cy  By
' Calculate the dot product.
DotProduct = BAx * BCx + BAy * BCy
End Function


The cross product of two vectors A = <x1, y1> and B = <x2, y2> is written A × B. The result is a new vector that is prependicular to both A and B and that has length:
A × B = A * B * Sin(theta)
where theta is the angle between the two vectors. You can calculate the cross product of two vectors in the XY plane using this equation:
A × B = <0, 0, x1 * y2  x2 * y1>
Note that this vector is parallel to the Zaxis. That makes sense because the vectors A and B lie in the XY plane and the cross product should give a vector perpendicular to both.
Exercise: Calculate <1, 0> × <0, 1>. Does the result make sense?
There are similar formulas (although they are a bit more complicated) for calculating cross products in higher dimensions.
The following code calculates the cross product of two vectors and returns the length of the result.


' Return the cross product AB x BC.
' The cross product is a vector perpendicular to AB
' and BC having length AB * BC * Sin(theta) and
' with direction given by the righthand rule.
' For two vectors in the XY plane, the result is a
' vector with X and Y components 0 so the Z component
' gives the vector's length and direction.
Public Function CrossProductLength( _
ByVal Ax As Single, ByVal Ay As Single, _
ByVal Bx As Single, ByVal By As Single, _
ByVal Cx As Single, ByVal Cy As Single _
) As Single
Dim BAx As Single
Dim BAy As Single
Dim BCx As Single
Dim BCy As Single
' Get the vectors' coordinates.
BAx = Ax  Bx
BAy = Ay  By
BCx = Cx  Bx
BCy = Cy  By
' Calculate the Z coordinate of the cross product.
CrossProductLength = BAx * BCy  BAy * BCx
End Function


Now you can use the dot product and cross product to find the sine and cosine of the angle between the two vectors.
Cos(theta) = A · B / (A * B)
Sin(theta) = A × B / (A * B)
A little trigonometry gives you:
Tan(theta) = Sin(theta) / Cos(theta)
So
Tan(theta) = [A × B / (A * B)] / [A · B / (A * B)]
= A × B / A · B
The following routines use these facts to calculate the angle between two vectors.


' Return the angle with tangent opp/hyp. The returned
' value is between PI and PI.
Public Function ATan2(ByVal opp As Single, ByVal adj As _
Single) As Single
Dim angle As Single
' Get the basic angle.
If Abs(adj) < 0.0001 Then
angle = PI / 2
Else
angle = Abs(Atn(opp / adj))
End If
' See if we are in quadrant 2 or 3.
If adj < 0 Then
' angle > PI/2 or angle < PI/2.
angle = PI  angle
End If
' See if we are in quadrant 3 or 4.
If opp < 0 Then
angle = angle
End If
' Return the result.
ATan2 = angle
End Function
' Return the angle ABC.
' Return a value between PI and PI.
' Note that the value is the opposite of what you might
' expect because Y coordinates increase downward.
Public Function GetAngle(ByVal Ax As Single, ByVal Ay As _
Single, ByVal Bx As Single, ByVal By As Single, ByVal _
Cx As Single, ByVal Cy As Single) As Single
Dim dot_product As Single
Dim cross_product As Single
' Get the dot product and cross product.
dot_product = DotProduct(Ax, Ay, Bx, By, Cx, Cy)
cross_product = CrossProductLength(Ax, Ay, Bx, By, Cx, _
Cy)
' Calculate the angle.
GetAngle = ATan2(cross_product, dot_product)
End Function


The book Visual Basic Graphics Programming contains more information on vector calculations used fro producing threedimensional graphics.





