Skip to content

Commit

Permalink
Merge pull request #57 from nbraud/cross
Browse files Browse the repository at this point in the history
Add cross-product and angle
  • Loading branch information
AstraLuma authored Oct 11, 2018
2 parents 29d0590 + 3b22df1 commit 7118259
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ Multiply a `Vector2` by another `Vector2` to get the dot product.
>>> Vector2(45, 60).length
75.0

### Cross-product

Take the cross-product between two (2D) vectors.
The result is expressed as a scalar, as it is known to lie on the z-axis.

>>> Vector(1, 0) ^ Vector(0, 1)
1

### Access Values

Convenient access to `Vector2` members via dot notation, indexes, or keys.
Expand Down Expand Up @@ -122,6 +130,16 @@ Rotate a vector in relation to its own origin and return a new `Vector2`.

Positive rotation is counter/anti-clockwise.

#### angle(vector)

Compute the angle between two vectors, expressed as a scalar in degrees.

>>> Vector(1, 0).angle(Vector(0, 1))
90

As with `rotate()`, angles are signed, and refer to a direct coordinate system
(i.e. positive rotations are counter-clockwise).

#### normalize()

Return the normalized `Vector2` for the given `Vector2`.
Expand Down
8 changes: 7 additions & 1 deletion ppb_vector/vector2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from math import cos, hypot, radians, sin
from math import acos, cos, degrees, hypot, radians, sin
from numbers import Number
from collections.abc import Sequence

Expand Down Expand Up @@ -46,6 +46,9 @@ def __rmul__(self, other):
if isinstance(other, Number):
return Vector2(self.x * other, self.y * other)

def __xor__(self, other):
return self.x * other.y - self.y * other.x

def __getitem__(self, item):
if hasattr(item, '__index__'):
item = item.__index__()
Expand Down Expand Up @@ -88,6 +91,9 @@ def __iter__(self):
def __neg__(self):
return self * -1

def angle(self, other):
return degrees(acos(self.normalize() * other.normalize()))

def rotate(self, degrees):
r = radians(degrees)
r_cos = cos(r)
Expand Down
5 changes: 5 additions & 0 deletions tests/test_vector2_rotate.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@
(Vector2(math.pi, math.e), 67, Vector2(-1.27467, 3.95397))
]

def isclose(x, y, epsilon = 6.5e-5):
d = (x - y) % 360
return (d < epsilon) or (d > 360 - epsilon)

@pytest.mark.parametrize('input, degrees, expected', data)
def test_multiple_rotations(input, degrees, expected):
assert input.rotate(degrees) == expected
assert isclose(input.angle(expected), degrees)

def test_for_exception():
with pytest.raises(TypeError):
Expand Down

0 comments on commit 7118259

Please sign in to comment.