Last active
November 23, 2017 02:19
-
-
Save chris-pws/d493d93ffc6f5227d794e1037ccedb34 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import itertools | |
import math | |
from decimal import Decimal, getcontext | |
getcontext().prec = 30 | |
class Vector: | |
CANNOT_NORMALIZE_ZERO_VECTOR_MSG = 'Cannot normalize the zero vector' | |
def __init__( self, coordinates ): | |
try: | |
if not coordinates: | |
raise ValueError | |
self.coordinates = tuple([Decimal(x) for x in coordinates]) | |
self.dimension = len(self.coordinates) | |
except ValueError: | |
raise ValueError( 'The coordinates must be nonempty' ) | |
except TypeError: | |
raise TypeError( 'The coordinates must be an iterable' ) | |
def __str__(self): | |
return 'Vector: {}'.format( | |
tuple([float('{0:.3f}'.format(n)) for n in self]) ) | |
def __iter__(self): | |
for i in self.coordinates: | |
yield Decimal(i) | |
def __getitem__( self, index ): | |
return self.coordinates[index] | |
def __eq__( self, v ): | |
return self.coordinates == v.coordinates | |
def __add__( self, v ): | |
try: | |
pairs = itertools.zip_longest( self, v, fillvalue=0.0) | |
return Vector([a + b for a, b in pairs]) | |
except TypeError as te: | |
raise NotImplemented from te | |
def __sub__( self, v ): | |
try: | |
pairs = itertools.zip_longest( self, v, fillvalue=0.0 ) | |
return Vector([a - b for a, b in pairs]) | |
except TypeError as te: | |
raise NotImplemented from te | |
def __mul__( self, scalar ): | |
return Vector([Decimal(scalar) * n for n in self]) | |
def magn(self): | |
# acquiring distance/magnitude | |
squares = Vector([n**2 for n in self]) | |
return math.sqrt( sum(squares) ) | |
def unit(self): | |
# here we are normalizing to a unit vector | |
# to capture direction | |
try: | |
magnitude = self.magn() | |
return self * ( Decimal('1.0') / Decimal(magnitude) ) | |
except ZeroDivisionError: | |
raise Exception(self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG) | |
def dot( self, v ): | |
pairs = zip( self, v ) | |
return sum( a * b for a, b in pairs ) | |
def angle_with( self, v, in_degrees=False ): | |
try: | |
u1 = self.unit() | |
u2 = v.unit() | |
angle_in_radians = math.acos( round( u1.dot(u2), 10 ) ) | |
if in_degrees: | |
degrees_per_radian = 180. / math.pi | |
return angle_in_radians * degrees_per_radian | |
else: | |
return angle_in_radians | |
except Exception as e: | |
if str(e) == self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG: | |
raise Exception('Cannot compute an angle with the zero vector') | |
else: | |
raise e | |
def parallel_to( self, v ): | |
#pairs = zip( self, v ) | |
#div = (self.coordinates[0] / v.coordinates[0]) | |
#return all( ( (a / b) == div ) for a, b in pairs ) | |
return ( self.is_zero() or | |
v.is_zero() or | |
self.angle_with(v) == 0 or | |
self.angle_with(v) == math.pi ) | |
def orthog_to( self, v, tolerance=1e-10 ): | |
return abs( self.dot(v) ) < tolerance | |
def is_zero( self, tolerance=1e-10 ): | |
return self.magn() < tolerance | |
def projected_on( self, b ): | |
b_unit = b.unit() | |
weight = Decimal( self.dot(b_unit) ) | |
parallel = b_unit * weight | |
return parallel | |
def orthog_proj( self, b ): | |
projection = self.projected_on(b) | |
orthog_comp = self - projection | |
return orthog_comp | |
def cross_product_with( self, v ): | |
return Vector([( self[1] * v[2] ) - ( v[1] * self[2] ), | |
-abs( ( self[0] * v[2] ) - ( v[0] * self[2] ) ), | |
( self[0] * v[1] ) - ( v[0] * self[1] )]) | |
def cp_parallelgm_area( self, v ): | |
cross = self.cross_product_with(v) | |
return cross.magn() | |
def cp_triangle_area( self, v ): | |
cross = self.cross_product_with(v) | |
return cross.magn() / 2 | |
v1 = Vector([1.5,9.547,3.691]) | |
v2 = Vector([-6.007,0.124,5.772]) | |
b1 = Vector([6.404,-9.144,2.759,8.718]) | |
v4 = Vector([1,8]) | |
print (v1.cp_triangle_area(v2)) | |
#print ( v3.is_orthog(v4) ) | |
#print ( v4.parallel_to(v1) ) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment