chiark / gitweb /
7d46075fbad09360c146434669fb9fa8e8f582a6
[cura.git] / Cura / fabmetheus_utilities / vector3index.py
1 """
2 Vector3 is a three dimensional vector class.
3
4 Below are examples of Vector3 use.
5
6 >>> from vector3 import Vector3
7 >>> origin = Vector3()
8 >>> origin
9 0.0, 0.0, 0.0
10 >>> pythagoras = Vector3( 3, 4, 0 )
11 >>> pythagoras
12 3.0, 4.0, 0.0
13 >>> pythagoras.magnitude()
14 5.0
15 >>> pythagoras.magnitudeSquared()
16 25
17 >>> triplePythagoras = pythagoras * 3.0
18 >>> triplePythagoras
19 9.0, 12.0, 0.0
20 >>> plane = pythagoras.dropAxis()
21 >>> plane
22 (3+4j)
23 """
24
25 from __future__ import absolute_import
26 try:
27         import psyco
28         psyco.full()
29 except:
30         pass
31 #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.
32 import __init__
33
34 from fabmetheus_utilities import xml_simple_writer
35 import math
36 import operator
37
38
39 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
40 __credits__ = 'Nophead <http://forums.reprap.org/profile.php?12,28>\nArt of Illusion <http://www.artofillusion.org/>'
41 __date__ = '$Date: 2008/21/04 $'
42 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
43
44
45 class Vector3Index:
46         'A three dimensional vector index class.'
47         __slots__ = ['index', 'x', 'y', 'z']
48
49         def __init__( self, index, x = 0.0, y = 0.0, z = 0.0 ):
50                 self.index = index
51                 self.x = x
52                 self.y = y
53                 self.z = z
54
55         def __abs__(self):
56                 'Get the magnitude of the Vector3.'
57                 return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
58
59         magnitude = __abs__
60
61         def __add__(self, other):
62                 'Get the sum of this Vector3 and other one.'
63                 return Vector3Index( self.index, self.x + other.x, self.y + other.y, self.z + other.z )
64
65         def __copy__(self):
66                 'Get the copy of this Vector3.'
67                 return Vector3Index( self.index, self.x, self.y, self.z )
68
69         __pos__ = __copy__
70
71         copy = __copy__
72
73         def __div__(self, other):
74                 'Get a new Vector3 by dividing each component of this one.'
75                 return Vector3Index( self.index, self.x / other, self.y / other, self.z / other )
76
77         def __eq__(self, other):
78                 'Determine whether this vector is identical to other one.'
79                 if other == None:
80                         return False
81                 if other.__class__ != self.__class__:
82                         return False
83                 return self.x == other.x and self.y == other.y and self.z == other.z
84
85         def __floordiv__(self, other):
86                 'Get a new Vector3 by floor dividing each component of this one.'
87                 return Vector3Index( self.index, self.x // other, self.y // other, self.z // other )
88
89         def __hash__(self):
90                 'Determine whether this vector is identical to other one.'
91                 return self.__repr__().__hash__()
92
93         def __iadd__(self, other):
94                 'Add other Vector3 to this one.'
95                 self.x += other.x
96                 self.y += other.y
97                 self.z += other.z
98                 return self
99
100         def __idiv__(self, other):
101                 'Divide each component of this Vector3.'
102                 self.x /= other
103                 self.y /= other
104                 self.z /= other
105                 return self
106
107         def __ifloordiv__(self, other):
108                 'Floor divide each component of this Vector3.'
109                 self.x //= other
110                 self.y //= other
111                 self.z //= other
112                 return self
113
114         def __imul__(self, other):
115                 'Multiply each component of this Vector3.'
116                 self.x *= other
117                 self.y *= other
118                 self.z *= other
119                 return self
120
121         def __isub__(self, other):
122                 'Subtract other Vector3 from this one.'
123                 self.x -= other.x
124                 self.y -= other.y
125                 self.z -= other.z
126                 return self
127
128         def __itruediv__(self, other):
129                 'True divide each component of this Vector3.'
130                 self.x = operator.truediv( self.x, other )
131                 self.y = operator.truediv( self.y, other )
132                 self.z = operator.truediv( self.z, other )
133                 return self
134
135         def __mul__(self, other):
136                 'Get a new Vector3 by multiplying each component of this one.'
137                 return Vector3Index( self.index, self.x * other, self.y * other, self.z * other )
138
139         def __ne__(self, other):
140                 'Determine whether this vector is not identical to other one.'
141                 return not self.__eq__(other)
142
143         def __neg__(self):
144                 return Vector3Index( self.index, - self.x, - self.y, - self.z )
145
146         def __nonzero__(self):
147                 return self.x != 0 or self.y != 0 or self.z != 0
148
149         def __rdiv__(self, other):
150                 'Get a new Vector3 by dividing each component of this one.'
151                 return Vector3Index( self.index, other / self.x, other / self.y, other / self.z )
152
153         def __repr__(self):
154                 'Get the string representation of this Vector3 index.'
155                 return '(%s, %s, %s, %s)' % (self.index, self.x, self.y, self.z)
156
157         def __rfloordiv__(self, other):
158                 'Get a new Vector3 by floor dividing each component of this one.'
159                 return Vector3Index( self.index, other // self.x, other // self.y, other // self.z )
160
161         def __rmul__(self, other):
162                 'Get a new Vector3 by multiplying each component of this one.'
163                 return Vector3Index( self.index, self.x * other, self.y * other, self.z * other )
164
165         def __rtruediv__(self, other):
166                 'Get a new Vector3 by true dividing each component of this one.'
167                 return Vector3Index( self.index, operator.truediv( other , self.x ), operator.truediv( other, self.y ), operator.truediv( other, self.z ) )
168
169         def __sub__(self, other):
170                 'Get the difference between the Vector3 and other one.'
171                 return Vector3Index( self.index, self.x - other.x, self.y - other.y, self.z - other.z )
172
173         def __truediv__(self, other):
174                 'Get a new Vector3 by true dividing each component of this one.'
175                 return Vector3Index( self.index, operator.truediv( self.x, other ), operator.truediv( self.y, other ), operator.truediv( self.z, other ) )
176
177         def _getAccessibleAttribute(self, attributeName):
178                 'Get the accessible attribute.'
179                 global globalGetAccessibleAttributeSet
180                 if attributeName in globalGetAccessibleAttributeSet:
181                         return getattr(self, attributeName, None)
182                 return None
183
184         def _setAccessibleAttribute(self, attributeName, value):
185                 'Set the accessible attribute.'
186                 if attributeName in globalSetAccessibleAttributeSet:
187                         setattr(self, attributeName, value)
188
189         def cross(self, other):
190                 'Calculate the cross product of this vector with other one.'
191                 return Vector3Index( self.index, self.y * other.z - self.z * other.y, - self.x * other.z + self.z * other.x, self.x * other.y - self.y * other.x )
192
193         def distance(self, other):
194                 'Get the Euclidean distance between this vector and other one.'
195                 return math.sqrt( self.distanceSquared(other) )
196
197         def distanceSquared(self, other):
198                 'Get the square of the Euclidean distance between this vector and other one.'
199                 separationX = self.x - other.x
200                 separationY = self.y - other.y
201                 separationZ = self.z - other.z
202                 return separationX * separationX + separationY * separationY + separationZ * separationZ
203
204         def dot(self, other):
205                 'Calculate the dot product of this vector with other one.'
206                 return self.x * other.x + self.y * other.y + self.z * other.z
207
208         def dropAxis( self, which = 2 ):
209                 'Get a complex by removing one axis of the vector3.'
210                 if which == 0:
211                         return complex( self.y, self.z )
212                 if which == 1:
213                         return complex( self.x, self.z )
214                 if which == 2:
215                         return complex( self.x, self.y )
216
217         def getFloatList(self):
218                 'Get the vector as a list of floats.'
219                 return [ float( self.x ), float( self.y ), float( self.z ) ]
220
221         def getIsDefault(self):
222                 'Determine if this is the zero vector.'
223                 if self.x != 0.0:
224                         return False
225                 if self.y != 0.0:
226                         return False
227                 return self.z == 0.0
228
229         def getNormalized(self):
230                 'Get the normalized Vector3.'
231                 magnitude = abs(self)
232                 if magnitude == 0.0:
233                         return self.copy()
234                 return self / magnitude
235
236         def magnitudeSquared(self):
237                 'Get the square of the magnitude of the Vector3.'
238                 return self.x * self.x + self.y * self.y + self.z * self.z
239
240         def maximize(self, other):
241                 'Maximize the Vector3.'
242                 self.x = max(other.x, self.x)
243                 self.y = max(other.y, self.y)
244                 self.z = max(other.z, self.z)
245
246         def minimize(self, other):
247                 'Minimize the Vector3.'
248                 self.x = min(other.x, self.x)
249                 self.y = min(other.y, self.y)
250                 self.z = min(other.z, self.z)
251
252         def normalize(self):
253                 '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.'
254                 magnitude = abs(self)
255                 if magnitude != 0.0:
256                         self /= magnitude
257
258         def reflect( self, normal ):
259                 'Reflect the Vector3 across the normal, which is assumed to be normalized.'
260                 distance = 2 * ( self.x * normal.x + self.y * normal.y + self.z * normal.z )
261                 return Vector3Index( self.index, self.x - distance * normal.x, self.y - distance * normal.y, self.z - distance * normal.z )
262
263         def setToVector3(self, other):
264                 'Set this Vector3 to be identical to other one.'
265                 self.x = other.x
266                 self.y = other.y
267                 self.z = other.z
268
269         def setToXYZ( self, x, y, z ):
270                 'Set the x, y, and z components of this Vector3.'
271                 self.x = x
272                 self.y = y
273                 self.z = z
274
275
276 globalGetAccessibleAttributeSet = 'x y z'.split()
277 globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet