-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvector.py
138 lines (106 loc) · 3.24 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
import math
############################################################
#
# unused, for reference only, use mathutils.Vector instead
#
############################################################
class Vector():
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def zero(cls):
return Vector(0, 0)
@classmethod
def from_scalar(cls, s):
return Vector(s, s)
@classmethod
def angle_between(cls, v1: 'Vector', v2: 'Vector'):
angle_between = v1.angle() - v2.angle()
if angle_between > math.pi:
angle_between -= 2 * math.pi
elif angle_between <= -math.pi:
angle_between += 2 * math.pi
return angle_between
@classmethod
def is_left(cls, line_point: 'Vector', line_direction: 'Vector', point: 'Vector'):
perpendicular_vector = Vector(line_direction.y, -line_direction.x)
return point.clone().sub(line_point).dot(perpendicular_vector) < 0
def add(self, v: 'Vector'):
self.x += v.x
self.y += v.y
return self
def angle(self):
return math.atan2(self.y, self.x)
def clone(self):
return Vector(self.x, self.y)
def copy(self, v: 'Vector'):
self.x = v.x
self.y = v.y
return self
def cross(self, v: 'Vector'):
return self.x * v.y - self.y * v.x
def distance_to(self, v: 'Vector'):
return math.sqrt(self.distance_to_squared(v))
def distance_to_squared(self, v: 'Vector'):
dx = self.x - v.x
dy = self.y - v.y
return dx ** 2 + dy ** 2
def divide(self, v: 'Vector'):
if v.x == 0 or v.y == 0:
return self
self.x /= v.x
self.y /= v.y
return self
def divide_scalar(self, s):
if s == 0:
return self
return self.multiply_scalar(1 / s)
def dot(self, v: 'Vector'):
return self.x * v.x + self.y * v.y
def equals(self, v: 'Vector'):
return self.x == v.x and self.y == v.y
def length(self):
return math.sqrt(self.length_squared)
def length_squared(self):
return self.x ** 2 + self.y ** 2
def multiply(self, v: 'Vector'):
self.x *= v.x
self.y *= v.y
return self
def multiply_scalar(self, s):
self.x *= s
self.y *= s
return self
def negate(self):
return self.multiply_scalar(-1)
def normalize(self):
length = self.length()
if length == 0:
return self
return self.divide_scalar(length)
# angle in radians
def rotate_around(self, center: 'Vector', angle):
cos = math.cos(angle)
sin = math.sin(angle)
x = self.x - center.x
y = self.y - center.y
self.x = x * cos - y * sin + center.x
self.y = x * sin + y * cos + center.y
return self
def set(self, v: 'Vector'):
self.x = v.x
self.y = v.y
return self
def set_x(self, x):
self.x = x
return self
def set_y(self, y):
self.y = y
return self
def set_length(self, length):
return self.normalize().multiply_scalar(length)
def sub(self, v: 'Vector'):
self.x -= v.x
self.y -= v.y
return self