From ff232f4e3af7a96d39ceac0938fde957482a4994 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Sat, 1 Feb 2014 20:46:05 -0500 Subject: [PATCH] Added cylinder geometry to opengl MeshData --- examples/GLMeshItem.py | 89 ++++++++++++++++++++++-------------- pyqtgraph/opengl/MeshData.py | 36 ++++++++++++++- 2 files changed, 88 insertions(+), 37 deletions(-) diff --git a/examples/GLMeshItem.py b/examples/GLMeshItem.py index 5ef8eb51..f017f19b 100644 --- a/examples/GLMeshItem.py +++ b/examples/GLMeshItem.py @@ -67,7 +67,7 @@ w.addItem(m2) ## Example 3: -## icosahedron +## sphere md = gl.MeshData.sphere(rows=10, cols=20) #colors = np.random.random(size=(md.faceCount(), 4)) @@ -79,7 +79,7 @@ colors[:,1] = np.linspace(0, 1, colors.shape[0]) md.setFaceColors(colors) m3 = gl.GLMeshItem(meshdata=md, smooth=False)#, shader='balloon') -#m3.translate(-5, -5, 0) +m3.translate(-5, -5, 0) w.addItem(m3) @@ -91,49 +91,68 @@ m4 = gl.GLMeshItem(meshdata=md, smooth=False, drawFaces=False, drawEdges=True, e m4.translate(0,10,0) w.addItem(m4) +# Example 5: +# cylinder +md = gl.MeshData.cylinder(rows=10, cols=20, radius=[1., 2.0], length=5.) +md2 = gl.MeshData.cylinder(rows=10, cols=20, radius=[2., 0.5], length=10.) +colors = np.ones((md.faceCount(), 4), dtype=float) +colors[::2,0] = 0 +colors[:,1] = np.linspace(0, 1, colors.shape[0]) +md.setFaceColors(colors) +m5 = gl.GLMeshItem(meshdata=md, smooth=True, drawEdges=True, edgeColor=(1,0,0,1), shader='balloon') +colors = np.ones((md.faceCount(), 4), dtype=float) +colors[::2,0] = 0 +colors[:,1] = np.linspace(0, 1, colors.shape[0]) +md2.setFaceColors(colors) +m6 = gl.GLMeshItem(meshdata=md2, smooth=True, drawEdges=False, shader='balloon') +m6.translate(0,0,7.5) + +m6.rotate(0., 0, 1, 1) +#m5.translate(-3,3,0) +w.addItem(m5) +w.addItem(m6) - -#def psi(i, j, k, offset=(25, 25, 50)): - #x = i-offset[0] - #y = j-offset[1] - #z = k-offset[2] - #th = np.arctan2(z, (x**2+y**2)**0.5) - #phi = np.arctan2(y, x) - #r = (x**2 + y**2 + z **2)**0.5 - #a0 = 1 - ##ps = (1./81.) * (2./np.pi)**0.5 * (1./a0)**(3/2) * (6 - r/a0) * (r/a0) * np.exp(-r/(3*a0)) * np.cos(th) - #ps = (1./81.) * 1./(6.*np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * np.exp(-r/(3*a0)) * (3 * np.cos(th)**2 - 1) +def psi(i, j, k, offset=(25, 25, 50)): + x = i-offset[0] + y = j-offset[1] + z = k-offset[2] + th = np.arctan2(z, (x**2+y**2)**0.5) + phi = np.arctan2(y, x) + r = (x**2 + y**2 + z **2)**0.5 + a0 = 1 + #ps = (1./81.) * (2./np.pi)**0.5 * (1./a0)**(3/2) * (6 - r/a0) * (r/a0) * np.exp(-r/(3*a0)) * np.cos(th) + ps = (1./81.) * 1./(6.*np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * np.exp(-r/(3*a0)) * (3 * np.cos(th)**2 - 1) - #return ps + return ps - ##return ((1./81.) * (1./np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * (r/a0) * np.exp(-r/(3*a0)) * np.sin(th) * np.cos(th) * np.exp(2 * 1j * phi))**2 + #return ((1./81.) * (1./np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * (r/a0) * np.exp(-r/(3*a0)) * np.sin(th) * np.cos(th) * np.exp(2 * 1j * phi))**2 -#print("Generating scalar field..") -#data = np.abs(np.fromfunction(psi, (50,50,100))) +print("Generating scalar field..") +data = np.abs(np.fromfunction(psi, (50,50,100))) -##data = np.fromfunction(lambda i,j,k: np.sin(0.2*((i-25)**2+(j-15)**2+k**2)**0.5), (50,50,50)); -#print("Generating isosurface..") -#verts = pg.isosurface(data, data.max()/4.) - -#md = gl.MeshData.MeshData(vertexes=verts) - -#colors = np.ones((md.vertexes(indexed='faces').shape[0], 4), dtype=float) -#colors[:,3] = 0.3 -#colors[:,2] = np.linspace(0, 1, colors.shape[0]) -#m1 = gl.GLMeshItem(meshdata=md, color=colors, smooth=False) - -#w.addItem(m1) -#m1.translate(-25, -25, -20) - -#m2 = gl.GLMeshItem(vertexes=verts, color=colors, smooth=True) - -#w.addItem(m2) -#m2.translate(-25, -25, -50) +#data = np.fromfunction(lambda i,j,k: np.sin(0.2*((i-25)**2+(j-15)**2+k**2)**0.5), (50,50,50)); +# print("Generating isosurface..") +# verts = pg.isosurface(data, data.max()/4.) +# print dir(gl.MeshData) +# md = gl.GLMeshItem(vertexes=verts) +# +# colors = np.ones((md.vertexes(indexed='faces').shape[0], 4), dtype=float) +# colors[:,3] = 0.3 +# colors[:,2] = np.linspace(0, 1, colors.shape[0]) +# m1 = gl.GLMeshItem(meshdata=md, color=colors, smooth=False) +# +# w.addItem(m1) +# m1.translate(-25, -25, -20) +# +# m2 = gl.GLMeshItem(vertexes=verts, color=colors, smooth=True) +# +# w.addItem(m2) +# m2.translate(-25, -25, -50) diff --git a/pyqtgraph/opengl/MeshData.py b/pyqtgraph/opengl/MeshData.py index 3046459d..74bfea7d 100644 --- a/pyqtgraph/opengl/MeshData.py +++ b/pyqtgraph/opengl/MeshData.py @@ -1,5 +1,5 @@ -from ..Qt import QtGui -from .. import functions as fn +from pyqtgraph.Qt import QtGui +import pyqtgraph.functions as fn import numpy as np class MeshData(object): @@ -516,4 +516,36 @@ class MeshData(object): return MeshData(vertexes=verts, faces=faces) + @staticmethod + def cylinder(rows, cols, radius=[1.0, 1.0], length=1.0, offset=False, ends=False): + """ + Return a MeshData instance with vertexes and faces computed + for a cylindrical surface. + The cylinder may be tapered with different radii at each end (truncated cone) + ends are open if ends = False + No closed ends implemented yet... + The easiest way may be to add a vertex at the top and bottom in the center of the face? + """ + verts = np.empty((rows+1, cols, 3), dtype=float) + if isinstance(radius, int): + radius = [radius, radius] # convert to list + ## compute vertexes + th = ((np.arange(cols) * 2 * np.pi / cols).reshape(1, cols)) # angle around + r = (np.linspace(radius[0],radius[1],num=rows+1, endpoint=True)).reshape(rows+1, 1) # radius as a function of z + verts[...,2] = np.linspace(-length/2.0, length/2.0, num=rows+1, endpoint=True).reshape(rows+1, 1) # z + if offset: + th = th + ((np.pi / cols) * np.arange(rows+1).reshape(rows+1,1)) ## rotate each row by 1/2 column + verts[...,0] = r * np.cos(th) # x = r cos(th) + verts[...,1] = r * np.sin(th) # y = r sin(th) + verts = verts.reshape((rows+1)*cols, 3) # just reshape: no redundant vertices... + ## compute faces + faces = np.empty((rows*cols*2, 3), dtype=np.uint) + rowtemplate1 = ((np.arange(cols).reshape(cols, 1) + np.array([[0, 1, 0]])) % cols) + np.array([[0, 0, cols]]) + rowtemplate2 = ((np.arange(cols).reshape(cols, 1) + np.array([[0, 1, 1]])) % cols) + np.array([[cols, 0, cols]]) + for row in range(rows): + start = row * cols * 2 + faces[start:start+cols] = rowtemplate1 + row * cols + faces[start+cols:start+(cols*2)] = rowtemplate2 + row * cols + + return MeshData(vertexes=verts, faces=faces) \ No newline at end of file