Skip to content
Snippets Groups Projects
Point.py 4.17 KiB
Newer Older
  • Learn to ignore specific revisions
  • Luke Campagnola's avatar
    Luke Campagnola committed
    # -*- coding: utf-8 -*-
    """
    Point.py -  Extension of QPointF which adds a few missing methods.
    Copyright 2010  Luke Campagnola
    Distributed under MIT/X11 license. See license.txt for more infomation.
    """
    
    
    from Qt import QtCore
    
    Luke Campagnola's avatar
    Luke Campagnola committed
    import numpy as np
    
    Luke Campagnola's avatar
    Luke Campagnola committed
    
    def clip(x, mn, mx):
        if x > mx:
            return mx
        if x < mn:
            return mn
        return x
    
    class Point(QtCore.QPointF):
        """Extension of QPointF which adds a few missing methods."""
        
        def __init__(self, *args):
            if len(args) == 1:
    
    Luke Campagnola's avatar
    Luke Campagnola committed
                if isinstance(args[0], QtCore.QSizeF):
                    QtCore.QPointF.__init__(self, float(args[0].width()), float(args[0].height()))
                    return
    
                elif isinstance(args[0], float) or isinstance(args[0], int):
                    QtCore.QPointF.__init__(self, float(args[0]), float(args[0]))
                    return
    
    Luke Campagnola's avatar
    Luke Campagnola committed
                elif hasattr(args[0], '__getitem__'):
    
    Luke Campagnola's avatar
    Luke Campagnola committed
                    QtCore.QPointF.__init__(self, float(args[0][0]), float(args[0][1]))
                    return
            elif len(args) == 2:
                QtCore.QPointF.__init__(self, args[0], args[1])
                return
            QtCore.QPointF.__init__(self, *args)
            
    
        def __len__(self):
            return 2
            
    
    Luke Campagnola's avatar
    Luke Campagnola committed
        def __reduce__(self):
            return (Point, (self.x(), self.y()))
            
    
    Luke Campagnola's avatar
    Luke Campagnola committed
        def __getitem__(self, i):
            if i == 0:
                return self.x()
            elif i == 1:
                return self.y()
            else:
    
    Luke Campagnola's avatar
    Luke Campagnola committed
                raise IndexError("Point has no index %s" % str(i))
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            
        def __setitem__(self, i, x):
            if i == 0:
                return self.setX(x)
            elif i == 1:
                return self.setY(x)
            else:
    
    Luke Campagnola's avatar
    Luke Campagnola committed
                raise IndexError("Point has no index %s" % str(i))
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            
        def __radd__(self, a):
            return self._math_('__radd__', a)
        
        def __add__(self, a):
            return self._math_('__add__', a)
        
        def __rsub__(self, a):
            return self._math_('__rsub__', a)
        
        def __sub__(self, a):
            return self._math_('__sub__', a)
        
        def __rmul__(self, a):
            return self._math_('__rmul__', a)
        
        def __mul__(self, a):
            return self._math_('__mul__', a)
        
        def __rdiv__(self, a):
            return self._math_('__rdiv__', a)
        
        def __div__(self, a):
            return self._math_('__div__', a)
        
        def __rpow__(self, a):
            return self._math_('__rpow__', a)
        
        def __pow__(self, a):
            return self._math_('__pow__', a)
        
        def _math_(self, op, x):
            #print "point math:", op
    
            #try:
                #fn  = getattr(QtCore.QPointF, op)
                #pt = fn(self, x)
                #print fn, pt, self, x
                #return Point(pt)
            #except AttributeError:
            x = Point(x)
            return Point(getattr(self[0], op)(x[0]), getattr(self[1], op)(x[1]))
    
    Luke Campagnola's avatar
    Luke Campagnola committed
        
        def length(self):
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            """Returns the vector length of this Point."""
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            return (self[0]**2 + self[1]**2) ** 0.5
        
    
        def norm(self):
            """Returns a vector in the same direction with unit length."""
            return self / self.length()
        
    
    Luke Campagnola's avatar
    Luke Campagnola committed
        def angle(self, a):
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            """Returns the angle in degrees between this vector and the vector a."""
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            n1 = self.length()
            n2 = a.length()
            if n1 == 0. or n2 == 0.:
                return None
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            ## Probably this should be done with arctan2 instead..
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            ang = np.arccos(clip(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            c = self.cross(a)
            if c > 0:
                ang *= -1.
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            return ang * 180. / np.pi
    
    Luke Campagnola's avatar
    Luke Campagnola committed
        
        def dot(self, a):
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            """Returns the dot product of a and this Point."""
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            a = Point(a)
            return self[0]*a[0] + self[1]*a[1]
        
        def cross(self, a):
            a = Point(a)
            return self[0]*a[1] - self[1]*a[0]
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            
        def proj(self, b):
            """Return the projection of this vector onto the vector b"""
            b1 = b / b.length()
            return self.dot(b1) * b1
    
    Luke Campagnola's avatar
    Luke Campagnola committed
        
        def __repr__(self):
            return "Point(%f, %f)" % (self[0], self[1])
        
        
        def min(self):
            return min(self[0], self[1])
        
        def max(self):
    
    Luke Campagnola's avatar
    Luke Campagnola committed
            return max(self[0], self[1])
            
        def copy(self):
    
            return Point(self)
            
        def toQPoint(self):
            return QtCore.QPoint(*self)