2 Vector3 is a three dimensional vector class.
4 Below are examples of Vector3 use.
6 >>> from vector3 import Vector3
10 >>> pythagoras = Vector3( 3, 4, 0 )
13 >>> pythagoras.magnitude()
15 >>> pythagoras.magnitudeSquared()
17 >>> triplePythagoras = pythagoras * 3.0
20 >>> plane = pythagoras.dropAxis()
25 from __future__ import absolute_import
27 from fabmetheus_utilities import xml_simple_writer
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__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
38 class Vector3(object):
39 'A three dimensional vector class.'
40 __slots__ = ['x', 'y', 'z']
42 def __init__(self, x=0.0, y=0.0, z=0.0):
48 'Get the magnitude of the Vector3.'
49 return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
53 def __add__(self, other):
54 'Get the sum of this Vector3 and other one.'
55 return Vector3( self.x + other.x, self.y + other.y, self.z + other.z )
58 'Get the copy of this Vector3.'
59 return Vector3( self.x, self.y, self.z )
65 def __div__(self, other):
66 'Get a new Vector3 by dividing each component of this one.'
67 return Vector3( self.x / other, self.y / other, self.z / other )
69 def __eq__(self, other):
70 'Determine whether this vector is identical to other one.'
73 if other.__class__ != self.__class__:
75 return self.x == other.x and self.y == other.y and self.z == other.z
77 def __floordiv__(self, other):
78 'Get a new Vector3 by floor dividing each component of this one.'
79 return Vector3( self.x // other, self.y // other, self.z // other )
82 'Determine whether this vector is identical to other one.'
83 return self.__repr__().__hash__()
85 def __iadd__(self, other):
86 'Add other Vector3 to this one.'
92 def __idiv__(self, other):
93 'Divide each component of this Vector3.'
99 def __ifloordiv__(self, other):
100 'Floor divide each component of this Vector3.'
106 def __imul__(self, other):
107 'Multiply each component of this Vector3.'
113 def __isub__(self, other):
114 'Subtract other Vector3 from this one.'
120 def __itruediv__(self, other):
121 'True divide each component of this Vector3.'
122 self.x = operator.truediv( self.x, other )
123 self.y = operator.truediv( self.y, other )
124 self.z = operator.truediv( self.z, other )
127 def __mul__(self, other):
128 'Get a new Vector3 by multiplying each component of this one.'
129 return Vector3( self.x * other, self.y * other, self.z * other )
131 def __ne__(self, other):
132 'Determine whether this vector is not identical to other one.'
133 return not self.__eq__(other)
136 return Vector3( - self.x, - self.y, - self.z )
138 def __nonzero__(self):
139 return self.x != 0 or self.y != 0 or self.z != 0
141 def __rdiv__(self, other):
142 'Get a new Vector3 by dividing each component of this one.'
143 return Vector3( other / self.x, other / self.y, other / self.z )
146 'Get the string representation of this Vector3.'
147 return '(%s, %s, %s)' % ( self.x, self.y, self.z )
149 def __rfloordiv__(self, other):
150 'Get a new Vector3 by floor dividing each component of this one.'
151 return Vector3( other // self.x, other // self.y, other // self.z )
153 def __rmul__(self, other):
154 'Get a new Vector3 by multiplying each component of this one.'
155 return Vector3( self.x * other, self.y * other, self.z * other )
157 def __rtruediv__(self, other):
158 'Get a new Vector3 by true dividing each component of this one.'
159 return Vector3( operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) )
161 def __sub__(self, other):
162 'Get the difference between the Vector3 and other one.'
163 return Vector3( self.x - other.x, self.y - other.y, self.z - other.z )
165 def __truediv__(self, other):
166 'Get a new Vector3 by true dividing each component of this one.'
167 return Vector3( operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) )
169 def _getAccessibleAttribute(self, attributeName):
170 'Get the accessible attribute.'
171 if attributeName in globalGetAccessibleAttributeSet:
172 return getattr(self, attributeName, None)
175 def _setAccessibleAttribute(self, attributeName, value):
176 'Set the accessible attribute.'
177 if attributeName in globalSetAccessibleAttributeSet:
178 setattr(self, attributeName, value)
180 def cross(self, other):
181 'Calculate the cross product of this vector with other one.'
182 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)
184 def distance(self, other):
185 'Get the Euclidean distance between this vector and other one.'
186 return math.sqrt( self.distanceSquared(other) )
188 def distanceSquared(self, other):
189 'Get the square of the Euclidean distance between this vector and other one.'
190 separationX = self.x - other.x
191 separationY = self.y - other.y
192 separationZ = self.z - other.z
193 return separationX * separationX + separationY * separationY + separationZ * separationZ
195 def dot(self, other):
196 'Calculate the dot product of this vector with other one.'
197 return self.x * other.x + self.y * other.y + self.z * other.z
199 def dropAxis( self, which = 2 ):
200 'Get a complex by removing one axis of the vector3.'
202 return complex( self.y, self.z )
204 return complex( self.x, self.z )
206 return complex( self.x, self.y )
208 def getFloatList(self):
209 'Get the vector as a list of floats.'
210 return [ float( self.x ), float( self.y ), float( self.z ) ]
212 def getIsDefault(self):
213 'Determine if this is the zero vector.'
220 def getNormalized(self):
221 'Get the normalized Vector3.'
222 magnitude = abs(self)
225 return self / magnitude
227 def magnitudeSquared(self):
228 'Get the square of the magnitude of the Vector3.'
229 return self.x * self.x + self.y * self.y + self.z * self.z
231 def maximize(self, other):
232 'Maximize the Vector3.'
233 self.x = max(other.x, self.x)
234 self.y = max(other.y, self.y)
235 self.z = max(other.z, self.z)
237 def minimize(self, other):
238 'Minimize the Vector3.'
239 self.x = min(other.x, self.x)
240 self.y = min(other.y, self.y)
241 self.z = min(other.z, self.z)
244 '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.'
245 magnitude = abs(self)
249 def reflect( self, normal ):
250 'Reflect the Vector3 across the normal, which is assumed to be normalized.'
251 distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z )
252 return Vector3( self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z )
254 def setToVector3(self, other):
255 'Set this Vector3 to be identical to other one.'
260 def setToXYZ( self, x, y, z ):
261 'Set the x, y, and z components of this Vector3.'
267 globalGetAccessibleAttributeSet = 'x y z'.split()
268 globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet
272 __slots__ = ['x', 'y', 'z']
277 def __eq__(self, other):
278 if isinstance(other, Vector3):
279 return self.x == other.x and \
280 self.y == other.y and \
283 assert hasattr(other, '__len__') and len(other) == 3
284 return self.x == other[0] and \
285 self.y == other[1] and \
288 def __getattr__(self, name):
290 return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \
293 raise AttributeError, name
295 def __getitem__(self, key):
296 return (self.x, self.y, self.z)[key]
299 return iter((self.x, self.y, self.z))
305 return 'Vector3(%.2f, %.2f, %.2f)' % (self.x,
309 if _enable_swizzle_set:
310 # This has detrimental performance on ordinary setattr as well
312 def __setattr__(self, name, value):
314 object.__setattr__(self, name, value)
317 l = [self.x, self.y, self.z]
318 for c, v in map(None, name, value):
319 l['xyz'.index(c)] = v
320 self.x, self.y, self.z = l
322 raise AttributeError, name
324 def __setitem__(self, key, value):
325 l = [self.x, self.y, self.z]
327 self.x, self.y, self.z = l