Added 3D scatter plot item
This commit is contained in:
parent
47b5eb6ab3
commit
f278abd55d
33
examples/GLScatterPlotItem.py
Normal file
33
examples/GLScatterPlotItem.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
## Add path to library (just for examples; you do not need this)
|
||||||
|
import sys, os
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
|
|
||||||
|
from pyqtgraph.Qt import QtCore, QtGui
|
||||||
|
import pyqtgraph.opengl as gl
|
||||||
|
|
||||||
|
app = QtGui.QApplication([])
|
||||||
|
w = gl.GLViewWidget()
|
||||||
|
w.opts['distance'] = 20
|
||||||
|
w.show()
|
||||||
|
|
||||||
|
g = gl.GLGridItem()
|
||||||
|
w.addItem(g)
|
||||||
|
|
||||||
|
pts = [
|
||||||
|
{'pos': (1,0,0), 'size':0.5, 'color':(1.0, 0.0, 0.0, 0.5)},
|
||||||
|
{'pos': (0,1,0), 'size':0.2, 'color':(0.0, 0.0, 1.0, 0.5)},
|
||||||
|
{'pos': (0,0,1), 'size':2./3., 'color':(0.0, 1.0, 0.0, 0.5)},
|
||||||
|
]
|
||||||
|
z = 0.5
|
||||||
|
d = 6.0
|
||||||
|
for i in range(50):
|
||||||
|
pts.append({'pos': (0,0,z), 'size':2./d, 'color':(0.0, 1.0, 0.0, 0.5)})
|
||||||
|
z *= 0.5
|
||||||
|
d *= 2.0
|
||||||
|
sp = gl.GLScatterPlotItem(pts)
|
||||||
|
w.addItem(sp)
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode.
|
||||||
|
if sys.flags.interactive != 1:
|
||||||
|
app.exec_()
|
102
opengl/items/GLScatterPlotItem.py
Normal file
102
opengl/items/GLScatterPlotItem.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
from OpenGL.GL import *
|
||||||
|
from .. GLGraphicsItem import GLGraphicsItem
|
||||||
|
from pyqtgraph import QtGui
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
__all__ = ['GLScatterPlotItem']
|
||||||
|
|
||||||
|
class GLScatterPlotItem(GLGraphicsItem):
|
||||||
|
"""Draws points at a list of 3D positions."""
|
||||||
|
|
||||||
|
def __init__(self, data=None):
|
||||||
|
GLGraphicsItem.__init__(self)
|
||||||
|
self.data = []
|
||||||
|
if data is not None:
|
||||||
|
self.setData(data)
|
||||||
|
|
||||||
|
def setData(self, data):
|
||||||
|
"""
|
||||||
|
Data may be either a list of dicts (one dict per point) or a numpy record array.
|
||||||
|
|
||||||
|
==================== ==================================================
|
||||||
|
Allowed fields are:
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
pos (x,y,z) tuple of coordinate values or QVector3D
|
||||||
|
color (r,g,b,a) tuple of floats (0.0-1.0) or QColor
|
||||||
|
size (float) diameter of spot in pixels
|
||||||
|
==================== ==================================================
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
self.data = data
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
|
||||||
|
def initializeGL(self):
|
||||||
|
w = 64
|
||||||
|
def fn(x,y):
|
||||||
|
r = ((x-w/2.)**2 + (y-w/2.)**2) ** 0.5
|
||||||
|
return 200 * (w/2. - np.clip(r, w/2.-1.0, w/2.))
|
||||||
|
pData = np.empty((w, w, 4))
|
||||||
|
pData[:] = 255
|
||||||
|
pData[:,:,3] = np.fromfunction(fn, pData.shape[:2])
|
||||||
|
#print pData.shape, pData.min(), pData.max()
|
||||||
|
pData = pData.astype(np.ubyte)
|
||||||
|
|
||||||
|
self.pointTexture = glGenTextures(1)
|
||||||
|
glActiveTexture(GL_TEXTURE0)
|
||||||
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.pointTexture)
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pData.shape[0], pData.shape[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, pData)
|
||||||
|
|
||||||
|
def paint(self):
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
glEnable( GL_BLEND )
|
||||||
|
glEnable( GL_ALPHA_TEST )
|
||||||
|
glEnable( GL_POINT_SMOOTH )
|
||||||
|
|
||||||
|
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST)
|
||||||
|
#glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, (0, 0, -1e-3))
|
||||||
|
#glPointParameterfv(GL_POINT_SIZE_MAX, (65500,))
|
||||||
|
#glPointParameterfv(GL_POINT_SIZE_MIN, (0,))
|
||||||
|
|
||||||
|
glEnable(GL_POINT_SPRITE)
|
||||||
|
glActiveTexture(GL_TEXTURE0)
|
||||||
|
glEnable( GL_TEXTURE_2D )
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.pointTexture)
|
||||||
|
|
||||||
|
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE)
|
||||||
|
#glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) ## use texture color exactly
|
||||||
|
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ## texture modulates current color
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
|
||||||
|
|
||||||
|
for pt in self.data:
|
||||||
|
pos = pt['pos']
|
||||||
|
try:
|
||||||
|
color = pt['color']
|
||||||
|
except KeyError:
|
||||||
|
color = (1,1,1,1)
|
||||||
|
try:
|
||||||
|
size = pt['size']
|
||||||
|
except KeyError:
|
||||||
|
size = 10
|
||||||
|
|
||||||
|
if isinstance(color, QtGui.QColor):
|
||||||
|
color = fn.glColor(color)
|
||||||
|
|
||||||
|
pxSize = self.view().pixelSize(QtGui.QVector3D(*pos))
|
||||||
|
|
||||||
|
glPointSize(size / pxSize)
|
||||||
|
glBegin( GL_POINTS )
|
||||||
|
glColor4f(*color) # x is blue
|
||||||
|
#glNormal3f(size, 0, 0)
|
||||||
|
glVertex3f(*pos)
|
||||||
|
glEnd()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user