Features:
- GLScatterPlotItem can work with arbitrarily-shaped vertex arrays - added colorToAlpha function Bugfixes: - GraphicsScene emits sigMouseClicked for all clicks - CanvasItem emits transformation change signal when mirrored - GLViewWidget.pixelSize correctly handles position specified as array - SRTTransform3D assumes Zscale=1 when converting from 2D transform
This commit is contained in:
parent
b25e34f564
commit
4ceae9f1a1
|
@ -73,7 +73,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
||||||
|
|
||||||
sigMouseHover = QtCore.Signal(object) ## emits a list of objects hovered over
|
sigMouseHover = QtCore.Signal(object) ## emits a list of objects hovered over
|
||||||
sigMouseMoved = QtCore.Signal(object) ## emits position of mouse on every move
|
sigMouseMoved = QtCore.Signal(object) ## emits position of mouse on every move
|
||||||
sigMouseClicked = QtCore.Signal(object) ## emitted when MouseClickEvent is not accepted by any items under the click.
|
sigMouseClicked = QtCore.Signal(object) ## emitted when mouse is clicked. Check for event.isAccepted() to see whether the event has already been acted on.
|
||||||
|
|
||||||
_addressCache = weakref.WeakValueDictionary()
|
_addressCache = weakref.WeakValueDictionary()
|
||||||
|
|
||||||
|
@ -343,10 +343,11 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
||||||
if int(item.flags() & item.ItemIsFocusable) > 0:
|
if int(item.flags() & item.ItemIsFocusable) > 0:
|
||||||
item.setFocus(QtCore.Qt.MouseFocusReason)
|
item.setFocus(QtCore.Qt.MouseFocusReason)
|
||||||
break
|
break
|
||||||
if not ev.isAccepted() and ev.button() is QtCore.Qt.RightButton:
|
#if not ev.isAccepted() and ev.button() is QtCore.Qt.RightButton:
|
||||||
#print "GraphicsScene emitting sigSceneContextMenu"
|
#print "GraphicsScene emitting sigSceneContextMenu"
|
||||||
self.sigMouseClicked.emit(ev)
|
#self.sigMouseClicked.emit(ev)
|
||||||
ev.accept()
|
#ev.accept()
|
||||||
|
self.sigMouseClicked.emit(ev)
|
||||||
return ev.isAccepted()
|
return ev.isAccepted()
|
||||||
|
|
||||||
#def claimEvent(self, item, button, eventType):
|
#def claimEvent(self, item, button, eventType):
|
||||||
|
|
|
@ -35,6 +35,7 @@ class SRTTransform3D(pg.Transform3D):
|
||||||
'angle': init._state['angle'],
|
'angle': init._state['angle'],
|
||||||
'axis': Vector(0, 0, 1),
|
'axis': Vector(0, 0, 1),
|
||||||
}
|
}
|
||||||
|
self._state['scale'][2] = 1.0
|
||||||
self.update()
|
self.update()
|
||||||
elif isinstance(init, QtGui.QMatrix4x4):
|
elif isinstance(init, QtGui.QMatrix4x4):
|
||||||
self.setFromMatrix(init)
|
self.setFromMatrix(init)
|
||||||
|
|
|
@ -205,6 +205,7 @@ class CanvasItem(QtCore.QObject):
|
||||||
self.userTransform = self.userTransform * inv
|
self.userTransform = self.userTransform * inv
|
||||||
self.updateTransform()
|
self.updateTransform()
|
||||||
self.selectBoxFromUser()
|
self.selectBoxFromUser()
|
||||||
|
self.sigTransformChangeFinished.emit(self)
|
||||||
#if flip:
|
#if flip:
|
||||||
#if tr['scale'][0] < 0 xor tr['scale'][1] < 0:
|
#if tr['scale'][0] < 0 xor tr['scale'][1] < 0:
|
||||||
#return
|
#return
|
||||||
|
|
46
functions.py
46
functions.py
|
@ -991,6 +991,52 @@ def imageToArray(img, copy=False, transpose=True):
|
||||||
else:
|
else:
|
||||||
return arr
|
return arr
|
||||||
|
|
||||||
|
def colorToAlpha(data, color):
|
||||||
|
"""
|
||||||
|
Given an RGBA image in *data*, convert *color* to be transparent.
|
||||||
|
*data* must be an array (w, h, 3 or 4) of ubyte values and *color* must be
|
||||||
|
an array (3) of ubyte values.
|
||||||
|
This is particularly useful for use with images that have a black or white background.
|
||||||
|
|
||||||
|
Algorithm is taken from Gimp's color-to-alpha function in plug-ins/common/colortoalpha.c
|
||||||
|
Credit:
|
||||||
|
/*
|
||||||
|
* Color To Alpha plug-in v1.0 by Seth Burgess, sjburges@gimp.org 1999/05/14
|
||||||
|
* with algorithm by clahey
|
||||||
|
*/
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = data.astype(float)
|
||||||
|
if data.shape[-1] == 3: ## add alpha channel if needed
|
||||||
|
d2 = np.empty(data.shape[:2]+(4,), dtype=data.dtype)
|
||||||
|
d2[...,:3] = data
|
||||||
|
d2[...,3] = 255
|
||||||
|
data = d2
|
||||||
|
|
||||||
|
color = color.astype(float)
|
||||||
|
alpha = np.zeros(data.shape[:2]+(3,), dtype=float)
|
||||||
|
output = data.copy()
|
||||||
|
|
||||||
|
for i in [0,1,2]:
|
||||||
|
d = data[...,i]
|
||||||
|
c = color[i]
|
||||||
|
mask = d > c
|
||||||
|
alpha[...,i][mask] = (d[mask] - c) / (255. - c)
|
||||||
|
imask = d < c
|
||||||
|
alpha[...,i][imask] = (c - d[imask]) / c
|
||||||
|
|
||||||
|
output[...,3] = alpha.max(axis=2) * 255.
|
||||||
|
|
||||||
|
mask = output[...,3] >= 1.0 ## avoid zero division while processing alpha channel
|
||||||
|
correction = 255. / output[...,3][mask] ## increase value to compensate for decreased alpha
|
||||||
|
for i in [0,1,2]:
|
||||||
|
output[...,i][mask] = ((output[...,i][mask]-color[i]) * correction) + color[i]
|
||||||
|
output[...,3][mask] *= data[...,3][mask] / 255. ## combine computed and previous alpha values
|
||||||
|
|
||||||
|
#raise Exception()
|
||||||
|
return np.clip(output, 0, 255).astype(np.ubyte)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#def isosurface(data, level):
|
#def isosurface(data, level):
|
||||||
#"""
|
#"""
|
||||||
|
|
|
@ -1269,7 +1269,15 @@ class ViewBox(GraphicsWidget):
|
||||||
|
|
||||||
for item in g.childItems():
|
for item in g.childItems():
|
||||||
item.setPen(fn.mkPen(color='y', width=3))
|
item.setPen(fn.mkPen(color='y', width=3))
|
||||||
item.setZValue(1000000)
|
g.setZValue(1000000)
|
||||||
|
|
||||||
|
if children:
|
||||||
|
g.path = QtGui.QGraphicsPathItem(g.childrenShape())
|
||||||
|
else:
|
||||||
|
g.path = QtGui.QGraphicsPathItem(g.shape())
|
||||||
|
g.path.setParentItem(g)
|
||||||
|
g.path.setPen(fn.mkPen('g'))
|
||||||
|
g.path.setZValue(100)
|
||||||
|
|
||||||
QtCore.QTimer.singleShot(timeout*1000, self.clearLocate)
|
QtCore.QTimer.singleShot(timeout*1000, self.clearLocate)
|
||||||
|
|
||||||
|
|
|
@ -202,9 +202,9 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
||||||
Pos may be a Vector or an (N,3) array of locations
|
Pos may be a Vector or an (N,3) array of locations
|
||||||
"""
|
"""
|
||||||
cam = self.cameraPosition()
|
cam = self.cameraPosition()
|
||||||
if isinstance(pos, np.ndarray) and pos.ndim == 2:
|
if isinstance(pos, np.ndarray):
|
||||||
cam = np.array(cam).reshape(1,3)
|
cam = np.array(cam).reshape((1,)*(pos.ndim-1)+(3,))
|
||||||
dist = ((pos-cam)**2).sum(axis=1)**0.5
|
dist = ((pos-cam)**2).sum(axis=-1)**0.5
|
||||||
else:
|
else:
|
||||||
dist = (pos-cam).length()
|
dist = (pos-cam).length()
|
||||||
xDist = dist * 2. * np.tan(0.5 * self.opts['fov'] * np.pi / 180.)
|
xDist = dist * 2. * np.tan(0.5 * self.opts['fov'] * np.pi / 180.)
|
||||||
|
|
|
@ -118,7 +118,10 @@ class GLScatterPlotItem(GLGraphicsItem):
|
||||||
#glUniform1i(self.shader.uniform('texture'), 0) ## inform the shader which texture to use
|
#glUniform1i(self.shader.uniform('texture'), 0) ## inform the shader which texture to use
|
||||||
glEnableClientState(GL_VERTEX_ARRAY)
|
glEnableClientState(GL_VERTEX_ARRAY)
|
||||||
try:
|
try:
|
||||||
glVertexPointerf(self.pos)
|
pos = self.pos
|
||||||
|
#if pos.ndim > 2:
|
||||||
|
#pos = pos.reshape((reduce(lambda a,b: a*b, pos.shape[:-1]), pos.shape[-1]))
|
||||||
|
glVertexPointerf(pos)
|
||||||
|
|
||||||
if isinstance(self.color, np.ndarray):
|
if isinstance(self.color, np.ndarray):
|
||||||
glEnableClientState(GL_COLOR_ARRAY)
|
glEnableClientState(GL_COLOR_ARRAY)
|
||||||
|
@ -131,19 +134,19 @@ class GLScatterPlotItem(GLGraphicsItem):
|
||||||
|
|
||||||
if not self.pxMode or isinstance(self.size, np.ndarray):
|
if not self.pxMode or isinstance(self.size, np.ndarray):
|
||||||
glEnableClientState(GL_NORMAL_ARRAY)
|
glEnableClientState(GL_NORMAL_ARRAY)
|
||||||
norm = np.empty(self.pos.shape)
|
norm = np.empty(pos.shape)
|
||||||
if self.pxMode:
|
if self.pxMode:
|
||||||
norm[:,0] = self.size
|
norm[...,0] = self.size
|
||||||
else:
|
else:
|
||||||
gpos = self.mapToView(self.pos.transpose()).transpose()
|
gpos = self.mapToView(pos.transpose()).transpose()
|
||||||
pxSize = self.view().pixelSize(gpos)
|
pxSize = self.view().pixelSize(gpos)
|
||||||
norm[:,0] = self.size / pxSize
|
norm[...,0] = self.size / pxSize
|
||||||
|
|
||||||
glNormalPointerf(norm)
|
glNormalPointerf(norm)
|
||||||
else:
|
else:
|
||||||
glNormal3f(self.size, 0, 0) ## vertex shader uses norm.x to determine point size
|
glNormal3f(self.size, 0, 0) ## vertex shader uses norm.x to determine point size
|
||||||
#glPointSize(self.size)
|
#glPointSize(self.size)
|
||||||
glDrawArrays(GL_POINTS, 0, len(self.pos))
|
glDrawArrays(GL_POINTS, 0, pos.size / pos.shape[-1])
|
||||||
finally:
|
finally:
|
||||||
glDisableClientState(GL_NORMAL_ARRAY)
|
glDisableClientState(GL_NORMAL_ARRAY)
|
||||||
glDisableClientState(GL_VERTEX_ARRAY)
|
glDisableClientState(GL_VERTEX_ARRAY)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user