Skip to content

Commit f00b07d

Browse files
authored
Fix rotation_between (#259)
* add more tests for `rotation_between` * fix methods for `rotation_between` * bump version to v1.5.1
1 parent b04d039 commit f00b07d

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Rotations"
22
uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc"
3-
version = "1.5.0"
3+
version = "1.5.1"
44

55
[deps]
66
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

src/rotation_between.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ Compute the quaternion that rotates vector `u` so that it aligns with vector
66
"""
77
function rotation_between end
88

9-
function rotation_between(u::SVector{2}, v::SVector{2})
9+
function rotation_between(u::StaticVector{2}, v::StaticVector{2})
1010
c = complex(v[1], v[2]) / complex(u[1], u[2])
11+
iszero(c) && throw(ArgumentError("Input vectors must be nonzero and finite."))
12+
isfinite(c) || throw(ArgumentError("Input vectors must be nonzero and finite."))
1113
theta = Base.angle(c)
1214
return Angle2d(theta)
1315
end
1416

15-
function rotation_between(u::SVector{3}, v::SVector{3})
17+
function rotation_between(u::StaticVector{3}, v::StaticVector{3})
1618
# Robustified version of implementation from https://www.gamedev.net/topic/429507-finding-the-quaternion-betwee-two-vectors/#entry3856228
1719
normprod = sqrt(dot(u, u) * dot(v, v))
1820
T = typeof(normprod)
@@ -22,9 +24,11 @@ function rotation_between(u::SVector{3}, v::SVector{3})
2224
@inbounds return QuatRotation(w, v[1], v[2], v[3]) # relies on normalization in constructor
2325
end
2426

25-
function rotation_between(u::SVector{N}, v::SVector{N}) where N
27+
function rotation_between(u::StaticVector{N}, v::StaticVector{N}) where N
2628
e1 = normalize(u)
2729
e2 = normalize(v - e1 * dot(e1, v))
30+
any(isnan, e1) && throw(ArgumentError("Input vectors must be nonzero and finite."))
31+
any(isnan, e2) && throw(ArgumentError("Input vectors must be nonzero and finite."))
2832
c = dot(e1, normalize(v))
2933
s = sqrt(1-c^2)
3034
P = [e1 e2 svd([e1 e2]'; full=true).Vt[StaticArrays.SUnitRange(3,N),:]']

test/rotation_tests.jl

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,14 +397,30 @@ all_types = (RotMatrix3, RotMatrix{3}, AngleAxis, RotationVec,
397397
end
398398

399399
@testset "$(N)-dimensional rotation_between" for N in 2:7
400-
for _ in 1:100
401-
u = randn(SVector{N})
402-
v = randn(SVector{N})
400+
@testset "random check" begin
401+
for _ in 1:100
402+
u = randn(SVector{N})
403+
v = randn(SVector{N})
404+
R = rotation_between(u,v)
405+
@test isrotation(R)
406+
@test R isa Rotation
407+
@test normalize(v) R * normalize(u)
408+
end
409+
end
410+
411+
@testset "mixed types" begin
412+
u = randn(MVector{N})
413+
v = randn(SizedVector{N})
403414
R = rotation_between(u,v)
404415
@test isrotation(R)
405416
@test R isa Rotation
406417
@test normalize(v) R * normalize(u)
407418
end
419+
420+
@testset "zero-vector" begin
421+
@test_throws ArgumentError rotation_between(zero(SVector{N}), rand(SVector{N}))
422+
@test_throws ArgumentError rotation_between(rand(SVector{N}), zero(SVector{N}))
423+
end
408424
end
409425

410426
#########################################################################

0 commit comments

Comments
 (0)