pyqtgraph/Point.py

149 lines
4.2 KiB
Python
Raw Normal View History

2010-03-22 05:48:52 +00:00
# -*- 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.
"""
2012-05-11 22:05:41 +00:00
from .Qt import QtCore
import numpy as np
2010-03-22 05:48:52 +00:00
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:
2010-11-22 03:50:04 +00:00
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
2010-11-22 03:50:04 +00:00
elif hasattr(args[0], '__getitem__'):
2010-03-22 05:48:52 +00:00
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
2010-11-22 03:50:04 +00:00
def __reduce__(self):
return (Point, (self.x(), self.y()))
2010-03-22 05:48:52 +00:00
def __getitem__(self, i):
if i == 0:
return self.x()
elif i == 1:
return self.y()
else:
2012-03-06 06:20:42 +00:00
raise IndexError("Point has no index %s" % str(i))
2010-03-22 05:48:52 +00:00
def __setitem__(self, i, x):
if i == 0:
return self.setX(x)
elif i == 1:
return self.setY(x)
else:
2012-03-06 06:20:42 +00:00
raise IndexError("Point has no index %s" % str(i))
2010-03-22 05:48:52 +00:00
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]))
2010-03-22 05:48:52 +00:00
def length(self):
"""Returns the vector length of this Point."""
2010-03-22 05:48:52 +00:00
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()
2010-03-22 05:48:52 +00:00
def angle(self, a):
"""Returns the angle in degrees between this vector and the vector a."""
2010-03-22 05:48:52 +00:00
n1 = self.length()
n2 = a.length()
if n1 == 0. or n2 == 0.:
return None
## Probably this should be done with arctan2 instead..
ang = np.arccos(clip(self.dot(a) / (n1 * n2), -1.0, 1.0)) ### in radians
2010-03-22 05:48:52 +00:00
c = self.cross(a)
if c > 0:
ang *= -1.
return ang * 180. / np.pi
2010-03-22 05:48:52 +00:00
def dot(self, a):
"""Returns the dot product of a and this Point."""
2010-03-22 05:48:52 +00:00
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]
def proj(self, b):
"""Return the projection of this vector onto the vector b"""
b1 = b / b.length()
return self.dot(b1) * b1
2010-03-22 05:48:52 +00:00
def __repr__(self):
return "Point(%f, %f)" % (self[0], self[1])
def min(self):
return min(self[0], self[1])
def max(self):
return max(self[0], self[1])
def copy(self):
return Point(self)
def toQPoint(self):
return QtCore.QPoint(*self)