diff --git a/ViaStitching/FillArea.py b/ViaStitching/FillArea.py old mode 100755 new mode 100644 index 2c40c61..8fbd6c5 --- a/ViaStitching/FillArea.py +++ b/ViaStitching/FillArea.py @@ -28,6 +28,16 @@ import shutil import os import random import pprint +import wx + +def wxPrint(msg): + wx.LogMessage(msg) +# +if sys.version[0] == '2': #maui + xrange +else: + xrange = range + """ # This script fills all areas of a specific net with Vias (Via Stitching) @@ -126,7 +136,7 @@ class FillArea: self.SetPCB(LoadBoard(self.filename)) def SetDebug(self): - print("Set debug") + wxPrint("Set debug") self.debug = True return self @@ -146,7 +156,8 @@ class FillArea: return self def SetNetname(self, netname): - self.netname = netname.upper() + self.netname = netname #.upper() + #wx.LogMessage(self.netname) return self def SetStepMM(self, s): @@ -222,8 +233,9 @@ STEP = '-' m.SetViaType(VIA_THROUGH) m.SetDrill(int(self.drill)) m.SetWidth(int(self.size)) - # No more possible to mark via as own since no timestamp_t binding - #m.SetTimeStamp(33) # USE 33 as timestamp to mark this via as generated + # again possible to mark via as own since no timestamp_t binding kicad v5.1.4 + m.SetTimeStamp(33) # USE 33 as timestamp to mark this via as generated by this script + #wx.LogMessage('adding vias') self.pcb.Add(m) def RefillBoardAreas(self): @@ -244,7 +256,8 @@ STEP = '-' area_clearance = area.GetClearance() area_priority = area.GetPriority() is_keepout_area = area.GetIsKeepout() - is_target_net = (area.GetNetname().upper() == self.netname) + is_target_net = (area.GetNetname() == self.netname) #(area.GetNetname().upper() == self.netname) + #wx.LogMessage(area.GetNetname()) #wx.LogMessage(area.GetNetname().upper()) if (not is_target_net): # Only process areas that are not in the target net offset = max(self.clearance, area_clearance) + self.size / 2 # Offset is half the size of the via plus the clearance of the via or the area @@ -253,9 +266,13 @@ STEP = '-' point_to_test = wxPoint(via.PosX + dx, via.PosY + dy) hit_test_area = area.HitTestFilledArea(point_to_test) # Collides with a filled area - hit_test_edge = area.HitTestForEdge(point_to_test) # Collides with an edge/corner - hit_test_zone = area.HitTestInsideZone(point_to_test) # Is inside a zone (e.g. KeepOut) - + hit_test_edge = area.HitTestForEdge(point_to_test,1) # Collides with an edge/corner + try: + hit_test_zone = area.HitTestInsideZone(point_to_test) # Is inside a zone (e.g. KeepOut) + except: + hit_test_zone = False + wxPrint('exception: missing HitTestInsideZone: To Be Fixed') + #hit_test_zone = area.HitTest(point_to_test) # Is inside a zone (e.g. KeepOut) kicad nightly 5.99 if is_keepout_area and (hit_test_area or hit_test_edge or hit_test_zone): return self.REASON_KEEPOUT # Collides with keepout @@ -264,7 +281,8 @@ STEP = '-' elif hit_test_zone: # Check if the zone is higher priority than other zones of the target net in the same point - target_areas_on_same_layer = filter(lambda x: ((x.GetPriority() > area_priority) and (x.GetLayer() == area_layer) and (x.GetNetname().upper() == self.netname)), all_areas) + #target_areas_on_same_layer = filter(lambda x: ((x.GetPriority() > area_priority) and (x.GetLayer() == area_layer) and (x.GetNetname().upper() == self.netname)), all_areas) + target_areas_on_same_layer = filter(lambda x: ((x.GetPriority() > area_priority) and (x.GetLayer() == area_layer) and (x.GetNetname() == self.netname)), all_areas) for area_with_higher_priority in target_areas_on_same_layer: if area_with_higher_priority.HitTestInsideZone(point_to_test): break # Area of target net has higher priority on this layer @@ -318,15 +336,16 @@ STEP = '-' target_tracks = self.pcb.GetTracks() if self.delete_vias: - # timestmap no more available - # target_tracks = filter(lambda x: (x.GetNetname().upper() == self.netname), self.pcb.GetTracks()) - # for via in target_tracks: - # pprint.pprint(via.GetTimeStamp()) - # if via.Type() == PCB_VIA_T: - # if via.GetTimeStamp() == 33: - # self.pcb.RemoveNative(via) - # self.RefillBoardAreas() - return # no need to run the rest of logic + # timestmap again available + #target_tracks = filter(lambda x: (x.GetNetname().upper() == self.netname), self.pcb.GetTracks()) + target_tracks = filter(lambda x: (x.GetNetname() == self.netname), self.pcb.GetTracks()) + for via in target_tracks: + #pprint.pprint(via.GetTimeStamp()) + if via.Type() == PCB_VIA_T: + if via.GetTimeStamp() == 33: + self.pcb.RemoveNative(via) + self.RefillBoardAreas() + return # no need to run the rest of logic lboard = self.pcb.ComputeBoundingBox(True) origin = lboard.GetPosition() @@ -341,16 +360,21 @@ STEP = '-' all_pads = self.pcb.GetPads() all_tracks = self.pcb.GetTracks() - all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.DrawingsList()) + try: + all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.DrawingsList()) + except: + all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.Drawings()) + #wxPrint("exception on missing BOARD.DrawingsList") all_areas = [self.pcb.GetArea(i) for i in xrange(self.pcb.GetAreaCount())] - target_areas = filter(lambda x: (x.GetNetname().upper() == self.netname), all_areas) # KeepOuts are filtered because they have no name + #target_areas = filter(lambda x: (x.GetNetname().upper() == self.netname), all_areas) # KeepOuts are filtered because they have no name + target_areas = filter(lambda x: (x.GetNetname() == self.netname), all_areas) # KeepOuts are filtered because they have no name via_list = [] # Create a list of existing vias => faster than scanning through the whole rectangle max_target_area_clearance = 0 # Enum all target areas (Search possible positions for vias on the target net) for area in target_areas: - print ("Processing Target Area: %s, LayerName: %s..." % (area.GetNetname(), area.GetLayerName())) + wxPrint ("Processing Target Area: %s, LayerName: %s..." % (area.GetNetname(), area.GetLayerName())) is_selected_area = area.IsSelected() area_clearance = area.GetClearance() @@ -381,22 +405,22 @@ STEP = '-' via_list.append(via_obj) if self.debug: - print("\nPost target areas:") + wxPrint("\nPost target areas:") self.PrintRect(rectangle) # Enum all vias - print ("Processing all vias of target area...") + wxPrint ("Processing all vias of target area...") for via in via_list: reason = self.CheckViaInAllAreas(via, all_areas) if reason != self.REASON_OK: rectangle[via.X][via.Y] = reason if self.debug: - print("\nPost areas:") + wxPrint("\nPost areas:") self.PrintRect(rectangle) # Same job with all pads => all pads on all layers - print ("Processing all pads...") + wxPrint ("Processing all pads...") for pad in all_pads: local_offset = max(pad.GetClearance(), self.clearance, max_target_area_clearance) + (self.size / 2) max_size = max(pad.GetSize().x, pad.GetSize().y) @@ -409,19 +433,21 @@ STEP = '-' for x in range(start_x, stop_x + 1): for y in range(start_y, stop_y + 1): - if isinstance(rectangle[x][y], ViaObject): - start_rect = wxPoint(origin.x + (l_clearance * x) - local_offset, - origin.y + (l_clearance * y) - local_offset) - size_rect = wxSize(2 * local_offset, 2 * local_offset) - if pad.HitTest(EDA_RECT(start_rect, size_rect), False): - rectangle[x][y] = self.REASON_PAD - + try: + if isinstance(rectangle[x][y], ViaObject): + start_rect = wxPoint(origin.x + (l_clearance * x) - local_offset, + origin.y + (l_clearance * y) - local_offset) + size_rect = wxSize(2 * local_offset, 2 * local_offset) + if pad.HitTest(EDA_RECT(start_rect, size_rect), False): + rectangle[x][y] = self.REASON_PAD + except: + wxPrint("exception on Processing all pads...") if self.debug: - print("\nPost pads:") + wxPrint("\nPost pads:") self.PrintRect(rectangle) # Same job with tracks => all tracks on all layers - print ("Processing all tracks...") + wxPrint ("Processing all tracks...") for track in all_tracks: start_x = track.GetStart().x start_y = track.GetStart().y @@ -462,11 +488,11 @@ STEP = '-' rectangle[x][y] = self.REASON_TRACK if self.debug: - print("\nPost tracks:") + wxPrint("\nPost tracks:") self.PrintRect(rectangle) # Same job with existing text - print ("Processing all existing drawings...") + wxPrint ("Processing all existing drawings...") for draw in all_drawings: inter = float(self.clearance + self.size) bbox = draw.GetBoundingBox() @@ -482,10 +508,10 @@ STEP = '-' rectangle[x][y] = self.REASON_DRAWING if self.debug: - print("Post Drawnings:") + wxPrint("Post Drawnings:") self.PrintRect(rectangle) - print ("Remove vias to guarantee step size...") + wxPrint ("Remove vias to guarantee step size...") clear_distance = 0 if self.step != 0.0: clear_distance = int((self.step+l_clearance) / l_clearance) # How much "via steps" should be removed around a via (round up) @@ -507,14 +533,14 @@ STEP = '-' self.AddVia(wxPoint(via.PosX + ran_x, via.PosY + ran_y), via.X, via.Y) if self.debug: - print("\nFinal result:") + wxPrint("\nFinal result:") self.PrintRect(rectangle) self.RefillBoardAreas() if self.filename: self.pcb.Save(self.filename) - print ("Done!") + wxPrint ("Done!") if __name__ == '__main__': if len(sys.argv) < 2: diff --git a/ViaStitching/FillAreaAction.py b/ViaStitching/FillAreaAction.py index e61f3ad..f52a716 100644 --- a/ViaStitching/FillAreaAction.py +++ b/ViaStitching/FillAreaAction.py @@ -22,8 +22,18 @@ import pcbnew import wx from . import FillArea from . import FillAreaDialog +import os - +def PopulateNets(anet,dlg): + nets = pcbnew.GetBoard().GetNetsByName() + for netname, net in nets.items(): + netname = net.GetNetname() + if netname != None and netname != "": + dlg.m_cbNet.Append(netname) + if anet != None: + index = dlg.m_cbNet.FindString(anet) + dlg.m_cbNet.Select(index) +# class FillAreaDialogEx(FillAreaDialog.FillAreaDialog): def onDeleteClick(self, event): @@ -33,27 +43,34 @@ class FillAreaDialogEx(FillAreaDialog.FillAreaDialog): class FillAreaAction(pcbnew.ActionPlugin): def defaults(self): - self.name = "Via stitching WX" - self.category = "Undefined" - self.description = "" - + self.name = "Via Stitching Generator" + self.category = "Modify PCB" + self.description = "Via Stitching for PCB Zone" + self.icon_file_name = os.path.join(os.path.dirname(__file__), "./stitching-vias.png") + self.show_toolbar_button = True + def Run(self): a = FillAreaDialogEx(None) - a.m_SizeMM.SetValue("0.46") + a.m_SizeMM.SetValue("0.8") a.m_StepMM.SetValue("2.54") - a.m_DrillMM.SetValue("0.2") - a.m_Netname.SetValue("GND") + a.m_DrillMM.SetValue("0.3") + #a.m_Netname.SetValue("GND") a.m_ClearanceMM.SetValue("0.2") a.m_Star.SetValue(True) + self.board = pcbnew.GetBoard() + PopulateNets("GND",a) modal_result = a.ShowModal() if modal_result == wx.ID_OK: - try: + wx.LogMessage('Via Stitching: Version 1.3') + if 1: #try: fill = FillArea.FillArea() fill.SetStepMM(float(a.m_StepMM.GetValue())) fill.SetSizeMM(float(a.m_SizeMM.GetValue())) fill.SetDrillMM(float(a.m_DrillMM.GetValue())) fill.SetClearanceMM(float(a.m_ClearanceMM.GetValue())) - fill.SetNetname(a.m_Netname.GetValue()) + #fill.SetNetname(a.m_Netname.GetValue()) + netname = a.m_cbNet.GetStringSelection() + fill.SetNetname(netname) if a.m_Debug.IsChecked(): fill.SetDebug() if a.m_Random.IsChecked(): @@ -63,17 +80,17 @@ class FillAreaAction(pcbnew.ActionPlugin): if a.m_only_selected.IsChecked(): fill.OnlyOnSelectedArea() fill.Run() - except Exception: + else: #except Exception: wx.MessageDialog(None, "Invalid parameter") elif modal_result == wx.ID_DELETE: - try: + if 1: #try: fill = FillArea.FillArea() - fill.SetNetname(a.m_Netname.GetValue()) + fill.SetNetname(a.m_cbNet.GetStringSelection()) #a.m_Netname.GetValue()) if a.m_Debug.IsChecked(): fill.SetDebug() fill.DeleteVias() fill.Run() - except Exception: + else: #except Exception: wx.MessageDialog(None, "Invalid parameter for delete") else: print("Cancel") diff --git a/ViaStitching/FillAreaDialog.py b/ViaStitching/FillAreaDialog.py index 42999e1..e19dea1 100644 --- a/ViaStitching/FillAreaDialog.py +++ b/ViaStitching/FillAreaDialog.py @@ -17,9 +17,14 @@ import wx.xrc class FillAreaDialog ( wx.Dialog ): def __init__( self, parent ): - wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Fill Area parameters", pos = wx.DefaultPosition, size = wx.Size( 369,389 ), style = wx.DEFAULT_DIALOG_STYLE ) + wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Fill Area parameters", pos = wx.DefaultPosition, size = wx.Size( 402,487 ), style = wx.DEFAULT_DIALOG_STYLE ) - self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) + import sys + if sys.version_info[0] == 2: + self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) + else: + self.SetSizeHints( wx.DefaultSize, wx.DefaultSize ) + #self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize ) bSizer3 = wx.BoxSizer( wx.VERTICAL ) @@ -54,8 +59,9 @@ class FillAreaDialog ( wx.Dialog ): self.m_staticText6.Wrap( -1 ) fgSizer1.Add( self.m_staticText6, 1, wx.ALL|wx.EXPAND, 5 ) - self.m_Netname = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) - fgSizer1.Add( self.m_Netname, 1, wx.ALL|wx.EXPAND, 5 ) + m_cbNetChoices = [] + self.m_cbNet = wx.ComboBox( self, wx.ID_ANY, u"GND", wx.DefaultPosition, wx.DefaultSize, m_cbNetChoices, 0 ) + fgSizer1.Add( self.m_cbNet, 0, wx.ALL, 5 ) self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, u"Step between via", wx.DefaultPosition, wx.DefaultSize, 0 ) self.m_staticText2.Wrap( -1 ) diff --git a/ViaStitching/FillAreaTpl.fbp b/ViaStitching/FillAreaTpl.fbp index be9e913..0780cee 100644 --- a/ViaStitching/FillAreaTpl.fbp +++ b/ViaStitching/FillAreaTpl.fbp @@ -44,7 +44,7 @@ FillAreaDialog - 369,389 + 402,487 wxDEFAULT_DIALOG_STYLE Fill Area parameters @@ -714,11 +714,11 @@ - + 5 - wxALL|wxEXPAND - 1 - + wxALL + 0 + 1 1 1 @@ -732,6 +732,7 @@ 1 0 + 1 1 @@ -749,12 +750,11 @@ 0 - 0 1 - m_Netname + m_cbNet 1 @@ -762,6 +762,7 @@ 1 Resizable + -1 1 @@ -772,11 +773,14 @@ wxFILTER_NONE wxDefaultValidator - + GND + + + @@ -800,8 +804,6 @@ - - diff --git a/ViaStitching/stitching-vias.png b/ViaStitching/stitching-vias.png new file mode 100644 index 0000000..22fba15 Binary files /dev/null and b/ViaStitching/stitching-vias.png differ diff --git a/ViaStitching/stitching-vias.svg b/ViaStitching/stitching-vias.svg new file mode 100644 index 0000000..e00528b --- /dev/null +++ b/ViaStitching/stitching-vias.svg @@ -0,0 +1,155 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + +