import director.objectmodel as om
import director.applogic as app
from shallowCopy import shallowCopy
import director.vtkAll as vtk
from director import transformUtils
from director import callbacks
from director import frameupdater
from director.fieldcontainer import FieldContainer
from PythonQt import QtCore, QtGui
import numpy as np
import os
import colorsys
import weakref
import itertools
[docs]class PolyDataItem(om.ObjectModelItem):
defaultScalarRangeMap = {
# 'intensity' : (400, 4000),
'spindle_angle' : (0, 360),
'azimuth' : (-2.5, 2.5),
'scan_delta' : (0.0, 0.3),
'point distance to plane' : (-0.2, 0.2),
'normal angle to plane' : (0.0, 10.0),
}
def __init__(self, name, polyData, view):
om.ObjectModelItem.__init__(self, name, om.Icons.Robot)
self.views = []
self.polyData = polyData
self.mapper = vtk.vtkPolyDataMapper()
self.mapper.SetInput(self.polyData)
self.actor = vtk.vtkActor()
self.actor.SetMapper(self.mapper)
self.shadowActor = None
self.scalarBarWidget = None
self.extraViewRenderers = {}
self.rangeMap = dict(PolyDataItem.defaultScalarRangeMap)
self.addProperty('Color By', 0, attributes=om.PropertyAttributes(enumNames=['Solid Color']))
self.addProperty('Visible', True)
self.addProperty('Alpha', 1.0,
attributes=om.PropertyAttributes(decimals=2, minimum=0, maximum=1.0, singleStep=0.1, hidden=False))
self.addProperty('Point Size', self.actor.GetProperty().GetPointSize(),
attributes=om.PropertyAttributes(decimals=0, minimum=1, maximum=20, singleStep=1, hidden=False))
self.addProperty('Surface Mode', 0,
attributes=om.PropertyAttributes(enumNames=['Surface', 'Wireframe', 'Surface with edges', 'Points'], hidden=True))
self.addProperty('Color', [1.0, 1.0, 1.0])
self.addProperty('Show Scalar Bar', False)
self._updateSurfaceProperty()
self._updateColorByProperty()
if view is not None:
self.addToView(view)
def _renderAllViews(self):
for view in self.views:
view.render()
[docs] def hasDataSet(self, dataSet):
return dataSet == self.polyData
[docs] def setPolyData(self, polyData):
self.polyData = polyData
self.mapper.SetInput(polyData)
self._updateSurfaceProperty()
self._updateColorByProperty()
self._updateColorBy(retainColorMap=True)
if self.getProperty('Visible'):
self._renderAllViews()
[docs] def setRangeMap(self, key, value):
self.rangeMap[key] = value
[docs] def getArrayNames(self):
pointData = self.polyData.GetPointData()
return [pointData.GetArrayName(i) for i in xrange(pointData.GetNumberOfArrays())]
[docs] def setSolidColor(self, color):
self.setProperty('Color', [float(c) for c in color])
self.colorBy(None)
def _isPointCloud(self):
return self.polyData.GetNumberOfPoints() and (self.polyData.GetNumberOfCells() == self.polyData.GetNumberOfVerts())
[docs] def colorBy(self, arrayName, scalarRange=None, lut=None):
if not arrayName:
self.mapper.ScalarVisibilityOff()
self.polyData.GetPointData().SetActiveScalars(None)
return
array = self.polyData.GetPointData().GetArray(arrayName)
if not array:
print 'colorBy(%s): array not found' % arrayName
self.mapper.ScalarVisibilityOff()
self.polyData.GetPointData().SetActiveScalars(None)
return
self.polyData.GetPointData().SetActiveScalars(arrayName)
if not lut:
lut = self._getDefaultColorMap(array, scalarRange)
#self.mapper.SetColorModeToMapScalars()
self.mapper.ScalarVisibilityOn()
self.mapper.SetUseLookupTableScalarRange(True)
self.mapper.SetLookupTable(lut)
self.mapper.SetInterpolateScalarsBeforeMapping(not self._isPointCloud())
if self.getProperty('Visible'):
self._renderAllViews()
[docs] def getChildFrame(self):
frameName = self.getProperty('Name') + ' frame'
return self.findChild(frameName)
[docs] def addToView(self, view):
if view in self.views:
return
self.views.append(view)
view.renderer().AddActor(self.actor)
if self.shadowActor:
view.renderer().AddActor(self.shadowActor)
view.render()
def _onPropertyChanged(self, propertySet, propertyName):
om.ObjectModelItem._onPropertyChanged(self, propertySet, propertyName)
if propertyName == 'Point Size':
self.actor.GetProperty().SetPointSize(self.getProperty(propertyName))
elif propertyName == 'Alpha':
self.actor.GetProperty().SetOpacity(self.getProperty(propertyName))
if self.shadowActor:
self.shadowActor.GetProperty().SetOpacity(self.getProperty(propertyName))
elif propertyName == 'Visible':
self.actor.SetVisibility(self.getProperty(propertyName))
if self.shadowActor:
self.shadowActor.SetVisibility(self.getProperty(propertyName))
elif propertyName == 'Surface Mode':
mode = self.properties.getPropertyEnumValue(propertyName)
prop = self.actor.GetProperty()
if mode == 'Surface':
prop.SetRepresentationToSurface()
prop.EdgeVisibilityOff()
if mode == 'Wireframe':
prop.SetRepresentationToWireframe()
elif mode == 'Surface with edges':
prop.SetRepresentationToSurface()
prop.EdgeVisibilityOn()
elif mode == 'Points':
prop.SetRepresentationToPoints()
elif propertyName == 'Color':
color = self.getProperty(propertyName)
self.actor.GetProperty().SetColor(color)
elif propertyName == 'Color By':
self._updateColorBy()
elif propertyName == 'Show Scalar Bar':
self._updateScalarBar()
self._renderAllViews()
[docs] def setScalarRange(self, rangeMin, rangeMax):
arrayName = self.getPropertyEnumValue('Color By')
if arrayName != 'Solid Color':
lut = self.mapper.GetLookupTable()
self.colorBy(arrayName, scalarRange=(rangeMin, rangeMax))
def _updateSurfaceProperty(self):
enableSurfaceMode = self.polyData.GetNumberOfPolys() or self.polyData.GetNumberOfStrips()
self.properties.setPropertyAttribute('Surface Mode', 'hidden', not enableSurfaceMode)
def _updateColorBy(self, retainColorMap=False):
arrayName = self.getPropertyEnumValue('Color By')
if arrayName == 'Solid Color':
self.colorBy(None)
else:
lut = self.mapper.GetLookupTable() if retainColorMap else None
self.colorBy(arrayName, lut=lut)
self._updateScalarBar()
def _updateColorByProperty(self):
enumNames = ['Solid Color'] + self.getArrayNames()
currentValue = self.properties.getProperty('Color By')
if currentValue >= len(enumNames):
self.setProperty('Color By', 0)
self.properties.setPropertyAttribute('Color By', 'enumNames', enumNames)
def _updateScalarBar(self):
barEnabled = self.getProperty('Show Scalar Bar')
colorBy = self.getProperty('Color By')
if barEnabled and colorBy != 0:
self._showScalarBar()
else:
self._hideScalarBar()
def _hideScalarBar(self):
if self.scalarBarWidget:
self.scalarBarWidget.Off()
self.scalarBarWidget.SetInteractor(None)
self.scalarBarWidget = None
self._renderAllViews()
def _showScalarBar(self):
title = self.properties.getPropertyEnumValue('Color By')
view = self.views[0]
lut = self.mapper.GetLookupTable()
self.scalarBarWidget = createScalarBarWidget(view, lut, title)
self._renderAllViews()
def _setScalarBarTextColor(self, color=(0,0,0)):
act = self.scalarBarWidget.GetScalarBarActor()
act.GetTitleTextProperty().SetColor(color)
act.GetLabelTextProperty().SetColor(color)
def _setScalarBarTitle(self, titleText):
act = self.scalarBarWidget.GetScalarBarActor()
act.SetTitle(titleText)
[docs] def getCoolToWarmColorMap(self, scalarRange):
f = vtk.vtkDiscretizableColorTransferFunction()
f.DiscretizeOn()
f.SetColorSpaceToDiverging()
f.SetNumberOfValues(256)
f.AddRGBPoint(scalarRange[0], 0.23, 0.299, 0.754)
f.AddRGBPoint(scalarRange[1], 0.706, 0.016, 0.15)
f.Build()
return f
def _getDefaultColorMap(self, array, scalarRange=None, hueRange=None):
name = array.GetName()
blueToRed = (0.667, 0)
redtoBlue = (0, 0.667)
hueMap = {
'Axes' : redtoBlue
}
scalarRange = scalarRange or self.rangeMap.get(name, array.GetRange())
hueRange = hueRange or hueMap.get(name, blueToRed)
lut = vtk.vtkLookupTable()
lut.SetNumberOfColors(256)
lut.SetHueRange(hueRange)
lut.SetRange(scalarRange)
lut.Build()
return lut
#return self.getCoolToWarmColorMap(scalarRange)
[docs] def shadowOn(self):
if self.shadowActor:
return
mat = [[1, 0, -1, 0],
[0, 1, -1, 0],
[0, 0, 0, 0],
[0, 0, 0, 1]]
shadowT = transformUtils.getTransformFromNumpy(mat)
baseTransform = self.actor.GetUserTransform()
if baseTransform:
shadowT.PreMultiply()
shadowT.Concatenate(baseTransform)
self.shadowActor = vtk.vtkActor()
self.shadowActor.SetMapper(self.mapper)
self.shadowActor.SetUserTransform(shadowT)
self.shadowActor.GetProperty().LightingOff()
self.shadowActor.GetProperty().SetColor(0, 0, 0)
for view in self.views:
view.renderer().AddActor(self.shadowActor)
[docs] def shadowOff(self):
for view in self.views:
view.renderer().RemoveActor(self.shadowActor)
self.shadowActor = None
[docs] def onRemoveFromObjectModel(self):
om.ObjectModelItem.onRemoveFromObjectModel(self)
self.removeFromAllViews()
[docs] def removeFromAllViews(self):
for view in list(self.views):
self.removeFromView(view)
assert len(self.views) == 0
self._hideScalarBar()
[docs] def removeFromView(self, view):
assert view in self.views
self.views.remove(view)
view.renderer().RemoveActor(self.actor)
if self.shadowActor:
view.renderer().RemoveActor(self.shadowActor)
for renderer in self.extraViewRenderers.get(view, []):
renderer.RemoveActor(self.actor)
view.render()
[docs]class TextItem(om.ObjectModelItem):
def __init__(self, name, text='', view=None):
om.ObjectModelItem.__init__(self, name)
self.views = []
self.actor = vtk.vtkTextActor()
prop = self.actor.GetTextProperty()
prop.SetFontSize(18)
self.actor.SetPosition(10,10)
self.actor.SetInput(text)
self.addProperty('Visible', True)
self.addProperty('Text', text)
self.addProperty('Position', [10, 10], attributes=om.PropertyAttributes(minimum=0, maximum=3000, singleStep=1))
self.addProperty('Font Size', 18, attributes=om.PropertyAttributes(minimum=6, maximum=128, singleStep=1))
self.addProperty('Bold', False)
self.addProperty('Italic', False)
if view:
self.addToView(view)
[docs] def addToView(self, view):
if view in self.views:
return
self.views.append(view)
view.renderer().AddActor(self.actor)
view.render()
def _renderAllViews(self):
for view in self.views:
view.render()
[docs] def onRemoveFromObjectModel(self):
om.ObjectModelItem.onRemoveFromObjectModel(self)
self.removeFromAllViews()
[docs] def removeFromAllViews(self):
for view in list(self.views):
self.removeFromView(view)
[docs] def removeFromView(self, view):
assert view in self.views
self.views.remove(view)
view.renderer().RemoveActor(self.actor)
view.render()
def _onPropertyChanged(self, propertySet, propertyName):
om.ObjectModelItem._onPropertyChanged(self, propertySet, propertyName)
if propertyName == 'Visible':
self.actor.SetVisibility(self.getProperty(propertyName))
self._renderAllViews()
elif propertyName == 'Text':
view = app.getCurrentRenderView()
self.actor.SetInput(self.getProperty(propertyName))
elif propertyName == 'Position':
pos = self.getProperty(propertyName)
self.actor.SetPosition(pos[0], pos[1])
elif propertyName == 'Font Size':
self.actor.GetTextProperty().SetFontSize(self.getProperty(propertyName))
elif propertyName == 'Bold Size':
self.actor.GetTextProperty().SetBold(self.getProperty(propertyName))
elif propertyName == 'Italic':
self.actor.GetTextProperty().SetItalic(self.getProperty(propertyName))
if self.getProperty('Visible'):
self._renderAllViews()
[docs]def updateText(text, name, **kwargs):
obj = om.findObjectByName(name)
obj = obj or showText(text, name, **kwargs)
obj.setProperty('Text', text)
return obj
[docs]def showText(text, name, fontSize=18, position=(10, 10), parent=None, view=None):
view = view or app.getCurrentRenderView()
assert view
item = TextItem(name, text, view=view)
item.setProperty('Font Size', fontSize)
item.setProperty('Position', list(position))
if isinstance(parent, str):
parentObj = om.getOrCreateContainer(parent)
else:
parentObj = parent
om.addToObjectModel(item, parentObj)
return item
[docs]def createAxesPolyData(scale, useTube):
axes = vtk.vtkAxes()
axes.SetComputeNormals(0)
axes.SetScaleFactor(scale)
axes.Update()
if useTube:
tube = vtk.vtkTubeFilter()
tube.SetInput(axes.GetOutput())
tube.SetRadius(0.002)
tube.SetNumberOfSides(12)
tube.Update()
axes = tube
return shallowCopy(axes.GetOutput())
[docs]class FrameItem(PolyDataItem):
def __init__(self, name, transform, view):
PolyDataItem.__init__(self, name, vtk.vtkPolyData(), view)
self.transform = transform
self._blockSignals = False
self.actor.SetUserTransform(transform)
self.widget = vtk.vtkFrameWidget()
self.widget.CreateDefaultRepresentation()
self.widget.EnabledOff()
self.rep = self.widget.GetRepresentation()
self.rep.SetTransform(transform)
self.traceData = None
self._frameSync = None
self.addProperty('Scale', 1.0, attributes=om.PropertyAttributes(decimals=2, minimum=0.01, maximum=100, singleStep=0.1, hidden=False))
self.addProperty('Edit', False)
self.addProperty('Trace', False)
self.addProperty('Tube', False)
self.properties.setPropertyIndex('Edit', 0)
self.properties.setPropertyIndex('Trace', 1)
self.properties.setPropertyIndex('Tube', 2)
self.callbacks.addSignal('FrameModified')
self.onTransformModifiedCallback = None
self.observerTag = self.transform.AddObserver('ModifiedEvent', self.onTransformModified)
self._updateAxesGeometry()
self.setProperty('Color By', 'Axes')
self.setProperty('Icon', om.Icons.Axes)
[docs] def connectFrameModified(self, func):
return self.callbacks.connect('FrameModified', func)
[docs] def disconnectFrameModified(self, callbackId):
self.callbacks.disconnect(callbackId)
[docs] def addToView(self, view):
PolyDataItem.addToView(self, view)
[docs] def copyFrame(self, transform):
self._blockSignals = True
self.transform.SetMatrix(transform.GetMatrix())
self._blockSignals = False
self.transform.Modified()
parent = self.parent()
if (parent and parent.getProperty('Visible')) or self.getProperty('Visible'):
self._renderAllViews()
[docs] def getFrameSync(self):
if self._frameSync is None:
self._frameSync = FrameSync()
self._frameSync.addFrame(self)
return self._frameSync
def _updateAxesGeometry(self):
scale = self.getProperty('Scale')
self.rep.SetWorldSize(scale)
self.setPolyData(createAxesPolyData(scale, self.getProperty('Tube')))
def _onPropertyChanged(self, propertySet, propertyName):
PolyDataItem._onPropertyChanged(self, propertySet, propertyName)
if propertyName == 'Scale':
scale = self.getProperty(propertyName)
self.rep.SetWorldSize(scale)
self._updateAxesGeometry()
elif propertyName == 'Edit':
view = app.getCurrentRenderView()
if view not in self.views:
view = self.views[0]
self.widget.SetInteractor(view.renderWindow().GetInteractor())
self.widget.SetEnabled(self.getProperty(propertyName))
isEditing = self.getProperty(propertyName)
if isEditing:
frameupdater.registerFrame(self)
elif propertyName == 'Trace':
trace = self.getProperty(propertyName)
if trace and not self.traceData:
self.traceData = FrameTraceVisualizer(self)
elif not trace and self.traceData:
om.removeFromObjectModel(self.traceData.getTraceData())
self.traceData = None
elif propertyName == 'Tube':
self._updateAxesGeometry()
[docs] def onRemoveFromObjectModel(self):
PolyDataItem.onRemoveFromObjectModel(self)
self.transform.RemoveObserver(self.observerTag)
self.widget.SetInteractor(None)
self.widget.EnabledOff()
for view in self.views:
view.renderer().RemoveActor(self.actor)
view.render()
[docs]class FrameTraceVisualizer(object):
def __init__(self, frame):
self.frame = frame
self.traceName = '%s trace' % frame.getProperty('Name')
self.lastPosition = np.array(frame.transform.GetPosition())
self.lineCell = vtk.vtkLine()
frame.connectFrameModified(self.onFrameModified)
[docs] def getTraceData(self):
t = self.frame.findChild(self.traceName)
if not t:
pts = vtk.vtkPoints()
pts.SetDataTypeToDouble()
pts.InsertNextPoint(self.frame.transform.GetPosition())
pd = vtk.vtkPolyData()
pd.SetPoints(pts)
pd.SetLines(vtk.vtkCellArray())
t = showPolyData(pd, self.traceName, parent=self.frame)
return t
[docs] def addPoint(self, point):
traceData = self.getTraceData()
pd = traceData.polyData
pd.GetPoints().InsertNextPoint(point)
numberOfPoints = pd.GetNumberOfPoints()
line = self.lineCell
ids = line.GetPointIds()
ids.SetId(0, numberOfPoints-2)
ids.SetId(1, numberOfPoints-1)
pd.GetLines().InsertNextCell(line.GetPointIds())
pd.Modified()
traceData._renderAllViews()
[docs] def onFrameModified(self, frame):
position = np.array(frame.transform.GetPosition())
if not np.allclose(position, self.lastPosition):
self.addPoint(position)
[docs]class FrameSync(object):
[docs] class FrameData(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __init__(self):
self.frames = {}
self._blockCallbacks = False
self._ids = itertools.count()
[docs] def addFrame(self, frame, ignoreIncoming=False):
if frame is None:
return
if self._findFrameId(frame) is not None:
return
frameId = self._ids.next()
callbackId = frame.connectFrameModified(self._onFrameModified)
self.frames[frameId] = FrameSync.FrameData(
ref=weakref.ref(frame),
baseTransform=self._computeBaseTransform(frame),
callbackId=callbackId,
ignoreIncoming=ignoreIncoming)
[docs] def removeFrame(self, frame):
frameId = self._findFrameId(frame)
if frameId is None:
raise KeyError(frame)
frame.disconnectFrameModified(self.frames[frameId].callbackId)
self._removeFrameId(frameId)
def _computeBaseTransform(self, frame):
currentDelta = None
for frameId, frameData in self.frames.items():
if frameData.ref() is None:
self._removeFrameId(frameId)
elif frameData.ref() is frame:
continue
else:
currentDelta = transformUtils.copyFrame(frameData.baseTransform.GetLinearInverse())
currentDelta.Concatenate(transformUtils.copyFrame(frameData.ref().transform))
break
t = transformUtils.copyFrame(frame.transform)
t.PostMultiply()
if currentDelta:
t.Concatenate(currentDelta.GetLinearInverse())
return t
def _removeFrameId(self, frameId):
del self.frames[frameId]
def _findFrameId(self, frame):
for frameId, frameData in self.frames.items():
if frameData.ref() is None:
self._removeFrameId(frameId)
elif frameData.ref() is frame:
return frameId
def _moveFrame(self, frameId, modifiedFrameId):
frameData = self.frames[frameId]
modifiedFrameData = self.frames[modifiedFrameId]
t = vtk.vtkTransform()
t.PostMultiply()
t.Concatenate(frameData.baseTransform)
t.Concatenate(modifiedFrameData.baseTransform.GetLinearInverse())
t.Concatenate(modifiedFrameData.ref().transform)
frameData.ref().copyFrame(t)
def _onFrameModified(self, frame):
if self._blockCallbacks:
return
modifiedFrameId = self._findFrameId(frame)
assert modifiedFrameId is not None
#print self, 'onFrameModified:', self.frames[modifiedFrameId].ref().getProperty('Name')
if self.frames[modifiedFrameId].ignoreIncoming:
self.frames[modifiedFrameId].baseTransform = self._computeBaseTransform(frame)
return
self._blockCallbacks = True
for frameId, frameData in self.frames.items():
if frameData.ref() is None:
self._removeFrameId(frameId)
elif frameId != modifiedFrameId:
#print ' ', self, 'moving:', self.frames[frameId].ref().getProperty('Name')
self._moveFrame(frameId, modifiedFrameId)
self._blockCallbacks = False
[docs]class ViewOptionsItem(om.ObjectModelItem):
def __init__(self, view):
om.ObjectModelItem.__init__(self, 'view options')
self.view = view
self.addProperty('Camera projection', 0, attributes=om.PropertyAttributes(enumNames=['Perspective', 'Parallel']))
self.addProperty('View angle', view.camera().GetViewAngle(), attributes=om.PropertyAttributes(minimum=2, maximum=180))
self.addProperty('Key light intensity', view.lightKit().GetKeyLightIntensity(), attributes=om.PropertyAttributes(minimum=0, maximum=5, singleStep=0.1, decimals=2))
self.addProperty('Light kit', True)
self.addProperty('Eye dome lighting', False)
self.addProperty('Orientation widget', True)
self.addProperty('Interactive render', True)
self.addProperty('Gradient background', True)
self.addProperty('Background color', view.backgroundRenderer().GetBackground())
self.addProperty('Background color 2', view.backgroundRenderer().GetBackground2())
def _onPropertyChanged(self, propertySet, propertyName):
om.ObjectModelItem._onPropertyChanged(self, propertySet, propertyName)
if propertyName in ('Gradient background', 'Background color', 'Background color 2'):
colors = [self.getProperty('Background color'), self.getProperty('Background color 2')]
if not self.getProperty('Gradient background'):
colors[1] = colors[0]
self.view.renderer().SetBackground(colors[0])
self.view.renderer().SetBackground2(colors[1])
elif propertyName == 'Camera projection':
if self.getPropertyEnumValue(propertyName) == 'Perspective':
self.view.camera().ParallelProjectionOff()
else:
self.view.camera().ParallelProjectionOn()
elif propertyName == 'Orientation widget':
if self.getProperty(propertyName):
self.view.orientationMarkerWidget().On()
else:
self.view.orientationMarkerWidget().Off()
elif propertyName == 'View angle':
angle = self.getProperty(propertyName)
self.view.camera().SetViewAngle(angle)
elif propertyName == 'Key light intensity':
intensity = self.getProperty(propertyName)
self.view.lightKit().SetKeyLightIntensity(intensity)
elif propertyName == 'Light kit':
self.view.setLightKitEnabled(self.getProperty(propertyName))
elif propertyName == 'Eye dome lighting':
if self.getProperty(propertyName):
enableEyeDomeLighting(self.view)
else:
disableEyeDomeLighting(self.view)
elif propertyName == 'Interactive render':
if self.getProperty(propertyName):
self.view.renderWindow().GetInteractor().EnableRenderOn()
else:
self.view.renderWindow().GetInteractor().EnableRenderOff()
self.view.render()
[docs]def showGrid(view, cellSize=0.5, numberOfCells=25, name='grid', parent='sensors', color=[1,1,1], alpha=0.05, gridTransform=None):
grid = vtk.vtkGridSource()
grid.SetScale(cellSize)
grid.SetGridSize(numberOfCells)
grid.SetSurfaceEnabled(True)
grid.Update()
gridObj = showPolyData(grid.GetOutput(), 'grid', view=view, alpha=alpha, color=color, visible=True, parent=parent)
gridObj.gridSource = grid
gridObj.actor.GetProperty().LightingOff()
gridObj.actor.SetPickable(False)
gridTransform = gridTransform or vtk.vtkTransform()
gridObj.actor.SetUserTransform(gridTransform)
showFrame(gridTransform, 'grid frame', scale=0.2, visible=False, parent=gridObj, view=view)
gridObj.setProperty('Surface Mode', 'Wireframe')
def computeViewBoundsNoGrid():
if not gridObj.getProperty('Visible'):
return
gridObj.actor.SetUseBounds(False)
bounds = view.renderer().ComputeVisiblePropBounds()
gridObj.actor.SetUseBounds(True)
if vtk.vtkMath.AreBoundsInitialized(bounds):
view.addCustomBounds(bounds)
else:
view.addCustomBounds([-1, 1, -1, 1, -1, 1])
view.connect('computeBoundsRequest(ddQVTKWidgetView*)', computeViewBoundsNoGrid)
return gridObj
[docs]def updatePolyData(polyData, name, **kwargs):
obj = om.findObjectByName(name)
obj = obj or showPolyData(polyData, name, **kwargs)
obj.setPolyData(polyData)
return obj
[docs]def updateFrame(frame, name, **kwargs):
obj = om.findObjectByName(name)
obj = obj or showFrame(frame, name, **kwargs)
obj.copyFrame(frame)
return obj
[docs]def showFrame(frame, name, view=None, parent='segmentation', scale=0.35, visible=True):
view = view or app.getCurrentRenderView()
assert view
if isinstance(parent, str):
parentObj = om.getOrCreateContainer(parent)
else:
parentObj = parent
item = FrameItem(name, frame, view)
om.addToObjectModel(item, parentObj)
item.setProperty('Visible', visible)
item.setProperty('Scale', scale)
return item
[docs]def showPolyData(polyData, name, color=None, colorByName=None, colorByRange=None, alpha=1.0, visible=True, view=None, parent='segmentation', cls=None):
view = view or app.getCurrentRenderView()
assert view
cls = cls or PolyDataItem
item = cls(name, polyData, view)
if isinstance(parent, str):
parentObj = om.getOrCreateContainer(parent)
else:
parentObj = parent
om.addToObjectModel(item, parentObj)
item.setProperty('Visible', visible)
item.setProperty('Alpha', alpha)
if colorByName and colorByName not in item.getArrayNames():
print 'showPolyData(colorByName=%s): array not found' % colorByName
colorByName = None
if colorByName:
item.setProperty('Color By', colorByName)
item.colorBy(colorByName, colorByRange)
else:
color = [1.0, 1.0, 1.0] if color is None else color
item.setProperty('Color', [float(c) for c in color])
item.colorBy(None)
return item
[docs]def addChildFrame(obj, initialTransform=None):
'''
Adds a child frame to the given PolyDataItem. If initialTransform is given,
the object's polydata is transformed using the inverse of initialTransform
and then a child frame is assigned to the object to maintain its original
position.
'''
if obj.getChildFrame():
return
if initialTransform:
pd = transformPolyData(obj.polyData, initialTransform.GetLinearInverse())
obj.setPolyData(pd)
t = obj.actor.GetUserTransform()
if t is None:
t = vtk.vtkTransform()
t.PostMultiply()
frame = showFrame(t, obj.getProperty('Name') + ' frame', parent=obj, scale=0.2, visible=False)
obj.actor.SetUserTransform(t)
return frame
[docs]def getRandomColor():
'''
Return a random color as a list of RGB values between 0.0 and 1.0.
'''
return colorsys.hsv_to_rgb(np.random.rand(), 1.0, 0.9)
[docs]def showClusterObjects(clusters, parent):
colors = [ QtCore.Qt.red,
QtCore.Qt.blue,
QtCore.Qt.yellow,
QtCore.Qt.green,
QtCore.Qt.magenta,
QtCore.Qt.cyan,
QtCore.Qt.darkCyan,
QtCore.Qt.darkGreen,
QtCore.Qt.darkMagenta ]
colors = [QtGui.QColor(c) for c in colors]
colors = [(c.red()/255.0, c.green()/255.0, c.blue()/255.0) for c in colors]
objects = []
for i, cluster in enumerate(clusters):
name = 'object %d' % i
color = colors[i % len(colors)]
clusterObj = showPolyData(cluster.mesh, name, color=color, parent=parent, alpha=1.0)
clusterFrame = showFrame(cluster.frame, name + ' frame', scale=0.2, visible=False, parent=clusterObj)
clusterBox = showPolyData(cluster.box, name + ' box', color=color, parent=clusterObj, alpha=0.6, visible=False)
clusterPoints = showPolyData(cluster.points, name + ' points', color=color, parent=clusterObj, visible=False, alpha=1.0)
if hasattr(cluster,'oriented_frame'):
orientedFrame = showFrame(cluster.oriented_frame, name + ' oriented frame', scale=0.2, visible=False, parent=clusterObj)
clusterPoints.setProperty('Point Size', 7)
clusterPoints.colorBy(None)
clusterObj.data = cluster
objects.append(clusterObj)
for obj in [clusterObj, clusterBox, clusterPoints]:
obj.actor.SetUserTransform(cluster.frame)
return objects
captionWidget = None
[docs]def getRayFromDisplayPoint(view, displayPoint):
'''
Given a view and an XY display point, returns two XYZ world points which
are the display point at the near/far clipping planes of the view.
'''
worldPt1 = [0,0,0,0]
worldPt2 = [0,0,0,0]
renderer = view.renderer()
vtk.vtkInteractorObserver.ComputeDisplayToWorld(renderer, displayPoint[0], displayPoint[1], 0, worldPt1)
vtk.vtkInteractorObserver.ComputeDisplayToWorld(renderer, displayPoint[0], displayPoint[1], 1, worldPt2)
worldPt1 = np.array(worldPt1[:3])
worldPt2 = np.array(worldPt2[:3])
return worldPt1, worldPt2
[docs]def pickImage(displayPoint, view, obj=None):
picker = vtk.vtkCellPicker()
if isinstance(obj, str):
obj = om.findObjectByName(obj)
assert obj
if obj:
picker.AddPickList(obj.actor)
picker.PickFromListOn()
picker.Pick(displayPoint[0], displayPoint[1], 0, view.renderer())
pickedDataset = picker.GetDataSet()
if obj:
return picker.GetPointIJK()
else:
return pickedDataset, picker.GetPointIJK()
[docs]def pickProp(displayPoint, view):
for tolerance in (0.0, 0.005, 0.01):
pickType = 'render' if tolerance == 0.0 else 'cells'
pickData = pickPoint(displayPoint, view, pickType=pickType, tolerance=tolerance)
pickedPoint = pickData.pickedPoint
pickedProp = pickData.pickedProp
pickedDataset = pickData.pickedDataset
if pickedProp is not None:
return pickedPoint, pickedProp, pickedDataset
return None, None, None
[docs]def pickPoint(displayPoint, view, obj=None, pickType='points', tolerance=0.01):
"""
:param displayPoint:
:param view:
:param obj:
:param pickType:
:param tolerance:
:return: FieldContainer with fields
pickedPoint
pickedProp
pickedDataset
pickedNormal - is None if no normal can be comp
pickedCellId - is None unless pickType="cells"
"""
assert pickType in ('points', 'cells', 'render')
view = view or app.getCurrentRenderView()
assert view
if isinstance(obj, str):
obj = om.findObjectByName(obj)
assert obj
if pickType == 'render':
picker = vtk.vtkPropPicker()
else:
picker = vtk.vtkPointPicker() if pickType == 'points' else vtk.vtkCellPicker()
picker.SetTolerance(tolerance)
if obj is not None:
if isinstance(obj, list):
for o in obj:
picker.AddPickList(o.actor)
obj = None
else:
picker.AddPickList(obj.actor)
picker.PickFromListOn()
picker.Pick(displayPoint[0], displayPoint[1], 0, view.renderer())
pickedProp = picker.GetViewProp()
pickedPoint = np.array(picker.GetPickPosition())
pickedDataset = pickedProp.GetMapper().GetInput() if isinstance(pickedProp, vtk.vtkActor) else None
if pickType == "cells":
pickedCellId = picker.GetCellId()
else:
pickedCellId = None
# populate pickedNormal if possible
pickedNormal = None
if pickType == 'cells':
pickedNormal = np.array(picker.GetPickNormal())
elif pickType == 'points' and pickedDataset:
pointId = picker.GetPointId()
normals = pickedDataset.GetPointData().GetNormals()
if normals:
pickedNormal = np.array(normals.GetTuple3(pointId))
#if pickedDataset and pickType == 'cells':
# print 'point id:', pickedDataset.GetCell(picker.GetCellId()).GetPointIds().GetId(picker.GetSubId())
#if pickType == 'points':
# print 'point id:', picker.GetPointId()
fields = FieldContainer(
pickedPoint=pickedPoint,
pickedProp=pickedProp,
pickedDataset=pickedDataset,
pickedNormal=pickedNormal,
pickedCellId=pickedCellId
)
return fields
[docs]def mapMousePosition(widget, mouseEvent):
mousePosition = mouseEvent.pos()
return mousePosition.x(), widget.height - mousePosition.y()
[docs]def getObjectByDataSet(polyData):
for obj in om.getObjects():
if obj.hasDataSet(polyData):
return obj
[docs]def getObjectByProp(prop):
if not prop:
return None
for obj in om.getObjects():
if isinstance(obj, FrameItem) and obj.widget.GetRepresentation() == prop:
return obj
if isinstance(prop, vtk.vtkActor):
return getObjectByDataSet(prop.GetMapper().GetInput())
[docs]def findPickedObject(displayPoint, view):
pickedPoint, pickedProp, pickedDataset = pickProp(displayPoint, view)
obj = getObjectByProp(pickedProp)
return obj, pickedPoint
[docs]def enableEyeDomeLighting(view):
seq = vtk.vtkSequencePass()
opaque = vtk.vtkOpaquePass()
peeling = vtk.vtkDepthPeelingPass()
peeling.SetMaximumNumberOfPeels(200)
peeling.SetOcclusionRatio(0.1)
translucent = vtk.vtkTranslucentPass()
peeling.SetTranslucentPass(translucent)
volume = vtk.vtkVolumetricPass()
overlay = vtk.vtkOverlayPass()
lights = vtk.vtkLightsPass()
passes=vtk.vtkRenderPassCollection()
passes.AddItem(lights)
passes.AddItem(opaque)
#passes.AddItem(peeling)
passes.AddItem(translucent)
#passes.AddItem(volume)
#passes.AddItem(overlay)
seq.SetPasses(passes)
edlPass = vtk.vtkEDLShading()
cameraPass = vtk.vtkCameraPass()
edlPass.SetDelegatePass(cameraPass)
cameraPass.SetDelegatePass(seq)
view.renderer().SetPass(edlPass)
[docs]def disableEyeDomeLighting(view):
view.renderer().SetPass(None)
[docs]def showImage(filename):
'''
Returns a QLabel displaying the image contents of given filename.
Make sure to assign the label, it will destruct when it goes out
of scope.
'''
image = QtGui.QImage(filename)
assert not image.isNull()
imageLabel = QtGui.QLabel()
imageLabel.setPixmap(QtGui.QPixmap.fromImage(image))
imageLabel.setScaledContents(True)
imageLabel.resize(imageLabel.pixmap.size())
imageLabel.setWindowTitle(os.path.basename(filename))
imageLabel.show()