PageRenderTime 25ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/skeinforge/miscellaneous/nophead/vector3.py

https://github.com/clothbot/DotSkeinforge
Python | 489 lines | 413 code | 46 blank | 30 comment | 11 complexity | 07052ed4feb42d8a73440ee65be9bd2e MD5 | raw file
  1. """
  2. Vec3 is a three dimensional vector class.
  3. Below are examples of Vector3 use.
  4. >>> from vector3 import Vector3
  5. >>> origin = Vector3()
  6. >>> origin
  7. 0.0, 0.0, 0.0
  8. >>> pythagoras = Vector3( 3, 4, 0 )
  9. >>> pythagoras
  10. 3.0, 4.0, 0.0
  11. >>> pythagoras.magnitude()
  12. 5.0
  13. >>> pythagoras.magnitudeSquared()
  14. 25
  15. >>> triplePythagoras = pythagoras * 3.0
  16. >>> triplePythagoras
  17. 9.0, 12.0, 0.0
  18. >>> plane = pythagoras.dropAxis( 2 )
  19. >>> plane
  20. (3+4j)
  21. """
  22. from __future__ import absolute_import
  23. try:
  24. import psyco
  25. psyco.full()
  26. except:
  27. pass
  28. #Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
  29. import __init__
  30. import math
  31. import operator
  32. __author__ = "Enrique Perez (perez_enrique@yahoo.com)"
  33. __credits__ = 'Nophead <http://forums.reprap.org/profile.php?12,28>\nArt of Illusion <http://www.artofillusion.org/>'
  34. __date__ = "$Date: 2008/21/04 $"
  35. __license__ = "GPL 3.0"
  36. class Vector3:
  37. "A three dimensional vector class."
  38. __slots__ = ['x', 'y', 'z']
  39. def __init__( self, x = 0.0, y = 0.0, z = 0.0 ):
  40. self.x = x
  41. self.y = y
  42. self.z = z
  43. def __abs__( self ):
  44. "Get the magnitude of the Vector3."
  45. return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
  46. magnitude = __abs__
  47. def __add__( self, other ):
  48. "Get the sum of this Vector3 and other one."
  49. return Vector3( self.x + other.x, self.y + other.y, self.z + other.z )
  50. def __copy__( self ):
  51. "Get the copy of this Vector3."
  52. return Vector3( self.x, self.y, self.z )
  53. __pos__ = __copy__
  54. copy = __copy__
  55. def __div__( self, other ):
  56. "Get a new Vector3 by dividing each component of this one."
  57. return Vector3( self.x / other, self.y / other, self.z / other )
  58. def __eq__( self, other ):
  59. "Determine whether this vector is identical to other one."
  60. if other == None:
  61. return False
  62. return self.x == other.x and self.y == other.y and self.z == other.z
  63. def __floordiv__( self, other ):
  64. "Get a new Vector3 by floor dividing each component of this one."
  65. return Vector3( self.x // other, self.y // other, self.z // other )
  66. def __hash__( self ):
  67. "Determine whether this vector is identical to other one."
  68. return self.__repr__().__hash__()
  69. def __iadd__( self, other ):
  70. "Add other Vector3 to this one."
  71. self.x += other.x
  72. self.y += other.y
  73. self.z += other.z
  74. return self
  75. def __idiv__( self, other ):
  76. "Divide each component of this Vector3."
  77. self.x /= other
  78. self.y /= other
  79. self.z /= other
  80. return self
  81. def __ifloordiv__( self, other ):
  82. "Floor divide each component of this Vector3."
  83. self.x //= other
  84. self.y //= other
  85. self.z //= other
  86. return self
  87. def __imul__( self, other ):
  88. "Multiply each component of this Vector3."
  89. self.x *= other
  90. self.y *= other
  91. self.z *= other
  92. return self
  93. def __isub__( self, other ):
  94. "Subtract other Vector3 from this one."
  95. self.x -= other.x
  96. self.y -= other.y
  97. self.z -= other.z
  98. return self
  99. def __itruediv__( self, other ):
  100. "True divide each component of this Vector3."
  101. self.x = operator.truediv( self.x, other )
  102. self.y = operator.truediv( self.y, other )
  103. self.z = operator.truediv( self.z, other )
  104. return self
  105. def __mul__( self, other ):
  106. "Get a new Vector3 by multiplying each component of this one."
  107. return Vector3( self.x * other, self.y * other, self.z * other )
  108. def __ne__( self, other ):
  109. "Determine whether this vector is not identical to other one."
  110. return not self.__eq__( other )
  111. def __neg__( self ):
  112. return Vector3( - self.x, - self.y, - self.z )
  113. def __nonzero__( self ):
  114. return self.x != 0 or self.y != 0 or self.z != 0
  115. def __repr__( self ):
  116. "Get the string representation of this Vector3."
  117. return '%s, %s, %s' % ( self.x, self.y, self.z )
  118. def __rdiv__( self, other ):
  119. "Get a new Vector3 by dividing each component of this one."
  120. return Vector3( other / self.x, other / self.y, other / self.z )
  121. def __rfloordiv__( self, other ):
  122. "Get a new Vector3 by floor dividing each component of this one."
  123. return Vector3( other // self.x, other // self.y, other // self.z )
  124. def __rmul__( self, other ):
  125. "Get a new Vector3 by multiplying each component of this one."
  126. return Vector3( self.x * other, self.y * other, self.z * other )
  127. def __rtruediv__( self, other ):
  128. "Get a new Vector3 by true dividing each component of this one."
  129. return Vector3( operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) )
  130. def __sub__( self, other ):
  131. "Get the difference between the Vector3 and other one."
  132. return Vector3( self.x - other.x, self.y - other.y, self.z - other.z )
  133. def __truediv__( self, other ):
  134. "Get a new Vector3 by true dividing each component of this one."
  135. return Vector3( operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) )
  136. def cross( self, other ):
  137. "Calculate the cross product of this vector with other one."
  138. return Vector3( self.y * other.z - self.z * other.y, - self.x * other.z + self.z * other.x, self.x * other.y - self.y * other.x )
  139. def distance( self, other ):
  140. "Get the Euclidean distance between this vector and other one."
  141. return math.sqrt( self.distanceSquared( other ) )
  142. def distanceSquared( self, other ):
  143. "Get the square of the Euclidean distance between this vector and other one."
  144. separationX = self.x - other.x
  145. separationY = self.y - other.y
  146. separationZ = self.z - other.z
  147. return separationX * separationX + separationY * separationY + separationZ * separationZ
  148. def dot( self, other ):
  149. "Calculate the dot product of this vector with other one."
  150. return self.x * other.x + self.y * other.y + self.z * other.z
  151. def dropAxis( self, which ):
  152. """Get a complex by removing one axis of this one.
  153. Keyword arguments:
  154. which -- the axis to drop (0=X, 1=Y, 2=Z)"""
  155. if which == 0:
  156. return complex( self.y, self.z )
  157. if which == 1:
  158. return complex( self.x, self.z )
  159. if which == 2:
  160. return complex( self.x, self.y )
  161. def getNormalized( self, other ):
  162. "Get the normalized Vector3."
  163. magnitude = abs( self )
  164. if magnitude == 0.0:
  165. return self.copy()
  166. return self / magnitude
  167. def magnitudeSquared( self ):
  168. "Get the square of the magnitude of the Vector3."
  169. return self.x * self.x + self.y * self.y + self.z * self.z
  170. def normalize( self ):
  171. "Scale each component of this Vector3 so that it has a magnitude of 1. If this Vector3 has a magnitude of 0, this method has no effect."
  172. magnitude = abs( self )
  173. if magnitude != 0.0:
  174. self /= magnitude
  175. def reflect( self, normal ):
  176. "Reflect the Vector3 across the normal, which is assumed to be normalized."
  177. distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z )
  178. return Vector3( self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z )
  179. def setToVec3( self, other ):
  180. "Set this Vector3 to be identical to other one."
  181. self.x = other.x
  182. self.y = other.y
  183. self.z = other.z
  184. def setToXYZ( self, x, y, z ):
  185. "Set the x, y, and z components of this Vector3."
  186. self.x = x
  187. self.y = y
  188. self.z = z
  189. """
  190. class Vector3:
  191. __slots__ = ['x', 'y', 'z']
  192. def __init__(self, x, y, z):
  193. self.x = x
  194. self.y = y
  195. self.z = z
  196. def __copy__(self):
  197. return self.__class__(self.x, self.y, self.z)
  198. copy = __copy__
  199. def __repr__(self):
  200. return 'Vector3(%.2f, %.2f, %.2f)' % (self.x,
  201. self.y,
  202. self.z)
  203. def __eq__(self, other):
  204. if isinstance(other, Vector3):
  205. return self.x == other.x and \
  206. self.y == other.y and \
  207. self.z == other.z
  208. else:
  209. assert hasattr(other, '__len__') and len(other) == 3
  210. return self.x == other[0] and \
  211. self.y == other[1] and \
  212. self.z == other[2]
  213. def __ne__(self, other):
  214. return not self.__eq__(other)
  215. def __nonzero__(self):
  216. return self.x != 0 or self.y != 0 or self.z != 0
  217. def __len__(self):
  218. return 3
  219. def __getitem__(self, key):
  220. return (self.x, self.y, self.z)[key]
  221. def __setitem__(self, key, value):
  222. l = [self.x, self.y, self.z]
  223. l[key] = value
  224. self.x, self.y, self.z = l
  225. def __iter__(self):
  226. return iter((self.x, self.y, self.z))
  227. def __getattr__(self, name):
  228. try:
  229. return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \
  230. for c in name])
  231. except ValueError:
  232. raise AttributeError, name
  233. if _enable_swizzle_set:
  234. # This has detrimental performance on ordinary setattr as well
  235. # if enabled
  236. def __setattr__(self, name, value):
  237. if len(name) == 1:
  238. object.__setattr__(self, name, value)
  239. else:
  240. try:
  241. l = [self.x, self.y, self.z]
  242. for c, v in map(None, name, value):
  243. l['xyz'.index(c)] = v
  244. self.x, self.y, self.z = l
  245. except ValueError:
  246. raise AttributeError, name
  247. def __add__(self, other):
  248. if isinstance(other, Vector3):
  249. # Vector + Vector -> Vector
  250. # Vector + Point -> Point
  251. # Point + Point -> Vector
  252. if self.__class__ is other.__class__:
  253. _class = Vector3
  254. else:
  255. _class = Point3
  256. return _class(self.x + other.x,
  257. self.y + other.y,
  258. self.z + other.z)
  259. else:
  260. assert hasattr(other, '__len__') and len(other) == 3
  261. return Vector3(self.x + other[0],
  262. self.y + other[1],
  263. self.z + other[2])
  264. __radd__ = __add__
  265. def __iadd__(self, other):
  266. if isinstance(other, Vector3):
  267. self.x += other.x
  268. self.y += other.y
  269. self.z += other.z
  270. else:
  271. self.x += other[0]
  272. self.y += other[1]
  273. self.z += other[2]
  274. return self
  275. def __sub__(self, other):
  276. if isinstance(other, Vector3):
  277. # Vector - Vector -> Vector
  278. # Vector - Point -> Point
  279. # Point - Point -> Vector
  280. if self.__class__ is other.__class__:
  281. _class = Vector3
  282. else:
  283. _class = Point3
  284. return Vector3(self.x - other.x,
  285. self.y - other.y,
  286. self.z - other.z)
  287. else:
  288. assert hasattr(other, '__len__') and len(other) == 3
  289. return Vector3(self.x - other[0],
  290. self.y - other[1],
  291. self.z - other[2])
  292. def __rsub__(self, other):
  293. if isinstance(other, Vector3):
  294. return Vector3(other.x - self.x,
  295. other.y - self.y,
  296. other.z - self.z)
  297. else:
  298. assert hasattr(other, '__len__') and len(other) == 3
  299. return Vector3(other.x - self[0],
  300. other.y - self[1],
  301. other.z - self[2])
  302. def __mul__(self, other):
  303. if isinstance(other, Vector3):
  304. # TODO component-wise mul/div in-place and on Vector2; docs.
  305. if self.__class__ is Point3 or other.__class__ is Point3:
  306. _class = Point3
  307. else:
  308. _class = Vector3
  309. return _class(self.x * other.x,
  310. self.y * other.y,
  311. self.z * other.z)
  312. else:
  313. assert type(other) in (int, long, float)
  314. return Vector3(self.x * other,
  315. self.y * other,
  316. self.z * other)
  317. __rmul__ = __mul__
  318. def __imul__(self, other):
  319. assert type(other) in (int, long, float)
  320. self.x *= other
  321. self.y *= other
  322. self.z *= other
  323. return self
  324. def __div__(self, other):
  325. assert type(other) in (int, long, float)
  326. return Vector3(operator.div(self.x, other),
  327. operator.div(self.y, other),
  328. operator.div(self.z, other))
  329. def __rdiv__(self, other):
  330. assert type(other) in (int, long, float)
  331. return Vector3(operator.div(other, self.x),
  332. operator.div(other, self.y),
  333. operator.div(other, self.z))
  334. def __floordiv__(self, other):
  335. assert type(other) in (int, long, float)
  336. return Vector3(operator.floordiv(self.x, other),
  337. operator.floordiv(self.y, other),
  338. operator.floordiv(self.z, other))
  339. def __rfloordiv__(self, other):
  340. assert type(other) in (int, long, float)
  341. return Vector3(operator.floordiv(other, self.x),
  342. operator.floordiv(other, self.y),
  343. operator.floordiv(other, self.z))
  344. def __truediv__(self, other):
  345. assert type(other) in (int, long, float)
  346. return Vector3(operator.truediv(self.x, other),
  347. operator.truediv(self.y, other),
  348. operator.truediv(self.z, other))
  349. def __rtruediv__(self, other):
  350. assert type(other) in (int, long, float)
  351. return Vector3(operator.truediv(other, self.x),
  352. operator.truediv(other, self.y),
  353. operator.truediv(other, self.z))
  354. def __neg__(self):
  355. return Vector3(-self.x,
  356. -self.y,
  357. -self.z)
  358. __pos__ = __copy__
  359. def __abs__(self):
  360. return math.sqrt(self.x ** 2 + \
  361. self.y ** 2 + \
  362. self.z ** 2)
  363. magnitude = __abs__
  364. def magnitude_squared(self):
  365. return self.x ** 2 + \
  366. self.y ** 2 + \
  367. self.z ** 2
  368. def normalize(self):
  369. d = self.magnitude()
  370. if d:
  371. self.x /= d
  372. self.y /= d
  373. self.z /= d
  374. return self
  375. def normalized(self):
  376. d = self.magnitude()
  377. if d:
  378. return Vector3(self.x / d,
  379. self.y / d,
  380. self.z / d)
  381. return self.copy()
  382. def dot(self, other):
  383. assert isinstance(other, Vector3)
  384. return self.x * other.x + \
  385. self.y * other.y + \
  386. self.z * other.z
  387. def cross(self, other):
  388. assert isinstance(other, Vector3)
  389. return Vector3(self.y * other.z - self.z * other.y,
  390. -self.x * other.z + self.z * other.x,
  391. self.x * other.y - self.y * other.x)
  392. def reflect(self, normal):
  393. # assume normal is normalized
  394. assert isinstance(normal, Vector3)
  395. d = 2 * (self.x * normal.x + self.y * normal.y + self.z * normal.z)
  396. return Vector3(self.x - d * normal.x,
  397. self.y - d * normal.y,
  398. self.z - d * normal.z)
  399. """