diff --git a/ViaStitching/FillArea.py b/ViaStitching/FillArea.py index 8fbd6c5..1fccefc 100644 --- a/ViaStitching/FillArea.py +++ b/ViaStitching/FillArea.py @@ -30,10 +30,13 @@ import random import pprint import wx + def wxPrint(msg): wx.LogMessage(msg) + + # -if sys.version[0] == '2': #maui +if sys.version[0] == '2': # maui xrange else: xrange = range @@ -70,6 +73,7 @@ FillArea.FillArea().SetDebug().SetNetname("GND").SetStepMM(1.27).SetSizeMM(0.6). """ + class ViaObject: """ @@ -82,6 +86,7 @@ class ViaObject: self.PosX = pos_x self.PosY = pos_y + class FillArea: """ @@ -89,14 +94,14 @@ class FillArea: pads and keepout areas """ - REASON_OK = 0 - REASON_NO_SIGNAL = 1 + REASON_OK = 0 + REASON_NO_SIGNAL = 1 REASON_OTHER_SIGNAL = 2 - REASON_KEEPOUT = 3 - REASON_TRACK = 4 - REASON_PAD = 5 - REASON_DRAWING = 6 - REASON_STEP = 7 + REASON_KEEPOUT = 3 + REASON_TRACK = 4 + REASON_PAD = 5 + REASON_DRAWING = 6 + REASON_STEP = 7 def __init__(self, filename=None): self.filename = None @@ -156,8 +161,8 @@ class FillArea: return self def SetNetname(self, netname): - self.netname = netname #.upper() - #wx.LogMessage(self.netname) + self.netname = netname # .upper() + # wx.LogMessage(self.netname) return self def SetStepMM(self, s): @@ -243,7 +248,7 @@ STEP = '-' area = self.pcb.GetArea(i) area.ClearFilledPolysList() area.UnFill() - filler = ZONE_FILLER(self.pcb); + filler = ZONE_FILLER(self.pcb) filler.Fill(self.pcb.Zones()) def CheckViaInAllAreas(self, via, all_areas): @@ -252,42 +257,47 @@ STEP = '-' ''' # Enum all area for area in all_areas: - area_layer = area.GetLayer() - area_clearance = area.GetClearance() - area_priority = area.GetPriority() - is_keepout_area = area.GetIsKeepout() - is_target_net = (area.GetNetname() == self.netname) #(area.GetNetname().upper() == self.netname) - #wx.LogMessage(area.GetNetname()) #wx.LogMessage(area.GetNetname().upper()) + area_layer = area.GetLayer() + area_clearance = area.GetClearance() + area_priority = area.GetPriority() + is_keepout_area = area.GetIsKeepout() + 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 + # 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 for dx in [-offset, offset]: - for dy in [-offset, offset]: # All 4 corners of the via are testet (upper, lower, left, right) but not the center - point_to_test = wxPoint(via.PosX + dx, via.PosY + dy) + # 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(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,1) # Collides with an edge/corner + hit_test_area = area.HitTestFilledArea(point_to_test) # Collides with a filled area + 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) + 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 + # 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 elif (hit_test_area or hit_test_edge): - return self.REASON_OTHER_SIGNAL # Collides with another signal (e.g. on another layer) + # Collides with another signal (e.g. on another layer) + return self.REASON_OTHER_SIGNAL 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() == 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 else: - return self.REASON_OTHER_SIGNAL # Collides with another signal (e.g. on another layer) + # Collides with another signal (e.g. on another layer) + return self.REASON_OTHER_SIGNAL return self.REASON_OK @@ -336,71 +346,81 @@ STEP = '-' target_tracks = self.pcb.GetTracks() if self.delete_vias: - # 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 + # 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) + lboard = self.pcb.ComputeBoundingBox(False) origin = lboard.GetPosition() # Create an initial rectangle: all is set to "REASON_NO_SIGNAL" # get a margin to avoid out of range l_clearance = self.clearance + self.size - x_limit = int((lboard.GetWidth() + l_clearance) / l_clearance) + 1 - y_limit = int((lboard.GetHeight() + l_clearance) / l_clearance) + 1 + x_limit = int((lboard.GetWidth() + l_clearance) / l_clearance) + 1 + y_limit = int((lboard.GetHeight() + l_clearance) / l_clearance) + 1 rectangle = [[self.REASON_NO_SIGNAL]*y_limit for i in xrange(x_limit)] - all_pads = self.pcb.GetPads() - all_tracks = self.pcb.GetTracks() + all_pads = self.pcb.GetPads() + all_tracks = self.pcb.GetTracks() try: - all_drawings = filter(lambda x: x.GetClass() == 'PTEXT' and self.pcb.GetLayerID(x.GetLayerName()) in (F_Cu, B_Cu), self.pcb.DrawingsList()) + 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()) + 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() == self.netname), all_areas) # KeepOuts are filtered because they have no name + 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 + # KeepOuts are filtered because they have no name + target_areas = filter(lambda x: (x.GetNetname() == self.netname), all_areas) 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: - wxPrint ("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() + is_selected_area = area.IsSelected() + area_clearance = area.GetClearance() if max_target_area_clearance < area_clearance: max_target_area_clearance = area_clearance if (not self.only_selected_area) or (self.only_selected_area and is_selected_area): # All areas or only the selected area - for x in xrange(len(rectangle)): # Check every possible point in the virtual coordinate system + # Check every possible point in the virtual coordinate system + for x in xrange(len(rectangle)): for y in xrange(len(rectangle[0])): - if rectangle[x][y] == self.REASON_NO_SIGNAL: # 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: current_x = origin.x + (x * l_clearance) # Center of the via current_y = origin.y + (y * l_clearance) test_result = True # Start with true, if a check fails, it is set to false - 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 + # 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 for dx in [-offset, offset]: - for dy in [-offset, offset]: # All 4 corners of the via are testet (upper, lower, left, right) but not the center - point_to_test = wxPoint(current_x + dx, current_y + dy) - hit_test_area = area.HitTestFilledArea(point_to_test) # Collides with a filled area - hit_test_edge = area.HitTestForEdge(point_to_test,area_clearance) # Collides with an edge/corner + # 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(point_to_test) # Collides with a filled area + # Collides with an edge/corner + hit_test_edge = area.HitTestForEdge(point_to_test, area_clearance) - test_result &= (hit_test_area and not hit_test_edge) # 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 + test_result &= (hit_test_area and not hit_test_edge) if test_result: - via_obj = ViaObject(x=x, y=y, pos_x=current_x, pos_y=current_y) # Create a via object with information about the via and place it in the rectangle + # Create a via object with information about the via and place it in the rectangle + via_obj = ViaObject(x=x, y=y, pos_x=current_x, pos_y=current_y) rectangle[x][y] = via_obj via_list.append(via_obj) @@ -409,7 +429,7 @@ STEP = '-' self.PrintRect(rectangle) # Enum all vias - wxPrint ("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: @@ -420,23 +440,23 @@ STEP = '-' self.PrintRect(rectangle) # Same job with all pads => all pads on all layers - wxPrint ("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) + max_size = max(pad.GetSize().x, pad.GetSize().y) - start_x = int(floor(((pad.GetPosition().x - (max_size / 2.0 + local_offset)) - origin.x) / l_clearance)) - stop_x = int(ceil(((pad.GetPosition().x + (max_size / 2.0 + local_offset)) - origin.x) / l_clearance)) + start_x = int(floor(((pad.GetPosition().x - (max_size / 2.0 + local_offset)) - origin.x) / l_clearance)) + stop_x = int(ceil(((pad.GetPosition().x + (max_size / 2.0 + local_offset)) - origin.x) / l_clearance)) - start_y = int(floor(((pad.GetPosition().y - (max_size / 2.0 + local_offset)) - origin.y) / l_clearance)) - stop_y = int(ceil(((pad.GetPosition().y + (max_size / 2.0 + local_offset)) - origin.y) / l_clearance)) + start_y = int(floor(((pad.GetPosition().y - (max_size / 2.0 + local_offset)) - origin.y) / l_clearance)) + stop_y = int(ceil(((pad.GetPosition().y + (max_size / 2.0 + local_offset)) - origin.y) / l_clearance)) for x in range(start_x, stop_x + 1): for y in range(start_y, stop_y + 1): try: if isinstance(rectangle[x][y], ViaObject): start_rect = wxPoint(origin.x + (l_clearance * x) - local_offset, - origin.y + (l_clearance * y) - 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 @@ -447,7 +467,7 @@ STEP = '-' self.PrintRect(rectangle) # Same job with tracks => all tracks on all layers - wxPrint ("Processing all tracks...") + wxPrint("Processing all tracks...") for track in all_tracks: start_x = track.GetStart().x start_y = track.GetStart().y @@ -470,38 +490,41 @@ STEP = '-' opx = stop_x opy = stop_y - clearance = max(track.GetClearance(), self.clearance, max_target_area_clearance) + (self.size / 2) + (track.GetWidth() / 2) + clearance = max(track.GetClearance(), self.clearance, max_target_area_clearance) + (self.size / 2) + (track.GetWidth() / 2) - start_x = int(floor(((start_x - clearance) - origin.x) / l_clearance)) - stop_x = int(ceil(((stop_x + clearance) - origin.x) / l_clearance)) + start_x = int(floor(((start_x - clearance) - origin.x) / l_clearance)) + stop_x = int(ceil(((stop_x + clearance) - origin.x) / l_clearance)) - start_y = int(floor(((start_y - clearance) - origin.y) / l_clearance)) - stop_y = int(ceil(((stop_y + clearance) - origin.y) / l_clearance)) + start_y = int(floor(((start_y - clearance) - origin.y) / l_clearance)) + stop_y = int(ceil(((stop_y + clearance) - origin.y) / l_clearance)) 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) - clearance, - origin.y + (l_clearance * y) - clearance) - size_rect = wxSize(2 * clearance, 2 * clearance) - if track.HitTest(EDA_RECT(start_rect, size_rect), False): - rectangle[x][y] = self.REASON_TRACK + try: + if isinstance(rectangle[x][y], ViaObject): + start_rect = wxPoint(origin.x + (l_clearance * x) - clearance, + origin.y + (l_clearance * y) - clearance) + size_rect = wxSize(2 * clearance, 2 * clearance) + if track.HitTest(EDA_RECT(start_rect, size_rect), False): + rectangle[x][y] = self.REASON_TRACK + except: + wxPrint("exception on Processing all tracks...") if self.debug: wxPrint("\nPost tracks:") self.PrintRect(rectangle) # Same job with existing text - wxPrint ("Processing all existing drawings...") + wxPrint("Processing all existing drawings...") for draw in all_drawings: - inter = float(self.clearance + self.size) - bbox = draw.GetBoundingBox() + inter = float(self.clearance + self.size) + bbox = draw.GetBoundingBox() start_x = int(floor(((bbox.GetPosition().x - inter) - origin.x) / l_clearance)) - stop_x = int(ceil(((bbox.GetPosition().x + (bbox.GetSize().x + inter)) - origin.x) / l_clearance)) + stop_x = int(ceil(((bbox.GetPosition().x + (bbox.GetSize().x + inter)) - origin.x) / l_clearance)) start_y = int(floor(((bbox.GetPosition().y - inter) - origin.y) / l_clearance)) - stop_y = int(ceil(((bbox.GetPosition().y + (bbox.GetSize().y + inter)) - origin.y) / l_clearance)) + stop_y = int(ceil(((bbox.GetPosition().y + (bbox.GetSize().y + inter)) - origin.y) / l_clearance)) for x in range(start_x, stop_x + 1): for y in range(start_y, stop_y + 1): @@ -511,10 +534,11 @@ STEP = '-' wxPrint("Post Drawnings:") self.PrintRect(rectangle) - wxPrint ("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) + # How much "via steps" should be removed around a via (round up) + clear_distance = int((self.step+l_clearance) / l_clearance) for x in xrange(len(rectangle)): for y in xrange(len(rectangle[0])): @@ -522,9 +546,9 @@ STEP = '-' if clear_distance: self.ClearViaInStepSize(rectangle, x, y, clear_distance) - via = rectangle[x][y] - ran_x = 0 - ran_y = 0 + via = rectangle[x][y] + ran_x = 0 + ran_y = 0 if self.random: ran_x = (random.random() * l_clearance / 2.0) - (l_clearance / 4.0) @@ -540,7 +564,8 @@ STEP = '-' if self.filename: self.pcb.Save(self.filename) - wxPrint ("Done!") + wxPrint("Done!") + if __name__ == '__main__': if len(sys.argv) < 2: