AngleBetweenVectors.jl

An accurate and stable calculation of the angle separating two vectors.
Author JeffreySarnoff
Popularity
28 Stars
Updated Last
10 Months Ago
Started In
June 2018

AngleBetweenVectors.jl

When computing the arc separating two cartesian vectors, this is robustly stable; others are not.


Copyright © 2018-2022 by Jeffrey Sarnoff.    This work is released under The MIT License.

Build Status Coverage Status DOI

preferred citiation
Sarnoff, Jeffrey (2022). AngleBetweenVectors (Version 0.3.1) [Source Code].
Open access at  https://github.com/JeffreySarnoff/AngleBetweenVectors.jl
https://doi.org/10.5281/zenodo.6745689

AngleBetweenVectors exports angle. angle(point1, point2) determines the angle of their separation. The smaller of the two solutions is used. π obtains If the points are opposed, [(1,0), (-1,0)]; so 0 <= angle(p1, p2) <= pi.

This function expects two points from a 2D, 3D .. ManyD space, in Cartesian coordinates. Tuples and Vectors are handled immediately (prefer Tuples for speed). To use another point representations, just define a Tuple constructor for it. NamedTuples and SVectors have this already.

Most software uses acos(dot(p1, p2) / sqrt(norm(p1) norm(p2)) instead. While they coincide often; it is exceedingly easy to find cases where angle is more accurate and then, usually they differ by a few ulps. Not always.


provides

  • angle( point₁, point₂ )
    • points are given as Cartesian coordinates
    • points may be of any finite dimension >= 2
    • points may be any type with a Tuple constructor defined

point representations that just work

  • points as Tuples
  • points as NamedTuples
  • points as Vectors
  • points as SVectors (StaticArrays)

working with other point representations

Just define a Tuple constructor for the representation. That's all.

# working with this?
struct Point3D{T}
    x::T
    y::T
    z::T
end

#  define this:
Base.Tuple(a::Point3D{T}) where {T} = (a.x, a.y, a.z)

#  this just works:
angle(point1::Point3D{T}, point2::Point3D{T})  where {T}

why use it

This implementation is more robustly accurate than the usual method.

You can work with points in 2D, 3D, .. 1000D .. ?.


notes

  • The shorter of two angles is given as an unoriented magnitude (0 <= radians < π).

  • Vectors are given by their Cartesian coordinates in 2D, 3D or .. N-dimensions.

  • This follows a note by Professor Kahan Computing Cross-Products and Rotations (pg 15):

"More uniformly accurate .. valid for Euclidean spaces of any dimension, it never errs by more than a modest multiple of ε."

Required Packages

No packages found.