geom.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. import math
  2. SNAP = 0.001
  3. class Vector2(object):
  4. def __init__(self, x=0.0, y=0.0):
  5. self.x = x
  6. self.y = y
  7. class Vector3(object):
  8. def __init__(self, x=0, y=0, z=0):
  9. self.x = x
  10. self.y = y
  11. self.z = z
  12. def clone(self):
  13. return Vector3(self.x, self.y, self.z)
  14. def cross(self, v1, v2):
  15. self.x = v1.y * v2.z - v1.z * v2.y
  16. self.y = v1.z * v2.x - v1.x * v2.z
  17. self.z = v1.x * v2.y - v1.y * v2.x
  18. return self
  19. def distance(self, v):
  20. dx = self.x - v.x
  21. dy = self.y - v.y
  22. dz = self.z - v.z
  23. return math.sqrt(dx*dx + dy*dy + dz*dz)
  24. def distanceSq(self, v):
  25. dx = self.x - v.x
  26. dy = self.y - v.y
  27. dz = self.z - v.z
  28. return (dx*dx + dy*dy + dz*dz)
  29. def dot(self, v):
  30. return self.x * v.x + self.y * v.y + self.z * v.z
  31. def length(self):
  32. return math.sqrt(self.x*self.x + self.y*self.y + self.z * self.z)
  33. def lengthSq(self):
  34. return (self.x*self.x + self.y*self.y + self.z * self.z)
  35. def addScalar(self, s):
  36. self.x += s
  37. self.y += s
  38. self.z += s
  39. return self
  40. def divScalar(self, s):
  41. self.x /= s
  42. self.y /= s
  43. self.z /= s
  44. return self
  45. def multScalar(self, s):
  46. self.x *= s
  47. self.y *= s
  48. self.z *= s
  49. return self
  50. def sub(self, a, b):
  51. self.x = a.x - b.x
  52. self.y = a.y - b.y
  53. self.z = a.z - b.z
  54. return self
  55. def subScalar(self, s):
  56. self.x -= s
  57. self.y -= s
  58. self.z -= s
  59. return self
  60. def equals(self, v, e=None):
  61. e = SNAP if e is None else e
  62. if v.x > self.x-e and v.x < self.x+e and \
  63. v.y > self.y-e and v.y < self.y+e and \
  64. v.z > self.z-e and v.z < self.z+e:
  65. return True
  66. else:
  67. return False
  68. def normalize(self):
  69. len = self.length()
  70. if len > 0.0:
  71. self.multScalar(1.0 / len)
  72. return self
  73. def set(self, x, y, z):
  74. self.x = x
  75. self.y = y
  76. self.z = z
  77. def tostring(self):
  78. return "%0.3f %0.3f %0.3f" % (self.x, self.y, self.z)
  79. class Matrix2(object):
  80. """
  81. Matrix2
  82. """
  83. def __init__(self, a=1.0, b=0.0, c=0.0, d=1.0, tx=0.0, ty=0.0):
  84. self.a = a
  85. self.b = b
  86. self.c = c
  87. self.d = d
  88. self.tx = tx
  89. self.ty = ty
  90. def append(self, a, b, c, d, tx, ty):
  91. a1 = self.a
  92. b1 = self.b
  93. c1 = self.c
  94. d1 = self.d
  95. self.a = a*a1+b*c1
  96. self.b = a*b1+b*d1
  97. self.c = c*a1+d*c1
  98. self.d = c*b1+d*d1
  99. self.tx = tx*a1+ty*c1+self.tx
  100. self.ty = tx*b1+ty*d1+self.ty
  101. def append_matrix(self, m):
  102. self.append(m.a, m.b, m.c, m.d, m.tx, m.ty)
  103. def multiply_point(self, vec):
  104. return [
  105. self.a*vec[0] + self.c*vec[1] + self.tx,
  106. self.b*vec[0] + self.d*vec[1] + self.ty
  107. ]
  108. def prepend(self, a, b, c, d, tx, ty):
  109. tx1 = self.tx
  110. if (a != 1.0 or b != 0.0 or c != 0.0 or d != 1.0):
  111. a1 = self.a
  112. c1 = self.c
  113. self.a = a1*a+self.b*c
  114. self.b = a1*b+self.b*d
  115. self.c = c1*a+self.d*c
  116. self.d = c1*b+self.d*d
  117. self.tx = tx1*a+self.ty*c+tx
  118. self.ty = tx1*b+self.ty*d+ty
  119. def prepend_matrix(self, m):
  120. self.prepend(m.a, m.b, m.c, m.d, m.tx, m.ty)
  121. def rotate(self, angle):
  122. cos = math.cos(angle)
  123. sin = math.sin(angle)
  124. a1 = self.a
  125. c1 = self.c
  126. tx1 = self.tx
  127. self.a = a1*cos-self.b*sin
  128. self.b = a1*sin+self.b*cos
  129. self.c = c1*cos-self.d*sin
  130. self.d = c1*sin+self.d*cos
  131. self.tx = tx1*cos-self.ty*sin
  132. self.ty = tx1*sin+self.ty*cos
  133. def scale(self, x, y):
  134. self.a *= x;
  135. self.d *= y;
  136. self.tx *= x;
  137. self.ty *= y;
  138. def translate(self, x, y):
  139. self.tx += x;
  140. self.ty += y;
  141. class Matrix4(object):
  142. """
  143. Matrix4
  144. """
  145. def __init__(self, data=None):
  146. if not data is None and len(data) == 16:
  147. self.n11 = data[0]; self.n12 = data[1]; self.n13 = data[2]; self.n14 = data[3]
  148. self.n21 = data[4]; self.n22 = data[5]; self.n23 = data[6]; self.n24 = data[7]
  149. self.n31 = data[8]; self.n32 = data[9]; self.n33 = data[10]; self.n34 = data[11]
  150. self.n41 = data[12]; self.n42 = data[13]; self.n43 = data[14]; self.n44 = data[15]
  151. else:
  152. self.n11 = 1.0; self.n12 = 0.0; self.n13 = 0.0; self.n14 = 0.0
  153. self.n21 = 0.0; self.n22 = 1.0; self.n23 = 0.0; self.n24 = 0.0
  154. self.n31 = 0.0; self.n32 = 0.0; self.n33 = 1.0; self.n34 = 0.0
  155. self.n41 = 0.0; self.n42 = 0.0; self.n43 = 0.0; self.n44 = 1.0
  156. def clone(self):
  157. return Matrix4(self.flatten())
  158. def flatten(self):
  159. return [self.n11, self.n12, self.n13, self.n14, \
  160. self.n21, self.n22, self.n23, self.n24, \
  161. self.n31, self.n32, self.n33, self.n34, \
  162. self.n41, self.n42, self.n43, self.n44]
  163. def identity(self):
  164. self.n11 = 1.0; self.n12 = 0.0; self.n13 = 0.0; self.n14 = 0.0
  165. self.n21 = 0.0; self.n22 = 1.0; self.n23 = 0.0; self.n24 = 0.0
  166. self.n31 = 0.0; self.n32 = 0.0; self.n33 = 1.0; self.n34 = 0.0
  167. self.n41 = 0.0; self.n42 = 0.0; self.n43 = 0.0; self.n44 = 1.0
  168. return self
  169. def multiply(self, a, b):
  170. a11 = a.n11; a12 = a.n12; a13 = a.n13; a14 = a.n14
  171. a21 = a.n21; a22 = a.n22; a23 = a.n23; a24 = a.n24
  172. a31 = a.n31; a32 = a.n32; a33 = a.n33; a34 = a.n34
  173. a41 = a.n41; a42 = a.n42; a43 = a.n43; a44 = a.n44
  174. b11 = b.n11; b12 = b.n12; b13 = b.n13; b14 = b.n14
  175. b21 = b.n21; b22 = b.n22; b23 = b.n23; b24 = b.n24
  176. b31 = b.n31; b32 = b.n32; b33 = b.n33; b34 = b.n34
  177. b41 = b.n41; b42 = b.n42; b43 = b.n43; b44 = b.n44
  178. self.n11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41
  179. self.n12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42
  180. self.n13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43
  181. self.n14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44
  182. self.n21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41
  183. self.n22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42
  184. self.n23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43
  185. self.n24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44
  186. self.n31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41
  187. self.n32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42
  188. self.n33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43
  189. self.n34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44
  190. self.n41 = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41
  191. self.n42 = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42
  192. self.n43 = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43
  193. self.n44 = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44
  194. return self
  195. def multiplyVector3(self, vec):
  196. vx = vec[0]
  197. vy = vec[1]
  198. vz = vec[2]
  199. d = 1.0 / (self.n41 * vx + self.n42 * vy + self.n43 * vz + self.n44)
  200. x = (self.n11 * vx + self.n12 * vy + self.n13 * vz + self.n14) * d
  201. y = (self.n21 * vx + self.n22 * vy + self.n23 * vz + self.n24) * d
  202. z = (self.n31 * vx + self.n32 * vy + self.n33 * vz + self.n34) * d
  203. return [x, y, z]
  204. def multiplyVec3(self, vec):
  205. vx = vec.x
  206. vy = vec.y
  207. vz = vec.z
  208. d = 1.0 / (self.n41 * vx + self.n42 * vy + self.n43 * vz + self.n44)
  209. x = (self.n11 * vx + self.n12 * vy + self.n13 * vz + self.n14) * d
  210. y = (self.n21 * vx + self.n22 * vy + self.n23 * vz + self.n24) * d
  211. z = (self.n31 * vx + self.n32 * vy + self.n33 * vz + self.n34) * d
  212. return Vector3(x, y, z)
  213. def multiplyVector4(self, v):
  214. vx = v[0]; vy = v[1]; vz = v[2]; vw = v[3];
  215. x = self.n11 * vx + self.n12 * vy + self.n13 * vz + self.n14 * vw;
  216. y = self.n21 * vx + self.n22 * vy + self.n23 * vz + self.n24 * vw;
  217. z = self.n31 * vx + self.n32 * vy + self.n33 * vz + self.n34 * vw;
  218. w = self.n41 * vx + self.n42 * vy + self.n43 * vz + self.n44 * vw;
  219. return [x, y, z, w];
  220. def det(self):
  221. #( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
  222. return (
  223. self.n14 * self.n23 * self.n32 * self.n41-
  224. self.n13 * self.n24 * self.n32 * self.n41-
  225. self.n14 * self.n22 * self.n33 * self.n41+
  226. self.n12 * self.n24 * self.n33 * self.n41+
  227. self.n13 * self.n22 * self.n34 * self.n41-
  228. self.n12 * self.n23 * self.n34 * self.n41-
  229. self.n14 * self.n23 * self.n31 * self.n42+
  230. self.n13 * self.n24 * self.n31 * self.n42+
  231. self.n14 * self.n21 * self.n33 * self.n42-
  232. self.n11 * self.n24 * self.n33 * self.n42-
  233. self.n13 * self.n21 * self.n34 * self.n42+
  234. self.n11 * self.n23 * self.n34 * self.n42+
  235. self.n14 * self.n22 * self.n31 * self.n43-
  236. self.n12 * self.n24 * self.n31 * self.n43-
  237. self.n14 * self.n21 * self.n32 * self.n43+
  238. self.n11 * self.n24 * self.n32 * self.n43+
  239. self.n12 * self.n21 * self.n34 * self.n43-
  240. self.n11 * self.n22 * self.n34 * self.n43-
  241. self.n13 * self.n22 * self.n31 * self.n44+
  242. self.n12 * self.n23 * self.n31 * self.n44+
  243. self.n13 * self.n21 * self.n32 * self.n44-
  244. self.n11 * self.n23 * self.n32 * self.n44-
  245. self.n12 * self.n21 * self.n33 * self.n44+
  246. self.n11 * self.n22 * self.n33 * self.n44)
  247. def lookAt(self, eye, center, up):
  248. x = Vector3(); y = Vector3(); z = Vector3();
  249. z.sub(eye, center).normalize();
  250. x.cross(up, z).normalize();
  251. y.cross(z, x).normalize();
  252. #eye.normalize()
  253. self.n11 = x.x; self.n12 = x.y; self.n13 = x.z; self.n14 = -x.dot(eye);
  254. self.n21 = y.x; self.n22 = y.y; self.n23 = y.z; self.n24 = -y.dot(eye);
  255. self.n31 = z.x; self.n32 = z.y; self.n33 = z.z; self.n34 = -z.dot(eye);
  256. self.n41 = 0.0; self.n42 = 0.0; self.n43 = 0.0; self.n44 = 1.0;
  257. return self;
  258. def multiplyScalar(self, s):
  259. self.n11 *= s; self.n12 *= s; self.n13 *= s; self.n14 *= s;
  260. self.n21 *= s; self.n22 *= s; self.n23 *= s; self.n24 *= s;
  261. self.n31 *= s; self.n32 *= s; self.n33 *= s; self.n34 *= s;
  262. self.n41 *= s; self.n42 *= s; self.n43 *= s; self.n44 *= s;
  263. return self
  264. @classmethod
  265. def inverse(cls, m1):
  266. # TODO: make this more efficient
  267. #( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
  268. m2 = Matrix4();
  269. m2.n11 = m1.n23*m1.n34*m1.n42 - m1.n24*m1.n33*m1.n42 + m1.n24*m1.n32*m1.n43 - m1.n22*m1.n34*m1.n43 - m1.n23*m1.n32*m1.n44 + m1.n22*m1.n33*m1.n44;
  270. m2.n12 = m1.n14*m1.n33*m1.n42 - m1.n13*m1.n34*m1.n42 - m1.n14*m1.n32*m1.n43 + m1.n12*m1.n34*m1.n43 + m1.n13*m1.n32*m1.n44 - m1.n12*m1.n33*m1.n44;
  271. m2.n13 = m1.n13*m1.n24*m1.n42 - m1.n14*m1.n23*m1.n42 + m1.n14*m1.n22*m1.n43 - m1.n12*m1.n24*m1.n43 - m1.n13*m1.n22*m1.n44 + m1.n12*m1.n23*m1.n44;
  272. m2.n14 = m1.n14*m1.n23*m1.n32 - m1.n13*m1.n24*m1.n32 - m1.n14*m1.n22*m1.n33 + m1.n12*m1.n24*m1.n33 + m1.n13*m1.n22*m1.n34 - m1.n12*m1.n23*m1.n34;
  273. m2.n21 = m1.n24*m1.n33*m1.n41 - m1.n23*m1.n34*m1.n41 - m1.n24*m1.n31*m1.n43 + m1.n21*m1.n34*m1.n43 + m1.n23*m1.n31*m1.n44 - m1.n21*m1.n33*m1.n44;
  274. m2.n22 = m1.n13*m1.n34*m1.n41 - m1.n14*m1.n33*m1.n41 + m1.n14*m1.n31*m1.n43 - m1.n11*m1.n34*m1.n43 - m1.n13*m1.n31*m1.n44 + m1.n11*m1.n33*m1.n44;
  275. m2.n23 = m1.n14*m1.n23*m1.n41 - m1.n13*m1.n24*m1.n41 - m1.n14*m1.n21*m1.n43 + m1.n11*m1.n24*m1.n43 + m1.n13*m1.n21*m1.n44 - m1.n11*m1.n23*m1.n44;
  276. m2.n24 = m1.n13*m1.n24*m1.n31 - m1.n14*m1.n23*m1.n31 + m1.n14*m1.n21*m1.n33 - m1.n11*m1.n24*m1.n33 - m1.n13*m1.n21*m1.n34 + m1.n11*m1.n23*m1.n34;
  277. m2.n31 = m1.n22*m1.n34*m1.n41 - m1.n24*m1.n32*m1.n41 + m1.n24*m1.n31*m1.n42 - m1.n21*m1.n34*m1.n42 - m1.n22*m1.n31*m1.n44 + m1.n21*m1.n32*m1.n44;
  278. m2.n32 = m1.n14*m1.n32*m1.n41 - m1.n12*m1.n34*m1.n41 - m1.n14*m1.n31*m1.n42 + m1.n11*m1.n34*m1.n42 + m1.n12*m1.n31*m1.n44 - m1.n11*m1.n32*m1.n44;
  279. m2.n33 = m1.n13*m1.n24*m1.n41 - m1.n14*m1.n22*m1.n41 + m1.n14*m1.n21*m1.n42 - m1.n11*m1.n24*m1.n42 - m1.n12*m1.n21*m1.n44 + m1.n11*m1.n22*m1.n44;
  280. m2.n34 = m1.n14*m1.n22*m1.n31 - m1.n12*m1.n24*m1.n31 - m1.n14*m1.n21*m1.n32 + m1.n11*m1.n24*m1.n32 + m1.n12*m1.n21*m1.n34 - m1.n11*m1.n22*m1.n34;
  281. m2.n41 = m1.n23*m1.n32*m1.n41 - m1.n22*m1.n33*m1.n41 - m1.n23*m1.n31*m1.n42 + m1.n21*m1.n33*m1.n42 + m1.n22*m1.n31*m1.n43 - m1.n21*m1.n32*m1.n43;
  282. m2.n42 = m1.n12*m1.n33*m1.n41 - m1.n13*m1.n32*m1.n41 + m1.n13*m1.n31*m1.n42 - m1.n11*m1.n33*m1.n42 - m1.n12*m1.n31*m1.n43 + m1.n11*m1.n32*m1.n43;
  283. m2.n43 = m1.n13*m1.n22*m1.n41 - m1.n12*m1.n23*m1.n41 - m1.n13*m1.n21*m1.n42 + m1.n11*m1.n23*m1.n42 + m1.n12*m1.n21*m1.n43 - m1.n11*m1.n22*m1.n43;
  284. m2.n44 = m1.n12*m1.n23*m1.n31 - m1.n13*m1.n22*m1.n31 + m1.n13*m1.n21*m1.n32 - m1.n11*m1.n23*m1.n32 - m1.n12*m1.n21*m1.n33 + m1.n11*m1.n22*m1.n33;
  285. m2.multiplyScalar(1.0 / m1.det());
  286. return m2;
  287. @classmethod
  288. def rotationMatrix(cls, x, y, z, angle):
  289. rot = Matrix4()
  290. c = math.cos(angle)
  291. s = math.sin(angle)
  292. t = 1 - c
  293. rot.n11 = t * x * x + c
  294. rot.n12 = t * x * y - s * z
  295. rot.n13 = t * x * z + s * y
  296. rot.n21 = t * x * y + s * z
  297. rot.n22 = t * y * y + c
  298. rot.n23 = t * y * z - s * x
  299. rot.n31 = t * x * z - s * y
  300. rot.n32 = t * y * z + s * x
  301. rot.n33 = t * z * z + c
  302. return rot
  303. @classmethod
  304. def scaleMatrix(cls, x, y, z):
  305. m = Matrix4()
  306. m.n11 = x
  307. m.n22 = y
  308. m.n33 = z
  309. return m
  310. @classmethod
  311. def translationMatrix(cls, x, y, z):
  312. m = Matrix4()
  313. m.n14 = x
  314. m.n24 = y
  315. m.n34 = z
  316. return m