InfiniteLine: Fix bounding box for differing x and y ranges

Previously, the same pixel -> local transform was used for both
direction, which breaks if the displayed coordinate range is not
the same for both axes.
This commit is contained in:
David Nadlinger 2018-07-15 23:26:12 +01:00 committed by Ogi
parent ed009d3779
commit ebc192dafd
2 changed files with 61 additions and 20 deletions

View File

@ -300,28 +300,28 @@ class InfiniteLine(GraphicsObject):
vr = self.viewRect() # bounds of containing ViewBox mapped to local coords. vr = self.viewRect() # bounds of containing ViewBox mapped to local coords.
if vr is None: if vr is None:
return QtCore.QRectF() return QtCore.QRectF()
## add a 4-pixel radius around the line for mouse interaction.
px = self.pixelLength(direction=Point(1,0), ortho=True) ## get pixel length orthogonal to the line
if px is None:
px = 0
pw = max(self.pen.width() / 2, self.hoverPen.width() / 2)
w = max(4, self._maxMarkerSize + pw) + 1
w = w * px
br = QtCore.QRectF(vr)
br.setBottom(-w)
br.setTop(w)
length = br.width() # Compute width of area around line to use for mouse interaction, in
left = br.left() + length * self.span[0] # pixels (at least 4 for thin lines).
right = br.left() + length * self.span[1] penWidth = max(self.pen.width() / 2, self.hoverPen.width() / 2)
br.setLeft(left) padding = max(4, self._maxMarkerSize + penWidth) + 1
br.setRight(right)
br = QtCore.QRectF()
orthoPadding = padding * (self.pixelLength(direction=Point(1,0), ortho=True) or 0)
br.setBottom(-orthoPadding)
br.setTop(orthoPadding)
paraPadding = padding * (self.pixelLength(direction=Point(1,0)) or 0)
length = vr.width()
left = vr.left() + length * self.span[0]
right = vr.left() + length * self.span[1]
br.setLeft(left - paraPadding)
br.setRight(right + paraPadding)
br = br.normalized() br = br.normalized()
vs = self.getViewBox().size() vs = self.getViewBox().size()
if self._bounds != br or self._lastViewSize != vs: if self._bounds != br or self._lastViewSize != vs:
self._bounds = br self._bounds = br
self._lastViewSize = vs self._lastViewSize = vs

View File

@ -44,7 +44,48 @@ def test_InfiniteLine():
px = pg.Point(-0.5, -1.0 / 3**0.5) px = pg.Point(-0.5, -1.0 / 3**0.5)
assert br.containsPoint(pos + 5 * px, QtCore.Qt.OddEvenFill) assert br.containsPoint(pos + 5 * px, QtCore.Qt.OddEvenFill)
assert not br.containsPoint(pos + 7 * px, QtCore.Qt.OddEvenFill) assert not br.containsPoint(pos + 7 * px, QtCore.Qt.OddEvenFill)
def test_InfiniteLine_scaled_bounding_box():
# Make plot with unequal axis ranges.
plt = pg.plot()
plt.setXRange(0, 1)
plt.setYRange(0, 1e-3)
plt.resize(400, 400)
QtTest.QTest.qWaitForWindowShown(plt)
QtTest.QTest.qWait(100)
# Vertical line.
vline = pg.InfiniteLine(angle=90)
vline.setPos(0.5)
plt.addItem(vline)
# Make sure there is some padding around the line...
vbr = vline.mapToScene(vline.boundingRect())
def contains(rect, x, y):
return rect.containsPoint(pg.Point(x, y), QtCore.Qt.OddEvenFill)
assert contains(vbr, 221, -1)
assert contains(vbr, 229, 381)
# ... but not too much.
assert not contains(vbr, 221, -10)
assert not contains(vbr, 210, -1)
assert not contains(vbr, 229, 390)
assert not contains(vbr, 240, 381)
# Same for horizontal line.
hline = pg.InfiniteLine(angle=0)
hline.setPos(0.5e-3)
plt.addItem(hline)
hbr = hline.mapToScene(hline.boundingRect())
assert contains(hbr, 47, 185)
assert contains(hbr, 403, 194)
assert not contains(hbr, 47, 175)
assert not contains(hbr, 37, 185)
assert not contains(hbr, 413, 194)
assert not contains(hbr, 403, 204)
def test_mouseInteraction(): def test_mouseInteraction():
plt = pg.plot() plt = pg.plot()