spokepov.py
来自「旋转16个LED灯控制程序」· Python 代码 · 共 1,102 行 · 第 1/3 页
PY
1,102 行
reddc = wx.MemoryDC() reddc.SelectObject(self.RedBuffer) reddc.SetPen(wx.RED_PEN) reddc.SetBrush(wx.RED_BRUSH) reddc.DrawRectangle(0, 0, width, height) reddc.SelectObject(wx.NullBitmap) self._BackgroundBuffer = wx.EmptyBitmap(width, height) dc = wx.MemoryDC() dc.SelectObject(self._BackgroundBuffer) # clear up the background dc.Clear(); #self.SetBackgroundColour((255,255,255)) middle = wx.Point(width/2, height/2) dDiameter = min(width, height) / (num_leds + hubsize) # ok draw the image (if there is one) if (self.image != None): dc.DrawBitmap(self.image.ConvertToBitmap(), 0, 0) # set up the pen for drawing: black outlines dc.SetPen(wx.GREY_PEN) dc.SetBrush(wx.TRANSPARENT_BRUSH) # ok draw the rings for ring in range(0, num_leds+1): diam = dDiameter * (hubsize+ring) dc.DrawCircle(middle.x, middle.y, diam/2) # OK draw the radials innerringD = dDiameter*hubsize outerringD = dDiameter*(num_leds+hubsize) for rad in range(0, ROWS_PER_WHEEL): x1 = innerringD/2 * math.sin(2*PI * rad / ROWS_PER_WHEEL); x2 = outerringD/2 * math.sin(2*PI * rad / ROWS_PER_WHEEL); y1 = innerringD/2 * math.cos(2*PI * rad / ROWS_PER_WHEEL); y2 = outerringD/2 * math.cos(2*PI * rad / ROWS_PER_WHEEL); dc.DrawLine(middle.x+x1, middle.y+y1, middle.x+x2, middle.y+y2); dc.SelectObject(wx.NullBitmap) # now call the buffered drawing procedure self.Draw() def Draw(self, dc = None): global model, hubsize (width, height) = self.GetSizeTuple() if not dc: dc = wx.ClientDC(self) if (self._BackgroundBuffer == None): self.UpdateBackground() if ((self._ForegroundMaskBuffer == None) or model.has_changed()): self.UpdateForegroundMask() model.set_changed(False) BlitBuffer = wx.EmptyBitmap(width, height) blitdc = wx.MemoryDC() blitdc.SelectObject(BlitBuffer) blitdc.DrawBitmap(self._BackgroundBuffer,0,0) self.mask = wx.Mask(self._ForegroundMaskBuffer, wx.WHITE) # mask with white transparent self.RedBuffer.SetMask(self.mask) blitdc.DrawBitmap(self.RedBuffer,0,0, True) blitdc.SelectObject(wx.NullBitmap) dc.DrawBitmap(BlitBuffer, 0, 0) def OnPaint(self, event): dc = wx.PaintDC(self) self.Draw(dc) def setImage(self, image): global model if (image == None): return (width, height) = self.GetSizeTuple() self.image = image.Scale(width, height) self.image.ConvertToMono(0,0,0) imagedata = self.image.GetData() #print len(imagedata) for j in range(0,height): s = "" for i in range(0,width): s += str(imagedata[ (j*width+i)*3 ])+" " #print s # create model from image for j in range(0,ROWS_PER_WHEEL): for i in range(0,num_leds): (x, y) = self.getXYPointForLED(i, j) foo = (int(x)*width+int(y))*3 pix = ord(imagedata[foo]) if (pix == 0): model[(j,i)] = 1 else: model[(j,i)] = 0 self.UpdateBackground() self.Draw()# RJW - 06/27/06 - Import a BMP, grab the top left corner pixels and map them# 1-1 to the wheel pixels. Do no scaling! def setImageRect(self, image): global model if (image == None): return (width, height) = self.GetSizeTuple() # note use of image here, not self.image image.ConvertToMono(0,0,0) imagedata = image.GetData() #print len(imagedata) #print "RPW" , ROWS_PER_WHEEL #print "NLEDS" , num_leds # create model from image, just basically copying the pixels # have to reverse the column order in order to get things to work OK for j in range(0,ROWS_PER_WHEEL): for i in range(0,num_leds): foo = (int(i)*ROWS_PER_WHEEL+int(ROWS_PER_WHEEL-j))*3 # print "j" , j , "i" , i , "foo" , foo pix = ord(imagedata[foo]) if (pix == 0): model[(j,i)] = 1 else: model[(j,i)] = 0 self.UpdateBackground() self.Draw() def getLEDForXYPoint(self, x, y): (width, height) = self.GetSizeTuple() dDiameter = min(width, height) / (num_leds + hubsize) # find led num by finding distance from point to middle lednum = int(math.sqrt( math.pow((width/2 - x), 2) + math.pow((height/2 - y), 2) ) / (dDiameter / 2) - hubsize) #find row by calculating angle x -= width/2 y -= height/2 radius = math.sqrt( math.pow(x, 2) + math.pow(y, 2) ) angle = math.asin(x/radius) * 180/PI angle = (angle + 360) % 360 if ((x > 0) and (y > 0)): angle = 180 - angle if ((x < 0) and (y > 0)): angle = 360 - angle + 180 return (lednum, int(angle / 360 * ROWS_PER_WHEEL)) def getXYPointForLED(self, led, row): (width, height) = self.GetSizeTuple() dDiameter = min(width, height) / (num_leds + hubsize) radius = (led + .5 + hubsize)*dDiameter/2 startangle = 270 - ((row+.5) * 360.0)/ROWS_PER_WHEEL angle = startangle * PI/180.0 return ( (math.sin(angle)*radius+(width/2), (height/2)-math.cos(angle)*radius)) def OnLeftDown(self, event): global model, num_leds, DRAWING, ERASING self.CaptureMouse() # figure out if we're erasing or drawing (lednum, rownum) = self.getLEDForXYPoint(event.GetPosition().x, event.GetPosition().y) #print (lednum, rownum) if ((lednum < 0) or (lednum > num_leds)): return # trick the double buffer, set the value, draw on the mask, then clear the modelchange (width, height) = self.GetSizeTuple() dc = wx.MemoryDC() dc.SelectObject(self._ForegroundMaskBuffer) startangle = 90.0 - ((rownum+1)*360.0/ROWS_PER_WHEEL) dAngle = 360.0/ROWS_PER_WHEEL dDiameter = min(width, height) / (num_leds + hubsize) diam = (lednum+.5+hubsize) * dDiameter dc.SetBrush(wx.TRANSPARENT_BRUSH) if (model[(rownum, lednum)] == 0): pen = wx.Pen("green", dDiameter/2, wx.SOLID) model[(rownum, lednum)] = 1 self.drawstate = DRAWING else: pen = wx.Pen("white", dDiameter/2, wx.SOLID) model[(rownum, lednum)] = 0 self.drawstate = ERASING pen.SetCap(wx.CAP_BUTT) dc.SetPen(pen) dc.DrawEllipticArc((width/2 - (diam/2) + .5), (height/2 - (diam/2) + .5), diam, diam, startangle,startangle+dAngle) dc.SelectObject(wx.NullBitmap) model.set_changed(False) self.Draw() def OnLeftUp(self, event): if self.HasCapture(): self.ReleaseMouse() self.drawstate = None def OnMotion(self, event): global DRAWING, ERASING if (self.drawstate != None): (lednum, rownum) = self.getLEDForXYPoint(event.GetPosition().x, event.GetPosition().y) if ((lednum < 0) or (lednum >= num_leds)): return # trick the double buffer, set the value, draw on the mask, then clear the modelchange (width, height) = self.GetSizeTuple() dc = wx.MemoryDC() dc.SelectObject(self._ForegroundMaskBuffer) startangle = 90.0 - ((rownum+1)*360.0/ROWS_PER_WHEEL) dAngle = 360.0/ROWS_PER_WHEEL dDiameter = min(width, height) / (num_leds + hubsize) diam = (lednum+.5+hubsize) * dDiameter dc.SetBrush(wx.TRANSPARENT_BRUSH) if (self.drawstate == DRAWING): pen = wx.Pen("green", dDiameter/2, wx.SOLID) model[(rownum, lednum)] = 1 else: pen = wx.Pen("white", dDiameter/2, wx.SOLID) model[(rownum, lednum)] = 0 pen.SetCap(wx.CAP_BUTT) dc.SetPen(pen) dc.DrawEllipticArc((width/2 - (diam/2) + .5), (height/2 - (diam/2) + .5), diam, diam, startangle,startangle+dAngle) dc.SelectObject(wx.NullBitmap) model.set_changed(False) self.Draw()class SetRotationDialog(wx.Dialog): def __init__( self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE, offset=0 ): self.parent = parent # Instead of calling wx.Dialog.__init__ we precreate the dialog # so we can set an extra style that must be set before # creation, and then we create the GUI dialog using the Create # method. pre = wx.PreDialog() pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP) pre.Create(parent, ID, title, pos, size, style) # This next step is the most important, it turns this Python # object into the real wrapper of the dialog (instead of pre) # as far as the wxPython extension is concerned. self.PostCreate(pre) # Now continue with the normal construction of the dialog # contents sizer = wx.BoxSizer(wx.VERTICAL) label = wx.StaticText(self, -1, "Set the rotation offset") sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, -1, "Offset:") box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5) self.text = wx.TextCtrl(self, -1, str(offset), size=(80,-1)) box.Add(self.text, 1, wx.ALIGN_CENTRE|wx.ALL, 5) sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5) btnsizer = wx.BoxSizer(wx.HORIZONTAL) btn = wx.Button(self, -1, "Write") btn.SetDefault() self.Bind(wx.EVT_BUTTON, self.OnWriteButton, btn) btnsizer.Add(btn) btn = wx.Button(self, wx.ID_CANCEL, "Done") btnsizer.Add(btn) sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) self.SetSizer(sizer) sizer.Fit(self) def OnWriteButton(self, evt): spov = SpokePOVComm() try: spov.write_eeprom(EEPROM_ROTOFFSET, int(self.text.GetLineText(0))) self.parent.SetStatusText("Wrote rotation offset successfully") except IOError: self.parent.SetStatusText("IO ERROR: Could not write rotation offset!")#---------------------------------------------------------------------------#################################### The top-level frame (menus, buttons, wheelpanel)####class SpokeSoftFrame(wx.Frame): """ This is the spokesoft Frame """ wheel = None filename = None def __init__(self, parent, title): global autorotation wx.Frame.__init__(self, parent, -1, title, pos=(50, 50), size=(WHEEL_W+6, WHEEL_H+130), style=(wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.RESIZE_BOX | wx.MAXIMIZE_BOX))) self.SetTitle("pySpokePOV ") # Create the menubar menuBar = wx.MenuBar() # and a menu filemenu = wx.Menu() # RJW - 06/28/06 - added Rect->Circ import and fg/bg copy routines filemenu.Append(0, "Open...", "Open a SpokePOV image file") filemenu.Append(1, "Import...", "Import a BMP file") filemenu.Append(2, "Import (Rect->Circ)...", "Import a BMP file (rectangle->circle)") filemenu.Append(3, "Save", "Save SpokePOV image to a file") filemenu.Append(4, "Save As...", "Save the SpokePOV image to a new file") filemenu.AppendSeparator() filemenu.Append(5, "Set Rotation...", "Set the rotation value for the SpokePOV") filemenu.AppendSeparator()
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?