248 lines
7.5 KiB
Python
Executable File
248 lines
7.5 KiB
Python
Executable File
from math import acos, sqrt, pi
|
|
from decimal import Decimal, getcontext
|
|
|
|
getcontext().prec = 30
|
|
|
|
|
|
class MyDecimal(Decimal):
|
|
def is_near_zero(self, eps=1e-10):
|
|
return abs(self) < eps
|
|
|
|
|
|
class Vector(object):
|
|
def __init__(self, coordinates):
|
|
try:
|
|
if not coordinates:
|
|
raise ValueError
|
|
self.coordinates = tuple([Decimal(c) for c in coordinates])
|
|
self.dimension = len(coordinates)
|
|
|
|
except ValueError:
|
|
raise ValueError('The coordinates must be nonempty')
|
|
|
|
except TypeError:
|
|
raise TypeError('The coordinates must be an iterable')
|
|
|
|
def __iter__(self):
|
|
self.current = 0
|
|
return self
|
|
|
|
def __next__(self):
|
|
if self.current >= len(self.coordinates):
|
|
raise StopIteration
|
|
else:
|
|
current_value = self.coordinates[self.current]
|
|
self.current += 1
|
|
return current_value
|
|
|
|
def next(self):
|
|
return self.__next__()
|
|
|
|
def __len__(self):
|
|
return len(self.coordinates)
|
|
|
|
def __getitem__(self, i):
|
|
return self.coordinates[i]
|
|
|
|
def __str__(self):
|
|
return 'Vector: {}'.format([round(coord, 3)
|
|
for coord in self.coordinates])
|
|
|
|
def __eq__(self, v):
|
|
return self.coordinates == v.coordinates
|
|
|
|
def is_zero(self):
|
|
return set(self.coordinates) == set([Decimal(0)])
|
|
|
|
def plus(self, other):
|
|
new_coordinates = [x + y for x, y in zip(self.coordinates, other.coordinates)]
|
|
return Vector(new_coordinates)
|
|
|
|
def minus(self, other):
|
|
return Vector([coords[0] - coords[1]
|
|
for coords in zip(self.coordinates, other.coordinates)])
|
|
|
|
def times_scalar(self, factor):
|
|
return Vector([Decimal(factor) * coord for coord in self.coordinates])
|
|
|
|
def magnitude(self):
|
|
return Decimal(sqrt(sum([coord * coord
|
|
for coord in self.coordinates])))
|
|
|
|
def normalize(self):
|
|
try:
|
|
return self.times_scalar(Decimal('1.0') / self.magnitude())
|
|
except ZeroDivisionError:
|
|
raise Exception('Cannot normalize the zero vector')
|
|
|
|
def dot_product(self, other):
|
|
return sum(x * y for x, y in zip(self.coordinates, other.coordinates))
|
|
|
|
def get_angle_rad(self, other):
|
|
dot_prod = round(self.normalize().dot_product(other.normalize()), 3)
|
|
return acos(dot_prod)
|
|
|
|
def get_angle_deg(self, other):
|
|
degrees_per_rad = 180. / pi
|
|
return degrees_per_rad * self.get_angle_rad(other)
|
|
|
|
def is_parallel(self, other):
|
|
return (self.is_zero() or other.is_zero() or
|
|
self.get_angle_rad(other) in [0, pi])
|
|
|
|
def is_orthogonal(self, other):
|
|
return round(self.dot_product(other), 3) == 0
|
|
|
|
def get_projected_vector(self, other):
|
|
"""
|
|
Gets projection of vector v in b
|
|
"""
|
|
b_normalized = other.normalize()
|
|
return b_normalized.times_scalar(self.dot_product(b_normalized))
|
|
|
|
def get_orthogonal_vector(self, other):
|
|
return self.minus(self.get_projected_vector(other))
|
|
|
|
def cross_product(self, other):
|
|
[x1, y1, z1] = self.coordinates
|
|
[x2, y2, z2] = other.coordinates
|
|
x = (y1 * z2) - (y2 * z1)
|
|
y = -((x1 * z2) - (x2 * z1))
|
|
z = (x1 * y2) - (x2 * y1)
|
|
return Vector([x, y, z])
|
|
|
|
def area_parallelogram(self, other):
|
|
return self.cross_product(other).magnitude()
|
|
|
|
def area_triangle(self, other):
|
|
return self.cross_product(other).magnitude() / 2
|
|
|
|
if __name__ == '__main__':
|
|
v = Vector([8.218, -9.341])
|
|
w = Vector([-1.129, 2.111])
|
|
addition = v.plus(w)
|
|
print('addition: {}'.format(addition))
|
|
|
|
v = Vector([7.119, 8.215])
|
|
w = Vector([-8.223, 0.878])
|
|
subtraction = v.minus(w)
|
|
print('subtraction: {}'.format(subtraction))
|
|
|
|
v = Vector([1.671, -1.012, -0.318])
|
|
multiplication = v.times_scalar(7.41)
|
|
print('multiplication: {}'.format(multiplication))
|
|
|
|
# *****************
|
|
|
|
v = Vector([-0.221, 7.437])
|
|
first_magintude = v.magnitude()
|
|
print('first_magintude: {}'.format(round(first_magintude, 3)))
|
|
|
|
v = Vector([8.813, -1.331, -6.247])
|
|
second_magintude = v.magnitude()
|
|
print('second_magintude: {}'.format(round(second_magintude, 3)))
|
|
|
|
v = Vector([5.581, -2.136])
|
|
first_normalization = v.normalize()
|
|
print('first_normailization: {}'.format(first_normalization))
|
|
|
|
v = Vector([1.996, 3.108, -4.554])
|
|
second_normalization = v.normalize()
|
|
print('second_normailization: {}'.format(second_normalization))
|
|
|
|
# *****************
|
|
|
|
v = Vector([7.887, 4.138])
|
|
w = Vector([-8.802, 6.776])
|
|
dot_product = v.dot_product(w)
|
|
print('first_dot_product: {}'.format(round(dot_product, 3)))
|
|
|
|
v = Vector([-5.955, -4.904, -1.874])
|
|
w = Vector([-4.496, -8.755, 7.103])
|
|
dot_product = v.dot_product(w)
|
|
print('second_dot_product: {}'.format(round(dot_product, 3)))
|
|
|
|
# *****************
|
|
|
|
v = Vector([3.183, -7.627])
|
|
w = Vector([-2.668, 5.319])
|
|
angle_rads = v.get_angle_rad(w)
|
|
print('first_angle_rads: {}'.format(angle_rads))
|
|
|
|
v = Vector([7.35, 0.221, 5.188])
|
|
w = Vector([2.751, 8.259, 3.985])
|
|
angle_degrees = v.get_angle_deg(w)
|
|
print('first_angle_rads: {}'.format(angle_degrees))
|
|
|
|
# *****************
|
|
|
|
v = Vector([-7.579, -7.88])
|
|
w = Vector([22.737, 23.64])
|
|
is_parallel = v.is_parallel(w)
|
|
is_orthogonal = v.is_orthogonal(w)
|
|
|
|
print('1 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
|
|
|
v = Vector([-2.029, 9.97, 4.172])
|
|
w = Vector([-9.231, -6.639, -7.245])
|
|
is_parallel = v.is_parallel(w)
|
|
is_orthogonal = v.is_orthogonal(w)
|
|
|
|
print('2 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
|
|
|
v = Vector([-2.328, -7.284, -1.214])
|
|
w = Vector([-1.821, 1.072, -2.94])
|
|
is_parallel = v.is_parallel(w)
|
|
is_orthogonal = v.is_orthogonal(w)
|
|
print('3 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
|
|
|
v = Vector([2.118, 4.827])
|
|
w = Vector([0, 0])
|
|
is_parallel = v.is_parallel(w)
|
|
is_orthogonal = v.is_orthogonal(w)
|
|
|
|
print('4 parallel: {}, orthogonal: {}'.format(is_parallel, is_orthogonal))
|
|
|
|
# *****************
|
|
|
|
v = Vector([3.039, 1.879])
|
|
w = Vector([0.825, 2.036])
|
|
projected_vector = v.get_projected_vector(w)
|
|
|
|
print('projected vector is: {}'.format(projected_vector))
|
|
|
|
v = Vector([-9.88, -3.264, -8.159])
|
|
w = Vector([-2.155, -9.353, -9.473])
|
|
orthogonal_vector = v.get_orthogonal_vector(w)
|
|
|
|
print('orthogonal vector is: {}'.format(orthogonal_vector))
|
|
|
|
v = Vector([3.009, -6.172, 3.692, -2.51])
|
|
w = Vector([6.404, -9.144, 2.759, 8.718])
|
|
projected_vector = v.get_projected_vector(w)
|
|
orthogonal_vector = v.get_orthogonal_vector(w)
|
|
|
|
print('second projected vector is: {}'.format(projected_vector))
|
|
|
|
print('second orthogonal vector is: {}'.format(orthogonal_vector))
|
|
|
|
# *****************
|
|
|
|
v1 = Vector([8.462, 7.893, -8.187])
|
|
w1 = Vector([6.984, -5.975, 4.778])
|
|
|
|
v2 = Vector([-8.987, -9.838, 5.031])
|
|
w2 = Vector([-4.268, -1.861, -8.866])
|
|
|
|
v3 = Vector([1.5, 9.547, 3.691])
|
|
w3 = Vector([-6.007, 0.124, 5.772])
|
|
|
|
first_cross_product = v1.cross_product(w1)
|
|
print('cross product is: {}'.format(first_cross_product))
|
|
|
|
area_parallelogram = v2.area_parallelogram(w2)
|
|
print('area parallelogram is: {}'.format(round(area_parallelogram, 3)))
|
|
|
|
area_triangle = v3.area_triangle(w3)
|
|
print('area triangle is: {}'.format(round(area_triangle, 3)))
|