PageRenderTime 64ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/skein_engines/skeinforge-40/fabmetheus_utilities/vector3.py

https://github.com/lImbus/ReplicatorG
Python | 528 lines | 448 code | 54 blank | 26 comment | 16 complexity | 8094c56ebf3c1d0a3cb3e088807f3138 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. __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
  34. __credits__ = 'Nophead <http://forums.reprap.org/profile.php?12,28>\nArt of Illusion <http://www.artofillusion.org/>'
  35. __date__ = '$Date: 2008/21/04 $'
  36. __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
  37. class Vector3:
  38. 'A three dimensional vector class.'
  39. __slots__ = ['x', 'y', 'z']
  40. def __init__(self, x=0.0, y=0.0, z=0.0):
  41. self.x = x
  42. self.y = y
  43. self.z = z
  44. def __abs__(self):
  45. 'Get the magnitude of the Vector3.'
  46. return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
  47. magnitude = __abs__
  48. def __add__(self, other):
  49. 'Get the sum of this Vector3 and other one.'
  50. return Vector3( self.x + other.x, self.y + other.y, self.z + other.z )
  51. def __copy__(self):
  52. 'Get the copy of this Vector3.'
  53. return Vector3( self.x, self.y, self.z )
  54. __pos__ = __copy__
  55. copy = __copy__
  56. def __div__(self, other):
  57. 'Get a new Vector3 by dividing each component of this one.'
  58. return Vector3( self.x / other, self.y / other, self.z / other )
  59. def __eq__(self, other):
  60. 'Determine whether this vector is identical to other one.'
  61. if other == None:
  62. return False
  63. if other.__class__ != self.__class__:
  64. return False
  65. return self.x == other.x and self.y == other.y and self.z == other.z
  66. def __floordiv__(self, other):
  67. 'Get a new Vector3 by floor dividing each component of this one.'
  68. return Vector3( self.x // other, self.y // other, self.z // other )
  69. def _getAccessibleAttribute(self, attributeName):
  70. 'Get the accessible attribute.'
  71. if attributeName in globalGetAccessibleAttributeSet:
  72. return getattr(self, attributeName, None)
  73. return None
  74. def __hash__(self):
  75. 'Determine whether this vector is identical to other one.'
  76. return self.__repr__().__hash__()
  77. def __iadd__(self, other):
  78. 'Add other Vector3 to this one.'
  79. self.x += other.x
  80. self.y += other.y
  81. self.z += other.z
  82. return self
  83. def __idiv__(self, other):
  84. 'Divide each component of this Vector3.'
  85. self.x /= other
  86. self.y /= other
  87. self.z /= other
  88. return self
  89. def __ifloordiv__(self, other):
  90. 'Floor divide each component of this Vector3.'
  91. self.x //= other
  92. self.y //= other
  93. self.z //= other
  94. return self
  95. def __imul__(self, other):
  96. 'Multiply each component of this Vector3.'
  97. self.x *= other
  98. self.y *= other
  99. self.z *= other
  100. return self
  101. def __isub__(self, other):
  102. 'Subtract other Vector3 from this one.'
  103. self.x -= other.x
  104. self.y -= other.y
  105. self.z -= other.z
  106. return self
  107. def __itruediv__(self, other):
  108. 'True divide each component of this Vector3.'
  109. self.x = operator.truediv( self.x, other )
  110. self.y = operator.truediv( self.y, other )
  111. self.z = operator.truediv( self.z, other )
  112. return self
  113. def __mul__(self, other):
  114. 'Get a new Vector3 by multiplying each component of this one.'
  115. return Vector3( self.x * other, self.y * other, self.z * other )
  116. def __ne__(self, other):
  117. 'Determine whether this vector is not identical to other one.'
  118. return not self.__eq__(other)
  119. def __neg__(self):
  120. return Vector3( - self.x, - self.y, - self.z )
  121. def __nonzero__(self):
  122. return self.x != 0 or self.y != 0 or self.z != 0
  123. def __repr__(self):
  124. 'Get the string representation of this Vector3.'
  125. return '(%s, %s, %s)' % ( self.x, self.y, self.z )
  126. def __rdiv__(self, other):
  127. 'Get a new Vector3 by dividing each component of this one.'
  128. return Vector3( other / self.x, other / self.y, other / self.z )
  129. def __rfloordiv__(self, other):
  130. 'Get a new Vector3 by floor dividing each component of this one.'
  131. return Vector3( other // self.x, other // self.y, other // self.z )
  132. def __rmul__(self, other):
  133. 'Get a new Vector3 by multiplying each component of this one.'
  134. return Vector3( self.x * other, self.y * other, self.z * other )
  135. def __rtruediv__(self, other):
  136. 'Get a new Vector3 by true dividing each component of this one.'
  137. return Vector3( operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) )
  138. def _setAccessibleAttribute(self, attributeName, value):
  139. 'Set the accessible attribute.'
  140. if attributeName in globalSetAccessibleAttributeSet:
  141. setattr(self, attributeName, value)
  142. def __sub__(self, other):
  143. 'Get the difference between the Vector3 and other one.'
  144. return Vector3( self.x - other.x, self.y - other.y, self.z - other.z )
  145. def __truediv__(self, other):
  146. 'Get a new Vector3 by true dividing each component of this one.'
  147. return Vector3( operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) )
  148. def cross(self, other):
  149. 'Calculate the cross product of this vector with other one.'
  150. 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)
  151. def distance(self, other):
  152. 'Get the Euclidean distance between this vector and other one.'
  153. return math.sqrt( self.distanceSquared(other) )
  154. def distanceSquared(self, other):
  155. 'Get the square of the Euclidean distance between this vector and other one.'
  156. separationX = self.x - other.x
  157. separationY = self.y - other.y
  158. separationZ = self.z - other.z
  159. return separationX * separationX + separationY * separationY + separationZ * separationZ
  160. def dot(self, other):
  161. 'Calculate the dot product of this vector with other one.'
  162. return self.x * other.x + self.y * other.y + self.z * other.z
  163. def dropAxis( self, which = 2 ):
  164. 'Get a complex by removing one axis of the vector3.'
  165. if which == 0:
  166. return complex( self.y, self.z )
  167. if which == 1:
  168. return complex( self.x, self.z )
  169. if which == 2:
  170. return complex( self.x, self.y )
  171. def getFloatList(self):
  172. 'Get the vector as a list of floats.'
  173. return [ float( self.x ), float( self.y ), float( self.z ) ]
  174. def getIsDefault(self):
  175. 'Determine if this is the zero vector.'
  176. if self.x != 0.0:
  177. return False
  178. if self.y != 0.0:
  179. return False
  180. return self.z == 0.0
  181. def getNormalized(self):
  182. 'Get the normalized Vector3.'
  183. magnitude = abs(self)
  184. if magnitude == 0.0:
  185. return self.copy()
  186. return self / magnitude
  187. def magnitudeSquared(self):
  188. 'Get the square of the magnitude of the Vector3.'
  189. return self.x * self.x + self.y * self.y + self.z * self.z
  190. def maximize(self, other):
  191. 'Maximize the Vector3.'
  192. self.x =max(other.x, self.x)
  193. self.y =max(other.y, self.y)
  194. self.z =max(other.z, self.z)
  195. def minimize(self, other):
  196. 'Minimize the Vector3.'
  197. self.x =min(other.x, self.x)
  198. self.y =min(other.y, self.y)
  199. self.z =min(other.z, self.z)
  200. def normalize(self):
  201. '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.'
  202. magnitude = abs(self)
  203. if magnitude != 0.0:
  204. self /= magnitude
  205. def reflect( self, normal ):
  206. 'Reflect the Vector3 across the normal, which is assumed to be normalized.'
  207. distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z )
  208. return Vector3( self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z )
  209. def setToVector3(self, other):
  210. 'Set this Vector3 to be identical to other one.'
  211. self.x = other.x
  212. self.y = other.y
  213. self.z = other.z
  214. def setToXYZ( self, x, y, z ):
  215. 'Set the x, y, and z components of this Vector3.'
  216. self.x = x
  217. self.y = y
  218. self.z = z
  219. globalGetAccessibleAttributeSet = 'x y z'.split()
  220. globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet
  221. """
  222. class Vector3:
  223. __slots__ = ['x', 'y', 'z']
  224. def __init__(self, x, y, z):
  225. self.x = x
  226. self.y = y
  227. self.z = z
  228. def __copy__(self):
  229. return self.__class__(self.x, self.y, self.z)
  230. copy = __copy__
  231. def __repr__(self):
  232. return 'Vector3(%.2f, %.2f, %.2f)' % (self.x,
  233. self.y,
  234. self.z)
  235. def __eq__(self, other):
  236. if isinstance(other, Vector3):
  237. return self.x == other.x and \
  238. self.y == other.y and \
  239. self.z == other.z
  240. else:
  241. assert hasattr(other, '__len__') and len(other) == 3
  242. return self.x == other[0] and \
  243. self.y == other[1] and \
  244. self.z == other[2]
  245. def __ne__(self, other):
  246. return not self.__eq__(other)
  247. def __nonzero__(self):
  248. return self.x != 0 or self.y != 0 or self.z != 0
  249. def __len__(self):
  250. return 3
  251. def __getitem__(self, key):
  252. return (self.x, self.y, self.z)[key]
  253. def __setitem__(self, key, value):
  254. l = [self.x, self.y, self.z]
  255. l[key] = value
  256. self.x, self.y, self.z = l
  257. def __iter__(self):
  258. return iter((self.x, self.y, self.z))
  259. def __getattr__(self, name):
  260. try:
  261. return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \
  262. for c in name])
  263. except ValueError:
  264. raise AttributeError, name
  265. if _enable_swizzle_set:
  266. # This has detrimental performance on ordinary setattr as well
  267. # if enabled
  268. def __setattr__(self, name, value):
  269. if len(name) == 1:
  270. object.__setattr__(self, name, value)
  271. else:
  272. try:
  273. l = [self.x, self.y, self.z]
  274. for c, v in map(None, name, value):
  275. l['xyz'.index(c)] = v
  276. self.x, self.y, self.z = l
  277. except ValueError:
  278. raise AttributeError, name
  279. def __add__(self, other):
  280. if isinstance(other, Vector3):
  281. # Vector + Vector -> Vector
  282. # Vector + Point -> Point
  283. # Point + Point -> Vector
  284. if self.__class__ is other.__class__:
  285. _class = Vector3
  286. else:
  287. _class = Point3
  288. return _class(self.x + other.x,
  289. self.y + other.y,
  290. self.z + other.z)
  291. else:
  292. assert hasattr(other, '__len__') and len(other) == 3
  293. return Vector3(self.x + other[0],
  294. self.y + other[1],
  295. self.z + other[2])
  296. __radd__ = __add__
  297. def __iadd__(self, other):
  298. if isinstance(other, Vector3):
  299. self.x += other.x
  300. self.y += other.y
  301. self.z += other.z
  302. else:
  303. self.x += other[0]
  304. self.y += other[1]
  305. self.z += other[2]
  306. return self
  307. def __sub__(self, other):
  308. if isinstance(other, Vector3):
  309. # Vector - Vector -> Vector
  310. # Vector - Point -> Point
  311. # Point - Point -> Vector
  312. if self.__class__ is other.__class__:
  313. _class = Vector3
  314. else:
  315. _class = Point3
  316. return Vector3(self.x - other.x,
  317. self.y - other.y,
  318. self.z - other.z)
  319. else:
  320. assert hasattr(other, '__len__') and len(other) == 3
  321. return Vector3(self.x - other[0],
  322. self.y - other[1],
  323. self.z - other[2])
  324. def __rsub__(self, other):
  325. if isinstance(other, Vector3):
  326. return Vector3(other.x - self.x,
  327. other.y - self.y,
  328. other.z - self.z)
  329. else:
  330. assert hasattr(other, '__len__') and len(other) == 3
  331. return Vector3(other.x - self[0],
  332. other.y - self[1],
  333. other.z - self[2])
  334. def __mul__(self, other):
  335. if isinstance(other, Vector3):
  336. # TODO component-wise mul/div in-place and on Vector2; docs.
  337. if self.__class__ is Point3 or other.__class__ is Point3:
  338. _class = Point3
  339. else:
  340. _class = Vector3
  341. return _class(self.x * other.x,
  342. self.y * other.y,
  343. self.z * other.z)
  344. else:
  345. assert type(other) in (int, long, float)
  346. return Vector3(self.x * other,
  347. self.y * other,
  348. self.z * other)
  349. __rmul__ = __mul__
  350. def __imul__(self, other):
  351. assert type(other) in (int, long, float)
  352. self.x *= other
  353. self.y *= other
  354. self.z *= other
  355. return self
  356. def __div__(self, other):
  357. assert type(other) in (int, long, float)
  358. return Vector3(operator.div(self.x, other),
  359. operator.div(self.y, other),
  360. operator.div(self.z, other))
  361. def __rdiv__(self, other):
  362. assert type(other) in (int, long, float)
  363. return Vector3(operator.div(other, self.x),
  364. operator.div(other, self.y),
  365. operator.div(other, self.z))
  366. def __floordiv__(self, other):
  367. assert type(other) in (int, long, float)
  368. return Vector3(operator.floordiv(self.x, other),
  369. operator.floordiv(self.y, other),
  370. operator.floordiv(self.z, other))
  371. def __rfloordiv__(self, other):
  372. assert type(other) in (int, long, float)
  373. return Vector3(operator.floordiv(other, self.x),
  374. operator.floordiv(other, self.y),
  375. operator.floordiv(other, self.z))
  376. def __truediv__(self, other):
  377. assert type(other) in (int, long, float)
  378. return Vector3(operator.truediv(self.x, other),
  379. operator.truediv(self.y, other),
  380. operator.truediv(self.z, other))
  381. def __rtruediv__(self, other):
  382. assert type(other) in (int, long, float)
  383. return Vector3(operator.truediv(other, self.x),
  384. operator.truediv(other, self.y),
  385. operator.truediv(other, self.z))
  386. def __neg__(self):
  387. return Vector3(-self.x,
  388. -self.y,
  389. -self.z)
  390. __pos__ = __copy__
  391. def __abs__(self):
  392. return math.sqrt(self.x ** 2 + \
  393. self.y ** 2 + \
  394. self.z ** 2)
  395. magnitude = __abs__
  396. def magnitude_squared(self):
  397. return self.x ** 2 + \
  398. self.y ** 2 + \
  399. self.z ** 2
  400. def normalize(self):
  401. d = self.magnitude()
  402. if d:
  403. self.x /= d
  404. self.y /= d
  405. self.z /= d
  406. return self
  407. def normalized(self):
  408. d = self.magnitude()
  409. if d:
  410. return Vector3(self.x / d,
  411. self.y / d,
  412. self.z / d)
  413. return self.copy()
  414. def dot(self, other):
  415. assert isinstance(other, Vector3)
  416. return self.x * other.x + \
  417. self.y * other.y + \
  418. self.z * other.z
  419. def cross(self, other):
  420. assert isinstance(other, Vector3)
  421. return Vector3(self.y * other.z - self.z * other.y,
  422. -self.x * other.z + self.z * other.x,
  423. self.x * other.y - self.y * other.x)
  424. def reflect(self, normal):
  425. # assume normal is normalized
  426. assert isinstance(normal, Vector3)
  427. d = 2 * (self.x * normal.x + self.y * normal.y + self.z * normal.z)
  428. return Vector3(self.x - d * normal.x,
  429. self.y - d * normal.y,
  430. self.z - d * normal.z)
  431. """