def convert(pcb, brd): IU_PER_MM = PCB_IU_PER_MM = 1e6 IU_PER_MILS = (IU_PER_MM * 0.0254) conv_unit_inch = 0.001 / IU_PER_MILS conv_unit_mm = 1.0 / IU_PER_MM units = pcbnew.GetUserUnits() # TODO: select units from board somehow conv_unit = conv_unit_mm # Board outline outlines = pcbnew.SHAPE_POLY_SET() pcb.GetBoardPolygonOutlines(outlines, "") outline = outlines.Outline(0) outline_points = [outline.Point(n) for n in range(outline.PointCount())] outline_maxx = max(map(lambda p: p.x, outline_points)) outline_maxy = max(map(lambda p: p.y, outline_points)) m_place_offset = pcb.GetDesignSettings().m_AuxOrigin # Parts module_list = pcb.GetModules() modules = [] while module_list: if not skip_module(module_list): modules.append(module_list) module_list = module_list.Next() pin_at = 0 writer = csv.writer(brd) # Logic taken from pcbnew/exporters/export_footprints_placefile.cpp # See https://gitlab.com/kicad/code/kicad/-/issues/2453 for module in modules: footprint_pos = module.GetPosition() footprint_pos -= m_place_offset layer = module.GetLayer() if (layer not in (pcbnew.B_Cu, pcbnew.F_Cu)): continue if (layer == pcbnew.B_Cu): footprint_pos.x = -footprint_pos.x module_bbox = module.GetBoundingBox() writer.writerow([ module.GetReference(), module.GetValue(), module.GetFPID().GetLibItemName(), round(footprint_pos.x * conv_unit, 4), round(-footprint_pos.y * conv_unit, 4), module.GetOrientation() / 10.0, "top" if layer == pcbnew.F_Cu else "bottom", ]) pin_at += module.GetPadCount()
def Run(self): print("WOT") # load board board = pcbnew.GetBoard() # get user units if pcbnew.GetUserUnits() == 1: user_units = 'mm' else: user_units = 'in' self.drc(board)
def __init__(self, board): '''Initialize the brand new instance.''' super(ViaStitchingDialog, self).__init__(None) self.SetTitle(_(u"ViaStitching v{0}").format(__version__)) self.Bind(wx.EVT_CLOSE, self.onCloseWindow) self.m_btnCancel.Bind(wx.EVT_BUTTON, self.onCloseWindow) self.m_btnOk.Bind(wx.EVT_BUTTON, self.onProcessAction) self.m_rClear.Bind(wx.EVT_RADIOBUTTON, self.onRadioButtonCheck) self.m_rFill.Bind(wx.EVT_RADIOBUTTON, self.onRadioButtonCheck) self.board = pcbnew.GetBoard() #Use the same unit set int PCBNEW self.ToUserUnit = None self.FromUserUnit = None units_mode = pcbnew.GetUserUnits() if units_mode == 0: self.ToUserUnit = pcbnew.ToMils self.FromUserUnit = pcbnew.FromMils self.m_lblUnit1.SetLabel(_(u"mils")) self.m_lblUnit2.SetLabel(_(u"mils")) self.m_txtVSpacing.SetValue("40") self.m_txtHSpacing.SetValue("40") elif units_mode == 1: self.ToUserUnit = pcbnew.ToMM self.FromUserUnit = pcbnew.FromMM self.m_lblUnit1.SetLabel(_(u"mm")) self.m_lblUnit2.SetLabel(_(u"mm")) self.m_txtVSpacing.SetValue("1") self.m_txtHSpacing.SetValue("1") elif units_mode == -1: wx.MessageBox(_(u"Not a valid frame")) self.Destroy() #Get default Vias dimensions via_dim_list = self.board.GetViasDimensionsList() via_dims = via_dim_list.pop() self.m_txtViaSize.SetValue("%.6f" % self.ToUserUnit(via_dims.m_Diameter)) self.m_txtViaDrillSize.SetValue("%.6f" % self.ToUserUnit(via_dims.m_Drill)) via_dim_list.push_back(via_dims) self.area = None self.net = None self.overlappings = None #Check for selected area if not self.GetAreaConfig(): wx.MessageBox(_(u"Please select a valid area")) self.Destroy() else: #Get overlapping items self.GetOverlappingItems() #Populate nets checkbox self.PopulateNets()
def Run(self): # load board board = pcbnew.GetBoard() # get user units if pcbnew.GetUserUnits() == 1: user_units = 'mm' else: user_units = 'in' # go to the project folder - so that log will be in proper place os.chdir(os.path.dirname(os.path.abspath(board.GetFileName()))) # set up logger logging.basicConfig( level=logging.DEBUG, filename="net2et distance.log", filemode='w', format='%(asctime)s %(name)s %(lineno)d:%(message)s', datefmt='%m-%d %H:%M:%S') logger = logging.getLogger(__name__) logger.info("Net2net distance plugin version: " + VERSION + " started") stdout_logger = logging.getLogger('STDOUT') sl_out = StreamToLogger(stdout_logger, logging.INFO) sys.stdout = sl_out stderr_logger = logging.getLogger('STDERR') sl_err = StreamToLogger(stderr_logger, logging.ERROR) sys.stderr = sl_err _pcbnew_frame = [ x for x in wx.GetTopLevelWindows() if x.GetTitle().lower().startswith('pcbnew') ][0] # get all selected nets either as tracks or as pads nets = set() selected_tracks = [x for x in board.GetTracks() if x.IsSelected()] nets.update([track.GetNetname() for track in selected_tracks]) modules = board.GetModules() for mod in modules: pads = mod.Pads() nets.update([pad.GetNetname() for pad in pads if pad.IsSelected()]) # if two pads are selected if len(nets) != 2: # if more or less than one show only a messagebox caption = 'Net2Net Distance' message = "You have to select two and only two nets" dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return try: dis, loc = net2net_distance.get_min_distance(board, list(nets)) except Exception: logger.exception("Fatal error when replicating") raise caption = 'Net2Net Track Distance' if user_units == 'mm': message = "Minimum distance between net segments is " + "%.3f" % ( dis / SCALE) + " mm" else: message = "Minimum distance between net segments is " + "%.4f" % ( dis / (SCALE * 25.4)) + " in" dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy()
def Run(self): # load board board = pcbnew.GetBoard() # get user units if pcbnew.GetUserUnits() == 1: user_units = 'mm' else: user_units = 'in' # go to the project folder - so that log will be in proper place os.chdir(os.path.dirname(os.path.abspath(board.GetFileName()))) # Remove all handlers associated with the root logger object. for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) # set up logger logging.basicConfig( level=logging.DEBUG, filename="place_footprints.log", filemode='w', format='%(asctime)s %(name)s %(lineno)d:%(message)s', datefmt='%m-%d %H:%M:%S') logger = logging.getLogger(__name__) logger.info("Place footprints plugin version: " + VERSION + " started") stdout_logger = logging.getLogger('STDOUT') sl_out = StreamToLogger(stdout_logger, logging.INFO) sys.stdout = sl_out stderr_logger = logging.getLogger('STDERR') sl_err = StreamToLogger(stderr_logger, logging.ERROR) sys.stderr = sl_err _pcbnew_frame = [ x for x in wx.GetTopLevelWindows() if x.GetTitle().lower().startswith('pcbnew') ][0] # check if there is exactly one module selected selected_modules = [ x for x in pcbnew.GetBoard().GetModules() if x.IsSelected() ] selected_names = [] for mod in selected_modules: selected_names.append("{}".format(mod.GetReference())) # if more or less than one show only a messagebox if len(selected_names) != 1: caption = 'Place footprints' message = "More or less than 1 footprint selected. Please select exactly one footprint and run the script again" dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return # this it the reference footprint pivot_module_reference = selected_names[0] # ask user which way to select other footprints (by increasing reference number or by ID) dlg = InitialDialog(_pcbnew_frame) res = dlg.ShowModal() placer = place_footprints.Placer(board) pivot_module = placer.get_mod_by_ref(pivot_module_reference) # by reference number if res == wx.ID_OK: # by ref module_reference_designator = ''.join( i for i in pivot_module_reference if not i.isdigit()) module_reference_number = int(''.join( i for i in pivot_module_reference if i.isdigit())) # get list of all modules with same reference designator list_of_all_modules_with_same_designator = placer.get_modules_with_reference_designator( module_reference_designator) sorted_list = natural_sort( list_of_all_modules_with_same_designator) # find only consequtive modules list_of_consecutive_modules = [] # go through the list in positive direction start_index = sorted_list.index(pivot_module_reference) count_start = module_reference_number for mod in sorted_list[start_index:]: if int(''.join(i for i in mod if i.isdigit())) == count_start: count_start = count_start + 1 list_of_consecutive_modules.append(mod) else: break # go through the list in negative direction count_start = module_reference_number reversed_list = list(reversed(sorted_list)) start_index = reversed_list.index(pivot_module_reference) for mod in reversed_list[start_index:]: if int(''.join(i for i in mod if i.isdigit())) == count_start: count_start = count_start - 1 list_of_consecutive_modules.append(mod) else: break sorted_modules = natural_sort( list(set(list_of_consecutive_modules))) # display dialog dlg = PlaceByReference(_pcbnew_frame, placer, pivot_module_reference, user_units) dlg.list_modules.AppendItems(sorted_modules) # highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) set_highlight_on_module(module) pcbnew.Refresh() # by default select all sheets number_of_items = dlg.list_modules.GetCount() for i in range(number_of_items): dlg.list_modules.Select(i) res = dlg.ShowModal() if res == wx.ID_CANCEL: # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return # get list of modules to place modules_to_place_indeces = dlg.list_modules.GetSelections() modules_to_place = natural_sort( [sorted_modules[i] for i in modules_to_place_indeces]) # get mode if dlg.com_arr.GetStringSelection() == u'Circular': delta_angle = float(dlg.val_y_angle.GetValue()) if user_units == 'mm': radius = float(dlg.val_x_mag.GetValue()) else: radius = float(dlg.val_x_mag.GetValue()) / 25.4 try: placer.place_circular(modules_to_place, pivot_module_reference, radius, delta_angle, False) logger.info("Placing complete") logging.shutdown() except Exception: logger.exception( "Fatal error when executing place footprints") caption = 'Place footprints' message = "Fatal error when executing place footprints.\n"\ + "You can raise an issue on GiHub page.\n" \ + "Please attach the place_footprints.log which you should find in the project folder." dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logging.shutdown() # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return if dlg.com_arr.GetStringSelection() == u'Linear': if user_units == 'mm': step_x = float(dlg.val_x_mag.GetValue()) step_y = float(dlg.val_y_angle.GetValue()) else: step_x = float(dlg.val_x_mag.GetValue()) / 25.4 step_y = float(dlg.val_y_angle.GetValue()) / 25.4 try: placer.place_linear(modules_to_place, pivot_module_reference, step_x, step_y) logger.info("Placing complete") logging.shutdown() except Exception: logger.exception( "Fatal error when executing place footprints") caption = 'Place footprints' message = "Fatal error when executing place footprints.\n"\ + "You can raise an issue on GiHub page.\n" \ + "Please attach the place_footprints.log which you should find in the project folder." dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logging.shutdown() # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return if dlg.com_arr.GetStringSelection() == u'Matrix': if user_units == 'mm': step_x = float(dlg.val_x_mag.GetValue()) step_y = float(dlg.val_y_angle.GetValue()) else: step_x = float(dlg.val_x_mag.GetValue()) / 25.4 step_y = float(dlg.val_y_angle.GetValue()) / 25.4 nr_columns = int(dlg.val_columns.GetValue()) try: placer.place_matrix(sorted_modules, step_x, step_y, nr_columns) logger.info("Placing complete") logging.shutdown() except Exception: logger.exception( "Fatal error when executing place footprints") caption = 'Place footprints' message = "Fatal error when executing place footprints.\n"\ + "You can raise an issue on GiHub page.\n" \ + "Please attach the place_footprints.log which you should find in the project folder." dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logging.shutdown() # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() # by sheet else: # get list of all modules with same ID list_of_modules = placer.get_list_of_modules_with_same_id( pivot_module.mod_id) # display dialog dlg = PlaceBySheet(_pcbnew_frame, placer, pivot_module_reference, user_units) levels = pivot_module.filename dlg.list_levels.Clear() dlg.list_levels.AppendItems(levels) res = dlg.ShowModal() if res == wx.ID_CANCEL: # clear highlight all modules by default # get the list from the GUI elements for module in list_of_modules: clear_highlight_on_module(module.mod) pcbnew.Refresh() return # based on the sheet list, find all the modules with same ID sheets_to_place_indeces = dlg.list_sheets.GetSelections() sheets_to_place = [ dlg.list_sheetsChoices[i] for i in sheets_to_place_indeces ] mod_references = [pivot_module_reference] for mod in list_of_modules: if mod.sheet_id in sheets_to_place: mod_references.append(mod.ref) logger.info("Modules to place: " + repr(mod_references)) # sort by reference number sorted_modules = natural_sort(mod_references) # get mode if dlg.com_arr.GetStringSelection() == u'Circular': delta_angle = float(dlg.val_y_angle.GetValue()) if user_units == 'mm': radius = float(dlg.val_x_mag.GetValue()) else: radius = float(dlg.val_x_mag.GetValue()) / 25.4 try: placer.place_circular(sorted_modules, pivot_module_reference, radius, delta_angle, True) logger.info("Placing complete") logging.shutdown() except Exception: logger.exception( "Fatal error when executing place footprints") caption = 'Place footprints' message = "Fatal error when executing place footprints.\n"\ + "You can raise an issue on GiHub page.\n" \ + "Please attach the place_footprints.log which you should find in the project folder." dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logging.shutdown() # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return if dlg.com_arr.GetStringSelection() == u'Linear': if user_units == 'mm': step_x = float(dlg.val_x_mag.GetValue()) step_y = float(dlg.val_y_angle.GetValue()) else: step_x = float(dlg.val_x_mag.GetValue()) / 25.4 step_y = float(dlg.val_y_angle.GetValue()) / 25.4 try: placer.place_linear(sorted_modules, pivot_module_reference, step_x, step_y) logger.info("Placing complete") logger.info("Sorted_modules: " + repr(sorted_modules)) logging.shutdown() except Exception: logger.exception( "Fatal error when executing place footprints") caption = 'Place footprints' message = "Fatal error when executing place footprints.\n"\ + "You can raise an issue on GiHub page.\n" \ + "Please attach the place_footprints.log which you should find in the project folder." dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logging.shutdown() # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return if dlg.com_arr.GetStringSelection() == u'Matrix': if user_units == 'mm': step_x = float(dlg.val_x_mag.GetValue()) step_y = float(dlg.val_y_angle.GetValue()) else: step_x = float(dlg.val_x_mag.GetValue()) / 25.4 step_y = float(dlg.val_y_angle.GetValue()) / 25.4 nr_columns = int(dlg.val_columns.GetValue()) try: placer.place_matrix(sorted_modules, step_x, step_y, nr_columns) logger.info("Placing complete") logging.shutdown() except Exception: caption = 'Place footprints' logger.exception( "Fatal error when executing place footprints") message = "Fatal error when executing place footprints.\n"\ + "You can raise an issue on GiHub page.\n" \ + "Please attach the place_footprints.log which you should find in the project folder." dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logging.shutdown() # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh() return # clear highlight all modules by default for mod in sorted_modules: module = board.FindModuleByReference(mod) clear_highlight_on_module(module) pcbnew.Refresh()
def Run(self): # load board board = pcbnew.GetBoard() # go to the project folder - so that log will be in proper place os.chdir(os.path.dirname(os.path.abspath(board.GetFileName()))) # set up logger logging.basicConfig( level=logging.DEBUG, filename="pad2pad_track_distance.log", filemode='w', format='%(asctime)s %(name)s %(lineno)d:%(message)s', datefmt='%m-%d %H:%M:%S') logger = logging.getLogger(__name__) logger.info("Length stats plugin version: " + VERSION + " started") stdout_logger = logging.getLogger('STDOUT') sl_out = StreamToLogger(stdout_logger, logging.INFO) sys.stdout = sl_out stderr_logger = logging.getLogger('STDERR') sl_err = StreamToLogger(stderr_logger, logging.ERROR) sys.stderr = sl_err _pcbnew_frame = [ x for x in wx.GetTopLevelWindows() if x.GetTitle().lower().startswith('pcbnew') ][0] # get user units if pcbnew.GetUserUnits() == 1: user_units = 'mm' else: user_units = 'in' # get all pads modules = board.GetModules() pads = [] for mod in modules: # get their pads module_pads = mod.PadsList() # get net for pad in module_pads: pads.append(pad) # get list of all selected pads selected_pads = [] for pad in pads: if pad.IsSelected(): selected_pads.append(pad) # check the nets on all the pads nets = [] for pad in selected_pads: nets.append(pad.GetNetname()) # if more or less than two pads are selected if len(selected_pads) != 2: caption = 'Pad2Pad Track Distance' message = "You have to select two and only two pads" dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return # and if they are on different nest if nets[0] != nets[1]: caption = 'Pad2Pad Track Distance' message = "The selected pads are not on the same net" dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return try: measure_distance = pad2pad_track_distance.Distance( board, selected_pads[0], selected_pads[1]) distance, resistance = measure_distance.get_length() except LookupError as error: caption = 'Pad2Pad Track Distance' message = str(error) dlg = wx.MessageDialog(_pcbnew_frame, message, caption, wx.OK | wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() logger.info(message) return except Exception: logger.exception("Fatal error when measuring") raise # trying to show in layout which tracks are taken into account - so far it does not work # as the selection is automatically cleared when exiting action plugin # I'll leave this code in just for reference selected_pads[0].ClearSelected() selected_pads[1].ClearSelected() # deselect all tracks except used ones all_tracks = board.GetTracks() dlg = Pad2PadTrackDistanceDialog(_pcbnew_frame, all_tracks, measure_distance.track_list) if user_units == 'mm': dlg.lbl_length.SetLabelText("%.3f" % (distance) + " mm") dlg.lbl_resistance.SetLabelText("%.4f" % resistance + " Ohm") else: dlg.lbl_length.SetLabelText("%.4f" % (distance / 25.4) + " in") dlg.lbl_resistance.SetLabelText("%.4f" % resistance + " Ohm") dlg.Show()