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 + -
显示快捷键?