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 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 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()