Finding the angle between two lines in 2D is easy, just find the angle of each line with the x-axis from the slope of the line and take the difference. In 3D it is not so obvious, but it can be shown (using the Cosine Rule) that the angle θ between two vectors a and b is given by:
Cos θ = (a.b)/(|a||b|)
Unfortunately this gives poor accuracy for angles close to zero; for instance an angle of 1.00E-7 radians evaluates with an error exceeding 1%, and 1.00E-8 radians evaluates as zero. A similar formula using the sine of the angle:
Sin θ = |(axb)|/(|a||b|)
has similar problems with angles close to 90 degrees, but combining the two gives:
Tan θ = |(axb)|/ (a.b)
which is accurate for all angles, and since the (|a||b|) values cancel out the computation time is similar to the other expressions.
I have added a new User Defined Function (UDF) to the VectorFunc.xlsb spreadsheet, which was described in Dots and Crosses. The revised spreadsheet can be downloaded from the link above, including full open-source code.
The input for the new ANG() function is either two or three points, each of which are defined by a row of 2 or 3 values for 2D or 3D lines. Each point must have the same number of dimensions. If the third point is omitted the function returns the angle at the origin between the lines to Point 1 and Point 2. If the third point is supplied, the function returns the angle at this point. Angles are returned in radians by default, or degrees if the optional fourth argument is set to 1. The screen shot below shows examples of each of these options.