#!/usr/bin/env python
import sys
import time
from iv import *
from qt import *
class CircularColorMap(object):
"""Circular color map to create a packed color array in view of data
transfer to Coin3D or Open Inventor.
See: http://astronomy.swin.edu.au/~pbourke/colour/colourramp/
"""
def __init__(self):
"""Create the lookup table.
See: http://astronomy.swin.edu.au/~pbourke/colour/colourramp/
"""
n = 6*256
r = zeros(n, UInt32)
g = zeros(n, UInt32)
b = zeros(n, UInt32)
up = arange(0, 256, 1, UInt32)
down = arange(255, -1, -1, UInt32)
r1, g1, b1 = (0, 1, 1) # cyan
for i, (r2, g2, b2) in enumerate((
(0, 0, 1), # blue
(1, 0, 1), # magenta
(1, 0, 0), # red
(1, 1, 0), # yellow
(0, 1, 0), # green
(0, 1, 1), # cyan
)):
s = slice(i*256, (i+1)*256)
if r1:
if r2: r[s] = 255
else: r[s] = down
elif r2: r[s] = up
if g1:
if g2: g[s] = 255
else: g[s] = down
elif g2: g[s] = up
if b1:
if b2: b[s] = 255
else: b[s] = down
elif b2: b[s] = up
r1, g1, b1 = r2, g2, b2
self.__m = (r << 16) + (g << 8) + b
self.__m <<= 8
self.__m += 255
# __init__()
def colors(self, data, datamin = None, datamax = None):
"""Map data to a packed color array.
"""
if datamin is None:
datamin = minimum.reduce(data)
if datamax is None:
datamax = maximum.reduce(data)
if datamax < datamin:
datamax, datamin = datamin, datamax
indices = (((len(self.__m)-1)/(datamax-datamin)) * data).astype(Int32)
return take(self.__m, indices)
# colors()
# class CircularColorMap
def sphericalHarmonics(nu, nv, colorMap):
"""Calculate the vertices and colors of a 'spherical harmonics' in view of
data transfer to Coin3D or Open Inventor.
See: http://astronomy.swin.edu.au/~pbourke/surfaces/sphericalh
"""
# Coin generates a warning when nu and/or nv are even.
assert(nu % 2 == 1)
assert(nv % 2 == 1)
tick = time.time()
i = arange(nu*nv)
u = i % nu
u %= nu
u = pi*u/(nu-1) # phi
v = i / nu
v %= nv
v = 2*pi*v/(nu-1) # theta
m = (4, 3, 2, 3, 6, 2, 6, 4)
r = sin(m[0]*u)**m[1]+cos(m[2]*u)**m[3]+sin(m[4]*v)**m[5]+cos(m[6]*v)**m[7]
xyzs = zeros((nu*nv, 3), Float)
xyzs[:, 0] = r*sin(u)*cos(v)
xyzs[:, 1] = r*sin(u)*sin(v)
xyzs[:, 2] = r*cos(u)
colors = colorMap.colors(v, 0.0, 2*pi)
message = 'Calculating %s vertices and colors took %s seconds' % (
nu*nv, time.time()-tick)
return xyzs, colors, message
# sphericalHarmonics()
def makeSurface(nu, nv, xyzs, colors):
"""Create a scene graph from vertex and color data."""
result = SoSeparator()
shapeHints = SoShapeHints()
shapeHints.vertexOrdering.setValue(SoShapeHints.COUNTERCLOCKWISE)
shapeHints.shapeType.setValue(SoShapeHints.UNKNOWN_SHAPE_TYPE)
result.addChild(shapeHints)
vertexProperty = SoVertexProperty()
vertexProperty.materialBinding.setValue(
SoMaterialBinding.PER_VERTEX_INDEXED)
vertexProperty.orderedRGBA.setValues(0, colors)
vertexProperty.vertex.setValues(0, xyzs)
# Define the QuadMesh.
quadMesh = SoQuadMesh()
quadMesh.verticesPerRow.setValue(nu)
quadMesh.verticesPerColumn.setValue(nv)
quadMesh.vertexProperty.setValue(vertexProperty)
result.addChild(quadMesh)
return result
# makeSurface()
class InventorMainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(
self, None, 'SoQt Main Window Example', Qt.WDestructiveClose)
self.colorMap = CircularColorMap()
self.setCaption("Spherical Harmonics")
# Since SoQt widgets are not derived from QWidget,
# it is sometimes usefull to give them a empty shell QWidget as parent:
shell = QWidget(self)
self.viewer = SoQtExaminerViewer(shell)
# and now
self.setCentralWidget(shell)
# instead of self.setCentralWidget(self.viewer) which raises an error.
self.viewer.setFeedbackVisibility(True)
toolBar = QToolBar(self)
QLabel('size:', toolBar)
sizeComboBox = QComboBox(toolBar)
for text in ('17 by 17',
'33 by 33',
'65 by 65',
'127 by 127',
'257 by 257',
'513 by 513',
'1025 by 1025',
'2047 by 2047',
'4097 by 4097'):
sizeComboBox.insertItem(text)
sizeComboBox.setCurrentItem(0)
sizeComboBox.setMaximumWidth(150)
toolBar.addSeparator()
self.newSurface(0)
self.connect(sizeComboBox, SIGNAL('activated(int)'), self.newSurface)
self.resize(600, 400)
# __init__()
def newSurface(self, index):
nu = 2**(4+index) + 1
nv = nu
xyzs, colors, message = sphericalHarmonics(nu, nv, self.colorMap)
root = makeSurface(nu, nv, xyzs, colors)
self.viewer.setSceneGraph(root)
self.viewer.viewAll()
self.statusBar().message(message)
# newSurface()
# InventorMainWindow()
def main():
app = QApplication(sys.argv)
SoQt.init(None)
demo = InventorMainWindow()
demo.show()
app.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()'))
SoQt.mainLoop()
# main()
if __name__ == '__main__':
if len(sys.argv) != 2:
print 'Usage: python numpy'
print 'where numpy must be Numeric, numarray, or numpy'
sys.exit(1)
if sys.argv[1] == 'Numeric':
from Numeric import *
elif sys.argv[1] == 'numarray':
from numarray import *
elif sys.argv[1] == 'numpy':
from numpy import *
main()
# Local Variables: ***
# mode: python ***
# End: ***