Forums
New posts
Search forums
Members
Current visitors
Log in
Register
What's new
Search
Search
Search titles only
By:
New posts
Search forums
Menu
Log in
Register
Install the app
Install
Forums
Archive
Archive
Python
Graphs/statistics using wxPython
JavaScript is disabled. For a better experience, please enable JavaScript in your browser before proceeding.
You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an
alternative browser
.
Reply to thread
Message
[QUOTE="Will McGugan, post: 1826494"] If you ever want to add an extra dimension, then using OpenGL with wxWindows is a breeze. See attached file for a 3d pie char.. Will McGugan -- [URL]http://www.willmcgugan.com[/URL] "".join({'*':'@','^':'.'}.get(c,0) or chr(97+(ord(c)-84)%26) for c in "jvyy*jvyyzpthtna^pbz") # Pie Chart Window # 2005 Will McGugan (will@willmcgugan.com) import wx from wx import glcanvas from OpenGL.GL import * import math import time sin = math.sin cos = math.cos PI = math.pi def DegToRad(deg): return deg*PI/180. class PieSegment(object): def __init__(self, radius, angle1, angle2, colour, depth): self.display_list = glGenLists(1) glNewList(self.display_list, GL_COMPILE) self.angle1 = angle1 self.angle2 = angle2 self.explode_angle = DegToRad( (angle2 + angle1) / 2.) DrawPieSegment(radius, angle1, angle2, colour, depth) glEndList() def __del__(self): glDeleteLists(self.display_list, 1) def Draw(self, angle1, angle2, explode): glPushMatrix() glRotate(angle1, 1.0, 0.0, 0.0); glRotate(angle2, 0.0, 0.0, 1.0); glTranslatef( sin(self.explode_angle)*explode, cos(self.explode_angle)*explode, 0. ) glCallList(self.display_list) glPopMatrix() def DrawPieSegment(radius, angle1, angle2, colour, depth): angle1 = DegToRad(angle1) angle2 = DegToRad(angle2) # Number of divisions in 360 degrees RES = 100. fan2D = [] step_degree = ((2*PI)/RES) step_count = int( (angle2 - angle1) / step_degree ) + 1 step_degree = ( angle2 - angle1 ) / float(step_count) # Precalculate the trig sina1 = sin(angle1) cosa1 = cos(angle1) sina2 = sin(angle2) cosa2 = cos(angle2) # Calculate the points in an arc for p in xrange(step_count+1): a = angle1 + p * step_degree x = sin(a) y = cos(a) fan2D.append( (x,y) ) z1 = +depth/2. z2 = -depth/2. glMaterial(GL_FRONT, GL_DIFFUSE, [colour[0], colour[1], colour[2], 1.0]) # Create a fan for the top and bottom of the pie segment glNormal(0, 0, +1.) glBegin(GL_TRIANGLE_FAN) glVertex(0, 0, z1) for x, y in fan2D: glVertex(x*radius, y*radius, z1) glEnd() glNormal(0, 0, -1.) glBegin(GL_TRIANGLE_FAN) glVertex(0, 0, z2) for x, y in fan2D: glVertex(x*radius, y*radius, z2) glEnd() # A strip for the curved edge glBegin(GL_TRIANGLE_STRIP) for x, y in fan2D: glNormal(x, y, 0.) xr = x * radius yr = y * radius glVertex(xr, yr, z1) glVertex(xr, yr, z2) glEnd() n1 = -cosa1, sina1, 0. n2 = cosa2, -sina2, 0. x1, y1 = sina1 * radius, cosa1 * radius x2, y2 = sina2 * radius, cosa2 * radius # Two quads for the radius edges glNormal(n1) glBegin(GL_QUADS) glVertex(0, 0, z1) glVertex(x1, y1, z1) glVertex(x1, y1, z2) glVertex(0, 0, z2) glEnd() glNormal(n2) glBegin(GL_QUADS) glVertex(0, 0, z1) glVertex(x2, y2, z1) glVertex(x2, y2, z2) glVertex(0, 0, z2) glEnd() class PieChartWindow(glcanvas.GLCanvas): def __init__(self, parent): attriblist = None glcanvas.GLCanvas.__init__(self, parent, -1, wx.DefaultPosition, wx.DefaultSize, 0, "GLCanvas", attriblist, wx.NullPalette) self.init = False self.segments = [] self.animating = False self.angle = 0. self.explode = 0. self.downx = 0 self.rot = 0. self.captured_mouse = False self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnTimer) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftButtonDown) self.Bind(wx.EVT_LEFT_UP, self.OnLeftButtonUp) self.Bind(wx.EVT_MOTION, self.OnMouseMove) self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_PAINT, self.OnPaint) def Animate(self): self.animating = True self.start_animate = time.clock() self.timer.Start(1000/20) def OnTimer(self, event): if self.IsShown(): self.Refresh() if not self.animating: self.timer.Stop(); def SetSegments(self, segments, angle=0., radius=150., depth=50.): self.segments = [] First = True if len(segments): angle = -(segments[0][0]/2. *360./100.) for seg in segments: seg_percent, colour = seg if seg_percent == 0: continue if seg_percent < .2: angle = angle + (seg_percent*360./100.) continue if First: angle = -(seg_percent/2. * 360./100.) First = False next_angle = angle + (seg_percent*360./100.) self.segments.append(PieSegment(radius, angle, next_angle, colour, depth)) angle=next_angle def PerspectiveProjection(self): w, h = 300., 300. a = 30. tana = math.tan(DegToRad(a/2.)) glMatrixMode(GL_PROJECTION); v = (w/2) / tana near = v / 10. vw = tana * near vh = tana * near glFrustum(-vw, vw, -vh, vh, near, v*3.0); glMatrixMode(GL_MODELVIEW); glTranslatef(0.0, 0.0, -v*1.2); glLight(GL_LIGHT0, GL_POSITION, [w/2, h/2, v*1.2, 0.0]); def InitGL(self): self.PerspectiveProjection() glMaterial(GL_FRONT, GL_AMBIENT, [0.3, 0.3, 0.3, 1.0]) glMaterial(GL_FRONT, GL_DIFFUSE, [0.9, 0.9, 0.9, 1.0]) glMaterial(GL_FRONT, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0]) glMaterial(GL_FRONT, GL_SHININESS, 70.0) glLight(GL_LIGHT0, GL_AMBIENT, [0.25, 0.25, 0.25, 1.0]) glLight(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0]) glLight(GL_LIGHT0, GL_SPECULAR, [.1, .1, .1, 1.0]) glLightModel(GL_LIGHT_MODEL_AMBIENT, [0.2, 0.2, 0.2, 1.0]) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) glClearColor(1,1,1,1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_MODELVIEW); def OnLeftButtonDown(self, event): self.downx = event.GetPosition()[0] self.captured_mouse = True self.CaptureMouse() def OnLeftButtonUp(self, event): if self.captured_mouse and self.HasCapture(): self.ReleaseMouse() def OnMouseMove(self, event): if event.Dragging() and event.LeftIsDown(): mx, my = event.GetPosition() rot_delta = self.downx - mx self.rot+= rot_delta self.downx = mx self.Refresh() def OnEraseBackground(self, event): pass def OnSize(self, event): size = self.GetClientSize() if self.GetContext(): self.SetCurrent() glViewport(0, 0, size.width, size.height) self.Refresh() event.Skip() def OnPaint(self, event): dc = wx.PaintDC(self) self.SetCurrent() if not self.init: self.InitGL() self.init = True self.OnDraw() def OnDraw(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if self.animating: t = time.clock() - self.start_animate if t < 1.: self.angle = 0. self.explode = 0. elif t < 2.: ts = t - 1. self.angle = -50. * ts elif t < 3.: ts = t - 2. self.angle = -50. self.explode = 15. * ts else: self.animating = False self.angle = -50. self.explode = 15. for segment in self.segments: segment.Draw(self.angle, self.rot, self.explode) self.SwapBuffers() if __name__ == "__main__": class TestFrame(wx.Frame): def __init__(self): super(TestFrame, self).__init__(None, -1, "Pie Chart Test", style=wx.DEFAULT_FRAME_STYLE) self.SetClientSize(wx.Size(300,300)) pie_chart = PieChartWindow(self) # List of tuples ( <Percentage of Pie>, ( <Red>, <Green>, <Blue> ) ) seg = [ ( 20, (1., 0.1, 0.1) ), ( 25, (0.05, .9, .1) ), ( 10, (.2, 0.1, 1.) ), ( 30, (.8, .9, .1) ) ] pie_chart.SetSegments( seg ) pie_chart.Animate() app = wx.App() frame = TestFrame() frame.Show(True) app.MainLoop() [/QUOTE]
Verification
Post reply
Forums
Archive
Archive
Python
Graphs/statistics using wxPython
Top