diff --git a/lib/matrix.rb b/lib/matrix.rb index b39973b..4f9708d 100644 --- a/lib/matrix.rb +++ b/lib/matrix.rb @@ -1999,6 +1999,29 @@ class Vector self / n end + # + # Returns an angle between vectors + # Vector[1,0].angle_between(Vector[0,1]) + # # => 1.5707963267948966 + # + def angle_between(v) + Vector.Raise ErrDimensionMismatch if size != v.size + raise ZeroVectorError, "Can't get angle of zero vector" if magnitude == 0 || v.magnitude == 0 + + Math.acos self.normalize.inner_product(v.normalize) + end + + # + # Returns a projection to another vector + # Vector[1,0].angle_between(Vector[0,1]) + # # => 1.5707963267948966 + # + def projection_to(v) + Vector.Raise ErrDimensionMismatch if size != v.size + + self.inner_product(v)/v.magnitude + end + #-- # CONVERTING #++ diff --git a/test/matrix/test_vector.rb b/test/matrix/test_vector.rb index fa29496..d70bc36 100644 --- a/test/matrix/test_vector.rb +++ b/test/matrix/test_vector.rb @@ -169,4 +169,13 @@ class TestVector < Test::Unit::TestCase v = Vector[1, 0, 0].cross_product Vector[0, 1, 0] assert_equal(Vector[0, 0, 1], v) end + + def test_angle_between + assert_in_epsilon(1.5707963267948966, Vector[1, 0].angle_between(Vector[0, 1])) + end + + def test_projection_to + assert_equal(1.0, Vector[1, 1].projection_to(Vector[1,0])) + assert_in_epsilon(0.7071067811865475, Vector[0, 1].projection_to(Vector[1, 1])) + end end