OSDN Git Service

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