Aluode/PerceptionLabPortable
0
1"""2Vector.py - Extension of QVector3D which adds a few missing methods.3Copyright 2010 Luke Campagnola4Distributed under MIT/X11 license. See license.txt for more information.5"""6from math import acos, degrees7 8from . import functions as fn9from .Qt import QT_LIB, QtCore, QtGui10 11 12class Vector(QtGui.QVector3D):13 """Extension of QVector3D which adds a few helpful methods."""14 15 def __init__(self, *args):16 """17 Handle additional constructions of a Vector18 19 ============== ================================================================================================20 **Arguments:**21 *args* Could be any of:22 23 * 3 numerics (x, y, and z)24 * 2 numerics (x, y, and `0` assumed for z)25 * Either of the previous in a list-like collection26 * 1 QSizeF (`0` assumed for z)27 * 1 QPointF (`0` assumed for z)28 * Any other valid QVector3D init args.29 ============== ================================================================================================30 """31 initArgs = args32 if len(args) == 1:33 if isinstance(args[0], QtCore.QSizeF):34 initArgs = (float(args[0].width()), float(args[0].height()), 0)35 elif isinstance(args[0], QtCore.QPoint) or isinstance(args[0], QtCore.QPointF):36 initArgs = (float(args[0].x()), float(args[0].y()), 0)37 elif hasattr(args[0], '__getitem__') and not isinstance(args[0], QtGui.QVector3D):38 vals = list(args[0])39 if len(vals) == 2:40 vals.append(0)41 if len(vals) != 3:42 raise Exception('Cannot init Vector with sequence of length %d' % len(args[0]))43 initArgs = vals44 elif isinstance(args[0], QtGui.QVector3D):45 # PySide6 6.1 does not accept initialization from QVector3D46 initArgs = args[0].x(), args[0].y(), args[0].z()47 elif len(args) == 2:48 initArgs = (args[0], args[1], 0)49 QtGui.QVector3D.__init__(self, *initArgs)50 51 def __len__(self):52 return 353 54 def __getitem__(self, i):55 if i == 0:56 return self.x()57 elif i == 1:58 return self.y()59 elif i == 2:60 return self.z()61 else:62 raise IndexError("Point has no index %s" % str(i))63 64 def __setitem__(self, i, x):65 if i == 0:66 return self.setX(x)67 elif i == 1:68 return self.setY(x)69 elif i == 2:70 return self.setZ(x)71 else:72 raise IndexError("Point has no index %s" % str(i))73 74 def __iter__(self):75 yield(self.x())76 yield(self.y())77 yield(self.z())78 79 def angle(self, a):80 """Returns the angle in degrees between this vector and the vector a."""81 n1 = self.length()82 n2 = a.length()83 if n1 == 0. or n2 == 0.:84 return None85 ## Probably this should be done with arctan2 instead..86 rads = acos(fn.clip_scalar(QtGui.QVector3D.dotProduct(self, a) / (n1 * n2), -1.0, 1.0)) ### in radians87# c = self.crossProduct(a)88# if c > 0:89# ang *= -1.90 return degrees(rads)91 92 def __abs__(self):93 return Vector(abs(self.x()), abs(self.y()), abs(self.z()))94 95 96 