-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathposition.py
139 lines (111 loc) · 3.68 KB
/
position.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
139
import ctypes
import math
lib = ctypes.CDLL('./lib/position.so')
lib.vec3d_dot.restype = ctypes.c_double
lib.vec3d_magnitude.restype = ctypes.c_double
lib.vec3d_distance.restype = ctypes.c_double
lib.vec3d_interior_angle.restype = ctypes.c_double
lib.vec3d_angle.restype = ctypes.c_double
class Position(ctypes.Structure):
_fields_ = [('x', ctypes.c_double),
('y', ctypes.c_double),
('z', ctypes.c_double)]
properties = ('x', 'y', 'z')
@property
def pointer(self):
return ctypes.byref(self)
def __repr__(self):
return '(%g, %g, %g)' % (self.x, self.y, self.z)
def __iter__(self):
yield self.x
yield self.y
yield self.z
@property
def copy(self):
return Position(self.x, self.y, self.z)
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
z = self.z + other.z
return Position(x, y, z)
def __iadd__(self, other):
self.x += other.x
self.y += other.y
self.z += other.z
return self
def __sub__(self, other):
x = self.x - other.x
y = self.y - other.y
z = self.z - other.z
return Position(x, y, z)
def __isub__(self, other):
self.x -= other.x
self.y -= other.y
self.z -= other.z
return self
def __mul__(self, other):
if type(other) == Position:
return self.x * other.x + self.y * other.y + self.z * other.z
else:
x = self.x * other
y = self.y * other
z = self.z * other
return Position(x, y, z)
def __imul__(self, other):
x = self.x * other
y = self.y * other
z = self.z * other
return Position(x, y, z)
def __neg__(self):
x = self.x * -1
y = self.y * -1
z = self.z * -1
return Position(x, y, z)
def cross(self, other):
x = self.y * other.z - self.z * other.y
y = self.z * other.x - self.x * other.z
z = self.x * other.y - self.y * other.x
return Position(x, y, z)
@property
def magnitude(self):
return math.sqrt(self * self)
def distance(self, other):
dx = self.x - other.x
dy = self.y - other.y
dz = self.z - other.z
return math.sqrt(dx * dx + dy * dy + dz * dz)
def normalize(self):
magnitude = self.magnitude
self.x /= magnitude
self.y /= magnitude
self.z /= magnitude
@property
def normalized(self):
magnitude = self.magnitude
x = self.x / magnitude
y = self.y / magnitude
z = self.z / magnitude
return Position(x, y, z)
def interior_angle(self, other):
return math.acos((self * other) / math.sqrt((self * self) * (other * other)))
def angle(self, other, normal):
angle = self.interior_angle(other)
if (self.cross(other)) * normal < 0:
angle *= -1
return angle
def rotate_x(self, angle):
y = self.y * math.cos(angle) - self.z * math.sin(angle)
z = self.y * math.sin(angle) + self.z * math.cos(angle)
self.y, self.z = y, z
def rotate_y(self, angle):
z = self.z * math.cos(angle) - self.x * math.sin(angle)
x = self.z * math.sin(angle) + self.x * math.cos(angle)
self.z, self.x = z, x
def rotate_z(self, angle):
x = self.x * math.cos(angle) - self.y * math.sin(angle)
y = self.x * math.sin(angle) + self.y * math.cos(angle)
self.x, self.y = x, y
def rotated(self, axis, angle):
p = Position()
lib.vec3d_rotate(p.pointer, self.pointer, axis.pointer, ctypes.c_double(angle))
return p