/fabmetheus_utilities/vector3.py

https://github.com/armyofevilrobots/optimized-skeinforge · Python · 292 lines · 210 code · 57 blank · 25 comment · 20 complexity · fa78722f9f19483316a36def520192b7 MD5 · raw file

  1. """
  2. Vector3 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()
  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. from fabmetheus_utilities import xml_simple_writer
  31. import math
  32. import operator
  33. import numpy
  34. __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
  35. __credits__ = 'Nophead <http://forums.reprap.org/profile.php?12,28>\nArt of Illusion <http://www.artofillusion.org/>'
  36. __date__ = '$Date: 2008/21/04 $'
  37. __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
  38. class _Vector3:
  39. 'A three dimensional vector class.'
  40. __slots__ = ['x', 'y', 'z']
  41. def __init__(self, x=0.0, y=0.0, z=0.0):
  42. self.x = x
  43. self.y = y
  44. self.z = z
  45. def __abs__(self):
  46. 'Get the magnitude of the Vector3.'
  47. return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
  48. magnitude = __abs__
  49. def __add__(self, other):
  50. 'Get the sum of this Vector3 and other one.'
  51. return Vector3( self.x + other.x, self.y + other.y, self.z + other.z )
  52. def __copy__(self):
  53. 'Get the copy of this Vector3.'
  54. return Vector3( self.x, self.y, self.z )
  55. __pos__ = __copy__
  56. copy = __copy__
  57. def __div__(self, other):
  58. 'Get a new Vector3 by dividing each component of this one.'
  59. return Vector3( self.x / other, self.y / other, self.z / other )
  60. def __eq__(self, other):
  61. 'Determine whether this vector is identical to other one.'
  62. if other == None:
  63. return False
  64. if other.__class__ != self.__class__:
  65. return False
  66. return self.x == other.x and self.y == other.y and self.z == other.z
  67. def __floordiv__(self, other):
  68. 'Get a new Vector3 by floor dividing each component of this one.'
  69. return Vector3( self.x // other, self.y // other, self.z // other )
  70. def _getAccessibleAttribute(self, attributeName):
  71. 'Get the accessible attribute.'
  72. if attributeName in globalGetAccessibleAttributeSet:
  73. return getattr(self, attributeName, None)
  74. return None
  75. def __hash__(self):
  76. 'Determine whether this vector is identical to other one.'
  77. return self.__repr__().__hash__()
  78. def __iadd__(self, other):
  79. 'Add other Vector3 to this one.'
  80. self.x += other.x
  81. self.y += other.y
  82. self.z += other.z
  83. return self
  84. def __idiv__(self, other):
  85. 'Divide each component of this Vector3.'
  86. self.x /= other
  87. self.y /= other
  88. self.z /= other
  89. return self
  90. def __ifloordiv__(self, other):
  91. 'Floor divide each component of this Vector3.'
  92. self.x //= other
  93. self.y //= other
  94. self.z //= other
  95. return self
  96. def __imul__(self, other):
  97. 'Multiply each component of this Vector3.'
  98. self.x *= other
  99. self.y *= other
  100. self.z *= other
  101. return self
  102. def __isub__(self, other):
  103. 'Subtract other Vector3 from this one.'
  104. self.x -= other.x
  105. self.y -= other.y
  106. self.z -= other.z
  107. return self
  108. def __itruediv__(self, other):
  109. 'True divide each component of this Vector3.'
  110. self.x = operator.truediv( self.x, other )
  111. self.y = operator.truediv( self.y, other )
  112. self.z = operator.truediv( self.z, other )
  113. return self
  114. def __mul__(self, other):
  115. 'Get a new Vector3 by multiplying each component of this one.'
  116. return Vector3( self.x * other, self.y * other, self.z * other )
  117. def __ne__(self, other):
  118. 'Determine whether this vector is not identical to other one.'
  119. return not self.__eq__(other)
  120. def __neg__(self):
  121. return Vector3( - self.x, - self.y, - self.z )
  122. def __nonzero__(self):
  123. return self.x != 0 or self.y != 0 or self.z != 0
  124. def __repr__(self):
  125. 'Get the string representation of this Vector3.'
  126. return '(%s, %s, %s)' % ( self.x, self.y, self.z )
  127. def __rdiv__(self, other):
  128. 'Get a new Vector3 by dividing each component of this one.'
  129. return Vector3( other / self.x, other / self.y, other / self.z )
  130. def __rfloordiv__(self, other):
  131. 'Get a new Vector3 by floor dividing each component of this one.'
  132. return Vector3( other // self.x, other // self.y, other // self.z )
  133. def __rmul__(self, other):
  134. 'Get a new Vector3 by multiplying each component of this one.'
  135. return Vector3( self.x * other, self.y * other, self.z * other )
  136. def __rtruediv__(self, other):
  137. 'Get a new Vector3 by true dividing each component of this one.'
  138. return Vector3( operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) )
  139. def _setAccessibleAttribute(self, attributeName, value):
  140. 'Set the accessible attribute.'
  141. if attributeName in globalSetAccessibleAttributeSet:
  142. setattr(self, attributeName, value)
  143. def __sub__(self, other):
  144. 'Get the difference between the Vector3 and other one.'
  145. return Vector3( self.x - other.x, self.y - other.y, self.z - other.z )
  146. def __truediv__(self, other):
  147. 'Get a new Vector3 by true dividing each component of this one.'
  148. return Vector3( operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) )
  149. def cross(self, other):
  150. 'Calculate the cross product of this vector with other one.'
  151. 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)
  152. def distance(self, other):
  153. 'Get the Euclidean distance between this vector and other one.'
  154. return math.sqrt( self.distanceSquared(other) )
  155. def distanceSquared(self, other):
  156. 'Get the square of the Euclidean distance between this vector and other one.'
  157. separationX = self.x - other.x
  158. separationY = self.y - other.y
  159. separationZ = self.z - other.z
  160. return separationX * separationX + separationY * separationY + separationZ * separationZ
  161. def dot(self, other):
  162. 'Calculate the dot product of this vector with other one.'
  163. return self.x * other.x + self.y * other.y + self.z * other.z
  164. def dropAxis( self, which = 2 ):
  165. 'Get a complex by removing one axis of the vector3.'
  166. if which == 0:
  167. return complex( self.y, self.z )
  168. if which == 1:
  169. return complex( self.x, self.z )
  170. if which == 2:
  171. return complex( self.x, self.y )
  172. def getFloatList(self):
  173. 'Get the vector as a list of floats.'
  174. return [ float( self.x ), float( self.y ), float( self.z ) ]
  175. def getIsDefault(self):
  176. 'Determine if this is the zero vector.'
  177. if self.x != 0.0:
  178. return False
  179. if self.y != 0.0:
  180. return False
  181. return self.z == 0.0
  182. def getNormalized(self):
  183. 'Get the normalized Vector3.'
  184. magnitude = abs(self)
  185. if magnitude == 0.0:
  186. return self.copy()
  187. return self / magnitude
  188. def magnitudeSquared(self):
  189. 'Get the square of the magnitude of the Vector3.'
  190. return self.x * self.x + self.y * self.y + self.z * self.z
  191. def maximize(self, other):
  192. 'Maximize the Vector3.'
  193. self.x =max(other.x, self.x)
  194. self.y =max(other.y, self.y)
  195. self.z =max(other.z, self.z)
  196. def minimize(self, other):
  197. 'Minimize the Vector3.'
  198. self.x =min(other.x, self.x)
  199. self.y =min(other.y, self.y)
  200. self.z =min(other.z, self.z)
  201. def normalize(self):
  202. '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.'
  203. magnitude = abs(self)
  204. if magnitude != 0.0:
  205. self /= magnitude
  206. def reflect( self, normal ):
  207. 'Reflect the Vector3 across the normal, which is assumed to be normalized.'
  208. distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z )
  209. return Vector3( self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z )
  210. def setToVector3(self, other):
  211. 'Set this Vector3 to be identical to other one.'
  212. self.x = other.x
  213. self.y = other.y
  214. self.z = other.z
  215. def setToXYZ( self, x, y, z ):
  216. 'Set the x, y, and z components of this Vector3.'
  217. self.x = x
  218. self.y = y
  219. self.z = z
  220. import sys
  221. import os
  222. try:
  223. if os.environ.has_key("FABMETHEUS_USE_NUMPY"):
  224. sys.stderr.write("Trying to use numpy...")
  225. from fabmetheus_utilities.vector3numpy import Vector3
  226. else:
  227. Vector3 = _Vector3
  228. except ImportError, exc:
  229. #We are using the slow python one...
  230. sys.stderr.write("Failed to import numpy, using slow Vector3. %s\n" % exc)
  231. Vector3 = _Vector3
  232. globalGetAccessibleAttributeSet = 'x y z'.split()
  233. globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet