chiark / gitweb /
Add back the ultimaker platform, and made the platform mesh simpler.
[cura.git] / Cura / slice / cura_sf / fabmetheus_utilities / vector3.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
27 from fabmetheus_utilities import xml_simple_writer
28 import math
29 import operator
30
31
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'
36
37
38 class Vector3(object):
39         'A three dimensional vector class.'
40         __slots__ = ['x', 'y', 'z']
41
42         def __init__(self, x=0.0, y=0.0, z=0.0):
43                 self.x = x
44                 self.y = y
45                 self.z = z
46
47         def __abs__(self):
48                 'Get the magnitude of the Vector3.'
49                 return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
50
51         magnitude = __abs__
52
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 )
56
57         def __copy__(self):
58                 'Get the copy of this Vector3.'
59                 return Vector3( self.x, self.y, self.z )
60
61         __pos__ = __copy__
62
63         copy = __copy__
64
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 )
68
69         def __eq__(self, other):
70                 'Determine whether this vector is identical to other one.'
71                 if other == None:
72                         return False
73                 if other.__class__ != self.__class__:
74                         return False
75                 return self.x == other.x and self.y == other.y and self.z == other.z
76
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 )
80
81         def __hash__(self):
82                 'Determine whether this vector is identical to other one.'
83                 return self.__repr__().__hash__()
84
85         def __iadd__(self, other):
86                 'Add other Vector3 to this one.'
87                 self.x += other.x
88                 self.y += other.y
89                 self.z += other.z
90                 return self
91
92         def __idiv__(self, other):
93                 'Divide each component of this Vector3.'
94                 self.x /= other
95                 self.y /= other
96                 self.z /= other
97                 return self
98
99         def __ifloordiv__(self, other):
100                 'Floor divide each component of this Vector3.'
101                 self.x //= other
102                 self.y //= other
103                 self.z //= other
104                 return self
105
106         def __imul__(self, other):
107                 'Multiply each component of this Vector3.'
108                 self.x *= other
109                 self.y *= other
110                 self.z *= other
111                 return self
112
113         def __isub__(self, other):
114                 'Subtract other Vector3 from this one.'
115                 self.x -= other.x
116                 self.y -= other.y
117                 self.z -= other.z
118                 return self
119
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 )
125                 return self
126
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 )
130
131         def __ne__(self, other):
132                 'Determine whether this vector is not identical to other one.'
133                 return not self.__eq__(other)
134
135         def __neg__(self):
136                 return Vector3( - self.x, - self.y, - self.z )
137
138         def __nonzero__(self):
139                 return self.x != 0 or self.y != 0 or self.z != 0
140
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 )
144
145         def __repr__(self):
146                 'Get the string representation of this Vector3.'
147                 return '(%s, %s, %s)' % ( self.x, self.y, self.z )
148
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 )
152
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 )
156
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 ) )
160
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 )
164
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 ) )
168
169         def _getAccessibleAttribute(self, attributeName):
170                 'Get the accessible attribute.'
171                 if attributeName in globalGetAccessibleAttributeSet:
172                         return getattr(self, attributeName, None)
173                 return None
174
175         def _setAccessibleAttribute(self, attributeName, value):
176                 'Set the accessible attribute.'
177                 if attributeName in globalSetAccessibleAttributeSet:
178                         setattr(self, attributeName, value)
179
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)
183
184         def distance(self, other):
185                 'Get the Euclidean distance between this vector and other one.'
186                 return math.sqrt( self.distanceSquared(other) )
187
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
194
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
198
199         def dropAxis( self, which = 2 ):
200                 'Get a complex by removing one axis of the vector3.'
201                 if which == 0:
202                         return complex( self.y, self.z )
203                 if which == 1:
204                         return complex( self.x, self.z )
205                 if which == 2:
206                         return complex( self.x, self.y )
207
208         def getFloatList(self):
209                 'Get the vector as a list of floats.'
210                 return [ float( self.x ), float( self.y ), float( self.z ) ]
211
212         def getIsDefault(self):
213                 'Determine if this is the zero vector.'
214                 if self.x != 0.0:
215                         return False
216                 if self.y != 0.0:
217                         return False
218                 return self.z == 0.0
219
220         def getNormalized(self):
221                 'Get the normalized Vector3.'
222                 magnitude = abs(self)
223                 if magnitude == 0.0:
224                         return self.copy()
225                 return self / magnitude
226
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
230
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)
236
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)
242
243         def normalize(self):
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)
246                 if magnitude != 0.0:
247                         self /= magnitude
248
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 )
253
254         def setToVector3(self, other):
255                 'Set this Vector3 to be identical to other one.'
256                 self.x = other.x
257                 self.y = other.y
258                 self.z = other.z
259
260         def setToXYZ( self, x, y, z ):
261                 'Set the x, y, and z components of this Vector3.'
262                 self.x = x
263                 self.y = y
264                 self.z = z
265
266
267 globalGetAccessibleAttributeSet = 'x y z'.split()
268 globalSetAccessibleAttributeSet = globalGetAccessibleAttributeSet
269
270 """
271 class Vector3:
272         __slots__ = ['x', 'y', 'z']
273
274
275         copy = __copy__
276
277         def __eq__(self, other):
278                 if isinstance(other, Vector3):
279                         return self.x == other.x and \
280                                    self.y == other.y and \
281                                    self.z == other.z
282                 else:
283                         assert hasattr(other, '__len__') and len(other) == 3
284                         return self.x == other[0] and \
285                                    self.y == other[1] and \
286                                    self.z == other[2]
287
288         def __getattr__(self, name):
289                 try:
290                         return tuple([(self.x, self.y, self.z)['xyz'.index(c)] \
291                                                   for c in name])
292                 except ValueError:
293                         raise AttributeError, name
294
295         def __getitem__(self, key):
296                 return (self.x, self.y, self.z)[key]
297
298         def __iter__(self):
299                 return iter((self.x, self.y, self.z))
300
301         def __len__(self):
302                 return 3
303
304         def __repr__(self):
305                 return 'Vector3(%.2f, %.2f, %.2f)' % (self.x,
306                                                                                           self.y,
307                                                                                           self.z)
308
309         if _enable_swizzle_set:
310                 # This has detrimental performance on ordinary setattr as well
311                 # if enabled
312                 def __setattr__(self, name, value):
313                         if len(name) == 1:
314                                 object.__setattr__(self, name, value)
315                         else:
316                                 try:
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
321                                 except ValueError:
322                                         raise AttributeError, name
323
324         def __setitem__(self, key, value):
325                 l = [self.x, self.y, self.z]
326                 l[key] = value
327                 self.x, self.y, self.z = l
328
329 """