-
Notifications
You must be signed in to change notification settings - Fork 0
/
vector.py
138 lines (103 loc) · 4.04 KB
/
vector.py
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Hakan Alp
from math import acos
from numpy import ndarray
class HCoord:
def __init__(self, x, y, z, w):
self.x = x
self.y = y
self.z = z
self.w = w
def asList(self) -> "list[float]":
return [self.x, self.y, self.z, self.w]
def clone(self) -> "HCoord":
return HCoord(self)
def asVertex3f(self, mat: "ndarray"):
v = mat.dot(self.asList())
return [v[0], v[1], v[2]]
def normalize(self) -> "HCoord":
l = self.len()
if l == 0:
return HCoord(0, 0, 0, self.w)
return HCoord(self.x / l, self.y / l, self.z / l, self.w / l)
def sqrlen(self) -> "float":
return self.x ** 2 + self.y ** 2 + self.z ** 2
def len(self) -> "float":
return (self.sqrlen()) ** 0.5
def dot(self, v2) -> "float":
return self.x * v2.x + self.y * v2.y + self.z * v2.z + self.w * v2.w
def __str__(self) -> "str":
return "[{:.2f}, {:.2f}, {:.2f}, {:.2f}]".format(self.x, self.y, self.z, self.w)
def __add__(self, v2) -> "HCoord":
return HCoord(self.x + v2.x, self.y + v2.y, self.z + v2.z, self.w + v2.w)
def __sub__(self, v2) -> "HCoord":
return self + (-v2)
def __neg__(self) -> "HCoord":
return HCoord(-self.x, -self.y, -self.z, -self.w)
def __mul__(self, i2): # TODO refactor this in feature.
if isinstance(i2, self.__class__): # dot product
return self.dot(i2)
elif isinstance(i2, int) or isinstance(i2, float): # scalar multiplication
return HCoord(self.x * i2, self.y * i2, self.z * i2, self.w)
else: # Matrix * Vector
return self * i2
def __rmul__(self, i2) -> "HCoord":
if isinstance(i2, self.__class__): # dot product
return self.dot(i2)
elif isinstance(i2, int) or isinstance(i2, float): # scalar multiplication
return HCoord(self.x * i2, self.y * i2, self.z * i2, self.w * i2)
def crossProduct(self, v2) -> "HCoord":
return HCoord(
self.y * v2.z - self.z * v2.y,
self.z * v2.x - self.x * v2.z,
self.x * v2.y - self.y * v2.x,
self.w,
)
def divide_scalar(self, scalar) -> "HCoord":
return self.__class__(
self.x / scalar, self.y / scalar, self.z / scalar, self.w / scalar
)
def projectionVec3(self, v2) -> "HCoord":
return self.projectionVec3(self, v2)
def angleBetweenVectors(self, v2) -> "float":
return self.angleBetweenVectors(self, v2)
def middle_point(self, v2) -> "HCoord ":
return self.middle_point(self, v2)
@staticmethod
def projectionVec3(v1, v2) -> "HCoord":
return v1 * ((v1 * v2) / (v1.len() ** 2))
@staticmethod
def angleBetweenVectors(v1, v2):
return acos((v1 * v2) / (v1.len() * v2.len()))
@staticmethod
def middle_point(v1, v2):
return Point3f((v1.x + v2.x) / 2, (v1.y + v2.y) / 2, (v1.z + v2.z) / 2)
@staticmethod
def average_point(*args) -> "Point3f":
x, y, z = 0, 0, 0
index = 0
for i in args:
if i == None:
continue
x += i.x
y += i.y
z += i.z
index += 1
return Point3f(x / index, y / index, z / index)
@staticmethod
def get_normal_vector(p1: "Point3f", p2: "Point3f", p3: "Point3f") -> "Vector3f":
m1 = p2 - p1
m2 = p3 - p2
return m1.normalize().crossProduct(m2.normalize()).normalize()
@staticmethod
def get_length_between_points(p1, p2) -> "float":
return ((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2 + (p2.z - p1.z) ** 2) ** 0.5
class Vector3f(HCoord):
def __init__(self, x, y, z):
HCoord.__init__(self, x, y, z, 0.0)
class Point3f(HCoord):
def __init__(self, x, y, z):
HCoord.__init__(self, x, y, z, 1.0)
def __sub__(self, other):
return Vector3f(self.x - other.x, self.y - other.y, self.z - other.z)
def __add__(self, other):
return Point3f(self.x + other.x, self.y + other.y, self.z + other.z)