-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVector3D.py
More file actions
106 lines (89 loc) · 4.06 KB
/
Copy pathVector3D.py
File metadata and controls
106 lines (89 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import math
import numbers
class Vector:
""" tri dimensional vector class"""
def __init__(self,x,y,z,):
__slots__ = ('x', 'y', 'z')
self.x = x
self.y = y
self.z = z
def __str__(self):
return "Vector({},{},{})".format(self.x,self.y,self.z)
def __repr__(self):
return "Vector({},{},{})".format(self.x,self.y,self.z)
def magnitude(self,):
if self.x == 0 and self.y == 0 and self.z == 0: # If the vector is a Zero Vector, return a 0 magnitude
return 0
return (self.x**2 + self.y**2 + self.z**2)**0.5
def __add__(self,other,):
"""Adds vectors"""
return Vector(self.x+other.x, self.y+other.y, self.z+other.z)
def __neg__(self):
return Vector(-self.x,-self.y,-self.z)
def __sub__(self, other):
"""Subtracts two vectors"""
return Vector(self.x-other.x, self.y-other.y, self.z-other.z)
def __mul__(self, other):
"""Vector * other: (Scalar multiplication OR Cross Product)"""
# 1. SCALAR MULTIPLICATION (Already optimal)
if isinstance(other, numbers.Number):
return Vector(self.x * other, self.y * other, self.z * other)
# 2. CROSS PRODUCT (Caching attributes for minor boost)
# Cache self components
sx, sy, sz = self.x, self.y, self.z
# Cache other components
ox, oy, oz = other.x, other.y, other.z
return Vector(sy * oz - oy * sz, # X component
sz * ox - oz * sx, # Y component
sx * oy - ox * sy) # Z component
def __rmul__(self, other):
"""other * Vector: (Only necessary for scalar * Vector)"""
# We only need to handle scalar multiplication here (e.g., 5 * vector).
# The cross product V1 * V2 is already handled by V1.__mul__(V2).
if isinstance(other, numbers.Number):
return Vector(self.x * other, self.y * other, self.z * other)
return NotImplemented
def __truediv__(self, divider,):
"""Scalar division of a vector"""
return Vector(self.x/divider, self.y/divider, self.z/divider)
def __eq__(self,other):
"""Compares two vectors to check for equality"""
if self.x == other.x and self.y == other.y and self.z == other.z:
return True
else:
return False
def __lt__(self,other):
"""Compares the magnitude of two vectors"""
return self.magnitude() < other.magnitude()
def normalize(self):
"""Normalizes the vector"""
mg_sqrd = self.x**2 + self.y**2 +self.z**2
if mg_sqrd==0:
raise Exception("ZeroVector {} has no direction and can´t be normalized".format(self))
return self/(mg_sqrd**0.5)
def dot_product(self,other):
"""returns the dot product of itself times another"""
return self.x*other.x + self.y*other.y + self.z*other.z
def angle(self,other):
"""Returns the flat angle between two vectors"""
dp = self.dot_product(other)
mga_sq = self.x**2 + self.y**2 + self.z**2
mgb_sq = other.x**2 + other.y**2 + other.z**2
if mga_sq == 0 or mgb_sq == 0:
return 0
mg_prod = math.sqrt(mga_sq * mgb_sq)
cos_theta = dp / mg_prod
cos_theta = max(-1.0, min(1.0, cos_theta))
return math.acos(cos_theta)
def colinear(self,other):
"""Boolean test for colinearity"""
if other.normalize()==self.normalize() or other.normalize() == -self.normalize():
return True
else:
return False
def remove_negatives(self):
"""Removes every negative component and replaces it with zeroes"""
return Vector(0 if self.x<0 else self.x, 0 if self.y<0 else self.y, 0 if self.z<0 else self.z)
def truncated(self):
"""Truncates all components to an integrer"""
return Vector(int(self.x),int(self.y),int(self.z))