import PythonQt
from PythonQt import QtCore, QtGui
import director.visualization as vis
import director.objectmodel as om
from director.debugVis import DebugData
import director.vtkAll as vtk
from director import callbacks
import numpy as np
from director.affordanceitems import AffordanceItem
[docs]class PointPicker(object):
def __init__(self, view, obj=None, callback=None, numberOfPoints=2, drawLines=True, abortCallback=None):
self.view = view
self.obj = obj
self.pickType = 'points'
self.tolerance = 0.01
self.numberOfPoints = numberOfPoints
self.drawLines = drawLines
self.drawClosedLoop = False
self.annotationObj = None
self.annotationFunc = callback
self.abortFunc = abortCallback
self.annotationName = 'annotation'
self.annotationFolder = 'segmentation'
self.eventFilter = None
self.clear()
[docs] def start(self):
self.installEventFilter()
self.clear()
[docs] def stop(self):
self.removeEventFilter()
[docs] def installEventFilter(self):
self.eventFilter = PythonQt.dd.ddPythonEventFilter()
self.view.vtkWidget().installEventFilter(self.eventFilter)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseMove)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseButtonPress)
self.eventFilter.addFilteredEventType(QtCore.QEvent.KeyPress)
self.eventFilter.addFilteredEventType(QtCore.QEvent.KeyRelease)
self.eventFilter.connect('handleEvent(QObject*, QEvent*)', self.onEvent)
[docs] def removeEventFilter(self):
if self.eventFilter:
self.view.vtkWidget().removeEventFilter(self.eventFilter)
self.eventFilter = None
[docs] def onEvent(self, obj, event):
if event.type() == QtCore.QEvent.KeyPress and event.key() == QtCore.Qt.Key_Escape:
self.stop()
self.clear()
if self.abortFunc is not None:
self.abortFunc()
return
if event.modifiers() != QtCore.Qt.ShiftModifier:
if self.annotationObj:
self.annotationObj.setProperty('Visible', False)
return
if self.annotationObj:
self.annotationObj.setProperty('Visible', True)
if event.type() == QtCore.QEvent.MouseMove:
self.onMouseMove(vis.mapMousePosition(obj, event), event.modifiers())
elif event.type() == QtCore.QEvent.MouseButtonPress:
self.onMousePress(vis.mapMousePosition(obj, event), event.modifiers())
[docs] def clear(self):
if self.annotationObj:
self.annotationObj.setProperty('Visible', False)
self.annotationObj = None
self.points = [None for i in xrange(self.numberOfPoints)]
self.hoverPos = None
self.lastMovePos = [0, 0]
[docs] def onMouseMove(self, displayPoint, modifiers=None):
self.lastMovePos = displayPoint
self.tick()
[docs] def onMousePress(self, displayPoint, modifiers=None):
for i in xrange(self.numberOfPoints):
if self.points[i] is None:
self.points[i] = self.hoverPos
break
if self.points[-1] is not None:
self.finish()
[docs] def finish(self):
points = [p.copy() for p in self.points]
if self.annotationFunc is not None:
self.annotationFunc(*points)
self.clear()
[docs] def draw(self):
d = DebugData()
points = [p if p is not None else self.hoverPos for p in self.points]
# draw points
for p in points:
if p is not None:
d.addSphere(p, radius=0.008)
if self.drawLines:
# draw lines
for a, b in zip(points, points[1:]):
if b is not None:
d.addLine(a, b)
# connect end points
if points[-1] is not None and self.drawClosedLoop:
d.addLine(points[0], points[-1])
self.annotationObj = vis.updatePolyData(d.getPolyData(),
self.annotationName,
parent=self.annotationFolder,
view=self.view)
self.annotationObj.setProperty('Color', [1,0,0])
self.annotationObj.actor.SetPickable(False)
[docs] def tick(self):
if self.obj is None:
pickedPointFields = vis.pickPoint(self.lastMovePos, self.view, pickType=self.pickType,
tolerance=self.tolerance)
self.hoverPos = pickedPointFields.pickedPoint
prop = pickedPointFields.pickedProp
if prop is None:
self.hoverPos = None
else:
pickedPointFields = vis.pickPoint(self.lastMovePos, self.view, obj=self.obj, pickType=self.pickType, tolerance=self.tolerance)
self.hoverPos = pickedPointFields.pickedPoint
self.draw()
[docs]class ImagePointPicker(object):
DOUBLE_CLICK_EVENT = 'DOUBLE_CLICK_EVENT'
def __init__(self, imageView, obj=None, callback=None, numberOfPoints=1, drawLines=True):
self.imageView = imageView
self.view = imageView.view
self.obj = obj
self.drawLines = drawLines
self.annotationObj = None
self.annotationFunc = callback
self.eventFilter = None
self.numberOfPoints = numberOfPoints
self.showCursor = False
self.cursorObj = None
self.callbacks = callbacks.CallbackRegistry([self.DOUBLE_CLICK_EVENT])
self.clear()
[docs] def start(self):
self.installEventFilter()
self.clear()
[docs] def stop(self):
self.removeEventFilter()
[docs] def installEventFilter(self):
self.eventFilter = PythonQt.dd.ddPythonEventFilter()
self.view.vtkWidget().installEventFilter(self.eventFilter)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseMove)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseButtonPress)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseButtonDblClick)
self.eventFilter.addFilteredEventType(QtCore.QEvent.KeyPress)
self.eventFilter.addFilteredEventType(QtCore.QEvent.KeyRelease)
self.eventFilter.connect('handleEvent(QObject*, QEvent*)', self.onEvent)
[docs] def removeEventFilter(self):
if self.eventFilter:
self.view.vtkWidget().removeEventFilter(self.eventFilter)
self.eventFilter = None
[docs] def connectDoubleClickEvent(self, func):
return self.callbacks.connect(self.DOUBLE_CLICK_EVENT, func)
[docs] def disconnectDoubleClickEvent(self, callbackId):
self.callbacks.disconnect(callbackId)
[docs] def onEvent(self, obj, event):
if event.type() == QtCore.QEvent.MouseButtonDblClick and event.button() == QtCore.Qt.LeftButton:
self.callbacks.process(self.DOUBLE_CLICK_EVENT, vis.mapMousePosition(obj, event), event.modifiers(), self.imageView)
if event.type() in (QtCore.QEvent.MouseMove, QtCore.QEvent.MouseButtonPress, QtCore.QEvent.Wheel):
if self.showCursor:
self.updateCursor(vis.mapMousePosition(obj, event))
elif event.type() == QtCore.QEvent.KeyPress:
if event.key() == QtCore.Qt.Key_Shift:
self.showCursor = True
elif event.type() == QtCore.QEvent.KeyRelease:
if event.key() == QtCore.Qt.Key_Shift:
self.showCursor = False
self.hideCursor()
if event.modifiers() != QtCore.Qt.ShiftModifier:
if self.annotationObj:
self.hoverPos = None
self.draw()
self.annotationObj.setProperty('Color', [1, 0, 0])
self.clear()
return
if self.annotationObj:
self.annotationObj.setProperty('Visible', True)
if event.type() == QtCore.QEvent.MouseMove:
self.onMouseMove(vis.mapMousePosition(obj, event), event.modifiers())
elif event.type() == QtCore.QEvent.MouseButtonPress:
self.onMousePress(vis.mapMousePosition(obj, event), event.modifiers())
[docs] def clear(self):
if self.annotationObj:
self.annotationObj.setProperty('Visible', False)
self.annotationObj = None
self.points = []
self.hoverPos = None
self.lastMovePos = [0, 0]
[docs] def onMouseMove(self, displayPoint, modifiers=None):
self.lastMovePos = displayPoint
self.hoverPos = self.displayPointToImagePoint(self.lastMovePos)
self.draw()
[docs] def onMousePress(self, displayPoint, modifiers=None):
point = self.displayPointToImagePoint(displayPoint)
if point is None:
return
self.points.append(point)
if len(self.points) == self.numberOfPoints:
self.finish()
[docs] def finish(self):
points = [np.array(p) for p in self.points]
self.clear()
if self.annotationFunc is not None:
self.annotationFunc(*points)
[docs] def draw(self):
d = DebugData()
points = list(self.points)
if self.hoverPos is not None:
points.append(self.hoverPos)
# draw points
for p in points:
d.addSphere(p, radius=5)
if self.drawLines and len(points) > 1:
for a, b in zip(points, points[1:]):
d.addLine(a, b)
# connect end points
# d.addLine(points[0], points[-1])
if self.annotationObj:
self.annotationObj.setPolyData(d.getPolyData())
else:
self.annotationObj = vis.updatePolyData(d.getPolyData(), 'annotation', parent='segmentation', color=[1,0,0], view=self.view)
self.annotationObj.addToView(self.view)
self.annotationObj.actor.SetPickable(False)
self.annotationObj.actor.GetProperty().SetLineWidth(2)
[docs] def hideCursor(self):
if self.cursorObj:
om.removeFromObjectModel(self.cursorObj)
[docs] def updateCursor(self, displayPoint):
center = self.displayPointToImagePoint(displayPoint, restrictToImageDimensions=False)
center = np.array(center)
d = DebugData()
d.addLine(center + [0, -3000, 0], center + [0, 3000, 0])
d.addLine(center + [-3000, 0, 0], center + [3000, 0, 0])
self.cursorObj = vis.updatePolyData(d.getPolyData(), 'cursor', alpha=0.5, view=self.view)
self.cursorObj.addToView(self.view)
self.cursorObj.actor.SetUseBounds(False)
self.cursorObj.actor.SetPickable(False)
self.view.render()
[docs] def displayPointToImagePoint(self, displayPoint, restrictToImageDimensions=True):
point = self.imageView.getImagePixel(displayPoint, restrictToImageDimensions)
if point is not None:
point[2] = -1.0
return point
[docs]class ObjectPicker(object):
def __init__(self, view, callback=None, abortCallback=None, numberOfObjects=1, getObjectsFunction=None, hoverColor=[1.0, 0.8, 0.8, 1.0]):
self.view = view
self.tolerance = 0.01
self.numberOfObjects = numberOfObjects
self.getObjectsFunction = getObjectsFunction
self.callbackFunc = callback
self.abortFunc = abortCallback
self.hoverColor = hoverColor[0:3]
self.hoverAlpha = hoverColor[3]
self.eventFilter = None
self.pickedObj = None
self.storedProps = {}
self.clear()
[docs] def start(self):
self.installEventFilter()
self.clear()
[docs] def stop(self):
self.removeEventFilter()
[docs] def installEventFilter(self):
self.eventFilter = PythonQt.dd.ddPythonEventFilter()
self.view.vtkWidget().installEventFilter(self.eventFilter)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseMove)
self.eventFilter.addFilteredEventType(QtCore.QEvent.MouseButtonPress)
self.eventFilter.addFilteredEventType(QtCore.QEvent.KeyPress)
self.eventFilter.addFilteredEventType(QtCore.QEvent.KeyRelease)
self.eventFilter.connect('handleEvent(QObject*, QEvent*)', self.onEvent)
[docs] def removeEventFilter(self):
if self.eventFilter:
self.view.vtkWidget().removeEventFilter(self.eventFilter)
self.eventFilter = None
[docs] def onEvent(self, obj, event):
if event.type() == QtCore.QEvent.KeyPress and event.key() == QtCore.Qt.Key_Escape:
self.stop()
self.clear()
if self.abortFunc is not None:
self.abortFunc()
return
if event.type() == QtCore.QEvent.MouseMove:
self.onMouseMove(vis.mapMousePosition(obj, event), event.modifiers())
elif event.type() == QtCore.QEvent.MouseButtonPress and event.button() == QtCore.Qt.LeftButton:
self.onMousePress(vis.mapMousePosition(obj, event), event.modifiers())
[docs] def clear(self):
self.objects = [None for i in xrange(self.numberOfObjects)]
self.hoverPos = None
self.lastMovePos = [0, 0]
self.unsetHoverProperties(self.pickedObj)
self.pickedObj = None
[docs] def onMouseMove(self, displayPoint, modifiers=None):
self.lastMovePos = displayPoint
self.tick()
[docs] def onMousePress(self, displayPoint, modifiers=None):
for i in xrange(self.numberOfObjects):
if self.objects[i] is None:
self.objects[i] = self.pickedObj
break
if self.objects[-1] is not None:
self.finish()
[docs] def finish(self):
if self.callbackFunc is not None:
try:
self.callbackFunc(self.objects)
finally:
self.clear()
self.stop()
[docs] def unsetHoverProperties(self, obj):
if obj is None:
return
for propName, value in self.storedProps.iteritems():
if obj.hasProperty(propName):
obj.setProperty(propName, value)
self.storedProps = {}
[docs] def setHoverProperties(self, obj):
if obj is None:
return
for propName, value in [['Color', self.hoverColor],
['Color Mode', 'Solid Color'],
['Alpha', self.hoverAlpha]]:
if obj.hasProperty(propName):
self.storedProps[propName] = obj.getProperty(propName)
obj.setProperty(propName, value)
[docs] def tick(self):
objs = self.getObjectsFunction() if self.getObjectsFunction else None
pickedPointFields = vis.pickPoint(self.lastMovePos, self.view, pickType='cells', tolerance=self.tolerance,
obj=objs)
self.hoverPos = pickedPointFields.pickedPoint
prop = pickedPointFields.pickedProp
prevPickedObj = self.pickedObj
curPickedObj = vis.getObjectByProp(prop)
if curPickedObj is not prevPickedObj:
self.unsetHoverProperties(prevPickedObj)
self.setHoverProperties(curPickedObj)
self.pickedObj = curPickedObj
[docs]class AffordancePicker(ObjectPicker):
def __init__(self, view, affordanceManager, filterFunc=None):
AffordancePicker.__init__(self, view, getObjectsFunction=self.getObjects)
self.affordanceManager = affordanceManager
self.filterFunc = filterFunc
[docs] def getObjects(self):
affs = self.affordanceManager.getAffordances()
affs = [a for a in affs if a.getProperty('Visible')]
if self.filterFunc is not None:
affs = [a for a in affs if self.filterFunc(a)]
return affs