Skip to content

Commit

Permalink
Handle angles of zero vectors
Browse files Browse the repository at this point in the history
  • Loading branch information
samirelanduk committed Apr 3, 2018
1 parent f2eea2b commit ca7df04
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 128 deletions.
9 changes: 6 additions & 3 deletions points/vectors.py
@@ -1,7 +1,7 @@
"""Contains the Vector class."""

import math
from math import sqrt, acos
from math import sqrt, acos, pi

class Vector:
"""A Vector is a sequence of numbers. They can represent a point in space,
Expand Down Expand Up @@ -256,8 +256,11 @@ def angle_with(self, other, degrees=False):
raise TypeError("{} is not a Vector".format(other))
if self.length() != other.length():
raise ValueError("{} and {} not equal length".format(self, other))
angle = acos(self.dot(other) / (self.magnitude() * other.magnitude()))
return math.degrees(angle) if degrees else angle
if self.magnitude() == 0 or other.magnitude() == 0:
ang = pi / 4
else:
ang = acos(self.dot(other) / (self.magnitude() * other.magnitude()))
return math.degrees(ang) if degrees else ang


class VectorSpan:
Expand Down
141 changes: 16 additions & 125 deletions tests/unit/test_vectors.py
@@ -1,3 +1,4 @@
import math
from unittest import TestCase
from unittest.mock import Mock, patch, MagicMock
from points.vectors import Vector
Expand Down Expand Up @@ -410,6 +411,21 @@ def test_can_get_angle_between_vectors(self, mock_dot, mock_mag):
self.assertAlmostEqual(vector1.angle_with(vector2), 1.0471, delta=0.0005)


@patch("points.vectors.Vector.magnitude")
@patch("points.vectors.Vector.dot")
def test_can_get_angle_between_vectors_when_zero(self, mock_dot, mock_mag):
mock_dot.return_value = 1
mock_mag.return_value = 0
vector1 = Vector(7, 1)
vector2 = Mock(Vector)
vector2.magnitude.return_value = 0.5
vector2.length.return_value = 2
self.assertAlmostEqual(vector1.angle_with(vector2), math.pi / 4, delta=0.0005)
vector2.magnitude.return_value = 0
mock_mag.return_value = 9
self.assertAlmostEqual(vector1.angle_with(vector2), math.pi / 4, delta=0.0005)


@patch("points.vectors.Vector.magnitude")
@patch("points.vectors.Vector.dot")
def test_can_get_angle_between_vectors_in_degrees(self, mock_dot, mock_mag):
Expand All @@ -436,128 +452,3 @@ def test_angle_requires_equal_length(self):
vector2.length.return_value = 3
with self.assertRaises(ValueError):
vector1.angle_with(vector2)





'''
class VectorRotation(TestCase):
def setUp(self):
self.vector = Mock()
self.matrix = Mock()
self.matrix.__matmul__ = MagicMock()
self.matrix.__matmul__.return_value = self.vector
@patch("points.matrices.Matrix")
def test_can_do_2d_rotation(self, mock_matrix):
self.vector._values = [-4, 3]
mock_matrix.return_value = self.matrix
v = Vector(3, 4)
v.rotate(pi / 2)
matrix_args = mock_matrix.call_args_list[0][0]
self.assertAlmostEqual(matrix_args[0][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[0][1], -1, delta=0.005)
self.assertAlmostEqual(matrix_args[1][0], 1, delta=0.005)
self.assertAlmostEqual(matrix_args[1][1], 0, delta=0.005)
self.matrix.__matmul__.assert_called_with(v)
self.assertEqual(v._values, [-4, 3])
@patch("points.matrices.Matrix")
def test_can_do_3d_rotation_x(self, mock_matrix):
self.vector._values = [-4, 3, 5]
mock_matrix.return_value = self.matrix
v = Vector(3, 4, 5)
v.rotate(pi / 2, "x")
matrix_args = mock_matrix.call_args_list[0][0]
self.assertAlmostEqual(matrix_args[0][0], 1, delta=0.005)
self.assertAlmostEqual(matrix_args[0][1], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[0][2], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[1][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[1][1], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[1][2], -1, delta=0.005)
self.assertAlmostEqual(matrix_args[2][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[2][1], 1, delta=0.005)
self.assertAlmostEqual(matrix_args[2][2], 0, delta=0.005)
self.matrix.__matmul__.assert_called_with(v)
self.assertEqual(v._values, [-4, 3, 5])
@patch("points.matrices.Matrix")
def test_can_do_3d_rotation_y(self, mock_matrix):
self.vector._values = [-4, 3, 5]
mock_matrix.return_value = self.matrix
v = Vector(3, 4, 5)
v.rotate(pi / 2, "y")
matrix_args = mock_matrix.call_args_list[0][0]
self.assertAlmostEqual(matrix_args[0][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[0][1], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[0][2], 1, delta=0.005)
self.assertAlmostEqual(matrix_args[1][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[1][1], 1, delta=0.005)
self.assertAlmostEqual(matrix_args[1][2], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[2][0], -1, delta=0.005)
self.assertAlmostEqual(matrix_args[2][1], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[2][2], 0, delta=0.005)
self.matrix.__matmul__.assert_called_with(v)
self.assertEqual(v._values, [-4, 3, 5])
@patch("points.matrices.Matrix")
def test_can_do_3d_rotation_z(self, mock_matrix):
self.vector._values = [-4, 3, 5]
mock_matrix.return_value = self.matrix
v = Vector(3, 4, 5)
v.rotate(pi / 2, "z")
matrix_args = mock_matrix.call_args_list[0][0]
self.assertAlmostEqual(matrix_args[0][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[0][1], -1, delta=0.005)
self.assertAlmostEqual(matrix_args[0][2], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[1][0], 1, delta=0.005)
self.assertAlmostEqual(matrix_args[1][1], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[1][2], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[2][0], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[2][1], 0, delta=0.005)
self.assertAlmostEqual(matrix_args[2][2], 1, delta=0.005)
self.matrix.__matmul__.assert_called_with(v)
self.assertEqual(v._values, [-4, 3, 5])
def test_only_2_and_3_d_vectors_can_rotate(self):
vector = Vector(1)
with self.assertRaises(ValueError):
vector.rotate(pi)
vector = Vector(1, 2, 3, 4)
with self.assertRaises(ValueError):
vector.rotate(pi)
def test_axis_must_be_valid(self):
vector = Vector(1, 2, 3)
with self.assertRaises(ValueError):
vector.rotate(pi, "n")
'''

0 comments on commit ca7df04

Please sign in to comment.