OSDN Git Service

e67580d661891c4c9e661a9474d58f2958964f3e
[meshio/pymeshio.git] / pymeshio / common.py
1 # coding: utf-8\r
2 """\r
3 common utilities.\r
4 """\r
5 import math\r
6 import struct\r
7 \r
8 \r
9 """\r
10 common structures.\r
11 """\r
12 class Vector2(object):\r
13     """\r
14     2D coordinate for uv value\r
15     """\r
16     __slots__=['x', 'y']\r
17     def __init__(self, x=0, y=0):\r
18         self.x=x\r
19         self.y=y\r
20 \r
21     def __str__(self):\r
22         return "<%f %f>" % (self.x, self.y)\r
23 \r
24     def __getitem__(self, key):\r
25         if key==0:\r
26             return self.x\r
27         elif key==1:\r
28             return self.y\r
29         else:\r
30             assert(False)\r
31 \r
32     def to_tuple(self):\r
33         return (self.x, self.y)\r
34 \r
35 \r
36 class Vector3(object):\r
37     """\r
38     3D coordinate for vertex position, normal direction\r
39     """\r
40     __slots__=['x', 'y', 'z']\r
41     def __init__(self, x=0, y=0, z=0):\r
42         self.x=x\r
43         self.y=y\r
44         self.z=z\r
45 \r
46     def __str__(self):\r
47         return "<%f %f %f>" % (self.x, self.y, self.z)\r
48 \r
49     def __getitem__(self, key):\r
50         if key==0:\r
51             return self.x\r
52         elif key==1:\r
53             return self.y\r
54         elif key==2:\r
55             return self.z\r
56         else:\r
57             assert(False)\r
58 \r
59     def to_tuple(self):\r
60         return (self.x, self.y, self.z)\r
61 \r
62     def __add__(l, r):\r
63         return Vector3(l.x+r.x, l.y+r.y, l.z+r.z)\r
64 \r
65 \r
66 class Quaternion(object):\r
67     """\r
68     rotation representation in vmd motion\r
69     """\r
70     __slots__=['x', 'y', 'z', 'w']\r
71     def __init__(self, x=0, y=0, z=0, w=1):\r
72         self.x=x\r
73         self.y=y\r
74         self.z=z\r
75         self.w=w\r
76 \r
77     def __str__(self):\r
78         return "<%f %f %f %f>" % (self.x, self.y, self.z, self.w)\r
79 \r
80     def __mul__(self, rhs):\r
81         u=numpy.array([self.x, self.y, self.z], 'f')\r
82         v=numpy.array([rhs.x, rhs.y, rhs.z], 'f')\r
83         xyz=self.w*v+rhs.w*u+numpy.cross(u, v)\r
84         q=Quaternion(xyz[0], xyz[1], xyz[2], self.w*rhs.w-numpy.dot(u, v))\r
85         return q\r
86 \r
87     def dot(self, rhs):\r
88         return self.x*rhs.x+self.y*rhs.y+self.z*rhs.z+self.w*rhs.w\r
89 \r
90     def getMatrix(self):\r
91         sqX=self.x*self.x\r
92         sqY=self.y*self.y\r
93         sqZ=self.z*self.z\r
94         xy=self.x*self.y\r
95         xz=self.x*self.z\r
96         yz=self.y*self.z\r
97         wx=self.w*self.x\r
98         wy=self.w*self.y\r
99         wz=self.w*self.z\r
100         return numpy.array([\r
101                 # 1\r
102                 [1-2*sqY-2*sqZ, 2*xy+2*wz, 2*xz-2*wy, 0],\r
103                 # 2\r
104                 [2*xy-2*wz, 1-2*sqX-2*sqZ, 2*yz+2*wx, 0],\r
105                 # 3\r
106                 [2*xz+2*wy, 2*yz-2*wx, 1-2*sqX-2*sqY, 0],\r
107                 # 4\r
108                 [0, 0, 0, 1]],\r
109                 'f')\r
110 \r
111     def getRHMatrix(self):\r
112         x=-self.x\r
113         y=-self.y\r
114         z=self.z\r
115         w=self.w\r
116         sqX=x*x\r
117         sqY=y*y\r
118         sqZ=z*z\r
119         xy=x*y\r
120         xz=x*z\r
121         yz=y*z\r
122         wx=w*x\r
123         wy=w*y\r
124         wz=w*z\r
125         return numpy.array([\r
126                 # 1\r
127                 [1-2*sqY-2*sqZ, 2*xy+2*wz, 2*xz-2*wy, 0],\r
128                 # 2\r
129                 [2*xy-2*wz, 1-2*sqX-2*sqZ, 2*yz+2*wx, 0],\r
130                 # 3\r
131                 [2*xz+2*wy, 2*yz-2*wx, 1-2*sqX-2*sqY, 0],\r
132                 # 4\r
133                 [0, 0, 0, 1]],\r
134                 'f')\r
135 \r
136     def getRollPitchYaw(self):\r
137         m=self.getMatrix()\r
138 \r
139         roll = math.atan2(m[0, 1], m[1, 1])\r
140         pitch = math.asin(-m[2, 1])\r
141         yaw = math.atan2(m[2, 0], m[2, 2])\r
142 \r
143         if math.fabs(math.cos(pitch)) < 1.0e-6:\r
144             roll += m[0, 1] > math.pi if 0.0 else -math.pi\r
145             yaw += m[2, 0] > math.pi if 0.0 else -math.pi\r
146 \r
147         return roll, pitch, yaw\r
148 \r
149     def getSqNorm(self):\r
150         return self.x*self.x+self.y*self.y+self.z*self.z+self.w*self.w\r
151 \r
152     def getNormalized(self):\r
153         f=1.0/self.getSqNorm()\r
154         q=Quaternion(self.x*f, self.y*f, self.z*f, self.w*f)\r
155         return q\r
156 \r
157     def getRightHanded(self):\r
158         "swap y and z axis"\r
159         return Quaternion(-self.x, -self.z, -self.y, self.w)\r
160 \r
161     @staticmethod\r
162     def createFromAxisAngle(axis, rad):\r
163         q=Quaternion()\r
164         half_rad=rad/2.0\r
165         c=math.cos(half_rad)\r
166         s=math.sin(half_rad)\r
167         return Quaternion(axis[0]*s, axis[1]*s, axis[2]*s, c)\r
168 \r
169 \r
170 class RGB(object):\r
171     """\r
172     material color\r
173     """\r
174     __slots__=['r', 'g', 'b']\r
175     def __init__(self, r=0, g=0, b=0):\r
176         self.r=r\r
177         self.g=g\r
178         self.b=b\r
179 \r
180     def __getitem__(self, key):\r
181         if key==0:\r
182             return self.r\r
183         elif key==1:\r
184             return self.g\r
185         elif key==2:\r
186             return self.b\r
187         else:\r
188             assert(False)\r
189 \r
190 \r
191 class RGBA(object):\r
192     """\r
193     material color\r
194     """\r
195     __slots__=['r', 'g', 'b', 'a']\r
196     def __init__(self, r=0, g=0, b=0, a=1):\r
197         self.r=r\r
198         self.g=g\r
199         self.b=b\r
200         self.a=a\r
201 \r
202     def __getitem__(self, key):\r
203         if key==0:\r
204             return self.r\r
205         elif key==1:\r
206             return self.g\r
207         elif key==2:\r
208             return self.b\r
209         elif key==3:\r
210             return self.a\r
211         else:\r
212             assert(False)\r
213 \r
214 \r
215 """\r
216 utilities\r
217 """\r
218 def radian_to_degree(x):\r
219     """darian to deglee"""\r
220 \r
221     return x/math.pi * 180.0\r
222 \r
223 \r
224 class ParseException(Exception):\r
225     pass\r
226 \r
227 \r
228 def readall(path: str) -> bytes:\r
229     with open(path, "rb") as f:\r
230         return f.read()\r
231 \r
232 \r
233 class BinaryLoader(object):\r
234     def __init__(self, io):\r
235         self.io=io\r
236 \r
237     def unpack(self, fmt: str, size: int) -> "read value as format":\r
238         result=struct.unpack(fmt, self.io.read(size))\r
239         return result[0]\r
240 \r
241     def read_uint(self, size):\r
242         if size==1:\r
243             return self.unpack("B", size)\r
244         if size==2:\r
245             return self.unpack("H", size)\r
246         if size==4:\r
247             return self.unpack("I", size)\r
248         print("not reach here")\r
249         raise ParseException("invalid int size: "+size)\r
250 \r
251     def read_float(self):\r
252         return self.unpack("f", 4)\r
253 \r
254     def read_vector2(self):\r
255         return Vector2(\r
256                 self.read_float(), \r
257                 self.read_float()\r
258                 )\r
259 \r
260     def read_vector3(self):\r
261         return Vector3(\r
262                 self.read_float(), \r
263                 self.read_float(), \r
264                 self.read_float()\r
265                 )\r
266 \r
267     def read_rgba(self):\r
268         return RGBA(\r
269                 self.read_float(), \r
270                 self.read_float(), \r
271                 self.read_float(),\r
272                 self.read_float()\r
273                 )\r
274 \r
275     def read_rgb(self):\r
276         return RGB(\r
277                 self.read_float(), \r
278                 self.read_float(), \r
279                 self.read_float()\r
280                 )\r
281 \r
282 \r