- Fix #27 for 6.0 branch of KiCad.

- Using pcb_group to allow via creation inside a group
- delete of via is no more possible via this pluging. Directly delete the generated pcb_group.
This commit is contained in:
Jean-Samuel Reynaud
2021-07-06 10:13:21 +02:00
parent c863e5e6a8
commit 3d14eb456d
2 changed files with 70 additions and 36 deletions

View File

@ -29,6 +29,8 @@ import os
import random import random
import pprint import pprint
import wx import wx
from inspect import currentframe, getframeinfo
import time
def wxPrint(msg): def wxPrint(msg):
@ -135,6 +137,8 @@ class FillArea:
self.tmp_dir = None self.tmp_dir = None
self.parent_area = None self.parent_area = None
self.pcb_group = None
self.target_net = None
def SetFile(self, filename): def SetFile(self, filename):
self.filename = filename self.filename = filename
@ -234,24 +238,26 @@ STEP = '-'
def AddVia(self, position, x, y): def AddVia(self, position, x, y):
if self.parent_area: if self.parent_area:
m = VIA(self.parent_area) m = PCB_VIA(self.parent_area)
m.SetPosition(position) m.SetPosition(position)
m.SetNet(self.pcb.FindNet(self.netname)) if self.target_net is None:
self.target_net = self.pcb.FindNet(self.netname)
m.SetNet(self.target_net)
m.SetViaType(VIATYPE_THROUGH) m.SetViaType(VIATYPE_THROUGH)
m.SetDrill(int(self.drill)) m.SetDrill(int(self.drill))
m.SetWidth(int(self.size)) m.SetWidth(int(self.size))
m.SetIsFree(True) m.SetIsFree(True)
# again possible to mark via as own since no timestamp_t binding kicad v5.1.4 # again possible to mark via as own since no timestamp_t binding kicad v5.1.4
# m.SetParentGroup(self.parent_group) # m.SetParentGroup(self.parent_group)
#wx.LogMessage('adding vias') # wx.LogMessage('adding vias')
self.pcb.Add(m) self.pcb.Add(m)
self.pcb_group.AddItem(m)
else: else:
wxPrint("\nUnable to find a valid parent area (zone)") wxPrint("\nUnable to find a valid parent area (zone)")
def RefillBoardAreas(self): def RefillBoardAreas(self):
for i in range(self.pcb.GetAreaCount()): for i in range(self.pcb.GetAreaCount()):
area = self.pcb.GetArea(i) area = self.pcb.GetArea(i)
area.ClearFilledPolysList()
area.UnFill() area.UnFill()
filler = ZONE_FILLER(self.pcb) filler = ZONE_FILLER(self.pcb)
filler.Fill(self.pcb.Zones()) filler.Fill(self.pcb.Zones())
@ -294,7 +300,7 @@ STEP = '-'
elif hit_test_zone: elif hit_test_zone:
# Check if the zone is higher priority than other zones of the target net in the same point # 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 ( target_areas_on_same_layer = filter(lambda x: ((x.GetPriority() > area_priority) and (
x.GetLayer() == area_layer) and (x.GetNetname() == self.netname)), all_areas) x.GetLayer() == area_layer) and (x.GetNetname() == self.netname)), all_areas)
for area_with_higher_priority in target_areas_on_same_layer: for area_with_higher_priority in target_areas_on_same_layer:
@ -345,28 +351,44 @@ STEP = '-'
rectangle[x_pos][y_pos] = self.REASON_STEP rectangle[x_pos][y_pos] = self.REASON_STEP
def Run(self): def Run(self):
VIA_GROUP_NAME = "ViaStitching {}".format(self.netname)
if self.debug:
print("Enumerate groups")
for i in self.pcb.Groups():
if i.GetName() == VIA_GROUP_NAME:
if self.debug:
print("Group {} Found !".format(VIA_GROUP_NAME))
self.pcb_group = i
if self.pcb_group is None:
self.pcb_group = PCB_GROUP(None)
self.pcb_group.SetName(VIA_GROUP_NAME)
self.pcb.Add(self.pcb_group)
""" """
Launch the process Launch the process
""" """
target_tracks = self.pcb.GetTracks()
if self.delete_vias: if self.delete_vias:
# timestmap again available # timestmap again available
#target_tracks = filter(lambda x: (x.GetNetname().upper() == self.netname), self.pcb.GetTracks()) # 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()) wx.MessageBox(
target_tracks_cp = list(target_tracks) "To delete vias:\n - select one of the generated via to select the group of vias named {}\n - hit delete key\n - That's all !".format(VIA_GROUP_NAME), "Information")
l = len(target_tracks_cp)
for i in range(l):
if target_tracks_cp[i].Type() == PCB_VIA_T:
# TODO: timestamp is no more available: looking for a better solution...
# if target_tracks_cp[i].GetTimeStamp() == 33:
# self.pcb.RemoveNative(target_tracks_cp[i])
None
self.RefillBoardAreas()
return # no need to run the rest of logic return # no need to run the rest of logic
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
target_tracks = self.pcb.GetTracks()
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
lboard = self.pcb.ComputeBoundingBox(False) lboard = self.pcb.ComputeBoundingBox(False)
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
origin = lboard.GetPosition() origin = lboard.GetPosition()
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
# Create an initial rectangle: all is set to "REASON_NO_SIGNAL" # Create an initial rectangle: all is set to "REASON_NO_SIGNAL"
# get a margin to avoid out of range # get a margin to avoid out of range
@ -378,13 +400,15 @@ STEP = '-'
all_pads = self.pcb.GetPads() all_pads = self.pcb.GetPads()
all_tracks = self.pcb.GetTracks() all_tracks = self.pcb.GetTracks()
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
try: try:
all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID( all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(
x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.DrawingsList()) x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.DrawingsList())
except: except:
all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID( all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(
x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.Drawings()) x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.Drawings())
#wxPrint("exception on missing BOARD.DrawingsList") # wxPrint("exception on missing BOARD.DrawingsList")
all_areas = [self.pcb.GetArea(i) for i in xrange(self.pcb.GetAreaCount())] 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
# KeepOuts are filtered because they have no name # KeepOuts are filtered because they have no name
@ -395,6 +419,8 @@ STEP = '-'
# Enum all target areas (Search possible positions for vias on the target net) # Enum all target areas (Search possible positions for vias on the target net)
for area in target_areas: for area in target_areas:
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
wxPrint("Processing Target Area: %s, LayerName: %s..." % (area.GetNetname(), area.GetLayerName())) wxPrint("Processing Target Area: %s, LayerName: %s..." % (area.GetNetname(), area.GetLayerName()))
if self.parent_area is None: if self.parent_area is None:
self.parent_area = area self.parent_area = area
@ -405,7 +431,12 @@ STEP = '-'
if (not self.only_selected_area) or (self.only_selected_area and is_selected_area): # All areas or only the selected area if (not self.only_selected_area) or (self.only_selected_area and is_selected_area): # All areas or only the selected area
# Check every possible point in the virtual coordinate system # Check every possible point in the virtual coordinate system
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
for x in xrange(len(rectangle)): for x in xrange(len(rectangle)):
if x % 10 == 0:
if self.debug:
print("%s: Line %u (x=%s;%s)" % (time.time(), currentframe().f_lineno, x, len(rectangle)))
for y in xrange(len(rectangle[0])): for y in xrange(len(rectangle[0])):
# No other "target area" found yet => go on with processing # No other "target area" found yet => go on with processing
if rectangle[x][y] == self.REASON_NO_SIGNAL: if rectangle[x][y] == self.REASON_NO_SIGNAL:
@ -416,12 +447,9 @@ STEP = '-'
# Offset is half the size of the via plus the clearance of the via or the area # Offset is half the size of the via plus the clearance of the via or the area
offset = max(self.clearance, area_clearance) + self.size / 2 offset = max(self.clearance, area_clearance) + self.size / 2
for dx in [-offset, offset]: point_to_test = wxPoint(int(current_x), int(current_y))
# All 4 corners of the via are testet (upper, lower, left, right) but not the center
for dy in [-offset, offset]:
point_to_test = wxPoint(current_x + dx, current_y + dy)
hit_test_area = area.HitTestFilledArea( hit_test_area = area.HitTestFilledArea(
area.GetLayer(), point_to_test) # Collides with a filled area area.GetLayer(), point_to_test, int(offset)) # Collides with a filled area
# Collides with an edge/corner # Collides with an edge/corner
hit_test_edge = area.HitTestForEdge(point_to_test, area_clearance) hit_test_edge = area.HitTestForEdge(point_to_test, area_clearance)
# test_result only remains true if the via is inside an area and not on an edge # test_result only remains true if the via is inside an area and not on an edge
@ -438,6 +466,8 @@ STEP = '-'
self.PrintRect(rectangle) self.PrintRect(rectangle)
# Enum all vias # Enum all vias
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
wxPrint("Processing all vias of target area...") wxPrint("Processing all vias of target area...")
for via in via_list: for via in via_list:
reason = self.CheckViaInAllAreas(via, all_areas) reason = self.CheckViaInAllAreas(via, all_areas)
@ -450,6 +480,8 @@ STEP = '-'
# Same job with all pads => all pads on all layers # Same job with all pads => all pads on all layers
wxPrint("Processing all pads...") wxPrint("Processing all pads...")
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
for pad in all_pads: for pad in all_pads:
local_offset = max(pad.GetLocalClearance(), self.clearance, max_target_area_clearance) + (self.size / 2) local_offset = max(pad.GetLocalClearance(), self.clearance, max_target_area_clearance) + (self.size / 2)
max_size = max(pad.GetSize().x, pad.GetSize().y) max_size = max(pad.GetSize().x, pad.GetSize().y)
@ -477,6 +509,8 @@ STEP = '-'
# Same job with tracks => all tracks on all layers # Same job with tracks => all tracks on all layers
wxPrint("Processing all tracks...") wxPrint("Processing all tracks...")
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
for track in all_tracks: for track in all_tracks:
start_x = track.GetStart().x start_x = track.GetStart().x
start_y = track.GetStart().y start_y = track.GetStart().y
@ -526,6 +560,8 @@ STEP = '-'
# Same job with existing text # Same job with existing text
wxPrint("Processing all existing drawings...") wxPrint("Processing all existing drawings...")
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
for draw in all_drawings: for draw in all_drawings:
inter = float(self.clearance + self.size) inter = float(self.clearance + self.size)
bbox = draw.GetBoundingBox() bbox = draw.GetBoundingBox()
@ -572,6 +608,8 @@ STEP = '-'
wxPrint("\nFinal result:") wxPrint("\nFinal result:")
self.PrintRect(rectangle) self.PrintRect(rectangle)
if self.debug:
print("%s: Line %u" % (time.time(), currentframe().f_lineno))
self.RefillBoardAreas() self.RefillBoardAreas()
if self.filename: if self.filename:

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
########################################################################### ###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018) ## Python code generated with wxFormBuilder (version 3.9.0 Jul 3 2021)
## http://www.wxformbuilder.org/ ## http://www.wxformbuilder.org/
## ##
## PLEASE DO *NOT* EDIT THIS FILE! ## PLEASE DO *NOT* EDIT THIS FILE!
@ -19,10 +19,6 @@ class FillAreaDialog ( wx.Dialog ):
def __init__( self, parent ): def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Fill Area parameters", pos = wx.DefaultPosition, size = wx.Size( 402,580 ), style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER ) wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"Fill Area parameters", pos = wx.DefaultPosition, size = wx.Size( 402,580 ), style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER )
import sys
if sys.version_info[0] == 2:
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
else:
self.SetSizeHints( wx.DefaultSize, wx.DefaultSize ) self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
bSizer3 = wx.BoxSizer( wx.VERTICAL ) bSizer3 = wx.BoxSizer( wx.VERTICAL )
@ -149,7 +145,7 @@ class FillAreaDialog ( wx.Dialog ):
pass pass
# Virtual event handlers, overide them in your derived class # Virtual event handlers, override them in your derived class
def onDeleteClick( self, event ): def onDeleteClick( self, event ):
event.Skip() event.Skip()