Exemplo n.º 1
0
    def flatten(self, color=None, alpha=None):
        if self.isOutline == True and self._render_count == 1:		# outline layer
            # reconstruct the contour (the original lines go in no particular order)
            curPoint = self.lineList[0]
            countourPoints = []
            for i in range(1000):
                countourPoints.append([curPoint[0][0], curPoint[0][1], curPoint[2]])
                dist = sys.float_info.max
    		    # find the closest point among the
                for ll in self.lineList:
                    llinv = [ll[1], ll[0], ll[2]]
                    if ll == curPoint or llinv == curPoint:
                        continue
                    d = (ll[0][0] - curPoint[1][0])**2 + (ll[0][1] - curPoint[1][1])**2
                    if d < dist:
                        dist = d
                        nextCurPoint = ll
                    d = (ll[1][0] - curPoint[1][0])**2 + (ll[1][1] - curPoint[1][1])**2
                    if d < dist:
                        dist = d
                        nextCurPoint = llinv
                    if dist < 1.e-4:
                        break
                if nextCurPoint[0] in countourPoints:
                    break
                curPoint = nextCurPoint

            # draw the filled contour    
            with self._new_mask() as mask:
                mask.ctx.move_to(countourPoints[0][0], countourPoints[0][1])
                wasArc = False
                for ll in countourPoints:
                    if ll[2]:
                        arc = ll[2]
                        center = self.scale_point(arc.center)
                        radius = self.scale[0] * arc.radius
                        two_pi = 2 * math.pi
                        angle1 = (arc.start_angle + two_pi) % two_pi
                        angle2 = (arc.end_angle + two_pi) % two_pi
                        if arc.direction == 'counterclockwise':
                            mask.ctx.arc(center[0], center[1], radius, angle1, angle2)
                        else:
                            mask.ctx.arc_negative(center[0], center[1], radius, angle1, angle2)
                    else:
                        mask.ctx.line_to(ll[0], ll[1])
                mask.ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0)
                mask.ctx.fill()
                self.ctx.mask_surface(mask.surface, 0.0, 0.0)
        GerberCairoContext.flatten(self, color, alpha)
class PcbGui(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()

        self.ctx = GerberCairoContext(8)
        self.ctx.units = 'metric'

        self.layers = {}
        self.components = []
        # self.components = self.load_pickplace()
        self.layer = "TopLayer"

        # self.geometry("{}x{}".format(self._image_ref.width(), self._image_ref.height()))

        self.clist = ComponentListGui(self)
        # self.clist.add_components(self.components, self.layer)
        self.clist.pack(expand=True, side="right")

        self.label = tk.Label(self)
        self.label.pack(expand=True, side="left")
        # self.draw_component()

        self.bind('<ButtonRelease-1>', self.draw_component)

    def select_gerber_folder(self):
        dir = tk.filedialog.askdirectory(title="Select folder with Gerbers")
        self.layers = {}
        for infile in listdir(dir):
            path = os.path.join(dir, infile)
            if infile.lower().endswith('gbl'):
                self.layers['gbl'] = gerber.load_layer(path)
            if infile.lower().endswith('gtl'):
                self.layers['gtl'] = gerber.load_layer(path)
            if infile.lower().endswith('gtp'):
                self.layers['gtp'] = gerber.load_layer(path)
        self.draw_component()

    def set_layer(self, layer):
        self.layer = layer
        self.draw_component()
        self.clist.add_components(self.components, self.layer)

    def menubar(self, root):
        menubar = tk.Menu(root)
        pageMenu = tk.Menu(menubar)
        pageMenu.add_command(label="Open Gerber folder",
                             command=self.select_gerber_folder)
        pageMenu.add_command(label="Open pick and place file",
                             command=self.load_pickplace)
        menubar.add_cascade(label="File", menu=pageMenu)

        layerMenu = tk.Menu(menubar)
        layerMenu.add_radiobutton(label="Top Layer",
                                  command=lambda: self.set_layer("TopLayer"))
        layerMenu.add_radiobutton(
            label="Bottom Layer",
            command=lambda: self.set_layer("BottomLayer"))
        menubar.add_cascade(label="Layer", menu=layerMenu)

        helpMenu = tk.Menu(menubar, name="help")
        helpMenu.add_command(label="About")
        menubar.add_cascade(label="Help", menu=helpMenu)
        return menubar

    # def load_gerber(self):
    #     self.layers = {}
    #     self.layers.append(gerber.load_layer('example.GTL'))
    # self.ctx.render_layers(layers, buffer, max_width=self.w, max_height=self.h, verbose=True)

    def draw_component(self, event=None):
        self.ctx.clear()

        if len(self.layers) > 0:
            if self.layer == "TopLayer":
                copper_settings = RenderSettings(color=theme.COLORS['black'],
                                                 alpha=0.8,
                                                 mirror=False)
                self.ctx.render_layer(self.layers["gtl"],
                                      settings=copper_settings,
                                      verbose=True)
                self.ctx.new_render_layer(mirror=False)
            if self.layer == "BottomLayer":
                copper_settings = RenderSettings(color=theme.COLORS['black'],
                                                 alpha=0.8,
                                                 mirror=True)
                self.ctx.render_layer(self.layers["gbl"],
                                      settings=copper_settings)
                self.ctx.new_render_layer(mirror=True)

            self.ctx._color = (1.0, 0.0, 1.0)
            layer = self.layer
            if self.clist.tb.selected_row != None:
                part_number = self.clist.tb.selected_row['PN']
            else:
                part_number = None
            for c in self.components:
                if (c['layer'] == layer) and (c['part_number'] == part_number):
                    print("{} {}".format(c['x_mm'], c['y_mm']))
                    self.ctx.render(
                        gerber.primitives.Circle((c['x_mm'], c['y_mm']), 1))
            self.ctx.flatten()
            buffer = BytesIO()
            self.ctx.dump(buffer)
            img = ImageTk.PhotoImage(Image.open(buffer))
            self.label.configure(image=img)
            self.label.image = img

    def load_pickplace(self):
        filename = tk.filedialog.askopenfilename(
            title="Select pick and place file")
        components = []
        filetype = "Kicad"
        with open(filename, "r") as ppfile:
            header_read = False
            for line in ppfile:
                line = shlex.split(line)
                if len(line) > 0:
                    if header_read == False:
                        # Try to determine the file type based on the contents
                        if line[0] == "Altium":
                            filetype = "Altium"
                        if line[0] == "Designator" or line[0] == "#":
                            header_read = True
                    else:
                        if filetype == "Altium":
                            component = {}
                            component['designator'] = line[0]
                            component['part_number'] = line[1]
                            component['x_mm'] = float(line[4][:-2])
                            component['y_mm'] = float(line[5][:-2])
                            component['layer'] = line[2]
                            component['description'] = line[7]
                            components.append(component)
                        elif filetype == "Kicad":
                            if len(line) > 6:
                                print(line)
                                component = {}
                                component['designator'] = line[0]
                                component['part_number'] = line[1]
                                component['x_mm'] = float(line[3])
                                component['y_mm'] = float(line[4])
                                component['layer'] = "TopLayer" if line[
                                    6] == "top" else "BottomLayer"
                                if component['layer'] == "BottomLayer":
                                    component['x_mm'] *= -1
                                component['description'] = line[2]
                                components.append(component)
        self.components = components
        self.clist.add_components(self.components, self.layer)