Source code for qwt.scale_map

# -*- coding: utf-8 -*-
#
# Licensed under the terms of the Qwt License
# Copyright (c) 2002 Uwe Rathmann, for the original C++ code
# Copyright (c) 2015 Pierre Raybaut, for the Python translation/optimization
# (see LICENSE file for more details)

"""
QwtScaleMap
-----------

.. autoclass:: QwtScaleMap
   :members:
"""

from qtpy.QtCore import QPointF, QRectF

from qwt._math import qwtFuzzyCompare


[docs] class QwtScaleMap(object): """ A scale map `QwtScaleMap` offers transformations from the coordinate system of a scale into the linear coordinate system of a paint device and vice versa. The scale and paint device intervals are both set to [0,1]. .. py:class:: QwtScaleMap([other=None]) Constructor (eventually, copy constructor) :param qwt.scale_map.QwtScaleMap other: Other scale map .. py:class:: QwtScaleMap(p1, p2, s1, s2) :noindex: Constructor (was provided by `PyQwt` but not by `Qwt`) :param int p1: First border of the paint interval :param int p2: Second border of the paint interval :param float s1: First border of the scale interval :param float s2: Second border of the scale interval """ def __init__(self, *args): self.__transform = None # QwtTransform self.__s1 = 0.0 self.__s2 = 1.0 self.__p1 = 0.0 self.__p2 = 1.0 other = None if len(args) == 1: (other,) = args elif len(args) == 4: p1, p2, s1, s2 = args self.__s1 = s1 self.__s2 = s2 self.__p1 = p1 self.__p2 = p2 elif len(args) != 0: raise TypeError( "%s() takes 0, 1, or 4 argument(s) (%s given)" % (self.__class__.__name__, len(args)) ) if other is None: self.__cnv = 1.0 self.__ts1 = 0.0 else: self.__s1 = other.__s1 self.__s2 = other.__s2 self.__p1 = other.__p1 self.__p2 = other.__p2 self.__cnv = other.__cnv self.__ts1 = other.__ts1 if other.__transform: self.__transform = other.__transform.copy() def __eq__(self, other): return ( self.__s1 == other.__s1 and self.__s2 == other.__s2 and self.__p1 == other.__p1 and self.__p2 == other.__p2 and self.__cnv == other.__cnv and self.__ts1 == other.__ts1 )
[docs] def s1(self): """ :return: First border of the scale interval """ return self.__s1
[docs] def s2(self): """ :return: Second border of the scale interval """ return self.__s2
[docs] def p1(self): """ :return: First border of the paint interval """ return self.__p1
[docs] def p2(self): """ :return: Second border of the paint interval """ return self.__p2
[docs] def pDist(self): """ :return: `abs(p2() - p1())` """ return abs(self.__p2 - self.__p1)
[docs] def sDist(self): """ :return: `abs(s2() - s1())` """ return abs(self.__s2 - self.__s1)
[docs] def transform_scalar(self, s): """ Transform a point related to the scale interval into an point related to the interval of the paint device :param float s: Value relative to the coordinates of the scale :return: Transformed value .. seealso:: :py:meth:`invTransform_scalar()` """ if self.__transform: s = self.__transform.transform(s) return self.__p1 + (s - self.__ts1) * self.__cnv
[docs] def invTransform_scalar(self, p): """ Transform an paint device value into a value in the interval of the scale. :param float p: Value relative to the coordinates of the paint device :return: Transformed value .. seealso:: :py:meth:`transform_scalar()` """ if self.__cnv == 0: s = self.__ts1 # avoid divide by zero else: s = self.__ts1 + (p - self.__p1) / self.__cnv if self.__transform: s = self.__transform.invTransform(s) return s
[docs] def isInverting(self): """ :return: True, when ( p1() < p2() ) != ( s1() < s2() ) """ return (self.__p1 < self.__p2) != (self.__s1 < self.__s2)
[docs] def setTransformation(self, transform): """ Initialize the map with a transformation :param qwt.transform.QwtTransform transform: Transformation """ if self.__transform != transform: self.__transform = transform self.setScaleInterval(self.__s1, self.__s2)
[docs] def transformation(self): """ :return: the transformation """ return self.__transform
[docs] def setScaleInterval(self, s1, s2): """ Specify the borders of the scale interval :param float s1: first border :param float s2: second border .. warning:: Scales might be aligned to transformation depending boundaries """ self.__s1 = s1 self.__s2 = s2 if self.__transform: self.__s1 = self.__transform.bounded(self.__s1) self.__s2 = self.__transform.bounded(self.__s2) self.updateFactor()
[docs] def setPaintInterval(self, p1, p2): """ Specify the borders of the paint device interval :param float p1: first border :param float p2: second border """ self.__p1 = p1 self.__p2 = p2 self.updateFactor()
def updateFactor(self): self.__ts1 = self.__s1 ts2 = self.__s2 if self.__transform: self.__ts1 = self.__transform.transform(self.__ts1) ts2 = self.__transform.transform(ts2) self.__cnv = 1.0 if self.__ts1 != ts2: self.__cnv = (self.__p2 - self.__p1) / (ts2 - self.__ts1)
[docs] def transform(self, *args): """ Transform a rectangle from scale to paint coordinates. Transfom a scalar: :param float scalar: Scalar Transfom a rectangle: :param qwt.scale_map.QwtScaleMap xMap: X map :param qwt.scale_map.QwtScaleMap yMap: Y map :param QRectF rect: Rectangle in paint coordinates Transfom a point: :param qwt.scale_map.QwtScaleMap xMap: X map :param qwt.scale_map.QwtScaleMap yMap: Y map :param QPointF pos: Position in scale coordinates .. seealso:: :py:meth:`invTransform()` """ if len(args) == 1: # Scalar transform return self.transform_scalar(args[0]) elif len(args) == 3 and isinstance(args[2], QPointF): xMap, yMap, pos = args return QPointF(xMap.transform(pos.x()), yMap.transform(pos.y())) elif len(args) == 3 and isinstance(args[2], QRectF): xMap, yMap, rect = args x1 = xMap.transform(rect.left()) x2 = xMap.transform(rect.right()) y1 = yMap.transform(rect.top()) y2 = yMap.transform(rect.bottom()) if x2 < x1: x1, x2 = x2, x1 if y2 < y1: y1, y2 = y2, y1 if qwtFuzzyCompare(x1, 0.0, x2 - x1) == 0: x1 = 0.0 if qwtFuzzyCompare(x2, 0.0, x2 - x1) == 0: x2 = 0.0 if qwtFuzzyCompare(y1, 0.0, y2 - y1) == 0: y1 = 0.0 if qwtFuzzyCompare(y2, 0.0, y2 - y1) == 0: y2 = 0.0 return QRectF(x1, y1, x2 - x1 + 1, y2 - y1 + 1) else: raise TypeError( "%s().transform() takes 1 or 3 argument(s) (%s " "given)" % (self.__class__.__name__, len(args)) )
[docs] def invTransform(self, *args): """Transform from paint to scale coordinates Scalar: scalemap.invTransform(scalar) Point (QPointF): scalemap.invTransform(xMap, yMap, pos) Rectangle (QRectF): scalemap.invTransform(xMap, yMap, rect) """ if len(args) == 1: # Scalar transform return self.invTransform_scalar(args[0]) elif isinstance(args[2], QPointF): xMap, yMap, pos = args return QPointF(xMap.invTransform(pos.x()), yMap.invTransform(pos.y())) elif isinstance(args[2], QRectF): xMap, yMap, rect = args x1 = xMap.invTransform(rect.left()) x2 = xMap.invTransform(rect.right() - 1) y1 = yMap.invTransform(rect.top()) y2 = yMap.invTransform(rect.bottom() - 1) r = QRectF(x1, y1, x2 - x1, y2 - y1) return r.normalized()