root/trunk/RBRapier/RBRapier/Tools/Vector.py

Revision 732, 19.9 kB (checked in by sholloway, 5 years ago)

*** empty log message ***

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 #~ Imports
24 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25
26 import math
27 import Numeric
28 from RBFoundation.IndexedProperty import IndexedProperty
29
30 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31 #~ Constants / Variables / Etc.
32 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33
34 _NumericType = Numeric.Float32
35
36 def DotH(v1, v2):
37     return Numeric.dot(v1[:3], v2[:3]) * v1[-1] * v2[-1]
38
39 def Cross3(v1, v2):
40     a1, b1, c1 = v1
41     a2, b2, c2 = v2
42     return (b1*c2-c1*b2, c1*a2-a1*c2, a1*b2-b1*a2)
43
44 def CrossMag3(v1, v2):
45     a1, b1, c1 = v1
46     a2, b2, c2 = v2
47     return Numeric.sqrt((b1*c2-c1*b2)**2 + (c1*a2-a1*c2)**2 + (a1*b2-b1*a2)**2)
48
49 def DotCross3(v1, v2):
50     a1, b1, c1 = v1
51     a2, b2, c2 = v2
52     return (a1*a2 + b1*b2 + c1*c2), (b1*c2-c1*b2, c1*a2-a1*c2, a1*b2-b1*a2)
53
54 def DotCross3H(v1, v2):
55     a1, b1, c1, h1 = v1
56     a2, b2, c2, h2 = v2
57     return (a1*a2 + b1*b2 + c1*c2)*h1*h2, (b1*c2-c1*b2, c1*a2-a1*c2, a1*b2-b1*a2, h1*h2)
58
59 def Cross3H(v1, v2):
60     a1, b1, c1, h1 = v1
61     a2, b2, c2, h2 = v2
62     return (b1*c2-c1*b2, c1*a2-a1*c2, a1*b2-b1*a2, h1*h2)
63
64 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65 #~ Definitions
66 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67
68 def LinearMapping((low_from, hi_from), (low_to, hi_to), aslambda=True):
69     """
70     >>> LinearMapping((10.,20.), (-1.,1.))
71     (0.20000000000000001, -3.0)
72     >>> LinearMapping((-1.,1.), (10.,20.))
73     (5.0, 15.0)
74     """
75     wr = (hi_to - low_to)/(hi_from - low_from)
76     tr = low_to - low_from*wr
77     if aslambda:
78         return lambda r: wr*(r-low_from)+low_to
79     else:
80         return (wr, low_to - low_from*wr)
81
82 def LinearDimMapping((low_from, dim_from), (low_to, dim_to), aslambda=True):
83     """
84     >>> LinearDimMapping((10.,10.), (-1.,2.))
85     (0.20000000000000001, -3.0)
86     >>> LinearDimMapping((-1.,2.), (10.,10.))
87     (5.0, 15.0)
88     """
89     wr = dim_to/dim_from
90     if aslambda:
91         return lambda r: wr*(r-low_from)+low_to
92     else:
93         return (wr, low_to - low_from*wr)
94
95 class Vector(object):
96     """
97     >>> x = Vector(1., 0., 0.); x
98     <[1.0, 0.0, 0.0]>
99     >>> y = Vector(0., 1., 0.); y
100     <[0.0, 1.0, 0.0]>
101     >>> z = Vector(0., 0., 1.); z
102     <[0.0, 0.0, 1.0]>
103     >>> xyz = Vector(x + y + z); xyz
104     <[1.0, 1.0, 1.0]>
105     >>> Vector.Cross3(x,y)
106     <[0.0, 0.0, 1.0]>
107     >>> Vector.Cross3(x,z)
108     <[0.0, -1.0, 0.0]>
109     >>> Vector.Cross3(y,z)
110     <[1.0, 0.0, 0.0]>
111     >>> Vector.Cross3(y,x)
112     <[0.0, 0.0, -1.0]>
113     >>> Vector.Cross3(z,y)
114     <[-1.0, 0.0, 0.0]>
115     >>> Vector.Cross3(z,z)
116     <[0.0, 0.0, 0.0]>
117     >>> Vector.Cross3(z,x)
118     <[0.0, 1.0, 0.0]>
119     >>> Vector.Cross3(x,x)
120     <[0.0, 0.0, 0.0]>
121     >>> Vector.Cross3(y,y)
122     <[0.0, 0.0, 0.0]>
123     >>> Vector.DeltaAngle(x,y)
124     90.000002504478161
125     >>> Vector.DeltaAngle(x,z)
126     90.000002504478161
127     >>> Vector.DeltaAngle(y,z)
128     90.000002504478161
129     >>> Vector.DeltaRadians(x,z)
130     1.57079637051
131     >>> Vector.DeltaRadians(x,y)
132     1.57079637051
133     >>> Vector.DeltaRadians(z,y)
134     1.57079637051
135     >>> x * 4
136     <[4.0, 0.0, 0.0]>
137     >>> x / 4.
138     <[0.25, 0.0, 0.0]>
139     >>> x + 1.
140     <[2.0, 1.0, 1.0]>
141     >>> x - 1.
142     <[0.0, -1.0, -1.0]>
143     >>> x + y
144     <[1.0, 1.0, 0.0]>
145     >>> x - y
146     <[1.0, -1.0, 0.0]>
147     >>> x * y
148     0.0
149     >>> x * y.Cross3(z)
150     1.0
151     >>> x * z.Cross3(y)
152     -1.0
153     >>> abs(4*x), abs(3*y), abs(2*z)
154     (4.0, 3.0, 2.0)
155     >>> -x
156     <[-1.0, 0.0, 0.0]>
157     >>> x = Vector(1.,1.,1.); x
158     <[1.0, 1.0, 1.0]>
159     >>> x.iNormalize(); x
160     <[0.57735025882720947, 0.57735025882720947, 0.57735025882720947]>
161     """
162     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163     #~ Constants / Variables / Etc.
164     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165
166     NumericType = _NumericType
167     Default = Numeric.asarray((0.,0.,0.), NumericType)
168
169     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
170     #~ Special
171     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172
173     def __init__(self, *args, **kw):
174         NumericType = kw.get('NumericType', None)
175         if NumericType is not None: self.NumericType = NumericType
176         if not args:
177             self.Set(self.Default)
178         elif isinstance(args[0], (Vector, self.__class__)):
179             self.Set(args[0])
180         elif isinstance(args[0], (tuple, list, Numeric.ArrayType)):
181             self.Set(args[0])
182         else:
183             self.Set(args[:len(self)])
184
185     def __repr__(self):
186         return "<%r>" % self.tolist()
187
188     def __len__(self):
189         return len(self.Default)
190     def __getitem__(self, key):
191         return self._array[key]
192     def __setitem__(self, key, value):
193         self._array[key] = value
194     def _self(self):
195         return self
196
197     def __pos__(self):
198         return self
199     def __neg__(self):
200         return self.__class__(-1 * self._array)
201     def __abs__(self):
202         return self.Magnitude()
203
204     def __iadd__(self, other):
205         if isinstance(other, Vector): other = other._array
206         self.Set(self._array + other)
207         return self
208     def __add__(self, other):
209         if isinstance(other, Vector): other = other._array
210         return self.__class__(self._array + other)
211     def __radd__(self, other):
212         if isinstance(other, Vector): other = other._array
213         return self.__class__(other + self._array)
214     def __isub__(self, other):
215         if isinstance(other, Vector): other = other._array
216         self.Set(self._array - other)
217         return self
218     def __sub__(self, other):
219         if isinstance(other, Vector): other = other._array
220         return self.__class__(self._array - other)
221     def __rsub__(self, other):
222         if isinstance(other, Vector): other = other._array
223         return self.__class__(other - self._array)
224        
225     def __idiv__(self, other):
226         if isinstance(other, Vector):
227             raise TypeError, "can't divide a Vector by a Vector"
228         else:
229             self.Set(self._array / other)
230         return self
231     def __div__(self, other):
232         if isinstance(other, Vector):
233             raise TypeError, "can't divide a Vector by a Vector"
234         else: return self.__class__(self._array / other)
235
236     def __imul__(self, other):
237         if isinstance(other, Vector):
238             raise TypeError, "can't multiply by a Vector in-place"
239         else:
240             self.Set(self._array * other)
241         return self
242
243     def __mul__(self, other):
244         if isinstance(other, Vector):
245             return self.Dot(other)
246         else: return self.__class__(self._array * other)
247
248     def __rmul__(self, other):
249         if isinstance(other, Vector):
250             return other.Dot(self)
251         else: return self.__class__(other * self._array)
252
253     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
254     #~ Public Methods
255     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
256
257     def asarray(self, *args):
258         if args: return Numeric.asarray(self._array, *args)
259         else: return self._array
260
261     def tolist(self):
262         return self._array.tolist()
263
264     def Set(self, other):
265         self._array = self._simplify(other)
266
267     def Dot(self, other):
268         return Numeric.dot(self._array, other._array)
269
270     def iCross3(self, other):
271         self[:] = Cross3(self._arrayh, other._array)
272
273     def Cross3(self, other):
274         return self.__class__(Cross3(self._array, other._array))
275
276     def Magnitude(self, squared=0):
277         value = self.Dot(self)
278         if squared: return value
279         else: return Numeric.sqrt(value)
280
281     def iNormalize(self):
282         self /= self.Magnitude()
283
284     def Normalize(self):
285         mag = self.Magnitude()
286         return self / mag
287
288     def DeltaAngle(self, other):
289         return math.degrees(self.DeltaRadians(other))
290
291     def DeltaRadians(self, other):
292         return Numeric.arccos(self.Dot(other))
293
294     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
295     #~ Protected Methods
296     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
297
298     def _simplify(self, value):
299         try: value = list(value[:len(self.Default)]) + list(self.Default[len(value):])
300         except TypeError: raise TypeError, 'New vector value must be iterable.  (value=%r)' % value
301         return Numeric.asarray(value, self.NumericType)
302
303 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304
305 class Vector3(Vector):
306     """
307     >>> a = Vector3(1,2,3); a
308     <[1.0, 2.0, 3.0]>
309     >>> a.X
310     1.0
311     >>> a.Y
312     2.0
313     >>> a.Z
314     3.0
315     """
316     X = IndexedProperty(Vector._self, 0)
317     Y = IndexedProperty(Vector._self, 1)
318     Z = IndexedProperty(Vector._self, 2)
319
320 class Vector4(Vector):
321     Default = Numeric.asarray((0.,0.,0.,0.), Vector.NumericType)
322
323 class ColorVector(Vector):
324     """
325     >>> a = ColorVector(1,2,3,4); a
326     <[1.0, 2.0, 3.0, 4.0]>
327     >>> a.R
328     1.0
329     >>> a.G
330     2.0
331     >>> a.B
332     3.0
333     >>> a.A
334     4.0
335     """
336
337     Default = Numeric.asarray((0.,0.,0.,1.), Vector.NumericType)
338     R = IndexedProperty(Vector._self, 0)
339     G = IndexedProperty(Vector._self, 1)
340     B = IndexedProperty(Vector._self, 2)
341     A = IndexedProperty(Vector._self, 3)
342
343 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344
345 class VectorH(Vector):
346     """
347     >>> x = VectorH(1., 0., 0.); x
348     <[1.0, 0.0, 0.0, 1.0]>
349     >>> y = VectorH(0., 1., 0.); y
350     <[0.0, 1.0, 0.0, 1.0]>
351     >>> z = VectorH(0., 0., 1.); z
352     <[0.0, 0.0, 1.0, 1.0]>
353     >>> xyz = VectorH(x + y + z); xyz
354     <[1.0, 1.0, 1.0, 1.0]>
355     >>> VectorH.Cross3H(x,y)
356     <[0.0, 0.0, 1.0, 1.0]>
357     >>> VectorH.Cross3H(x,z)
358     <[0.0, -1.0, 0.0, 1.0]>
359     >>> VectorH.Cross3H(y,z)
360     <[1.0, 0.0, 0.0, 1.0]>
361     >>> VectorH.Cross3H(y,x)
362     <[0.0, 0.0, -1.0, 1.0]>
363     >>> VectorH.Cross3H(z,y)
364     <[-1.0, 0.0, 0.0, 1.0]>
365     >>> VectorH.Cross3H(z,z)
366     <[0.0, 0.0, 0.0, 1.0]>
367     >>> VectorH.Cross3H(z,x)
368     <[0.0, 1.0, 0.0, 1.0]>
369     >>> VectorH.Cross3H(x,x)
370     <[0.0, 0.0, 0.0, 1.0]>
371     >>> VectorH.Cross3H(y,y)
372     <[0.0, 0.0, 0.0, 1.0]>
373     >>> VectorH.DeltaAngle(x,y)
374     90.000002504478161
375     >>> VectorH.DeltaAngle(x,z)
376     90.000002504478161
377     >>> VectorH.DeltaAngle(y,z)
378     90.000002504478161
379     >>> VectorH.DeltaRadians(x,z)
380     1.57079637051
381     >>> VectorH.DeltaRadians(x,y)
382     1.57079637051
383     >>> VectorH.DeltaRadians(z,y)
384     1.57079637051
385     >>> x * 4
386     <[4.0, 0.0, 0.0, 1.0]>
387     >>> x / 4.
388     <[0.25, 0.0, 0.0, 1.0]>
389     >>> x + 1.
390     <[2.0, 1.0, 1.0, 1.0]>
391     >>> x - 1.
392     <[0.0, -1.0, -1.0, 1.0]>
393     >>> x + y
394     <[1.0, 1.0, 0.0, 1.0]>
395     >>> x - y
396     <[1.0, -1.0, 0.0, 1.0]>
397     >>> x * y
398     0.0
399     >>> x * y.Cross3H(z)
400     1.0
401     >>> x * z.Cross3H(y)
402     -1.0
403     >>> abs(4*x), abs(3*y), abs(2*z)
404     (4.0, 3.0, 2.0)
405     >>> -x
406     <[-1.0, 0.0, 0.0, 1.0]>
407     """
408
409     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
410     #~ Constants / Variables / Etc.
411     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
412
413     NumericType = _NumericType
414     Default = Numeric.asarray((0.,0.,0.,1.), NumericType)
415
416     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
417     #~ Special
418     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
419
420     def __init__(self, *args):
421         if not args:
422             Vector.__init__(self, *args)
423         elif isinstance(args[0], VectorH):
424             self.Set(args[0])
425         elif isinstance(args[0], Vector):
426             self.Set(args[0][0:len(self)-1])
427         else:
428             Vector.__init__(self, *args)
429
430     def __getitem__(self, key):
431         return self._arrayh[key]
432     def __setitem__(self, key, value):
433         self._arrayh[key] = value
434         try: self._arrayh /= self._arrayh[-1:]
435         except ZeroDivisionError: pass
436
437     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
438     #~ Public Methods
439     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
440
441     def asarray(self, *args):
442         if args: return Numeric.asarray(self._arrayh, *args)
443         else: return self._arrayh
444
445     def tolist(self):
446         return self._arrayh.tolist()
447
448     def Set(self, other):
449         self._arrayh = self._simplify(other)
450
451     def iCross3H(self, other):
452         self[:] = Cross3H(self._arrayh, other._arrayh)
453
454     def Cross3H(self, other):
455         return self.__class__(Cross3H(self._arrayh, other._arrayh))
456
457     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
458     #~ Protected Methods
459     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
460
461     def _GetArray(self):
462         return self._arrayh[:-1]
463     def _SetArray(self, value):
464         self._arrayh[:-1] = value
465     _array = property(_GetArray, _SetArray)
466
467     def _simplify(self, value):
468         try: value = list(value[:len(self.Default)]) + list(self.Default[len(value):])
469         except TypeError: raise TypeError, 'New vector value must be iterable.  (value=%r)' % value
470         result = Numeric.asarray(value, self.NumericType)
471         # Homogonize
472         try: result /= result[-1:]
473         except ZeroDivisionError: pass
474         return result
475
476 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
477
478 class Vector3H(VectorH):
479     """
480     >>> a = Vector3H(2,4,6,2); a
481     <[1.0, 2.0, 3.0, 1.0]>
482     >>> a.X
483     1.0
484     >>> a.Y
485     2.0
486     >>> a.Z
487     3.0
488     >>> a.W
489     1.0
490     >>> a.W = 0.25; a.W
491     1.0
492     >>> a
493     <[4.0, 8.0, 12.0, 1.0]>
494     """
495     X = IndexedProperty(Vector._self, 0)
496     Y = IndexedProperty(Vector._self, 1)
497     Z = IndexedProperty(Vector._self, 2)
498     W = IndexedProperty(Vector._self, 3)
499
500 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
501
502 class UnitVector(Vector):
503     Default = Numeric.asarray((0.,0.,1.), Vector.NumericType)
504
505     def __setitem__(self, key, value):
506         A = self._array
507         A[key] = value
508         try: A /= A[-1:]
509         except ZeroDivisionError: pass
510         A /= Numeric.sqrt(Numeric.dot(A, A))
511
512     def _simplify(self, value):
513         try: value = list(value[:len(self.Default)]) + list(self.Default[len(value):])
514         except TypeError: raise TypeError, 'New vector value must be iterable.  (value=%r)' % value
515         result = Numeric.asarray(value, self.NumericType)
516         # Normalize
517         result /= Numeric.sqrt(Numeric.dot(result, result))
518         return result
519
520 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
521
522 UnitVector3 = UnitVector
523
524 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
525
526 class UnitVectorH(VectorH):
527     Default = Numeric.asarray((0.,0.,1.,1.), VectorH.NumericType)
528
529     def __setitem__(self, key, value):
530         A = self._arrayh
531         A[key] = value
532         try: A /= A[-1:]
533         except ZeroDivisionError: pass
534         A[:-1] /= Numeric.sqrt(Numeric.dot(A[:-1], A[:-1]))
535
536     def _simplify(self, value):
537         try: value = list(value[:len(self.Default)]) + list(self.Default[len(value):])
538         except TypeError: raise TypeError, 'New vector value must be iterable.  (value=%r)' % value
539         result = Numeric.asarray(value, self.NumericType)
540         # Homogonize
541         try: result /= result[-1:]
542         except ZeroDivisionError: pass
543         # Normalize
544         result[:-1] /= Numeric.sqrt(Numeric.dot(result[:-1], result[:-1]))
545         return result
546
547 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
548
549 UnitVector3H = UnitVectorH
550
551 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
552 #~ Vector Property Definitions
553 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
554
555 class VectorPropertyMixin(object):
556     def __init__(self, name, default=None, lazy=1, doc='', **kw):
557         self.__name__ = name
558         self.__doc__ = doc
559         self._hidden_name = '__' + name + 'Vector'
560         self._lazy = lazy
561         self._createkw = kw
562         if default is not None:
563             self.VectorClass = type(self.VectorClass.__name__+'%', (self.VectorClass,),
564                 {'Default': Numeric.asarray(default, self.VectorClass.NumericType)})
565
566     def __get__(self, obj, klass):
567         if obj:
568             result = getattr(obj, self._hidden_name, None)
569             if result is None and self._lazy:
570                 result = self.VectorClass(**self._createkw)
571                 setattr(obj, self._hidden_name, result)
572             return result
573         else: return self
574
575     def __set__(self, obj, value):
576         vector = getattr(obj, self._hidden_name, None)
577         if vector is None:
578             setattr(obj, self._hidden_name, self.VectorClass(value))
579         else: vector.Set(value)
580
581     def __delete__(self, obj):
582         delattr(obj, self._hidden_name)
583
584 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
585
586 class Vector3Property(VectorPropertyMixin):
587     """
588     >>> class Test(object):
589     ...     vp = Vector3Property('vp')
590     ...
591     >>> t = Test()
592     >>> t.vp
593     <[0.0, 0.0, 0.0]>
594     >>> t.vp = 1.,
595     >>> t.vp
596     <[1.0, 0.0, 0.0]>
597     >>> t.vp = 1.,2.,3.,4.,5.,6.,
598     >>> t.vp
599     <[1.0, 2.0, 3.0]>
600     >>> t.vp = 1.,2.,3.
601     >>> t.vp
602     <[1.0, 2.0, 3.0]>
603     >>> t.vp[1]
604     2.0
605     >>> t.vp[1] = 13.
606     >>> t.vp
607     <[1.0, 13.0, 3.0]>
608     >>>
609     """
610     VectorClass = Vector3
611
612 class Vector4Property(VectorPropertyMixin):
613     VectorClass = Vector4
614
615 class ColorVectorProperty(VectorPropertyMixin):
616     VectorClass = ColorVector
617
618 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
619
620 class Vector3HProperty(VectorPropertyMixin):
621     """
622     >>> class Test(object):
623     ...     vp = Vector3HProperty('vp')
624     ...
625     >>> t = Test()
626     >>> t.vp
627     <[0.0, 0.0, 0.0, 1.0]>
628     >>> t.vp = 1.,
629     >>> t.vp
630     <[1.0, 0.0, 0.0, 1.0]>
631     >>> t.vp = 1.,2.,3.,4.,5.,6.,
632     >>> t.vp
633     <[0.25, 0.5, 0.75, 1.0]>
634     >>> t.vp = 1.,2.,3.
635     >>> t.vp
636     <[1.0, 2.0, 3.0, 1.0]>
637     >>> t.vp[1]
638     2.0
639     >>> t.vp[1] = 13.
640     >>> t.vp
641     <[1.0, 13.0, 3.0, 1.0]>
642     >>>
643     """
644     VectorClass = Vector3H
645
646 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
647
648 class UnitVector3Property(VectorPropertyMixin):
649     """
650     >>> class Test(object):
651     ...     vp = UnitVector3Property('vp')
652     ...
653     >>> t = Test(); t.vp
654     <[0.0, 0.0, 1.0]>
655     >>> round(abs(t.vp), 4)
656     1.0
657     >>> t.vp = 1.,; t.vp
658     <[0.70710676908493042, 0.0, 0.70710676908493042]>
659     >>> round(abs(t.vp), 4)
660     1.0
661     >>> t.vp = 1.,2.,3.,4.,5.,6.,; t.vp
662     <[0.26726123690605164, 0.53452247381210327, 0.80178368091583252]>
663     >>> round(abs(t.vp), 4)
664     1.0
665     >>> t.vp = 1.,2.,3.; t.vp
666     <[0.26726123690605164, 0.53452247381210327, 0.80178368091583252]>
667     >>> round(abs(t.vp), 4)
668     1.0
669     >>> t.vp[1]
670     0.53452247381210327
671     >>> t.vp[1] = 13.; t.vp
672     <[0.02051524817943573, 0.99789345264434814, 0.06154574453830719]>
673     >>> round(abs(t.vp), 4)
674     1.0
675     """
676     VectorClass = UnitVector3
677
678 class UnitVector3HProperty(VectorPropertyMixin):
679     """
680     >>> class Test(object):
681     ...     vp = UnitVector3HProperty('vp')
682     ...
683     >>> t = Test(); t.vp
684     <[0.0, 0.0, 1.0, 1.0]>
685     >>> round(abs(t.vp), 4)
686     1.0
687     >>> t.vp = 1.,; t.vp
688     <[0.70710676908493042, 0.0, 0.70710676908493042, 1.0]>
689     >>> round(abs(t.vp), 4)
690     1.0
691     >>> t.vp = 1.,2.,3.,4.,5.,6.,; t.vp
692     <[0.26726123690605164, 0.53452247381210327, 0.80178368091583252, 1.0]>
693     >>> round(abs(t.vp), 4)
694     1.0
695     >>> t.vp = 1.,2.,3.; t.vp
696     <[0.26726123690605164, 0.53452247381210327, 0.80178368091583252, 1.0]>
697     >>> round(abs(t.vp), 4)
698     1.0
699     >>> t.vp[1]
700     0.53452247381210327
701     >>> t.vp[1] = 13.; t.vp
702     <[0.02051524817943573, 0.99789345264434814, 0.06154574453830719, 1.0]>
703     >>> round(abs(t.vp), 4)
704     1.0
705     """
706     VectorClass = UnitVector3H
707
708 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
709 #~ Testing
710 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
711
712 if __name__=='__main__':
713     print "Testing..."
714     import doctest, Vector
715     doctest.testmod(Vector)
716     print "Test complete."
717
Note: See TracBrowser for help on using the browser.