overhaul/cleanup of ROI code, particularly for PolyLineROI
(should be no major API changes here)
This commit is contained in:
parent
0e1b57cf01
commit
26c73d3583
@ -245,15 +245,16 @@ class ROI(GraphicsObject):
|
||||
def handleMoveStarted(self):
|
||||
self.preMoveState = self.getState()
|
||||
|
||||
def addTranslateHandle(self, pos, axes=None, item=None, name=None):
|
||||
def addTranslateHandle(self, pos, axes=None, item=None, name=None, index=None):
|
||||
pos = Point(pos)
|
||||
return self.addHandle({'name': name, 'type': 't', 'pos': pos, 'item': item})
|
||||
return self.addHandle({'name': name, 'type': 't', 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addFreeHandle(self, pos, axes=None, item=None, name=None):
|
||||
pos = Point(pos)
|
||||
return self.addHandle({'name': name, 'type': 'f', 'pos': pos, 'item': item})
|
||||
def addFreeHandle(self, pos=None, axes=None, item=None, name=None, index=None):
|
||||
if pos is not None:
|
||||
pos = Point(pos)
|
||||
return self.addHandle({'name': name, 'type': 'f', 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addScaleHandle(self, pos, center, axes=None, item=None, name=None, lockAspect=False):
|
||||
def addScaleHandle(self, pos, center, axes=None, item=None, name=None, lockAspect=False, index=None):
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
info = {'name': name, 'type': 's', 'center': center, 'pos': pos, 'item': item, 'lockAspect': lockAspect}
|
||||
@ -261,53 +262,92 @@ class ROI(GraphicsObject):
|
||||
info['xoff'] = True
|
||||
if pos.y() == center.y():
|
||||
info['yoff'] = True
|
||||
return self.addHandle(info)
|
||||
return self.addHandle(info, index=index)
|
||||
|
||||
def addRotateHandle(self, pos, center, item=None, name=None):
|
||||
def addRotateHandle(self, pos, center, item=None, name=None, index=None):
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
return self.addHandle({'name': name, 'type': 'r', 'center': center, 'pos': pos, 'item': item})
|
||||
return self.addHandle({'name': name, 'type': 'r', 'center': center, 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addScaleRotateHandle(self, pos, center, item=None, name=None):
|
||||
def addScaleRotateHandle(self, pos, center, item=None, name=None, index=None):
|
||||
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})
|
||||
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):
|
||||
def addRotateFreeHandle(self, pos, center, axes=None, item=None, name=None, index=None):
|
||||
pos = Point(pos)
|
||||
center = Point(center)
|
||||
return self.addHandle({'name': name, 'type': 'rf', 'center': center, 'pos': pos, 'item': item})
|
||||
return self.addHandle({'name': name, 'type': 'rf', 'center': center, 'pos': pos, 'item': item}, index=index)
|
||||
|
||||
def addHandle(self, info):
|
||||
def addHandle(self, info, index=None):
|
||||
## If a Handle was not supplied, create it now
|
||||
if 'item' not in info or info['item'] is None:
|
||||
#print "BEFORE ADD CHILD:", self.childItems()
|
||||
h = Handle(self.handleSize, typ=info['type'], pen=self.handlePen, parent=self)
|
||||
#print "AFTER ADD CHILD:", self.childItems()
|
||||
h.setPos(info['pos'] * self.state['size'])
|
||||
info['item'] = h
|
||||
else:
|
||||
h = info['item']
|
||||
iid = len(self.handles)
|
||||
h.connectROI(self, iid)
|
||||
#h.mouseMoveEvent = lambda ev: self.pointMoveEvent(iid, ev)
|
||||
#h.mousePressEvent = lambda ev: self.pointPressEvent(iid, ev)
|
||||
#h.mouseReleaseEvent = lambda ev: self.pointReleaseEvent(iid, ev)
|
||||
self.handles.append(info)
|
||||
if info['pos'] is None:
|
||||
info['pos'] = h.pos()
|
||||
|
||||
## connect the handle to this ROI
|
||||
#iid = len(self.handles)
|
||||
h.connectROI(self)
|
||||
if index is None:
|
||||
self.handles.append(info)
|
||||
else:
|
||||
self.handles.insert(index, info)
|
||||
|
||||
h.setZValue(self.zValue()+1)
|
||||
#if self.isSelected():
|
||||
#h.show()
|
||||
#else:
|
||||
#h.hide()
|
||||
self.stateChanged()
|
||||
return h
|
||||
|
||||
def replaceHandle(self, ind, handle):
|
||||
oldHandle = self.handles[ind]
|
||||
self.handles[ind] = handle
|
||||
oldHandle['item'].disconnectROI(self)
|
||||
handle['item'].connectROI(self, ind)
|
||||
def indexOfHandle(self, handle):
|
||||
if isinstance(handle, Handle):
|
||||
index = [i for i, info in enumerate(self.handles) if info['item'] is handle]
|
||||
if len(index) == 0:
|
||||
raise Exception("Cannot remove handle; it is not attached to this ROI")
|
||||
return index[0]
|
||||
else:
|
||||
return handle
|
||||
|
||||
def removeHandle(self, handle):
|
||||
"""Remove a handle from this ROI. Argument may be either a Handle instance or the integer index of the handle."""
|
||||
index = self.indexOfHandle(handle)
|
||||
|
||||
handle = self.handles[index]['item']
|
||||
self.handles.pop(index)
|
||||
handle.disconnectROI(self)
|
||||
if len(handle.rois) == 0:
|
||||
self.scene().removeItem(handle)
|
||||
self.stateChanged()
|
||||
|
||||
def replaceHandle(self, oldHandle, newHandle):
|
||||
"""Replace one handle in the ROI for another. This is useful when connecting multiple ROIs together.
|
||||
*oldHandle* may be a Handle instance or the index of a handle."""
|
||||
#print "========================="
|
||||
#print "replace", oldHandle, newHandle
|
||||
#print self
|
||||
#print self.handles
|
||||
#print "-----------------"
|
||||
index = self.indexOfHandle(oldHandle)
|
||||
info = self.handles[index]
|
||||
self.removeHandle(index)
|
||||
info['item'] = newHandle
|
||||
info['pos'] = newHandle.pos()
|
||||
self.addHandle(info, index=index)
|
||||
#print self.handles
|
||||
|
||||
def checkRemoveHandle(self, handle):
|
||||
## This is used when displaying a Handle's context menu to determine
|
||||
## whether removing is allowed.
|
||||
## Subclasses may wish to override this to disable the menu entry.
|
||||
## Note: by default, handles are not user-removable even if this method returns True.
|
||||
return True
|
||||
|
||||
|
||||
def getLocalHandlePositions(self, index=None):
|
||||
"""Returns the position of a handle in ROI coordinates"""
|
||||
if index == None:
|
||||
@ -451,19 +491,20 @@ class ROI(GraphicsObject):
|
||||
#self.movePoint(pt, ev.scenePos(), ev.modifiers())
|
||||
|
||||
|
||||
def checkPointMove(self, pt, pos, modifiers):
|
||||
def checkPointMove(self, handle, pos, modifiers):
|
||||
"""When handles move, they must ask the ROI if the move is acceptable.
|
||||
By default, this always returns True. Subclasses may wish override.
|
||||
"""
|
||||
return True
|
||||
|
||||
|
||||
def movePoint(self, pt, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True):
|
||||
def movePoint(self, handle, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True):
|
||||
## called by Handles when they are moved.
|
||||
## pos is the new position of the handle in scene coords, as requested by the handle.
|
||||
|
||||
newState = self.stateCopy()
|
||||
h = self.handles[pt]
|
||||
index = self.indexOfHandle(handle)
|
||||
h = self.handles[index]
|
||||
p0 = self.mapToScene(h['pos'] * self.state['size'])
|
||||
p1 = Point(pos)
|
||||
|
||||
@ -485,7 +526,9 @@ class ROI(GraphicsObject):
|
||||
self.translate(p1-p0, snap=snap, update=False)
|
||||
|
||||
elif h['type'] == 'f':
|
||||
newPos = self.mapFromScene(pos)
|
||||
h['item'].setPos(self.mapFromScene(pos))
|
||||
h['pos'] = newPos
|
||||
self.freeHandleMoved = True
|
||||
#self.sigRegionChanged.emit(self) ## should be taken care of by call to stateChanged()
|
||||
|
||||
@ -641,7 +684,7 @@ class ROI(GraphicsObject):
|
||||
if self.state[k] != self.lastState[k]:
|
||||
changed = True
|
||||
|
||||
|
||||
self.prepareGeometryChange()
|
||||
if changed:
|
||||
## Move all handles to match the current configuration of the ROI
|
||||
for h in self.handles:
|
||||
@ -935,12 +978,15 @@ class Handle(UIGraphicsItem):
|
||||
'sr': (12, 0),
|
||||
'rf': (12, 0),
|
||||
}
|
||||
|
||||
sigClicked = QtCore.Signal(object, object) # self, event
|
||||
sigRemoveRequested = QtCore.Signal(object) # self
|
||||
|
||||
def __init__(self, radius, typ=None, pen=(200, 200, 220), parent=None, deletable=False):
|
||||
#print " create item with parent", parent
|
||||
#self.bounds = QtCore.QRectF(-1e-10, -1e-10, 2e-10, 2e-10)
|
||||
#self.setFlags(self.ItemIgnoresTransformations | self.ItemSendsScenePositionChanges)
|
||||
self.roi = []
|
||||
self.rois = []
|
||||
self.radius = radius
|
||||
self.typ = typ
|
||||
self.pen = fn.mkPen(pen)
|
||||
@ -961,17 +1007,19 @@ class Handle(UIGraphicsItem):
|
||||
#self.updateShape()
|
||||
self.setZValue(11)
|
||||
|
||||
def connectROI(self, roi, i):
|
||||
def connectROI(self, roi):
|
||||
### roi is the "parent" roi, i is the index of the handle in roi.handles
|
||||
self.roi.append((roi, i))
|
||||
self.rois.append(roi)
|
||||
|
||||
def disconnectROI(self, roi):
|
||||
for i, r in enumerate(self.roi):
|
||||
if r[0] == roi:
|
||||
self.roi.pop(i)
|
||||
self.rois.remove(roi)
|
||||
#for i, r in enumerate(self.roi):
|
||||
#if r[0] == roi:
|
||||
#self.roi.pop(i)
|
||||
|
||||
def close(self):
|
||||
self.parentItem().handleRemoved(self)
|
||||
#def close(self):
|
||||
#for r in self.roi:
|
||||
#r.removeHandle(self)
|
||||
|
||||
def setDeletable(self, b):
|
||||
self.deletable = b
|
||||
@ -979,8 +1027,9 @@ class Handle(UIGraphicsItem):
|
||||
self.setAcceptedMouseButtons(self.acceptedMouseButtons() | QtCore.Qt.RightButton)
|
||||
else:
|
||||
self.setAcceptedMouseButtons(self.acceptedMouseButtons() & ~QtCore.Qt.RightButton)
|
||||
#def boundingRect(self):
|
||||
#return self.bounds
|
||||
|
||||
def removeClicked(self):
|
||||
self.sigRemoveRequested.emit(self)
|
||||
|
||||
def hoverEvent(self, ev):
|
||||
hover = False
|
||||
@ -1029,7 +1078,7 @@ class Handle(UIGraphicsItem):
|
||||
def buildMenu(self):
|
||||
menu = QtGui.QMenu()
|
||||
menu.setTitle("Handle")
|
||||
menu.addAction("Remove handle", self.close)
|
||||
self.removeAction = menu.addAction("Remove handle", self.removeClicked)
|
||||
return menu
|
||||
|
||||
def getMenu(self):
|
||||
@ -1041,6 +1090,10 @@ class Handle(UIGraphicsItem):
|
||||
|
||||
def raiseContextMenu(self, ev):
|
||||
menu = self.scene().addParentContextMenus(self, self.getMenu(), ev)
|
||||
|
||||
## Make sure it is still ok to remove this handle
|
||||
removeAllowed = all([r.checkRemoveHandle(self) for r in self.rois])
|
||||
self.removeAction.setEnabled(removeAllowed)
|
||||
pos = ev.screenPos()
|
||||
menu.popup(QtCore.QPoint(pos.x(), pos.y()))
|
||||
|
||||
@ -1057,12 +1110,12 @@ class Handle(UIGraphicsItem):
|
||||
|
||||
if ev.isFinish():
|
||||
if self.isMoving:
|
||||
for r in self.roi:
|
||||
r[0].stateChangeFinished()
|
||||
for r in self.rois:
|
||||
r.stateChangeFinished()
|
||||
self.isMoving = False
|
||||
elif ev.isStart():
|
||||
for r in self.roi:
|
||||
r[0].handleMoveStarted()
|
||||
for r in self.rois:
|
||||
r.handleMoveStarted()
|
||||
self.isMoving = True
|
||||
self.startPos = self.scenePos()
|
||||
self.cursorOffset = self.scenePos() - ev.buttonDownScenePos()
|
||||
@ -1072,13 +1125,13 @@ class Handle(UIGraphicsItem):
|
||||
self.movePoint(pos, ev.modifiers(), finish=False)
|
||||
|
||||
def movePoint(self, pos, modifiers=QtCore.Qt.KeyboardModifier(), finish=True):
|
||||
for r in self.roi:
|
||||
if not r[0].checkPointMove(r[1], pos, modifiers):
|
||||
for r in self.rois:
|
||||
if not r.checkPointMove(self, pos, modifiers):
|
||||
return
|
||||
#print "point moved; inform %d ROIs" % len(self.roi)
|
||||
# A handle can be used by multiple ROIs; tell each to update its handle position
|
||||
for r in self.roi:
|
||||
r[0].movePoint(r[1], pos, modifiers, finish=finish)
|
||||
for r in self.rois:
|
||||
r.movePoint(self, pos, modifiers, finish=finish)
|
||||
|
||||
def buildPath(self):
|
||||
size = self.radius
|
||||
@ -1269,15 +1322,12 @@ class MultiLineROI(QtGui.QGraphicsObject):
|
||||
if w == w0:
|
||||
continue
|
||||
l.scale([1.0, w/w0], center=[0.5,0.5])
|
||||
#self.emit(QtCore.SIGNAL('regionChanged'), self)
|
||||
self.sigRegionChanged.emit(self)
|
||||
|
||||
def roiChangeStartedEvent(self):
|
||||
#self.emit(QtCore.SIGNAL('regionChangeStarted'), self)
|
||||
self.sigRegionChangeStarted.emit(self)
|
||||
|
||||
def roiChangeFinishedEvent(self):
|
||||
#self.emit(QtCore.SIGNAL('regionChangeFinished'), self)
|
||||
self.sigRegionChangeFinished.emit(self)
|
||||
|
||||
|
||||
@ -1395,99 +1445,129 @@ class PolygonROI(ROI):
|
||||
class PolyLineROI(ROI):
|
||||
"""Container class for multiple connected LineSegmentROIs. Responsible for adding new
|
||||
line segments, and for translation/(rotation?) of multiple lines together."""
|
||||
def __init__(self, positions, size=[1,1], closed=False, pos=None, **args):
|
||||
def __init__(self, positions, closed=False, pos=None, **args):
|
||||
|
||||
if pos is None:
|
||||
pos = [0,0]
|
||||
pen=args.get('pen', fn.mkPen((100,100,255)))
|
||||
ROI.__init__(self, pos, size, **args)
|
||||
|
||||
#pen=args.get('pen', fn.mkPen((100,100,255)))
|
||||
ROI.__init__(self, pos, size=[1,1], **args)
|
||||
self.closed = closed
|
||||
self.segments = []
|
||||
|
||||
for i, p in enumerate(positions[:-1]):
|
||||
h = None
|
||||
if len(self.segments) > 0:
|
||||
h = self.segments[-1].handles[-1]['item']
|
||||
self.segments.append(LineSegmentROI([p, positions[i+1]], pos=pos, handles=(h, None), pen=pen, parent=self, movable=False))
|
||||
for p in positions:
|
||||
self.addFreeHandle(p)
|
||||
|
||||
start = -1 if self.closed else 0
|
||||
for i in range(start, len(self.handles)-1):
|
||||
self.addSegment(self.handles[i]['item'], self.handles[i+1]['item'])
|
||||
#for i in range(len(positions)-1):
|
||||
#h2 = self.addFreeHandle(positions[i+1])
|
||||
#segment = LineSegmentROI(handles=(h, h2), pen=pen, parent=self, movable=False)
|
||||
#self.segments.append(segment)
|
||||
#h = h2
|
||||
|
||||
|
||||
for i, s in enumerate(self.segments):
|
||||
h = s.handles[0]
|
||||
self.addFreeHandle(h['pos'], item=h['item'])
|
||||
s.setZValue(self.zValue() +1)
|
||||
#for i, s in enumerate(self.segments):
|
||||
#h = s.handles[0]
|
||||
#self.addFreeHandle(h['pos'], item=h['item'])
|
||||
#s.setZValue(self.zValue() +1)
|
||||
|
||||
h = self.segments[-1].handles[1]
|
||||
self.addFreeHandle(h['pos'], item=h['item'])
|
||||
#h = self.segments[-1].handles[1]
|
||||
#self.addFreeHandle(h['pos'], item=h['item'])
|
||||
|
||||
h1 = self.segments[-1].handles[-1]['item']
|
||||
h2 = self.segments[0].handles[0]['item']
|
||||
if closed:
|
||||
self.segments.append(LineSegmentROI([positions[-1], positions[0]], pos=pos, handles=(h1, h2), pen=pen, parent=self, movable=False))
|
||||
h2.setParentItem(self.segments[-1])
|
||||
for s in self.segments:
|
||||
self.setSegmentSettings(s)
|
||||
#if closed:
|
||||
#h1 = self.handles[-1]['item']
|
||||
#h2 = self.handles[0]['item']
|
||||
#self.segments.append(LineSegmentROI([positions[-1], positions[0]], pos=pos, handles=(h1, h2), pen=pen, parent=self, movable=False))
|
||||
#h2.setParentItem(self.segments[-1])
|
||||
|
||||
def movePoint(self, *args, **kargs):
|
||||
pass
|
||||
#def segmentChanged(self, obj):
|
||||
|
||||
#for s in self.segments:
|
||||
#self.setSegmentSettings(s)
|
||||
|
||||
#def movePoint(self, *args, **kargs):
|
||||
#pass
|
||||
def setSegmentSettings(self, s):
|
||||
s.setParentROI(self)
|
||||
s.sigClicked.connect(self.newHandleRequested)
|
||||
s.setAcceptedMouseButtons(QtCore.Qt.LeftButton)
|
||||
for h in s.handles:
|
||||
|
||||
def addSegment(self, h1, h2, index=None):
|
||||
seg = LineSegmentROI(handles=(h1, h2), pen=self.pen, parent=self, movable=False)
|
||||
if index is None:
|
||||
self.segments.append(seg)
|
||||
else:
|
||||
self.segments.insert(index, seg)
|
||||
seg.sigClicked.connect(self.segmentClicked)
|
||||
seg.setAcceptedMouseButtons(QtCore.Qt.LeftButton)
|
||||
seg.setZValue(self.zValue()+1)
|
||||
for h in seg.handles:
|
||||
h['item'].setDeletable(True)
|
||||
h['item'].setAcceptedMouseButtons(h['item'].acceptedMouseButtons() | QtCore.Qt.LeftButton) ## have these handles take left clicks too, so that handles cannot be added on top of other handles
|
||||
|
||||
def setMouseHover(self, hover):
|
||||
## Inform all the ROI's segments that the mouse is(not) hovering over it
|
||||
if self.mouseHovering == hover:
|
||||
return
|
||||
self.mouseHovering = hover
|
||||
#if self.mouseHovering == hover:
|
||||
#return
|
||||
#self.mouseHovering = hover
|
||||
ROI.setMouseHover(self, hover)
|
||||
for s in self.segments:
|
||||
s.setMouseHover(hover)
|
||||
|
||||
def newHandleRequested(self, segment, ev=None, pos=None): ## pos should be in this item's coordinate system
|
||||
|
||||
def addHandle(self, info, index=None):
|
||||
h = ROI.addHandle(self, info, index=index)
|
||||
h.sigRemoveRequested.connect(self.removeHandle)
|
||||
return h
|
||||
|
||||
def segmentClicked(self, segment, ev=None, pos=None): ## pos should be in this item's coordinate system
|
||||
if ev != None:
|
||||
pos = segment.mapToParent(ev.pos())
|
||||
elif pos != None:
|
||||
pos = pos
|
||||
else:
|
||||
raise Exception("Either an event or a position must be given.")
|
||||
h1 = segment.handles[0]
|
||||
h2 = segment.handles[1]
|
||||
h1 = segment.handles[0]['item']
|
||||
h2 = segment.handles[1]['item']
|
||||
|
||||
for i, s in enumerate(self.segments):
|
||||
if s == segment:
|
||||
#newSegment = LineSegmentROI([pos, h2['pos']], [0,0], handles=(None, h2['item']), pen=segment.pen, movable=False, acceptsHandles=True, parent=self)
|
||||
newSegment = LineSegmentROI([h1['pos'], pos], [0,0], handles=(h1['item'], None), pen=segment.pen, movable=False, acceptsHandles=True, parent=self)
|
||||
self.setSegmentSettings(newSegment)
|
||||
self.segments.insert(i, newSegment)
|
||||
break
|
||||
|
||||
segment.replaceHandle(0, newSegment.handles[1])
|
||||
i = self.segments.index(segment)
|
||||
h3 = self.addFreeHandle(pos, index=self.indexOfHandle(h2))
|
||||
self.addSegment(h3, h2, index=i+1)
|
||||
segment.replaceHandle(h2, h3)
|
||||
|
||||
self.handles.insert(i+1, newSegment.handles[1])
|
||||
|
||||
#def report(self):
|
||||
#for s in self.segments:
|
||||
#print s
|
||||
#for h in s.handles:
|
||||
#print " ", h
|
||||
#for h in self.handles:
|
||||
#print h
|
||||
|
||||
|
||||
def handleRemoved(self, segment, handle):
|
||||
#self.segments[i-1].replaceHandle(1, self.segments[ind].handles[1])
|
||||
for i, s in enumerate(self.segments):
|
||||
if s == segment:
|
||||
#s.replaceHandle(0, self.segments[i-1].handles[0])
|
||||
if s != self.segments[-1]:
|
||||
j = i+1
|
||||
else:
|
||||
j=0
|
||||
self.segments[j].replaceHandle(0, segment.handles[0])
|
||||
break
|
||||
|
||||
handle.disconnectROI(self.segments[j])
|
||||
#handle.disconnectROI(self)
|
||||
self.handles.pop(j)
|
||||
#segment.handles[1]['item'].setParentItem(self.segments[(i+1)%len(self.segments)])
|
||||
self.segments.remove(segment)
|
||||
segment.close()
|
||||
def removeHandle(self, handle, updateSegments=True):
|
||||
ROI.removeHandle(self, handle)
|
||||
handle.sigRemoveRequested.disconnect(self.removeHandle)
|
||||
|
||||
if not updateSegments:
|
||||
return
|
||||
segments = handle.rois[:]
|
||||
|
||||
if len(segments) == 1:
|
||||
self.removeSegment(segments[0])
|
||||
else:
|
||||
handles = [h['item'] for h in segments[1].handles]
|
||||
handles.remove(handle)
|
||||
segments[0].replaceHandle(handle, handles[0])
|
||||
self.removeSegment(segments[1])
|
||||
|
||||
def removeSegment(self, seg):
|
||||
for handle in seg.handles[:]:
|
||||
seg.removeHandle(handle['item'])
|
||||
self.segments.remove(seg)
|
||||
seg.sigClicked.disconnect(self.segmentClicked)
|
||||
self.scene().removeItem(seg)
|
||||
|
||||
def checkRemoveHandle(self, h):
|
||||
## called when a handle is about to display its context menu
|
||||
if self.closed:
|
||||
return len(self.handles) > 3
|
||||
else:
|
||||
return len(self.handles) > 2
|
||||
|
||||
def paint(self, p, *args):
|
||||
#for s in self.segments:
|
||||
@ -1499,10 +1579,11 @@ class PolyLineROI(ROI):
|
||||
pass
|
||||
|
||||
def boundingRect(self):
|
||||
r = QtCore.QRectF()
|
||||
for h in self.handles:
|
||||
r |= self.mapFromItem(h['item'], h['item'].boundingRect()).boundingRect() ## |= gives the union of the two QRectFs
|
||||
return r
|
||||
return self.shape().boundingRect()
|
||||
#r = QtCore.QRectF()
|
||||
#for h in self.handles:
|
||||
#r |= self.mapFromItem(h['item'], h['item'].boundingRect()).boundingRect() ## |= gives the union of the two QRectFs
|
||||
#return r
|
||||
|
||||
def shape(self):
|
||||
p = QtGui.QPainterPath()
|
||||
@ -1512,14 +1593,16 @@ class PolyLineROI(ROI):
|
||||
p.lineTo(self.handles[0]['item'].pos())
|
||||
return p
|
||||
|
||||
|
||||
class LineSegmentROI(ROI):
|
||||
"""
|
||||
ROI subclass with two freely-moving handles defining a line.
|
||||
"""
|
||||
|
||||
def __init__(self, positions, pos=None, handles=(None,None), acceptsHandles=False, **args):
|
||||
def __init__(self, positions=(None, None), pos=None, handles=(None,None), **args):
|
||||
if pos is None:
|
||||
pos = [0,0]
|
||||
|
||||
ROI.__init__(self, pos, [1,1], **args)
|
||||
#ROI.__init__(self, positions[0])
|
||||
if len(positions) > 2:
|
||||
@ -1528,35 +1611,35 @@ class LineSegmentROI(ROI):
|
||||
for i, p in enumerate(positions):
|
||||
self.addFreeHandle(p, item=handles[i])
|
||||
|
||||
self.setZValue(1000)
|
||||
self.parentROI = None
|
||||
self.hasParentROI = False
|
||||
self.setAcceptsHandles(acceptsHandles)
|
||||
#self.setZValue(1000)
|
||||
#self.parentROI = None
|
||||
#self.hasParentROI = False
|
||||
#self.setAcceptsHandles(acceptsHandles)
|
||||
|
||||
def setParentROI(self, parent):
|
||||
self.parentROI = parent
|
||||
if parent != None:
|
||||
self.hasParentROI = True
|
||||
else:
|
||||
self.hasParentROI = False
|
||||
#def setParentROI(self, parent):
|
||||
#self.parentROI = parent
|
||||
#if parent != None:
|
||||
#self.hasParentROI = True
|
||||
#else:
|
||||
#self.hasParentROI = False
|
||||
|
||||
def setAcceptsHandles(self, b):
|
||||
if b:
|
||||
self.setAcceptedMouseButtons(QtCore.Qt.LeftButton)
|
||||
else:
|
||||
self.setAcceptedMouseButtons(QtCore.Qt.NoButton)
|
||||
#def setAcceptsHandles(self, b):
|
||||
#if b:
|
||||
#self.setAcceptedMouseButtons(QtCore.Qt.LeftButton)
|
||||
#else:
|
||||
#self.setAcceptedMouseButtons(QtCore.Qt.NoButton)
|
||||
|
||||
def close(self):
|
||||
#for h in self.handles:
|
||||
#if len(h['item'].roi) == 1:
|
||||
#h['item'].scene().removeItem(h['item'])
|
||||
#elif h['item'].parentItem() == self:
|
||||
#h['item'].setParentItem(self.parentItem())
|
||||
#def close(self):
|
||||
##for h in self.handles:
|
||||
##if len(h['item'].roi) == 1:
|
||||
##h['item'].scene().removeItem(h['item'])
|
||||
##elif h['item'].parentItem() == self:
|
||||
##h['item'].setParentItem(self.parentItem())
|
||||
|
||||
self.scene().removeItem(self)
|
||||
#self.scene().removeItem(self)
|
||||
|
||||
def handleRemoved(self, handle):
|
||||
self.parentROI.handleRemoved(self, handle)
|
||||
#def handleRemoved(self, handle):
|
||||
#self.parentROI.handleRemoved(self, handle)
|
||||
|
||||
#def hoverEvent(self, ev):
|
||||
#if (self.translatable or self.acceptsHandles) and (not ev.isExit()) and ev.acceptDrags(QtCore.Qt.LeftButton):
|
||||
@ -1576,21 +1659,21 @@ class LineSegmentROI(ROI):
|
||||
#else:
|
||||
#ev.ignore()
|
||||
|
||||
def newHandleRequested(self, evPos):
|
||||
#def newHandleRequested(self, evPos):
|
||||
#print "newHandleRequested"
|
||||
|
||||
#if evPos - self.handles[0].pos() == Point(0.,0.) or evPos-handles[1].pos() == Point(0.,0.):
|
||||
# return
|
||||
self.parentROI.newHandleRequested(self, self.mapToParent(evPos)) ## so now evPos should be passed in in the parents coordinate system
|
||||
#self.parentROI.newHandleRequested(self, self.mapToParent(evPos)) ## so now evPos should be passed in in the parents coordinate system
|
||||
|
||||
def listPoints(self):
|
||||
return [p['item'].pos() for p in self.handles]
|
||||
|
||||
def movePoint(self, *args, **kargs):
|
||||
ROI.movePoint(self, *args, **kargs)
|
||||
self.prepareGeometryChange()
|
||||
for h in self.handles:
|
||||
h['pos'] = h['item'].pos()
|
||||
#def movePoint(self, *args, **kargs):
|
||||
#ROI.movePoint(self, *args, **kargs)
|
||||
#self.prepareGeometryChange()
|
||||
#for h in self.handles:
|
||||
#h['pos'] = h['item'].pos()
|
||||
|
||||
def paint(self, p, *args):
|
||||
p.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||
@ -1607,10 +1690,11 @@ class LineSegmentROI(ROI):
|
||||
#p.drawLine(h1, h2)
|
||||
|
||||
def boundingRect(self):
|
||||
r = QtCore.QRectF()
|
||||
for h in self.handles:
|
||||
r |= self.mapFromItem(h['item'], h['item'].boundingRect()).boundingRect() ## |= gives the union of the two QRectFs
|
||||
return r
|
||||
return self.shape().boundingRect()
|
||||
#r = QtCore.QRectF()
|
||||
#for h in self.handles:
|
||||
#r |= self.mapFromItem(h['item'], h['item'].boundingRect()).boundingRect() ## |= gives the union of the two QRectFs
|
||||
#return r
|
||||
|
||||
def shape(self):
|
||||
p = QtGui.QPainterPath()
|
||||
@ -1619,11 +1703,12 @@ class LineSegmentROI(ROI):
|
||||
|
||||
h1 = self.handles[0]['item'].pos()
|
||||
h2 = self.handles[1]['item'].pos()
|
||||
pxv = self.pixelVectors(h2-h1)[1] * 4
|
||||
pxv = self.pixelVectors(h2-h1)[1]
|
||||
|
||||
if pxv == (None, None):
|
||||
p.addRect(self.boundingRect())
|
||||
if pxv is None:
|
||||
return p
|
||||
|
||||
pxv *= 4
|
||||
|
||||
p.moveTo(h1+pxv)
|
||||
p.lineTo(h2+pxv)
|
||||
@ -1633,13 +1718,13 @@ class LineSegmentROI(ROI):
|
||||
|
||||
return p
|
||||
|
||||
def stateCopy(self):
|
||||
sc = {}
|
||||
sc['pos'] = Point(self.state['pos'])
|
||||
sc['size'] = Point(self.state['size'])
|
||||
sc['angle'] = self.state['angle']
|
||||
#sc['handles'] = self.handles
|
||||
return sc
|
||||
#def stateCopy(self):
|
||||
#sc = {}
|
||||
#sc['pos'] = Point(self.state['pos'])
|
||||
#sc['size'] = Point(self.state['size'])
|
||||
#sc['angle'] = self.state['angle']
|
||||
##sc['handles'] = self.handles
|
||||
#return sc
|
||||
|
||||
def getArrayRegion(self, data, img, axes=(0,1)):
|
||||
"""
|
||||
@ -1647,15 +1732,6 @@ class LineSegmentROI(ROI):
|
||||
Since this pulls 1D data from a 2D coordinate system, the return value will have ndim = data.ndim-1
|
||||
"""
|
||||
|
||||
|
||||
#shape = self.state['size']
|
||||
|
||||
#origin = self.mapToItem(img, QtCore.QPointF(0, 0))
|
||||
|
||||
## vx and vy point in the directions of the slice axes, but must be scaled properly
|
||||
#vx = self.mapToItem(img, QtCore.QPointF(1, 0)) - origin
|
||||
#vy = self.mapToItem(img, QtCore.QPointF(0, 1)) - origin
|
||||
|
||||
imgPts = [self.mapToItem(img, h['item'].pos()) for h in self.handles]
|
||||
rgns = []
|
||||
for i in range(len(imgPts)-1):
|
||||
@ -1666,23 +1742,6 @@ class LineSegmentROI(ROI):
|
||||
|
||||
return np.concatenate(rgns, axis=axes[0])
|
||||
|
||||
|
||||
#lvx = np.sqrt(vx.x()**2 + vx.y()**2)
|
||||
#lvy = np.sqrt(vy.x()**2 + vy.y()**2)
|
||||
#pxLen = img.width() / float(data.shape[axes[0]])
|
||||
#sx = pxLen / lvx
|
||||
#sy = pxLen / lvy
|
||||
|
||||
#vectors = ((vx.x()*sx, vx.y()*sx), (vy.x()*sy, vy.y()*sy))
|
||||
#shape = self.state['size']
|
||||
#shape = [abs(shape[0]/sx), abs(shape[1]/sy)]
|
||||
|
||||
#origin = (origin.x(), origin.y())
|
||||
|
||||
##print "shape", shape, "vectors", vectors, "origin", origin
|
||||
|
||||
#return fn.affineSlice(data, shape=shape, vectors=vectors, origin=origin, axes=axes, order=1)
|
||||
|
||||
|
||||
class SpiralROI(ROI):
|
||||
def __init__(self, pos=None, size=None, **args):
|
||||
|
Loading…
Reference in New Issue
Block a user