From 9456d07ae835acb77dc7c928675da3f9f324d3fe Mon Sep 17 00:00:00 2001 From: Valentin Valls Date: Wed, 14 May 2014 11:38:24 +0200 Subject: [PATCH 1/2] Fix scale-rotate ROI handler to allow to use a random scale axis and not only x/y The code relative to scaleSnap is maybe broken --- pyqtgraph/graphicsItems/ROI.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/pyqtgraph/graphicsItems/ROI.py b/pyqtgraph/graphicsItems/ROI.py index b775a4ad..c9794302 100644 --- a/pyqtgraph/graphicsItems/ROI.py +++ b/pyqtgraph/graphicsItems/ROI.py @@ -572,8 +572,6 @@ class ROI(GraphicsObject): """ pos = Point(pos) center = Point(center) - if pos[0] != center[0] and pos[1] != center[1]: - raise Exception("Scale/rotate handles must have either the same x or y coordinate as their center point.") return self.addHandle({'name': name, 'type': 'sr', 'center': center, 'pos': pos, 'item': item}, index=index) def addRotateFreeHandle(self, pos, center, axes=None, item=None, name=None, index=None): @@ -952,13 +950,6 @@ class ROI(GraphicsObject): h['pos'] = self.mapFromParent(p1) elif h['type'] == 'sr': - if h['center'][0] == h['pos'][0]: - scaleAxis = 1 - nonScaleAxis=0 - else: - scaleAxis = 0 - nonScaleAxis=1 - try: if lp1.length() == 0 or lp0.length() == 0: return @@ -971,15 +962,19 @@ class ROI(GraphicsObject): if self.rotateSnap or (modifiers & QtCore.Qt.ControlModifier): ang = round(ang / self.rotateSnapAngle) * self.rotateSnapAngle - hs = abs(h['pos'][scaleAxis] - c[scaleAxis]) - newState['size'][scaleAxis] = lp1.length() / hs + newState['size'][0] = self.state['size'][0] * lp1.length() / lp0.length() + newState['size'][1] = self.state['size'][1] * lp1.length() / lp0.length() #if self.scaleSnap or (modifiers & QtCore.Qt.ControlModifier): if self.scaleSnap: ## use CTRL only for angular snap here. - newState['size'][scaleAxis] = round(newState['size'][scaleAxis] / self.snapSize) * self.snapSize - if newState['size'][scaleAxis] == 0: - newState['size'][scaleAxis] = 1 - if self.aspectLocked: - newState['size'][nonScaleAxis] = newState['size'][scaleAxis] + newState['size'][0] = round(newState['size'][0] / self.snapSize) * self.snapSize + newState['size'][1] = round(newState['size'][1] / self.snapSize) * self.snapSize + if newState['size'][0] == 0: + newState['size'][0] = 1 + if newState['size'][1] == 0: + newState['size'][1] = 1 + # MC TODO what about this: + # if self.aspectLocked: + # newState['size'][nonScaleAxis] = newState['size'][scaleAxis] c1 = c * newState['size'] tr = QtGui.QTransform() From 219f79947e6fce79948a099b2d39591ac31bc542 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 27 Jan 2021 10:39:08 -0800 Subject: [PATCH 2/2] maintain non-scaling behavior for parallel sides make sure aspectLocked still gets checked add example --- examples/ROIExamples.py | 4 +++- pyqtgraph/graphicsItems/ROI.py | 25 ++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/examples/ROIExamples.py b/examples/ROIExamples.py index fe3e4db8..5aef130a 100644 --- a/examples/ROIExamples.py +++ b/examples/ROIExamples.py @@ -126,7 +126,9 @@ r3b.addRotateHandle([0, 1], [1, 0]) ## handles rotating/scaling around center r3b.addScaleRotateHandle([0, 0.5], [0.5, 0.5]) -r3b.addScaleRotateHandle([1, 0.5], [0.5, 0.5]) + +# handles rotating/scaling around arbitrary point +r3b.addScaleRotateHandle([0.3, 0], [0.9, 0.7]) v3.disableAutoRange('xy') v3.autoRange() diff --git a/pyqtgraph/graphicsItems/ROI.py b/pyqtgraph/graphicsItems/ROI.py index c9794302..48c24c22 100644 --- a/pyqtgraph/graphicsItems/ROI.py +++ b/pyqtgraph/graphicsItems/ROI.py @@ -572,6 +572,8 @@ class ROI(GraphicsObject): """ pos = Point(pos) center = Point(center) + if pos[0] == center[0] and pos[1] == center[1]: + raise Exception("Scale/rotate handles cannot be at their center point.") return self.addHandle({'name': name, 'type': 'sr', 'center': center, 'pos': pos, 'item': item}, index=index) def addRotateFreeHandle(self, pos, center, axes=None, item=None, name=None, index=None): @@ -961,21 +963,22 @@ class ROI(GraphicsObject): return if self.rotateSnap or (modifiers & QtCore.Qt.ControlModifier): ang = round(ang / self.rotateSnapAngle) * self.rotateSnapAngle - - newState['size'][0] = self.state['size'][0] * lp1.length() / lp0.length() - newState['size'][1] = self.state['size'][1] * lp1.length() / lp0.length() - #if self.scaleSnap or (modifiers & QtCore.Qt.ControlModifier): - if self.scaleSnap: ## use CTRL only for angular snap here. - newState['size'][0] = round(newState['size'][0] / self.snapSize) * self.snapSize - newState['size'][1] = round(newState['size'][1] / self.snapSize) * self.snapSize + + if self.aspectLocked or h['center'][0] != h['pos'][0]: + newState['size'][0] = self.state['size'][0] * lp1.length() / lp0.length() + if self.scaleSnap: # use CTRL only for angular snap here. + newState['size'][0] = round(newState['size'][0] / self.snapSize) * self.snapSize + + if self.aspectLocked or h['center'][1] != h['pos'][1]: + newState['size'][1] = self.state['size'][1] * lp1.length() / lp0.length() + if self.scaleSnap: # use CTRL only for angular snap here. + newState['size'][1] = round(newState['size'][1] / self.snapSize) * self.snapSize + if newState['size'][0] == 0: newState['size'][0] = 1 if newState['size'][1] == 0: newState['size'][1] = 1 - # MC TODO what about this: - # if self.aspectLocked: - # newState['size'][nonScaleAxis] = newState['size'][scaleAxis] - + c1 = c * newState['size'] tr = QtGui.QTransform() tr.rotate(ang)