|
From: Kevin A. <ka...@us...> - 2004-05-01 17:05:43
|
Update of /cvsroot/pythoncard/PythonCard/samples/spirographInteractive In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16158/samples/spirographInteractive Added Files: .cvsignore readme.txt spirographInteractive.py spirographInteractive.rsrc.py Log Message: made spirographInteractive its own sample --- NEW FILE: .cvsignore --- .cvsignore *.pyc *.log .DS_Store --- NEW FILE: spirographInteractive.py --- #!/usr/bin/python """ __version__ = "$Revision: 1.1 $" __date__ = "$Date: 2004/05/01 17:05:32 $" """ """ this is a direct port of the Java applet at http://www.wordsmith.org/anu/java/spirograph.html """ from PythonCard import clipboard, dialog, graphic, model import wx import os import random import math class Spirograph(model.Background): def on_initialize(self, event): self.filename = None comp = self.components self.sliderLabels = { 'stcFixedCircleRadius':comp.stcFixedCircleRadius.text, 'stcMovingCircleRadius':comp.stcMovingCircleRadius.text, 'stcMovingCircleOffset':comp.stcMovingCircleOffset.text, 'stcRevolutionsInRadians':comp.stcRevolutionsInRadians.text, } self.setSliderLabels() if self.components.chkDarkCanvas.checked: self.components.bufOff.backgroundColor = 'black' self.components.bufOff.clear() self.doSpirograph() def doSpirograph(self): comp = self.components canvas = comp.bufOff width, height = canvas.size xOffset = width / 2 yOffset = height / 2 R = comp.sldFixedCircleRadius.value r = comp.sldMovingCircleRadius.value O = comp.sldMovingCircleOffset.value revolutions = comp.sldRevolutionsInRadians.value color = comp.btnColor.backgroundColor canvas.foregroundColor = color canvas.autoRefresh = 0 canvas.clear() if comp.radDrawingStyle.stringSelection == 'Lines': drawLines = 1 else: drawLines = 0 t = 0.0 if R+r+O == 0: # avoid divide by zero errors s = 5.0/0.0000001 else: s = 5.0/(R+r+O) rSum = R + r # avoid divide by zero errors if r == 0: r = 0.0000001 exprResult = (rSum * t) / r lastX = rSum*math.cos(t) - O*math.cos(exprResult) + xOffset lastY = rSum*math.sin(t) - O*math.sin(exprResult) + yOffset self.keepDrawing = 1 points = [] while abs(t) <= revolutions: exprResult = (rSum * t) / r x = rSum*math.cos(t) - O*math.cos(exprResult) + xOffset y = rSum*math.sin(t) - O*math.sin(exprResult) + yOffset if drawLines: points.append((lastX, lastY, x, y)) lastX = x lastY = y else: points.append((x, y)) t += s if drawLines: canvas.drawLineList(points) else: canvas.drawPointList(points) canvas.autoRefresh = 1 canvas.refresh() def on_btnColor_mouseClick(self, event): result = dialog.colorDialog(self) if result['accepted']: self.components.bufOff.foregroundColor = result['color'] event.target.backgroundColor = result['color'] self.doSpirograph() def on_select(self, event): name = event.target.name # only process Sliders if name.startswith('sld'): labelName = 'stc' + name[3:] self.components[labelName].text = self.sliderLabels[labelName] + \ ' ' + str(event.target.value) self.doSpirograph() def on_chkDarkCanvas_mouseClick(self, event): if event.target.checked: self.components.bufOff.backgroundColor = 'black' else: self.components.bufOff.backgroundColor = 'white' self.doSpirograph() def setSliderLabels(self): comp = self.components for key in self.sliderLabels: sliderName = 'sld' + key[3:] comp[key].text = self.sliderLabels[key] + ' ' + str(comp[sliderName].value) def on_btnRandom_mouseClick(self, event): comp = self.components comp.sldFixedCircleRadius.value = random.randint(1, 100) comp.sldMovingCircleRadius.value = random.randint(-50, 50) comp.sldMovingCircleOffset.value = random.randint(1, 100) self.setSliderLabels() self.doSpirograph() def openFile(self): wildcard = "All files (*.*)|*.*" result = dialog.openFileDialog(None, "Import which file?", '', '', wildcard) if result['accepted']: path = result['paths'][0] os.chdir(os.path.dirname(path)) try: self.filename = path filename = os.path.splitext(os.path.basename(path))[0] if filename.startswith('spiro'): items = filename[5:].split('_') comp = self.components comp.sldFixedCircleRadius.value = int(items[0]) comp.sldMovingCircleRadius.value = int(items[1]) comp.sldMovingCircleOffset.value = int(items[2]) comp.btnColor.backgroundColor = eval(items[3]) comp.chkDarkCanvas.checked = int(items[4]) if items[5] == 'L': comp.radDrawingStyle.stringSelection = 'Lines' else: comp.radDrawingStyle.stringSelection = 'Points' comp.sldRevolutionsInRadians.value = int(items[6]) self.setSliderLabels() bmp = graphic.Bitmap(self.filename) self.components.bufOff.drawBitmap(bmp, (0, 0)) except: pass def on_menuFileOpen_select(self, event): self.openFile() def on_menuFileSaveAs_select(self, event): if self.filename is None: path = '' filename = '' else: path, filename = os.path.split(self.filename) comp = self.components style = comp.radDrawingStyle.stringSelection[0] filename = 'spiro' + str(comp.sldFixedCircleRadius.value) + '_' + \ str(comp.sldMovingCircleRadius.value) + '_' + \ str(comp.sldMovingCircleOffset.value) + '_' + \ str(comp.btnColor.backgroundColor) + '_' + \ str(comp.chkDarkCanvas.checked) + '_' + \ style + '_' + \ str(comp.sldRevolutionsInRadians.value) + \ '.png' wildcard = "All files (*.*)|*.*" result = dialog.saveFileDialog(None, "Save As", path, filename, wildcard) if result['accepted']: path = result['paths'][0] fileType = graphic.bitmapType(path) try: bmp = self.components.bufOff.getBitmap() bmp.SaveFile(path, fileType) return 1 except: return 0 else: return 0 def on_menuEditCopy_select(self, event): clipboard.setClipboard(self.components.bufOff.getBitmap()) def on_menuEditPaste_select(self, event): bmp = clipboard.getClipboard() if isinstance(bmp, wx.Bitmap): self.components.bufOff.drawBitmap(bmp) def on_editClear_command(self, event): self.components.bufOff.clear() def on_menuFileExit_select(self, event): self.close() if __name__ == '__main__': app = model.Application(Spirograph) app.MainLoop() --- NEW FILE: readme.txt --- spirograph.py is a direct port of the Java applet by Anu Garg at: http://www.wordsmith.org/anu/java/spirograph.html The following quote is from Anu's page: What is a Spirograph? A Spirograph is formed by rolling a circle inside or outside of another circle. The pen is placed at any point on the rolling circle. If the radius of fixed circle is R, the radius of moving circle is r, and the offset of the pen point in the moving circle is O, then the equation of the resulting curve is defined by: x = (R+r)*cos(t) - O*cos(((R+r)/r)*t) y = (R+r)*sin(t) - O*sin(((R+r)/r)*t) There is a second sample called spirographInteractive.py which draws the complete spirograph as each slider, color, or other value is changed. This makes spirographInteractive much more like the Java applet and the drawing speed is similar. On a machine with a faster video card, drawing should be sufficiently fast that the UI won't be sluggish unless the number of revolutions is quite high. However, since spirographInteractive doesn't allow you to see the individual points or lines of the pattern as they are drawn or overlay multiple patterns and is more demanding of machine resources I decided to make it a separate program rather than complicating the code and UI of the spirograph sample. --- NEW FILE: spirographInteractive.rsrc.py --- {'stack':{'type':'Stack', 'name':'Spirograph', 'backgrounds': [ {'type':'Background', 'name':'bgSpirograph', 'title':'Spirograph PythonCard Application', 'position':(5, 5), 'size':(750, 595), 'statusBar':1, 'menubar': {'type':'MenuBar', 'menus': [ {'type':'Menu', 'name':'menuFile', 'label':'&File', 'items': [ {'type':'MenuItem', 'name':'menuFileOpen', 'label':'&Open...\tCtrl+O', }, {'type':'MenuItem', 'name':'menuFileSaveAs', 'label':'Save &As...', }, {'type':'MenuItem', 'name':'fileSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuFileExit', 'label':'E&xit\tAlt+X', }, ] }, {'type':'Menu', 'name':'menuEdit', 'label':'&Edit', 'items': [ {'type':'MenuItem', 'name':'menuEditCopy', 'label':'&Copy\tCtrl+C', }, {'type':'MenuItem', 'name':'menuEditPaste', 'label':'&Paste\tCtrl+V', }, {'type':'MenuItem', 'name':'editSep1', 'label':'-', }, {'type':'MenuItem', 'name':'menuEditClear', 'label':'&Clear', 'command':'editClear', }, ] }, ] }, 'components': [ {'type':'BitmapCanvas', 'name':'bufOff', 'position':(3, 3), 'size':(525, 525), 'thickness':1, }, {'type':'StaticText', 'name':'stcFixedCircleRadius', 'position':(540, 30), 'text':'Fixed circle radius (1 - 100):', }, {'type':'StaticText', 'name':'stcMovingCircleRadius', 'position':(540, 70), 'text':'Moving circle radius (-50 - 50):', }, {'type':'StaticText', 'name':'stcMovingCircleOffset', 'position':(540, 110), 'text':'Moving circle offset (1 - 100):', }, {'type':'StaticText', 'name':'stcRevolutionsInRadians', 'position':(540, 260), 'text':'Revolutions in radians (1 - 500):', }, {'type':'Slider', 'name':'sldFixedCircleRadius', 'position':(540, 46), 'size':(200, 20), 'layout':'horizontal', 'max':100, 'min':1, 'value':74, }, {'type':'Slider', 'name':'sldMovingCircleRadius', 'position':(540, 86), 'size':(200, 20), 'layout':'horizontal', 'max':50, 'min':-50, 'value':25, }, {'type':'Slider', 'name':'sldMovingCircleOffset', 'position':(540, 126), 'size':(200, 20), 'layout':'horizontal', 'max':100, 'min':1, 'value':78, }, {'type':'Button', 'name':'btnColor', 'position':(540, 154), 'label':'Foreground Color', 'backgroundColor':(0, 128, 255), }, {'type':'CheckBox', 'name':'chkDarkCanvas', 'position':(652, 160), 'checked':0, 'label':'Dark Canvas', }, {'type':'RadioGroup', 'name':'radDrawingStyle', 'position':(540, 200), 'items':['Lines', 'Points'], 'label':'Draw as', 'layout':'horizontal', 'max':1, 'stringSelection':'Lines', }, {'type':'Slider', 'name':'sldRevolutionsInRadians', 'position':(540, 276), 'size':(200, 20), 'layout':'horizontal', 'max':500, 'min':1, 'value':50, }, {'type':'Button', 'name':'btnRandom', 'position':(540, 360), 'label':'Random Circle Values', }, ] # end components } # end background ] # end backgrounds } } |